0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #include <ndrx_config.h>
0036 #include <ndrstandard.h>
0037 #include <ndebug.h>
0038 #include <singlegrp.h>
0039 #include <lcfint.h>
0040 #include <sys/stat.h>
0041 #include <sys_unix.h>
0042 #include <sys/time.h>
0043 #include <sys_test.h>
0044 #include <exatomic.h>
0045
0046
0047
0048
0049 #define NDRX_SG_GET_PTR(sg_no) \
0050 (ndrx_sg_shm_t *)((char *)ndrx_G_shmcfg->commands \
0051 + sizeof(ndrx_G_shmcfg->commands[0])*ndrx_G_libnstd_cfg.lcfmax \
0052 + sizeof(ndrx_sg_shm_t)*(sg_no-1))
0053
0054
0055
0056
0057
0058
0059 exprivate int ndrx_sg_chk_timestamp(int singlegrp_no, ndrx_sg_shm_t *sg);
0060
0061
0062
0063
0064 expublic int ndrx_sg_init(void)
0065 {
0066 return EXSUCCEED;
0067 }
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079 expublic ndrx_sg_shm_t *ndrx_sg_get(int singlegrp_no)
0080 {
0081 ndrx_sg_shm_t *ret = NULL;
0082
0083
0084 if (singlegrp_no < 0 || singlegrp_no > ndrx_G_libnstd_cfg.pgmax)
0085 {
0086 NDRX_LOG(log_error, "Invalid single group number: %d", singlegrp_no);
0087 goto out;
0088 }
0089
0090
0091 if (NULL==ndrx_G_shmcfg)
0092 {
0093 NDRX_LOG(log_error, "LCF shared memory is not attached!");
0094 goto out;
0095 }
0096
0097
0098
0099
0100 ret = (ndrx_sg_shm_t *)((char *)ndrx_G_shmcfg->commands
0101 + sizeof(ndrx_G_shmcfg->commands[0])*ndrx_G_libnstd_cfg.lcfmax
0102 + sizeof(ndrx_sg_shm_t)*(singlegrp_no-1));
0103 out:
0104 return ret;
0105 }
0106
0107
0108
0109
0110 expublic void ndrx_sg_reset(void)
0111 {
0112 if (NULL!=ndrx_G_shmcfg)
0113 {
0114 memset( (char *)ndrx_G_shmcfg->commands
0115 + sizeof(ndrx_G_shmcfg->commands[0])*ndrx_G_libnstd_cfg.lcfmax,
0116 0, sizeof(ndrx_sg_shm_t)*ndrx_G_libnstd_cfg.pgmax);
0117
0118 ndrx_G_shmcfg->is_mmon=EXFALSE;
0119 }
0120 }
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130 expublic void ndrx_sg_unlock(ndrx_sg_shm_t * sg, int reason)
0131 {
0132 unsigned char is_locked = NDRX_ATOMIC_LOAD(&sg->is_locked);
0133
0134 #if 0
0135
0136 if (ndrx_G_systest_lockloss > 0)
0137 {
0138 NDRX_LOG(log_error, "SYSTEST: no-unlock (lockloss)");
0139 }
0140 else if (is_locked)
0141 {
0142 #endif
0143 NDRX_ATOMIC_STORE(&sg->is_srv_booted, EXFALSE);
0144 NDRX_ATOMIC_STORE(&sg->is_clt_booted, EXFALSE);
0145 NDRX_ATOMIC_STORE(&sg->is_locked, EXFALSE);
0146 NDRX_ATOMIC_STORE(&sg->reason, reason);
0147 #if 0
0148 }
0149 #endif
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163 exprivate int ndrx_sg_do_refresh_int(int singlegrp_no, ndrx_sg_shm_t * sg,
0164 short nodeid, int srvid, int chk_lock, time_t new_last_refresh, long new_sequence)
0165 {
0166 int ret = EXSUCCEED;
0167 ndrx_sg_shm_t sg_local;
0168 pid_t pid;
0169 ndrx_sg_shm_t * sg_shm = NDRX_SG_GET_PTR(singlegrp_no);
0170
0171 if (NULL==sg)
0172 {
0173
0174 ndrx_sg_load(&sg_local, sg_shm);
0175 sg=&sg_local;
0176 }
0177
0178 if (chk_lock)
0179 {
0180 if (!sg->is_locked)
0181 {
0182 NDRX_LOG(log_error, "ERROR Group %d is not locked, but "
0183 "must be - terminating!", singlegrp_no);
0184 userlog("ERROR Group %d is not locked, but "
0185 "must be - terminating!", singlegrp_no);
0186 EXFAIL_OUT(ret);
0187 }
0188
0189
0190 if (sg->lockprov_pid!=(pid=getpid()))
0191 {
0192 NDRX_LOG(log_error, "ERROR Group %d is locked by PID %d, "
0193 "but must be locked by PID %d - terminating!",
0194 singlegrp_no, sg->lockprov_pid, (int)pid);
0195 userlog("ERROR Group %d is locked by PID %d, "
0196 "but must be locked by PID %d - terminating!",
0197 singlegrp_no, sg->lockprov_pid, (int)pid);
0198 EXFAIL_OUT(ret);
0199 }
0200
0201 if (sg->lockprov_nodeid!=nodeid)
0202 {
0203 NDRX_LOG(log_error, "ERROR Group %d is locked by Node %hd, "
0204 "but must be locked by Node %hd - terminating!",
0205 singlegrp_no, sg->lockprov_nodeid, nodeid);
0206 userlog("ERROR Group %d is locked by Node %hd, "
0207 "but must be locked by Node %hd - terminating!",
0208 singlegrp_no, sg->lockprov_nodeid, nodeid);
0209 EXFAIL_OUT(ret);
0210 }
0211
0212 if (sg->lockprov_srvid!=srvid)
0213 {
0214 NDRX_LOG(log_error, "ERROR Group %d is locked by Server id %d, "
0215 "but must be locked by Server %d - terminating!",
0216 singlegrp_no, sg->lockprov_srvid, srvid);
0217 userlog("ERROR Group %d is locked by Server is %d, "
0218 "but must be locked by Server %d - terminating!",
0219 singlegrp_no, sg->lockprov_srvid, srvid);
0220 EXFAIL_OUT(ret);
0221 }
0222
0223 if (EXSUCCEED!=ndrx_sg_chk_timestamp(singlegrp_no, sg))
0224 {
0225 EXFAIL_OUT(ret);
0226 }
0227 }
0228
0229 NDRX_ATOMIC_STORE(&sg_shm->last_refresh, new_last_refresh);
0230 NDRX_ATOMIC_STORE(&sg_shm->sequence, new_sequence);
0231
0232 out:
0233 return ret;
0234 }
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245 expublic int ndrx_sg_do_refresh(int singlegrp_no, ndrx_sg_shm_t * sg,
0246 short nodeid, int srvid, time_t new_last_refresh, long new_sequence)
0247 {
0248 return ndrx_sg_do_refresh_int(singlegrp_no, sg, nodeid, srvid,
0249 EXTRUE, new_last_refresh, new_sequence);
0250 }
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262 expublic int ndrx_sg_do_lock(int singlegrp_no, short nodeid, int srvid, char *procname,
0263 time_t new_last_refresh, long new_sequence)
0264 {
0265 int ret = EXSUCCEED;
0266 ndrx_sg_shm_t * sg_shm, sg;
0267
0268 sg_shm = NDRX_SG_GET_PTR(singlegrp_no);
0269 ndrx_sg_load(&sg, sg_shm);
0270
0271 if (sg.is_locked)
0272 {
0273 NDRX_LOG(log_error, "ERROR: Group %d already locked by Node %hd, PID %d, Procname [%s] - terminating",
0274 singlegrp_no, sg.lockprov_nodeid, sg.lockprov_pid, sg.lockprov_procname);
0275 userlog("ERROR: Group %d already locked by Node %hd, PID %d, Procname [%s] - terminating",
0276 singlegrp_no, sg.lockprov_nodeid, sg.lockprov_pid, sg.lockprov_procname);
0277 EXFAIL_OUT(ret);
0278 }
0279
0280 if (EXSUCCEED != ndrx_sg_do_refresh_int(singlegrp_no,
0281 &sg, nodeid, srvid, EXFALSE, new_last_refresh, new_sequence))
0282 {
0283 EXFAIL_OUT(ret);
0284 }
0285
0286
0287 ndrx_volatile_strcpy(sg_shm->lockprov_procname, procname, sizeof(sg.lockprov_procname));
0288 __sync_synchronize();
0289
0290 NDRX_ATOMIC_STORE(&sg_shm->lockprov_nodeid, nodeid);
0291 NDRX_ATOMIC_STORE(&sg_shm->lockprov_pid, getpid());
0292 NDRX_ATOMIC_STORE(&sg_shm->lockprov_srvid, srvid);
0293 NDRX_ATOMIC_STORE(&sg_shm->is_locked, EXTRUE);
0294 NDRX_ATOMIC_STORE(&sg_shm->reason, 0);
0295
0296 NDRX_LOG(log_debug, "Group %d locked on node %hd", singlegrp_no, nodeid);
0297 userlog("Group %d locked on node %hd", singlegrp_no, nodeid);
0298
0299 out:
0300 return ret;
0301 }
0302
0303
0304
0305
0306
0307
0308
0309 expublic void ndrx_sg_load(ndrx_sg_shm_t * sg, ndrx_sg_shm_t * sg_shm)
0310 {
0311
0312 sg->is_locked = NDRX_ATOMIC_LOAD(&sg_shm->is_locked);
0313 sg->is_mmon = NDRX_ATOMIC_LOAD(&sg_shm->is_mmon);
0314 sg->is_srv_booted = NDRX_ATOMIC_LOAD(&sg_shm->is_srv_booted);
0315 sg->is_clt_booted = NDRX_ATOMIC_LOAD(&sg_shm->is_clt_booted);
0316 sg->flags = NDRX_ATOMIC_LOAD(&sg_shm->flags);
0317 sg->last_refresh = NDRX_ATOMIC_LOAD(&sg_shm->last_refresh);
0318 sg->sequence = NDRX_ATOMIC_LOAD(&sg_shm->sequence);
0319 sg->lockprov_nodeid = NDRX_ATOMIC_LOAD(&sg_shm->lockprov_nodeid);
0320 sg->lockprov_pid = NDRX_ATOMIC_LOAD(&sg_shm->lockprov_pid);
0321 sg->lockprov_srvid = NDRX_ATOMIC_LOAD(&sg_shm->lockprov_srvid);
0322 ndrx_volatile_strcpy(sg->lockprov_procname, sg_shm->lockprov_procname,
0323 sizeof(sg->lockprov_procname));
0324
0325 ndrx_volatile_memcy(sg->sg_nodes, sg_shm->sg_nodes, sizeof(sg->sg_nodes));
0326
0327 sg->reason = NDRX_ATOMIC_LOAD(&sg_shm->reason);
0328 }
0329
0330
0331
0332
0333
0334
0335
0336 exprivate int ndrx_sg_chk_timestamp(int singlegrp_no, ndrx_sg_shm_t *sg)
0337 {
0338 int ret=EXSUCCEED;
0339 struct timespec ts;
0340 long long time_diff;
0341
0342 ndrx_realtime_get(&ts);
0343
0344 time_diff=(long long)ts.tv_sec-(long long)sg->last_refresh;
0345
0346
0347 if (llabs(time_diff) > ndrx_G_libnstd_cfg.sgrefreshmax)
0348 {
0349
0350 ndrx_sg_unlock(NDRX_SG_GET_PTR(singlegrp_no), NDRX_SG_RSN_EXPIRED);
0351
0352 NDRX_LOG(log_error, "ERROR: Lock for singleton group %d is inconsistent "
0353 "(did not refresh in %d sec, diff %lld sec)! "
0354 "Marking group as not locked!", singlegrp_no, ndrx_G_libnstd_cfg.sgrefreshmax,
0355 time_diff);
0356
0357 userlog("ERROR: Lock for singleton group %d is inconsistent "
0358 "(did not refresh in %d sec, diff %lld sec)! "
0359 "Marking group as not locked!", singlegrp_no, ndrx_G_libnstd_cfg.sgrefreshmax,
0360 time_diff);
0361
0362 EXFAIL_OUT(ret);
0363 }
0364 out:
0365 return ret;
0366 }
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377 expublic int ndrx_sg_is_locked_int(int singlegrp_no, ndrx_sg_shm_t * sg,
0378 char *reference_file, long flags)
0379 {
0380 int ret = EXFALSE;
0381 ndrx_sg_shm_t sg_local;
0382
0383 if (NULL==sg)
0384 {
0385 sg=ndrx_sg_get(singlegrp_no);
0386
0387 if (NULL==sg)
0388 {
0389 NDRX_LOG(log_error, "singleton group %d not found", singlegrp_no);
0390 ret=EXFAIL;
0391 goto out;
0392 }
0393 }
0394
0395 if (!sg->is_locked)
0396 {
0397 ret=EXFALSE;
0398 goto out;
0399 }
0400
0401
0402 ndrx_sg_load(&sg_local, sg);
0403
0404 if (EXSUCCEED!=ndrx_sg_chk_timestamp(singlegrp_no, &sg_local))
0405 {
0406 ret=EXFALSE;
0407 goto out;
0408 }
0409
0410 if (flags & NDRX_SG_SRVBOOTCHK
0411 && !(sg_local.flags & NDRX_SG_NO_ORDER)
0412 && !sg_local.is_srv_booted)
0413 {
0414
0415
0416
0417 NDRX_LOG(log_debug, "Singleton group %d servers not booted",
0418 singlegrp_no);
0419 ret=EXFALSE;
0420 goto out;
0421 }
0422
0423 else if (flags & NDRX_SG_CHK_PID)
0424 {
0425 if (!ndrx_sys_is_process_running_by_pid(sg_local.lockprov_pid))
0426 {
0427
0428 ndrx_sg_unlock(sg, NDRX_SG_RSN_NOPID);
0429
0430 NDRX_LOG(log_error, "ERROR: Lock for singleton group %d is inconsistent "
0431 "(lock provider PID %d is not running)! "
0432 "Marking group as not locked!", singlegrp_no, sg_local.lockprov_pid);
0433
0434 userlog("ERROR: Lock for singleton group %d is inconsistent "
0435 "(lock provider PID %d is not running)! "
0436 "Marking group as not locked!", singlegrp_no, sg_local.lockprov_pid);
0437
0438 ret=EXFALSE;
0439 goto out;
0440 }
0441 }
0442
0443
0444
0445
0446 if (NULL!=reference_file)
0447 {
0448 struct stat st;
0449 int rc;
0450 struct timeval now;
0451
0452 rc = stat(reference_file, &st);
0453
0454 if (0!=rc)
0455 {
0456 int err=errno;
0457
0458 ndrx_sg_unlock(sg, NDRX_SG_RSN_REFNOFILE);
0459
0460 NDRX_LOG(log_error, "ERROR: Lock for singleton group %d is inconsistent "
0461 "(reference file [%s] failed to open: %s)! "
0462 "Marking group as not locked!", singlegrp_no, reference_file, strerror(err));
0463
0464 userlog("ERROR: Lock for singleton group %d is inconsistent "
0465 "(reference file [%s] is missing: %s)! "
0466 "Marking group as not locked!", singlegrp_no, reference_file, strerror(err));
0467
0468 ret=EXFALSE;
0469 goto out;
0470 }
0471
0472
0473
0474
0475
0476 gettimeofday(&now,NULL);
0477
0478 if (st.st_mtime > now.tv_sec)
0479 {
0480
0481 ndrx_sg_unlock(sg, NDRX_SG_RSN_REFFFUT);
0482
0483 NDRX_LOG(log_error, "ERROR: Lock for singleton group %d is inconsistent "
0484 "(reference file %s is in future)! "
0485 "Marking group as not locked!", singlegrp_no, reference_file);
0486
0487 userlog("ERROR: Lock for singleton group %d is inconsistent "
0488 "(reference file %s is in future)! "
0489 "Marking group as not locked!", singlegrp_no, reference_file);
0490
0491 ret=EXFALSE;
0492 goto out;
0493 }
0494 }
0495
0496
0497 ret=EXTRUE;
0498
0499 out:
0500 return ret;
0501 }
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516 expublic int ndrx_sg_is_locked(int singlegrp_no, char *reference_file, long flags)
0517 {
0518 return ndrx_sg_is_locked_int(singlegrp_no, NULL, reference_file, flags);
0519 }
0520
0521
0522
0523
0524 expublic int ndrx_sg_nrgroups()
0525 {
0526 return ndrx_G_libnstd_cfg.pgmax;
0527 }
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539 expublic void ndrx_sg_get_lock_snapshoot(int *lock_status_out, int *lock_status_out_len, long flags)
0540 {
0541 int i=0;
0542 int locked;
0543 ndrx_sg_shm_t *p;
0544
0545
0546 if (*lock_status_out_len>ndrx_G_libnstd_cfg.pgmax)
0547 {
0548 *lock_status_out_len = ndrx_G_libnstd_cfg.pgmax;
0549 }
0550
0551 memset(lock_status_out, 0, sizeof(int)*(*lock_status_out_len));
0552
0553 for (i=0; i<*lock_status_out_len; i++)
0554 {
0555 p=ndrx_sg_get(i+1);
0556
0557 if (EXTRUE==ndrx_sg_is_locked_int(i+1, p, NULL, flags))
0558 {
0559 if (p->flags & NDRX_SG_NO_ORDER)
0560 {
0561 lock_status_out[i]=NDRX_SG_NO_ORDER;
0562 }
0563 else
0564 {
0565 lock_status_out[i]=NDRX_SG_IN_USE;
0566 }
0567 NDRX_LOG(log_debug, "Group %d lock flag: 0x%x", i+1, lock_status_out[i]);
0568 }
0569 }
0570
0571 return;
0572 }
0573
0574
0575
0576
0577
0578
0579
0580 expublic void ndrx_sg_bootflag_clt_set(int singlegrp_no)
0581 {
0582 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0583 NDRX_ATOMIC_STORE(&sg->is_clt_booted, EXTRUE);
0584 }
0585
0586
0587
0588
0589
0590 expublic unsigned char ndrx_sg_bootflag_clt_get(int singlegrp_no)
0591 {
0592 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0593 return NDRX_ATOMIC_LOAD(&sg->is_clt_booted);
0594 }
0595
0596
0597
0598
0599
0600
0601
0602 expublic void ndrx_sg_bootflag_srv_set(int singlegrp_no)
0603 {
0604 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0605 NDRX_ATOMIC_STORE(&sg->is_srv_booted, EXTRUE);
0606 }
0607
0608
0609
0610
0611
0612 expublic unsigned char ndrx_sg_bootflag_srv_get(int singlegrp_no)
0613 {
0614 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0615 return NDRX_ATOMIC_LOAD(&sg->is_srv_booted);
0616 }
0617
0618
0619
0620
0621
0622
0623 expublic int ndrx_sg_is_valid(int singlegrp_no)
0624 {
0625 int ret = EXTRUE;
0626
0627 if (singlegrp_no <= 0 || singlegrp_no > ndrx_G_libnstd_cfg.pgmax)
0628 {
0629 NDRX_LOG(log_error, "Invalid single group number: %d", singlegrp_no);
0630 ret=EXFALSE;
0631 goto out;
0632 }
0633
0634 out:
0635 return ret;
0636 }
0637
0638
0639
0640
0641
0642
0643 expublic void ndrx_sg_flags_set(int singlegrp_no, unsigned short flags)
0644 {
0645 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0646 NDRX_ATOMIC_STORE(&sg->flags, flags);
0647 }
0648
0649
0650
0651
0652
0653 expublic unsigned short ndrx_sg_flags_get(int singlegrp_no)
0654 {
0655 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0656 return NDRX_ATOMIC_LOAD(&sg->flags);
0657 }
0658
0659
0660
0661
0662 expublic void ndrx_sg_nodes_set(int singlegrp_no, char *sg_nodes)
0663 {
0664 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0665 ndrx_volatile_memcy(sg->sg_nodes, sg_nodes, sizeof(sg->sg_nodes));
0666 }
0667
0668
0669
0670
0671
0672 expublic int ndrx_sg_is_singleton(int singlegrp_no)
0673 {
0674 int ret = EXFALSE;
0675 if (ndrx_sg_is_valid(singlegrp_no))
0676 {
0677 unsigned char flags;
0678 ndrx_sg_shm_t * sg = NDRX_SG_GET_PTR(singlegrp_no);
0679 flags = NDRX_ATOMIC_LOAD(&sg->flags);
0680
0681 if (flags & NDRX_SG_SINGLETON)
0682 {
0683 ret=EXTRUE;
0684 }
0685 }
0686
0687 return ret;
0688 }
0689
0690