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
0036
0037
0038
0039
0040
0041 #include <stdio.h>
0042 #include <stdlib.h>
0043 #include <string.h>
0044 #include <errno.h>
0045 #include <regex.h>
0046 #include <utlist.h>
0047 #include <stdarg.h>
0048
0049 #include <ndebug.h>
0050 #include <atmi.h>
0051 #include <atmi_int.h>
0052 #include <typed_buf.h>
0053 #include <ndrstandard.h>
0054 #include <ubf.h>
0055 #include <Exfields.h>
0056 #include <nstdutil.h>
0057
0058 #include <exnet.h>
0059 #include <ndrxdcmn.h>
0060
0061 #include "tmsrv.h"
0062 #include "../libatmisrv/srv_int.h"
0063 #include "userlog.h"
0064 #include <xa_cmn.h>
0065 #include <exhash.h>
0066 #include <unistd.h>
0067 #include <Exfields.h>
0068 #include <singlegrp.h>
0069 #include <sys_test.h>
0070
0071
0072 #define LOG_MAX 1024
0073
0074 #define LOG_COMMAND_STAGE 'S'
0075 #define LOG_COMMAND_I 'I'
0076 #define LOG_COMMAND_J 'J'
0077 #define LOG_COMMAND_RMSTAT 'R'
0078
0079 #define LOG_VERSION_1 1
0080 #define LOG_VERSION_2 2
0081
0082 #define CHK_THREAD_ACCESS if (ndrx_gettid()!=p_tl->lockthreadid)\
0083 {\
0084 NDRX_LOG(log_error, "Transaction [%s] not locked for thread %" PRIu64 ", but for %" PRIu64,\
0085 p_tl->tmxid, ndrx_gettid(), p_tl->lockthreadid);\
0086 userlog("Transaction [%s] not locked for thread %" PRIu64 ", but for %" PRIu64,\
0087 p_tl->tmxid, ndrx_gettid(), p_tl->lockthreadid);\
0088 return EXFAIL;\
0089 }
0090 #define LOG_RS_SEP ';'
0091
0092
0093
0094 exprivate atmi_xa_log_t *M_tx_hash = NULL;
0095 exprivate MUTEX_LOCKDECL(M_tx_hash_lock);
0096
0097
0098 exprivate int tms_log_write_line(atmi_xa_log_t *p_tl, char command, const char *fmt, ...);
0099 exprivate int tms_parse_info(char *buf, atmi_xa_log_t *p_tl);
0100 exprivate int tms_parse_stage(char *buf, atmi_xa_log_t *p_tl);
0101 exprivate int tms_parse_rmstatus(char *buf, atmi_xa_log_t *p_tl);
0102 exprivate void tms_gen_file_name(char *fname, size_t fnamesz, char *tmxid);
0103
0104
0105
0106
0107
0108
0109 expublic int tms_unlock_entry(atmi_xa_log_t *p_tl)
0110 {
0111 CHK_THREAD_ACCESS;
0112
0113 NDRX_LOG(log_info, "Transaction [%s] unlocked by thread %" PRIu64, p_tl->tmxid,
0114 p_tl->lockthreadid);
0115
0116 MUTEX_LOCK_V(M_tx_hash_lock);
0117 p_tl->lockthreadid = 0;
0118 MUTEX_UNLOCK_V(M_tx_hash_lock);
0119
0120 return EXSUCCEED;
0121 }
0122
0123
0124
0125
0126
0127
0128 expublic int tms_log_exists_file(char *tmxid)
0129 {
0130 char fname[PATH_MAX+1];
0131 int err=0;
0132
0133 tms_gen_file_name(fname, sizeof(fname), tmxid);
0134
0135 if (EXSUCCEED == access(fname, 0))
0136 {
0137 return EXTRUE;
0138 }
0139
0140 err=errno;
0141
0142 if (ENOENT==err)
0143 {
0144 return EXFALSE;
0145 }
0146
0147 NDRX_LOG(log_error, "Failed to check file [%s] presence: %s",
0148 fname, strerror(err));
0149 userlog("Failed to check file [%s] presence: %s",
0150 fname, strerror(err));
0151
0152 return EXFAIL;
0153 }
0154
0155
0156
0157
0158
0159
0160 expublic int tms_log_exists_entry(char *tmxid)
0161 {
0162 atmi_xa_log_t *r = NULL;
0163
0164 MUTEX_LOCK_V(M_tx_hash_lock);
0165 EXHASH_FIND_STR( M_tx_hash, tmxid, r);
0166 MUTEX_UNLOCK_V(M_tx_hash_lock);
0167
0168 if (NULL!=r)
0169 {
0170 return EXTRUE;
0171 }
0172 else
0173 {
0174 return EXFALSE;
0175 }
0176 }
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194 expublic atmi_xa_log_t * tms_log_get_entry(char *tmxid, int dowait, int *locke)
0195 {
0196 atmi_xa_log_t *r = NULL;
0197 ndrx_stopwatch_t w;
0198
0199 if (dowait)
0200 {
0201 ndrx_stopwatch_reset(&w);
0202 }
0203
0204 if (NULL!=locke)
0205 {
0206 *locke=EXFALSE;
0207 }
0208
0209 restart:
0210 MUTEX_LOCK_V(M_tx_hash_lock);
0211 EXHASH_FIND_STR( M_tx_hash, tmxid, r);
0212
0213 if (NULL!=r)
0214 {
0215 if (r->lockthreadid)
0216 {
0217 if (dowait && ndrx_stopwatch_get_delta(&w) < dowait)
0218 {
0219 MUTEX_UNLOCK_V(M_tx_hash_lock);
0220
0221 usleep(100000);
0222 goto restart;
0223
0224 }
0225
0226 NDRX_LOG(log_error, "Transaction [%s] already locked for thread_id: %"
0227 PRIu64 " lock time: %d msec",
0228 tmxid, r->lockthreadid, dowait);
0229
0230 userlog("tmsrv: Transaction [%s] already locked for thread_id: %" PRIu64
0231 "lock time: %d msec",
0232 tmxid, r->lockthreadid, dowait);
0233 r = NULL;
0234
0235
0236 if (NULL!=locke)
0237 {
0238 *locke=EXTRUE;
0239 }
0240
0241 }
0242 else
0243 {
0244 r->lockthreadid = ndrx_gettid();
0245 NDRX_LOG(log_info, "Transaction [%s] locked for thread_id: %" PRIu64,
0246 tmxid, r->lockthreadid);
0247 }
0248 }
0249
0250 MUTEX_UNLOCK_V(M_tx_hash_lock);
0251
0252 return r;
0253 }
0254
0255
0256
0257
0258
0259 exprivate int tms_log_setseq(atmi_xa_log_t *p_tl)
0260 {
0261 int ret= EXSUCCEED;
0262 long grp_flags=0;
0263
0264
0265
0266 if (G_atmi_env.procgrp_no)
0267 {
0268 p_tl->sg_sequence=tpsgislocked(G_atmi_env.procgrp_no
0269 , TPPG_SGVERIFY|TPPG_NONSGSUCC
0270 , &grp_flags);
0271
0272 if (EXFAIL==p_tl->sg_sequence)
0273 {
0274 NDRX_LOG(log_error, "tpsgislocked failed %s", tpstrerror(tperrno));
0275 EXFAIL_OUT(ret);
0276 }
0277
0278 if (grp_flags & TPPG_SINGLETON && p_tl->sg_sequence<=0)
0279 {
0280 NDRX_LOG(log_error, "Singleton group %d lock lost (at start) - exit(-1)",
0281 G_atmi_env.procgrp_no);
0282 userlog("Singleton group %d lock lost (at start) - exit(-1)",
0283 G_atmi_env.procgrp_no);
0284
0285 exit(EXFAIL);
0286 }
0287 }
0288
0289 out:
0290 return ret;
0291 }
0292
0293
0294
0295
0296
0297 expublic int tms_log_checkpointseq(atmi_xa_log_t *p_tl)
0298 {
0299 int ret=EXSUCCEED;
0300 long seq;
0301 long grp_flags=0;
0302
0303
0304
0305 if (G_atmi_env.procgrp_no)
0306 {
0307 seq=tpsgislocked(G_atmi_env.procgrp_no, TPPG_SGVERIFY|TPPG_NONSGSUCC, &grp_flags);
0308
0309 if (seq < 0)
0310 {
0311 NDRX_LOG(log_error, "tpsgislocked returns %s", tpstrerror(tperrno));
0312 EXFAIL_OUT(ret);
0313 }
0314
0315 if ((grp_flags & TPPG_SINGLETON) && 0==seq)
0316 {
0317 NDRX_LOG(log_error, "Singleton group %d on node %ld lock lost - exit(-1)",
0318 G_atmi_env.procgrp_no, tpgetnodeid());
0319 userlog("Singleton group %d on node %ld lock lost - exit(-1)",
0320 G_atmi_env.procgrp_no, tpgetnodeid());
0321
0322 exit(EXFAIL);
0323 }
0324
0325
0326 if (NULL!=p_tl)
0327 {
0328
0329
0330
0331 if ( (grp_flags & TPPG_SINGLETON) && (seq - p_tl->sg_sequence >= G_atmi_env.sglockinc))
0332 {
0333 NDRX_LOG(log_error, "Singleton group %d on node %ld lock lost (tl seq %ld, cur seq %ld) - exit(-1), ",
0334 G_atmi_env.procgrp_no, tpgetnodeid(), p_tl->sg_sequence, seq);
0335 userlog("Singleton group %d on node %ld lock lost (tl seq %ld, cur seq %ld) - exit(-1), ",
0336 G_atmi_env.procgrp_no, tpgetnodeid(), p_tl->sg_sequence, seq);
0337
0338 exit(EXFAIL);
0339 }
0340
0341
0342 p_tl->sg_sequence=seq;
0343 }
0344 }
0345 out:
0346 return ret;
0347 }
0348
0349
0350
0351
0352
0353
0354
0355
0356 expublic int tms_log_start(atmi_xa_tx_info_t *xai, int txtout, long tmflags,
0357 long *btid)
0358 {
0359 int ret = EXSUCCEED;
0360 int hash_added = EXFALSE;
0361 atmi_xa_log_t *tmp = NULL;
0362 atmi_xa_rm_status_btid_t *bt;
0363
0364 if (NULL==(tmp = NDRX_CALLOC(sizeof(atmi_xa_log_t), 1)))
0365 {
0366 NDRX_LOG(log_error, "NDRX_CALLOC() failed: %s", strerror(errno));
0367 ret=EXFAIL;
0368 goto out;
0369 }
0370 tmp->txstage = XA_TX_STAGE_ACTIVE;
0371
0372 tmp->tmnodeid = xai->tmnodeid;
0373 tmp->tmsrvid = xai->tmsrvid;
0374 tmp->tmrmid = xai->tmrmid;
0375 NDRX_STRCPY_SAFE(tmp->tmxid, xai->tmxid);
0376
0377 tmp->t_start = ndrx_utc_tstamp();
0378 tmp->t_update = ndrx_utc_tstamp();
0379 tmp->txtout = txtout;
0380 tmp->log_version = LOG_VERSION_2;
0381 ndrx_stopwatch_reset(&tmp->ttimer);
0382
0383 if (EXSUCCEED!=tms_log_setseq(tmp))
0384 {
0385 EXFAIL_OUT(ret);
0386 }
0387
0388
0389 tmp->lockthreadid = ndrx_gettid();
0390
0391
0392
0393
0394
0395
0396 MUTEX_LOCK_V(M_tx_hash_lock);
0397 EXHASH_ADD_STR( M_tx_hash, tmxid, tmp);
0398 MUTEX_UNLOCK_V(M_tx_hash_lock);
0399 hash_added = EXTRUE;
0400
0401
0402
0403
0404
0405
0406 if (EXSUCCEED!=tms_open_logfile(tmp, "a"))
0407 {
0408 NDRX_LOG(log_error, "Failed to create transaction log file");
0409 userlog("Failed to create transaction log file");
0410 EXFAIL_OUT(ret);
0411 }
0412
0413
0414 if (EXSUCCEED!=tms_log_info(tmp))
0415 {
0416 NDRX_LOG(log_error, "Failed to log tran info");
0417 userlog("Failed to log tran info");
0418 EXFAIL_OUT(ret);
0419 }
0420
0421
0422 if (!(tmflags & TMFLAGS_DYNAMIC_REG))
0423 {
0424
0425
0426
0427 char start_stat = XA_RM_STATUS_ACTIVE;
0428
0429 *btid = tms_btid_gettid(tmp, xai->tmrmid);
0430
0431
0432 if (EXSUCCEED!=tms_btid_add(tmp, xai->tmrmid, *btid, XA_RM_STATUS_NULL,
0433 0, 0, &bt))
0434 {
0435 NDRX_LOG(log_error, "Failed to add BTID: %ld", *btid);
0436 EXFAIL_OUT(ret);
0437 }
0438
0439 if (tmflags & TMFLAGS_TPNOSTARTXID)
0440 {
0441 NDRX_LOG(log_info, "TPNOSTARTXID => starting as %c - prepared",
0442 XA_RM_STATUS_PREP);
0443 start_stat = XA_RM_STATUS_UNKOWN;
0444 }
0445
0446
0447 if (EXSUCCEED!=tms_log_rmstatus(tmp, bt, start_stat, 0, 0))
0448 {
0449 NDRX_LOG(log_error, "Failed to write RM status to file: %ld", *btid);
0450 EXFAIL_OUT(ret);
0451 }
0452 }
0453
0454 out:
0455
0456
0457 if (EXSUCCEED!=ret)
0458 {
0459 tms_remove_logfile(tmp, hash_added);
0460 }
0461 else
0462 {
0463 if (NULL!=tmp)
0464 {
0465 tms_unlock_entry(tmp);
0466 }
0467 }
0468 return ret;
0469 }
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482 expublic int tms_log_addrm(atmi_xa_tx_info_t *xai, short rmid, int *p_is_already_logged,
0483 long *btid, long flags)
0484 {
0485 int ret = EXSUCCEED;
0486 atmi_xa_log_t *p_tl= NULL;
0487 atmi_xa_rm_status_btid_t *bt = NULL;
0488
0489
0490
0491
0492
0493
0494
0495
0496 if (NULL==(p_tl = tms_log_get_entry(xai->tmxid, NDRX_LOCK_WAIT_TIME, NULL)))
0497 {
0498 NDRX_LOG(log_error, "No transaction/lock timeout under xid_str: [%s]",
0499 xai->tmxid);
0500 ret=EXFAIL;
0501 goto out_nolock;
0502 }
0503
0504 if (1 > rmid || rmid>NDRX_MAX_RMS)
0505 {
0506 NDRX_LOG(log_error, "RMID %hd out of bounds!!!");
0507 EXFAIL_OUT(ret);
0508 }
0509
0510
0511
0512
0513 if (p_tl->is_background || XA_TX_STAGE_ACTIVE!=p_tl->txstage)
0514 {
0515 NDRX_LOG(log_error, "cannot register xid [%s] is_background: (%d) stage: (%hd)",
0516 xai->tmxid, p_tl->is_background, p_tl->txstage);
0517 EXFAIL_OUT(ret);
0518 }
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530 ret = tms_btid_addupd(p_tl, rmid, btid, XA_RM_STATUS_NULL,
0531 0, 0, p_is_already_logged, &bt);
0532
0533
0534 if (!(*p_is_already_logged))
0535 {
0536 char start_stat = XA_RM_STATUS_ACTIVE;
0537
0538 NDRX_LOG(log_info, "RMID %hd/%ld added to xid_str: [%s]",
0539 rmid, *btid, xai->tmxid);
0540
0541 if (flags & TMFLAGS_TPNOSTARTXID)
0542 {
0543 NDRX_LOG(log_info, "TPNOSTARTXID => adding as %c - unknown",
0544 XA_RM_STATUS_UNKOWN);
0545 start_stat = XA_RM_STATUS_UNKOWN;
0546 }
0547
0548 if (EXSUCCEED!=tms_log_rmstatus(p_tl, bt, start_stat, 0, 0))
0549 {
0550 NDRX_LOG(log_error, "Failed to write RM status to file: %ld", *btid);
0551 EXFAIL_OUT(ret);
0552 }
0553 }
0554 else
0555 {
0556 NDRX_LOG(log_info, "RMID %hd/%ld already joined to xid_str: [%s]",
0557 rmid, *btid, xai->tmxid);
0558 }
0559
0560 out:
0561
0562 tms_unlock_entry(p_tl);
0563
0564 out_nolock:
0565
0566 return ret;
0567 }
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577 expublic int tms_log_chrmstat(atmi_xa_tx_info_t *xai, short rmid,
0578 long btid, char rmstatus, UBFH *p_ub)
0579 {
0580 int ret = EXSUCCEED;
0581 atmi_xa_log_t *p_tl= NULL;
0582 atmi_xa_rm_status_btid_t *bt = NULL;
0583 int locke;
0584
0585 NDRX_LOG(log_debug, "xid: [%s] BTID %ld change status to [%c]",
0586 xai->tmxid, btid, rmstatus);
0587
0588 if (NULL==(p_tl = tms_log_get_entry(xai->tmxid, NDRX_LOCK_WAIT_TIME, &locke)))
0589 {
0590 if (locke)
0591 {
0592 NDRX_LOG(log_error, "Lock acquire timed out for xid_str: [%s] - TPETIME",
0593 xai->tmxid);
0594 atmi_xa_set_error_fmt(p_ub, TPETIME, NDRX_XA_ERSN_LOCK,
0595 "Failed to acquire locked!");
0596 }
0597 else
0598 {
0599 NDRX_LOG(log_error, "No transaction under xid_str: [%s] - match ",
0600 xai->tmxid);
0601
0602 atmi_xa_set_error_fmt(p_ub, TPEMATCH, NDRX_XA_ERSN_NOTX,
0603 "Failed to get transaction or locked for processing!");
0604 }
0605
0606 ret=EXFAIL;
0607 goto out_nolock;
0608 }
0609
0610 bt = tms_btid_find(p_tl, rmid, btid);
0611
0612 if (rmstatus==bt->rmstatus)
0613 {
0614 NDRX_LOG(log_warn, "xid: [%s] BTID %ld already in status [%c]",
0615 xai->tmxid, btid, rmstatus);
0616 }
0617
0618 if (XA_RM_STATUS_UNKOWN!=bt->rmstatus)
0619 {
0620 NDRX_LOG(log_error, "No transaction under xid_str: [%s] - match ",
0621 xai->tmxid);
0622
0623 atmi_xa_set_error_fmt(p_ub, TPEMATCH, NDRX_XA_ERSN_INVPARAM,
0624 "BTID %ld in status %c but want to set to: %c!",
0625 btid, bt->rmstatus, rmstatus);
0626
0627 EXFAIL_OUT(ret);
0628 }
0629
0630
0631
0632 if (EXSUCCEED!=tms_log_rmstatus(p_tl, bt, rmstatus, 0, 0))
0633 {
0634 NDRX_LOG(log_error, "Failed to write RM status to file: %ld, "
0635 "new stat: %c old stat: [%c]",
0636 btid, rmstatus, bt->rmstatus);
0637
0638 atmi_xa_set_error_fmt(p_ub, TPEMATCH, NDRX_XA_ERSN_RMLOGFAIL,
0639 "BTID %ld in status %c but want to set to: %c!",
0640 btid, bt->rmstatus, rmstatus);
0641
0642 EXFAIL_OUT(ret);
0643 }
0644
0645 NDRX_LOG(log_debug, "xid: [%s] BTID %ld change status to [%c] OK",
0646 xai->tmxid, btid, rmstatus);
0647
0648 out:
0649
0650 tms_unlock_entry(p_tl);
0651
0652 out_nolock:
0653
0654 return ret;
0655 }
0656
0657
0658
0659
0660
0661
0662
0663 exprivate void tms_gen_file_name(char *fname, size_t fnamesz, char *tmxid)
0664 {
0665 snprintf(fname, fnamesz, "%s/TRN-%ld-%hd-%d-%s",
0666 G_tmsrv_cfg.tlog_dir, G_tmsrv_cfg.vnodeid, G_atmi_env.xa_rmid,
0667 G_server_conf.srv_id, tmxid);
0668 }
0669
0670
0671
0672
0673
0674
0675 exprivate void tms_get_file_name(atmi_xa_log_t *p_tl)
0676 {
0677 tms_gen_file_name(p_tl->fname, sizeof(p_tl->fname), p_tl->tmxid);
0678 }
0679
0680
0681
0682
0683
0684
0685 expublic int tms_open_logfile(atmi_xa_log_t *p_tl, char *mode)
0686 {
0687 int ret = EXSUCCEED;
0688
0689 if (EXEOS==p_tl->fname[0])
0690 {
0691 tms_get_file_name(p_tl);
0692 }
0693
0694 if (NULL!=p_tl->f)
0695 {
0696
0697
0698
0699 goto out;
0700 }
0701
0702
0703 if (ndrx_G_systest_lockloss || NULL==(p_tl->f=NDRX_FOPEN(p_tl->fname, mode)))
0704 {
0705 userlog("Failed to open XA transaction log file: [%s]: %s",
0706 p_tl->fname, strerror(errno));
0707 NDRX_LOG(log_error, "Failed to open XA transaction "
0708 "log file: [%s]: %s",
0709 p_tl->fname, strerror(errno));
0710 ret=EXFAIL;
0711 goto out;
0712 }
0713
0714 NDRX_LOG(log_debug, "XA tx log file [%s] open for [%s]",
0715 p_tl->fname, mode);
0716
0717 out:
0718 return ret;
0719 }
0720
0721
0722
0723
0724
0725
0726 expublic int tms_housekeep(char *logfile)
0727 {
0728 long diff;
0729 int err;
0730 int ret = EXFALSE;
0731
0732
0733 if ((diff=ndrx_file_age(logfile)) > G_tmsrv_cfg.housekeeptime)
0734 {
0735 NDRX_LOG(log_error, "Corrupted log file [%s] age %ld sec (housekeep %d) - removing",
0736 logfile, diff, G_tmsrv_cfg.housekeeptime);
0737 userlog("Corrupted log file [%s] age %ld sec (housekeep %d) - removing",
0738 logfile, diff, G_tmsrv_cfg.housekeeptime);
0739
0740 if (ndrx_G_systest_lockloss || EXSUCCEED!=unlink(logfile))
0741 {
0742 err = errno;
0743 NDRX_LOG(log_error, "Failed to unlink [%s]: %s", logfile, strerror(err));
0744 userlog("Failed to unlink [%s]: %s", logfile, strerror(err));
0745 }
0746 else
0747 {
0748 ret=EXTRUE;
0749 }
0750 }
0751
0752 return ret;
0753 }
0754
0755
0756
0757
0758
0759
0760
0761
0762
0763
0764 expublic int tms_load_logfile(char *logfile, char *tmxid, atmi_xa_log_t **pp_tl,
0765 int *log_removed, int *housekeepable)
0766 {
0767 int ret = EXSUCCEED;
0768 int len;
0769 char buf[1024];
0770 char *p;
0771 int line = 1;
0772 int got_term_last=EXFALSE, infos_ok=EXFALSE, missing_term_in_file=EXFALSE;
0773 int do_housekeep = EXFALSE;
0774 int wrote, err;
0775 long diff;
0776 *pp_tl = NULL;
0777
0778 *log_removed = EXFALSE;
0779 *housekeepable = EXFALSE;
0780
0781 if (NULL==(*pp_tl = NDRX_CALLOC(sizeof(atmi_xa_log_t), 1)))
0782 {
0783 NDRX_LOG(log_error, "NDRX_CALLOC() failed: %s", strerror(errno));
0784 EXFAIL_OUT(ret);
0785 }
0786
0787 if (strlen(logfile)>PATH_MAX)
0788 {
0789 NDRX_LOG(log_error, "Invalid file name!");
0790 EXFAIL_OUT(ret);
0791 }
0792
0793 NDRX_STRCPY_SAFE((*pp_tl)->fname, logfile);
0794
0795 len = strlen(tmxid);
0796 if (len>sizeof((*pp_tl)->tmxid)-1)
0797 {
0798 NDRX_LOG(log_error, "tmxid too long [%s]!", tmxid);
0799 EXFAIL_OUT(ret);
0800 }
0801
0802 NDRX_STRCPY_SAFE((*pp_tl)->tmxid, tmxid);
0803
0804 (*pp_tl)->txstage = XA_TX_STAGE_ACTIVE;
0805
0806
0807 if (EXSUCCEED!=tms_log_setseq(*pp_tl))
0808 {
0809 EXFAIL_OUT(ret);
0810 }
0811
0812
0813 if (EXSUCCEED!=tms_open_logfile(*pp_tl, "a+"))
0814 {
0815 NDRX_LOG(log_error, "Failed to open transaction file!");
0816 EXFAIL_OUT(ret);
0817 }
0818
0819
0820
0821
0822 if (EXSUCCEED!=fseek((*pp_tl)->f, 0, SEEK_SET))
0823 {
0824 NDRX_LOG(log_error, "Failed to fseek: %s", strerror(errno));
0825 EXFAIL_OUT(ret);
0826 }
0827
0828
0829
0830
0831 while (fgets(buf, sizeof(buf), (*pp_tl)->f))
0832 {
0833 got_term_last = EXFALSE;
0834 len = strlen(buf);
0835
0836 if (1 < len && '\n'==buf[len-1])
0837 {
0838 buf[len-1]=EXEOS;
0839 len--;
0840 got_term_last = EXTRUE;
0841 }
0842
0843
0844 if (1 < len && '\r'==buf[len-1])
0845 {
0846 buf[len-1]=EXEOS;
0847 len--;
0848 }
0849
0850 NDRX_LOG(log_debug, "Parsing line: [%s]", buf);
0851
0852 if (!got_term_last)
0853 {
0854
0855
0856
0857
0858
0859 missing_term_in_file = EXTRUE;
0860 continue;
0861 }
0862
0863
0864
0865 p = strchr(buf, ':');
0866
0867 if (NULL==p)
0868 {
0869 NDRX_LOG(log_error, "Symbol ':' not found on line [%d]!",
0870 line);
0871 EXFAIL_OUT(ret);
0872 }
0873 p++;
0874
0875
0876 NDRX_LOG(log_error, "Record: %c log_version: %d", *p, (*pp_tl)->log_version);
0877
0878
0879
0880
0881 if ((!infos_ok && LOG_COMMAND_J==*p) || ((*pp_tl)->log_version > LOG_VERSION_1))
0882 {
0883 char *rs = strchr(buf, LOG_RS_SEP);
0884 unsigned long crc32_calc=0, crc32_got=0;
0885
0886 if (NULL==rs)
0887 {
0888 NDRX_LOG(log_error, "TMSRV log file [%s] missing %c sep on line [%s] - ignore line",
0889 logfile, LOG_RS_SEP, buf);
0890 userlog("TMSRV log file [%s] missing %c sep on line [%s] - ignore line",
0891 logfile, LOG_RS_SEP, buf);
0892 continue;
0893 }
0894
0895 *rs = EXEOS;
0896 rs++;
0897
0898
0899 crc32_calc = ndrx_Crc32_ComputeBuf(0, buf, strlen(buf));
0900 sscanf(rs, "%lx", &crc32_got);
0901
0902
0903 if (crc32_calc!=crc32_got)
0904 {
0905 NDRX_LOG(log_error, "TMSRV log file [%s] invalid log [%s] line "
0906 "crc32 calc: [%lx] vs rec: [%lx] - ignore line",
0907 logfile, buf, crc32_calc, crc32_got);
0908 userlog("TMSRV log file [%s] invalid log [%s] line "
0909 "crc32 calc: [%lx] vs rec: [%lx] - ignore line",
0910 logfile, buf, crc32_calc, crc32_got);
0911 continue;
0912 }
0913 }
0914
0915 switch (*p)
0916 {
0917
0918 case LOG_COMMAND_I:
0919
0920 case LOG_COMMAND_J:
0921
0922 if (infos_ok)
0923 {
0924 NDRX_LOG(log_error, "TMSRV log file [%s] duplicate info block",
0925 logfile);
0926 userlog("TMSRV log file [%s] duplicate info block",
0927 logfile);
0928 do_housekeep=EXTRUE;
0929 EXFAIL_OUT(ret);
0930 }
0931
0932
0933 (*pp_tl)->log_version = *p - LOG_COMMAND_I + 1;
0934
0935 if (EXSUCCEED!=tms_parse_info(buf, *pp_tl))
0936 {
0937 EXFAIL_OUT(ret);
0938 }
0939
0940 infos_ok = EXTRUE;
0941 break;
0942 case LOG_COMMAND_STAGE:
0943
0944 if (!infos_ok)
0945 {
0946 NDRX_LOG(log_error, "TMSRV log file [%s] Info record required first",
0947 logfile);
0948 userlog("TMSRV log file [%s] Info record required first",
0949 logfile);
0950 do_housekeep=EXTRUE;
0951 EXFAIL_OUT(ret);
0952 }
0953
0954 if (EXSUCCEED!=tms_parse_stage(buf, *pp_tl))
0955 {
0956 EXFAIL_OUT(ret);
0957 }
0958
0959 break;
0960 case LOG_COMMAND_RMSTAT:
0961
0962 if (!infos_ok)
0963 {
0964 NDRX_LOG(log_error, "TMSRV log file [%s] Info record required first",
0965 logfile);
0966 userlog("TMSRV log file [%s] Info record required first",
0967 logfile);
0968 do_housekeep=EXTRUE;
0969 EXFAIL_OUT(ret);
0970 }
0971
0972 if (EXSUCCEED!=tms_parse_rmstatus(buf, *pp_tl))
0973 {
0974 EXFAIL_OUT(ret);
0975 }
0976
0977 break;
0978 default:
0979 NDRX_LOG(log_warn, "Unknown record %c on line %d", *p, line);
0980 break;
0981 }
0982
0983 line++;
0984 }
0985
0986
0987 if (!feof((*pp_tl)->f))
0988 {
0989 err = ferror((*pp_tl)->f);
0990
0991 NDRX_LOG(log_error, "TMSRV log file [%s] failed to read: %s",
0992 logfile, strerror(err));
0993 userlog("TMSRV log file [%s] failed to read: %s",
0994 logfile, strerror(err));
0995 EXFAIL_OUT(ret);
0996 }
0997
0998 if (!infos_ok)
0999 {
1000 NDRX_LOG(log_error, "TMSRV log file [%s] no [%c] info record - not loading",
1001 logfile, LOG_COMMAND_J);
1002 userlog("TMSRV log file [%s] no [%c] info record - not loading",
1003 logfile, LOG_COMMAND_J);
1004 do_housekeep=EXTRUE;
1005 EXFAIL_OUT(ret);
1006 }
1007
1008
1009 if (missing_term_in_file)
1010 {
1011
1012 if (got_term_last)
1013 {
1014 NDRX_LOG(log_error, "TMSRV log file [%s] - invalid read, "
1015 "previous lines seen without \\n",
1016 logfile);
1017 userlog("TMSRV log file [%s] - invalid read, "
1018 "previous lines without \\n",
1019 logfile);
1020 EXFAIL_OUT(ret);
1021 }
1022 else
1023 {
1024
1025 NDRX_LOG(log_error, "Terminating last line (with out checksum)");
1026
1027 if (ndrx_G_systest_lockloss)
1028 {
1029 wrote=EXFAIL;
1030 }
1031 else
1032 {
1033 wrote=fprintf((*pp_tl)->f, "\n");
1034 }
1035
1036 if (wrote!=1)
1037 {
1038 err = ferror((*pp_tl)->f);
1039 NDRX_LOG(log_error, "TMSRV log file [%s] failed to terminate line: %s",
1040 logfile, strerror(err));
1041 userlog("TMSRV log file [%s] failed to terminate line: %s",
1042 logfile, strerror(err));
1043 EXFAIL_OUT(ret);
1044 }
1045 }
1046 }
1047
1048
1049
1050
1051 (*pp_tl)->is_background = EXTRUE;
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070 if (XA_TX_STAGE_PREPARING == (*pp_tl)->txstage
1071 || XA_TX_STAGE_ACTIVE == (*pp_tl)->txstage)
1072 {
1073 NDRX_LOG(log_error, "XA Transaction [%s] was in active or preparing stage and "
1074 "tmsrv is restarted - ABORTING", (*pp_tl)->tmxid);
1075
1076 userlog("XA Transaction [%s] was in active or preparing stage and "
1077 "tmsrv is restarted - ABORTING", (*pp_tl)->tmxid);
1078
1079
1080 (*pp_tl)->lockthreadid = ndrx_gettid();
1081 tms_log_stage(*pp_tl, XA_TX_STAGE_ABORTING, EXTRUE);
1082 (*pp_tl)->lockthreadid = 0;
1083 }
1084
1085 MUTEX_LOCK_V(M_tx_hash_lock);
1086 EXHASH_ADD_STR( M_tx_hash, tmxid, (*pp_tl));
1087 MUTEX_UNLOCK_V(M_tx_hash_lock);
1088
1089 NDRX_LOG(log_debug, "TX [%s] loaded OK", tmxid);
1090 out:
1091
1092
1093 if (EXSUCCEED!=ret)
1094 {
1095 userlog("Failed to load/recover transaction [%s]", logfile);
1096 if (NULL!=*pp_tl)
1097 {
1098
1099
1100 if (tms_is_logfile_open(*pp_tl))
1101 {
1102 tms_close_logfile(*pp_tl);
1103 }
1104
1105 tms_remove_logfree(*pp_tl, EXFALSE);
1106 *pp_tl = NULL;
1107 }
1108 }
1109
1110
1111 if (do_housekeep)
1112 {
1113 *housekeepable=EXTRUE;
1114
1115
1116 if (tms_housekeep(logfile))
1117 {
1118 *log_removed=EXTRUE;
1119 }
1120 }
1121
1122 return ret;
1123 }
1124
1125
1126
1127
1128
1129
1130 expublic int tms_is_logfile_open(atmi_xa_log_t *p_tl)
1131 {
1132 if (p_tl->f)
1133 return EXTRUE;
1134 else
1135 return EXFALSE;
1136 }
1137
1138
1139
1140
1141
1142 expublic void tms_close_logfile(atmi_xa_log_t *p_tl)
1143 {
1144 if (NULL!=p_tl->f)
1145 {
1146 NDRX_FCLOSE(p_tl->f);
1147 p_tl->f = NULL;
1148 }
1149 }
1150
1151
1152
1153
1154
1155
1156 expublic void tms_remove_logfree(atmi_xa_log_t *p_tl, int hash_rm)
1157 {
1158 int i;
1159 atmi_xa_rm_status_btid_t *el, *elt;
1160
1161 if (hash_rm)
1162 {
1163 MUTEX_LOCK_V(M_tx_hash_lock);
1164 EXHASH_DEL(M_tx_hash, p_tl);
1165 MUTEX_UNLOCK_V(M_tx_hash_lock);
1166 }
1167
1168
1169
1170 for (i=0; i<NDRX_MAX_RMS; i++)
1171 {
1172 EXHASH_ITER(hh, p_tl->rmstatus[i].btid_hash, el, elt)
1173 {
1174 EXHASH_DEL(p_tl->rmstatus[i].btid_hash, el);
1175 NDRX_FREE(el);
1176 }
1177 }
1178
1179 NDRX_FREE(p_tl);
1180 }
1181
1182
1183
1184
1185
1186
1187
1188 expublic void tms_remove_logfile(atmi_xa_log_t *p_tl, int hash_rm)
1189 {
1190 int have_file = EXFALSE;
1191
1192 if (tms_is_logfile_open(p_tl))
1193 {
1194 have_file = EXTRUE;
1195 tms_close_logfile(p_tl);
1196 }
1197 else if (0 == access(p_tl->fname, 0))
1198 {
1199 have_file = EXTRUE;
1200 }
1201
1202 if (have_file)
1203 {
1204 if (ndrx_G_systest_lockloss || EXSUCCEED!=unlink(p_tl->fname))
1205 {
1206 int err = errno;
1207 NDRX_LOG(log_debug, "Failed to remove tx log file [%s]: %d (%s)",
1208 p_tl->fname, err, strerror(err));
1209 userlog("Failed to remove tx log file [%s]: %d (%s)",
1210 p_tl->fname, err, strerror(err));
1211 }
1212 }
1213
1214
1215 tms_remove_logfree(p_tl, hash_rm);
1216 }
1217
1218
1219
1220
1221 exprivate int tms_log_write_line(atmi_xa_log_t *p_tl, char command, const char *fmt, ...)
1222 {
1223 int ret = EXSUCCEED;
1224 char msg[LOG_MAX+1] = {EXEOS};
1225 char msg2[LOG_MAX+1] = {EXEOS};
1226 int len, wrote, exp;
1227 int make_error = EXFALSE;
1228 unsigned long crc32;
1229 va_list ap;
1230
1231 CHK_THREAD_ACCESS;
1232
1233
1234 if (NULL==p_tl->f)
1235 {
1236 return EXSUCCEED;
1237 }
1238
1239 va_start(ap, fmt);
1240 (void) vsnprintf(msg, sizeof(msg), fmt, ap);
1241 va_end(ap);
1242
1243 snprintf(msg2, sizeof(msg2), "%lld:%c:%s", ndrx_utc_tstamp(), command, msg);
1244 len = strlen(msg2);
1245
1246
1247
1248 if (1==G_atmi_env.test_tmsrv_write_fail)
1249 {
1250 make_error = EXTRUE;
1251 }
1252 else if (2==G_atmi_env.test_tmsrv_write_fail)
1253 {
1254
1255 if (ndrx_rand() % 4 == 0)
1256 {
1257 make_error = EXTRUE;
1258 }
1259
1260 }
1261
1262 crc32 = ndrx_Crc32_ComputeBuf(0, msg2, len);
1263
1264
1265
1266
1267 wrote=0;
1268
1269
1270
1271
1272
1273
1274
1275 if (p_tl->log_version == LOG_VERSION_1)
1276 {
1277 NDRX_LOG(log_debug, "Log format: v%d", p_tl->log_version);
1278
1279 exp = len+1;
1280 if (make_error)
1281 {
1282 exp++;
1283 }
1284
1285 if (ndrx_G_systest_lockloss)
1286 {
1287 wrote=EXFAIL;
1288 }
1289 else
1290 {
1291 wrote=fprintf(p_tl->f, "%s\n", msg2);
1292 }
1293
1294 }
1295 else
1296 {
1297
1298 exp = len+8+1+1;
1299
1300 if (make_error)
1301 {
1302 crc32+=1;
1303 exp++;
1304 }
1305
1306 if (ndrx_G_systest_lockloss)
1307 {
1308 wrote=EXFAIL;
1309 }
1310 else
1311 {
1312 wrote=fprintf(p_tl->f, "%s%c%08lx\n", msg2, LOG_RS_SEP, crc32);
1313 }
1314 }
1315
1316 if (wrote != exp)
1317 {
1318 int err = errno;
1319
1320
1321 if (make_error)
1322 {
1323 NDRX_LOG(log_error, "QA point: make_error TRUE");
1324 err = ENOSPC;
1325 }
1326
1327 NDRX_LOG(log_error, "ERROR! Failed to write transaction log file: req_len=%d, written=%d: %s",
1328 exp, wrote, strerror(err));
1329 userlog("ERROR! Failed to write transaction log file: req_len=%d, written=%d: %s",
1330 exp, wrote, strerror(err));
1331
1332 ret=EXFAIL;
1333 goto out;
1334 }
1335
1336
1337 out:
1338
1339
1340 if (ndrx_G_systest_lockloss || EXSUCCEED!=fflush(p_tl->f))
1341 {
1342 int err=errno;
1343 userlog("ERROR! Failed to fflush(): %s", strerror(err));
1344 NDRX_LOG(log_error, "ERROR! Failed to fflush(): %s", strerror(err));
1345 ret=EXFAIL;
1346 }
1347
1348 return ret;
1349 }
1350
1351
1352
1353
1354
1355
1356
1357
1358 expublic int tms_log_info(atmi_xa_log_t *p_tl)
1359 {
1360 int ret = EXSUCCEED;
1361 char rmsbuf[NDRX_MAX_RMS*3+1]={EXEOS};
1362 int i;
1363 int len;
1364
1365 CHK_THREAD_ACCESS;
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385 if (EXSUCCEED!=tms_log_write_line(p_tl, LOG_COMMAND_J, "%hd:%hd:%hd:%ld:%s",
1386 p_tl->tmrmid, p_tl->tmnodeid, p_tl->tmsrvid, p_tl->txtout, rmsbuf))
1387 {
1388 ret=EXFAIL;
1389 goto out;
1390 }
1391
1392 out:
1393 return ret;
1394 }
1395
1396 #define TOKEN_READ_VARS \
1397 int first = EXTRUE;\
1398 char *p;
1399
1400
1401 #define TOKEN_READ(X, Y)\
1402 if (NULL==(p = strtok(first?buf:NULL, ":")))\
1403 {\
1404 NDRX_LOG(log_error, "Missing token: %s.%s!", X, Y);\
1405 EXFAIL_OUT(ret);\
1406 }\
1407 if (first)\
1408 first = EXFALSE;\
1409
1410 #define TOKEN_READ_OPT(X, Y)\
1411 if (NULL==(p = strtok(first?buf:NULL, ":")))\
1412 {\
1413 NDRX_LOG(log_warn, "Missing token: %s.%s - optional, ignore!", X, Y);\
1414 }\
1415 if (first)\
1416 first = EXFALSE;\
1417
1418
1419
1420
1421
1422
1423
1424 exprivate int tms_parse_info(char *buf, atmi_xa_log_t *p_tl)
1425 {
1426 int ret = EXSUCCEED;
1427 TOKEN_READ_VARS;
1428 char *p2;
1429 char *saveptr1 = NULL;
1430 int rmid;
1431 long long tdiff;
1432
1433
1434 TOKEN_READ("info", "tstamp");
1435 p_tl->t_start = strtoull (p, NULL, 10);
1436
1437 tdiff = ndrx_utc_tstamp() - p_tl->t_start;
1438
1439 ndrx_stopwatch_reset(&p_tl->ttimer);
1440 ndrx_stopwatch_minus(&p_tl->ttimer, tdiff);
1441 NDRX_LOG(log_debug, "Transaction age: %ld ms (t_start: %llu tdiff: %lld)",
1442 ndrx_stopwatch_get_delta(&p_tl->ttimer), p_tl->t_start, tdiff);
1443
1444
1445 TOKEN_READ("info", "cmdid");
1446
1447 TOKEN_READ("info", "tmrmid");
1448 TOKEN_READ("info", "tmnodeid");
1449 TOKEN_READ("info", "tmsrvid");
1450 p_tl->tmrmid = G_atmi_env.xa_rmid;
1451 p_tl->tmnodeid = G_tmsrv_cfg.vnodeid;
1452 p_tl->tmsrvid = G_server_conf.srv_id;
1453
1454 TOKEN_READ("info", "txtout");
1455 p_tl->txtout = atol(p);
1456
1457
1458 #if 0
1459 TOKEN_READ("info", "rmsbuf");
1460
1461 - not used anymore. All active branches are logged as RM status
1462 p2 = strtok_r (p, ",", &saveptr1);
1463 while (p2 != NULL)
1464 {
1465
1466 rmid = atoi(p2);
1467 if (rmid<1 || rmid>NDRX_MAX_RMS)
1468 {
1469 NDRX_LOG(log_error, "Invalid RMID: %d!", rmid);
1470 EXFAIL_OUT(ret);
1471 }
1472
1473 p_tl->rmstatus[rmid-1].rmstatus =XA_RM_STATUS_ACTIVE;
1474
1475 p2 = strtok_r (NULL, ",", &saveptr1);
1476 }
1477 #endif
1478
1479 out:
1480 return ret;
1481 }
1482
1483 #define CRASH_CLASS_EXIT 0
1484 #define CRASH_CLASS_NO_WRITE 1
1485
1486
1487
1488
1489
1490
1491
1492
1493 expublic int tms_log_stage(atmi_xa_log_t *p_tl, short stage, int forced)
1494 {
1495 int ret = EXSUCCEED;
1496 short stage_org=EXFAIL;
1497
1498 int make_crash = EXFALSE;
1499 int crash_stage, crash_class;
1500
1501
1502 CHK_THREAD_ACCESS;
1503
1504 if (p_tl->txstage!=stage)
1505 {
1506 stage_org = p_tl->txstage;
1507 p_tl->txstage = stage;
1508
1509 NDRX_LOG(log_debug, "tms_log_stage: new stage - %hd (cc %d)",
1510 p_tl->txstage, G_atmi_env.test_tmsrv_commit_crash);
1511
1512
1513
1514
1515
1516
1517
1518
1519 crash_stage = G_atmi_env.test_tmsrv_commit_crash % 100;
1520 crash_class = G_atmi_env.test_tmsrv_commit_crash / 100;
1521
1522
1523 if (stage > 0 && crash_class==CRASH_CLASS_EXIT && stage == crash_stage)
1524 {
1525 NDRX_LOG(log_debug, "QA commit crash...");
1526 G_atmi_env.test_tmsrv_write_fail=EXTRUE;
1527 make_crash=EXTRUE;
1528 }
1529
1530
1531 if (stage > 0 && crash_class==CRASH_CLASS_NO_WRITE && stage == crash_stage)
1532 {
1533 NDRX_LOG(log_debug, "QA no write crash");
1534 ret=EXFAIL;
1535 goto out;
1536 }
1537
1538 else
1539 {
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552 int w_cnt=1, i;
1553
1554 if (XA_TX_STAGE_ABORTING==stage)
1555 {
1556 w_cnt=3;
1557 }
1558 else if (XA_TX_STAGE_COMMITTING==stage)
1559 {
1560
1561
1562
1563
1564
1565
1566
1567
1568 if (EXSUCCEED!=tms_log_checkpointseq(p_tl))
1569 {
1570 EXFAIL_OUT(ret);
1571 }
1572 }
1573
1574 for (i=0; i<w_cnt; i++)
1575 {
1576 if (EXSUCCEED!=tms_log_write_line(p_tl, LOG_COMMAND_STAGE, "%hd", stage))
1577 {
1578 ret=EXFAIL;
1579 goto out;
1580 }
1581 }
1582 }
1583
1584
1585 if ((XA_TX_STAGE_COMMITTING==stage) || (XA_TX_STAGE_ABORTING==stage))
1586 {
1587 if (ndrx_G_systest_lockloss)
1588 {
1589
1590 EXFAIL_OUT(ret);
1591 }
1592 else if (EXSUCCEED!=ndrx_fsync_fsync(p_tl->f, G_atmi_env.xa_fsync_flags) ||
1593 EXSUCCEED!=ndrx_fsync_dsync(G_tmsrv_cfg.tlog_dir, G_atmi_env.xa_fsync_flags))
1594 {
1595 EXFAIL_OUT(ret);
1596 }
1597
1598
1599
1600
1601 if (EXSUCCEED!=tms_log_checkpointseq(p_tl))
1602 {
1603 EXFAIL_OUT(ret);
1604 }
1605
1606 }
1607 }
1608
1609 out:
1610
1611
1612 if (make_crash)
1613 {
1614 exit(1);
1615 }
1616
1617
1618
1619
1620
1621
1622 if (forced)
1623 {
1624 return EXSUCCEED;
1625 }
1626 else if (EXSUCCEED!=ret && EXFAIL!=stage_org)
1627 {
1628 p_tl->txstage = stage_org;
1629 }
1630
1631
1632 return ret;
1633 }
1634
1635
1636
1637
1638
1639
1640
1641
1642 exprivate int tms_parse_stage(char *buf, atmi_xa_log_t *p_tl)
1643 {
1644 int ret = EXSUCCEED;
1645 short stage;
1646 TOKEN_READ_VARS;
1647
1648 TOKEN_READ("stage", "tstamp");
1649 p_tl->t_update = atol(p);
1650 TOKEN_READ("info", "cmdid");
1651
1652 TOKEN_READ("stage", "txstage");
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663 stage=(short)atoi(p);
1664
1665 if (stage < p_tl->txstage)
1666 {
1667 NDRX_LOG(log_error, "Transaction logs recover: stage for [%s] downgrade was %hd, read %hd",
1668 p_tl->tmxid, p_tl->txstage, stage);
1669 userlog("Transaction logs recover: stage for [%s] downgrade was %hd, read %hd",
1670 p_tl->tmxid, p_tl->txstage, stage);
1671 }
1672
1673 if (p_tl->txstage>=XA_TX_STAGE_ABORTING &&
1674 p_tl->txstage<=XA_TX_STAGE_ABFORGOT_HEU)
1675 {
1676 if (stage>=XA_TX_STAGE_ABORTING &&
1677 stage<=XA_TX_STAGE_ABFORGOT_HEU)
1678 {
1679 p_tl->txstage = stage;
1680 }
1681 else
1682 {
1683 NDRX_LOG(log_error, "Invalid stage for [%s] was %hd (abort range) read %hd - IGNORE",
1684 p_tl->tmxid, p_tl->txstage, stage);
1685 userlog("Invalid stage for [%s] was %hd (abort range) read %hd - IGNORE",
1686 p_tl->tmxid, p_tl->txstage, stage);
1687 }
1688 }
1689 else
1690 {
1691 p_tl->txstage = stage;
1692 }
1693
1694 out:
1695 return ret;
1696 }
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708 expublic int tms_log_rmstatus(atmi_xa_log_t *p_tl, atmi_xa_rm_status_btid_t *bt,
1709 char rmstatus, int rmerrorcode, short rmreason)
1710 {
1711 int ret = EXSUCCEED;
1712 int do_log = EXFALSE;
1713
1714 CHK_THREAD_ACCESS;
1715
1716 if (bt->rmstatus != rmstatus)
1717 {
1718 do_log = EXTRUE;
1719 }
1720
1721 bt->rmstatus = rmstatus;
1722 bt->rmerrorcode = rmerrorcode;
1723 bt->rmreason = rmreason;
1724
1725 if (do_log)
1726 {
1727 if (EXSUCCEED!=tms_log_write_line(p_tl, LOG_COMMAND_RMSTAT, "%hd:%c:%d:%hd:%ld",
1728 bt->rmid, rmstatus, rmerrorcode, rmreason, bt->btid))
1729 {
1730 ret=EXFAIL;
1731 goto out;
1732 }
1733 }
1734
1735 out:
1736 return ret;
1737 }
1738
1739
1740
1741
1742
1743
1744
1745 exprivate int tms_parse_rmstatus(char *buf, atmi_xa_log_t *p_tl)
1746 {
1747 int ret = EXSUCCEED;
1748 char rmstatus;
1749 int rmerrorcode;
1750 short rmreason;
1751 int rmid;
1752 long btid;
1753 atmi_xa_rm_status_btid_t *bt = NULL;
1754
1755 TOKEN_READ_VARS;
1756
1757 TOKEN_READ("rmstat", "tstamp");
1758 p_tl->t_update = atol(p);
1759 TOKEN_READ("info", "cmdid");
1760
1761 TOKEN_READ("rmstat", "rmid");
1762
1763 rmid = atoi(p);
1764 if (rmid<1 || rmid>NDRX_MAX_RMS)
1765 {
1766 NDRX_LOG(log_error, "Invalid RMID: %d!", rmid);
1767 EXFAIL_OUT(ret);
1768 }
1769
1770 TOKEN_READ("rmstat", "rmstatus");
1771 rmstatus = *p;
1772
1773 TOKEN_READ("rmstat", "rmerrorcode");
1774 rmerrorcode = atoi(p);
1775
1776 TOKEN_READ("rmstat", "rmreason");
1777 rmreason = (short)atoi(p);
1778
1779 TOKEN_READ_OPT("rmstat", "btid");
1780
1781 if (NULL!=p)
1782 {
1783 btid = atol(p);
1784 }
1785 else
1786 {
1787 btid=0;
1788 }
1789
1790
1791
1792
1793
1794
1795
1796 ret = tms_btid_addupd(p_tl, rmid,
1797 &btid, rmstatus, rmerrorcode, rmreason, NULL, &bt);
1798
1799 out:
1800 return ret;
1801 }
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812 expublic atmi_xa_log_list_t* tms_copy_hash2list(int copy_mode)
1813 {
1814 atmi_xa_log_list_t *ret = NULL;
1815 atmi_xa_log_t * r, *rt;
1816 atmi_xa_log_list_t *tmp;
1817
1818 if (copy_mode & COPY_MODE_ACQLOCK)
1819 {
1820 MUTEX_LOCK_V(M_tx_hash_lock);
1821 }
1822
1823
1824
1825 EXHASH_ITER(hh, M_tx_hash, r, rt)
1826 {
1827
1828 if (r->is_background && !(copy_mode & COPY_MODE_BACKGROUND))
1829 continue;
1830
1831 if (!r->is_background && !(copy_mode & COPY_MODE_FOREGROUND))
1832 continue;
1833
1834 if (NULL==(tmp = NDRX_CALLOC(1, sizeof(atmi_xa_log_list_t))))
1835 {
1836 NDRX_LOG(log_error, "Failed to malloc %d: %s",
1837 sizeof(atmi_xa_log_list_t), strerror(errno));
1838 goto out;
1839 }
1840
1841
1842
1843
1844
1845
1846 memcpy(&tmp->p_tl, r, sizeof(*r));
1847
1848 LL_APPEND(ret, tmp);
1849 }
1850
1851 out:
1852 if (copy_mode & COPY_MODE_ACQLOCK)
1853 {
1854 MUTEX_UNLOCK_V(M_tx_hash_lock);
1855 }
1856
1857 return ret;
1858 }
1859
1860
1861
1862
1863 expublic void tms_tx_hash_lock(void)
1864 {
1865 MUTEX_LOCK_V(M_tx_hash_lock);
1866 }
1867
1868
1869
1870
1871 expublic void tms_tx_hash_unlock(void)
1872 {
1873 MUTEX_UNLOCK_V(M_tx_hash_lock);
1874 }
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886 expublic int tms_log_cpy_info_to_fb(UBFH *p_ub, atmi_xa_log_t *p_tl, int incl_rm_stat)
1887 {
1888 int ret = EXSUCCEED;
1889 long tspent;
1890 short i;
1891 tspent = p_tl->txtout - ndrx_stopwatch_get_delta_sec(&p_tl->ttimer);
1892 atmi_xa_rm_status_btid_t *el, *elt;
1893
1894 if (tspent<0)
1895 {
1896 tspent = 0;
1897 }
1898
1899 if (
1900 EXSUCCEED!=Bchg(p_ub, TMXID, 0, (char *)p_tl->tmxid, 0L) ||
1901 EXSUCCEED!=Bchg(p_ub, TMRMID, 0, (char *)&(p_tl->tmrmid), 0L) ||
1902 EXSUCCEED!=Bchg(p_ub, TMNODEID, 0, (char *)&(p_tl->tmnodeid), 0L) ||
1903 EXSUCCEED!=Bchg(p_ub, TMSRVID, 0, (char *)&(p_tl->tmsrvid), 0L) ||
1904 EXSUCCEED!=Bchg(p_ub, TMTXTOUT, 0, (char *)&(p_tl->txtout), 0L) ||
1905 EXSUCCEED!=Bchg(p_ub, TMTXTOUT_LEFT, 0, (char *)&tspent, 0L) ||
1906 EXSUCCEED!=Bchg(p_ub, TMTXSTAGE, 0, (char *)&(p_tl->txstage), 0L) ||
1907 EXSUCCEED!=Bchg(p_ub, TMTXTRYCNT, 0, (char *)&(p_tl->trycount), 0L) ||
1908 EXSUCCEED!=Bchg(p_ub, TMTXTRYMAXCNT, 0, (char *)&(G_tmsrv_cfg.max_tries), 0L)
1909 )
1910 {
1911 NDRX_LOG(log_error, "Failed to return fields: [%s]",
1912 Bstrerror(Berror));
1913 EXFAIL_OUT(ret);
1914 }
1915
1916
1917 for (i=0; incl_rm_stat && i<NDRX_MAX_RMS; i++)
1918 {
1919
1920 EXHASH_ITER(hh, p_tl->rmstatus[i].btid_hash, el, elt)
1921 {
1922
1923 long rmerrorcode = (long)el->rmerrorcode;
1924
1925 if (
1926 EXSUCCEED!=Badd(p_ub, TMTXRMID, (char *)&el->rmid, 0L) ||
1927 EXSUCCEED!=Badd(p_ub, TMTXBTID, (char *)&el->btid, 0L) ||
1928 EXSUCCEED!=Badd(p_ub, TMTXRMSTATUS,
1929 (char *)&(el->rmstatus), 0L) ||
1930 EXSUCCEED!=Badd(p_ub, TMTXRMERRCODE,
1931 (char *)&rmerrorcode, 0L) ||
1932 EXSUCCEED!=Badd(p_ub, TMTXRMREASON,
1933 (char *)&(el->rmreason), 0L)
1934 )
1935 {
1936
1937
1938
1939 NDRX_LOG(log_error, "Failed to return fields: [%s] - ignore",
1940 Bstrerror(Berror));
1941
1942
1943 goto out;
1944 }
1945 }
1946 }
1947
1948 out:
1949 return ret;
1950 }
1951
1952