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 <string.h>
0036 #include <stdio.h>
0037 #include <stdlib.h>
0038 #include <memory.h>
0039 #include <errno.h>
0040 #include <dlfcn.h>
0041
0042 #include <atmi.h>
0043 #include <atmi_tls.h>
0044 #include <ndrstandard.h>
0045 #include <ndebug.h>
0046 #include <ndrxdcmn.h>
0047 #include <userlog.h>
0048 #include <tx.h>
0049 #include <Exfields.h>
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 exprivate int tx_map_error1(const char *dbg, int tpret, int allow_error)
0066 {
0067 int ret = TX_FAIL;
0068 int tperr;
0069
0070 if (0==tpret)
0071 {
0072 tperr = EXSUCCEED;
0073 }
0074 else
0075 {
0076 tperr = tperrno;
0077 }
0078
0079 NDRX_LOG(log_debug, "tpret=%d tperr=%d", tpret, tperr);
0080
0081 switch (tperr)
0082 {
0083 case 0:
0084 ret = TX_OK;
0085 break;
0086 case TPEPROTO:
0087 ret = TX_PROTOCOL_ERROR;
0088 break;
0089 case TPESVCFAIL:
0090 case TPESVCERR:
0091 case TPETIME:
0092 if (allow_error)
0093 {
0094 ret = TX_ERROR;
0095 }
0096 else
0097 {
0098 ret = TX_FAIL;
0099 }
0100 break;
0101 case TPESYSTEM:
0102 case TPEOS:
0103 case TPERMERR:
0104 case TPEINVAL:
0105 ret = TX_FAIL;
0106 break;
0107 case TPEHAZARD:
0108 ret = TX_HAZARD;
0109 break;
0110 case TPEHEURISTIC:
0111 ret = TX_MIXED;
0112 break;
0113 case TPEMATCH:
0114 case TPEABORT:
0115 ret = TX_ROLLBACK;
0116 break;
0117 }
0118
0119 if (TX_OK==ret)
0120 {
0121 NDRX_LOG(log_debug, "%s: TX_OK", dbg);
0122 }
0123 else
0124 {
0125 NDRX_LOG(log_error, "%s tp error %d mapped to tx %d: %s", dbg,
0126 tperr, ret, tpstrerror(tperr));
0127 }
0128
0129 return ret;
0130 }
0131
0132
0133
0134
0135
0136 expublic int tx_begin(void)
0137 {
0138 int ret;
0139 ATMI_TLS_ENTRY;
0140
0141 ret = tpbegin(G_atmi_tls->tx_transaction_timeout, 0);
0142
0143
0144 ret = tx_map_error1(__func__, ret, EXTRUE);
0145
0146 return ret;
0147
0148 }
0149
0150
0151
0152
0153
0154 expublic int tx_close(void)
0155 {
0156 int ret;
0157
0158 ret = tpclose();
0159
0160 ret = tx_map_error1(__func__, ret, EXTRUE);
0161
0162 return ret;
0163 }
0164
0165
0166
0167
0168
0169
0170
0171 expublic int tx_commit(void)
0172 {
0173 int ret, ret2;
0174 long flags = 0;
0175 ATMI_TLS_ENTRY;
0176
0177 if (TX_COMMIT_DECISION_LOGGED==G_atmi_tls->tx_commit_return)
0178 {
0179 flags|=TP_CMT_LOGGED;
0180 }
0181
0182 ret = tpcommit(flags);
0183
0184 ret = tx_map_error1(__func__, ret, EXFALSE);
0185
0186
0187
0188 if (TX_CHAINED==G_atmi_tls->tx_transaction_control)
0189 {
0190 if (TX_PROTOCOL_ERROR == ret || TX_FAIL==ret)
0191
0192 {
0193 NDRX_LOG(log_error, "Fatal error cannot chain tx");
0194 }
0195 else
0196 {
0197 ret2 = tpbegin(G_atmi_tls->tx_transaction_timeout, 0);
0198 ret2 = tx_map_error1("tx_commit next tran begin: ", ret2, EXTRUE);
0199
0200
0201 if (TX_OK!=ret2)
0202 {
0203 ret2 += TX_NO_BEGIN;
0204 }
0205 }
0206
0207 ret = ret2;
0208 }
0209
0210 NDRX_LOG(log_debug, "returns %d", ret);
0211 return ret;
0212 }
0213
0214
0215
0216
0217
0218
0219 expublic int ndrx_tx_info(TXINFO * txinfo)
0220 {
0221 int ret = TX_OK;
0222 UBFH *p_ub = NULL;
0223 short txstage;
0224 ATMI_TLS_ENTRY;
0225
0226 txinfo->transaction_control = G_atmi_tls->tx_transaction_control;
0227 txinfo->transaction_timeout = G_atmi_tls->tx_transaction_timeout;
0228 txinfo->when_return = G_atmi_tls->tx_commit_return;
0229
0230
0231
0232 if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
0233 {
0234 NDRX_LOG(log_warn, "XA interface is no topen!");
0235 ret = TX_PROTOCOL_ERROR;
0236 }
0237 else if (!G_atmi_tls->G_atmi_xa_curtx.txinfo)
0238 {
0239 txinfo->xid.formatID = EXFAIL;
0240 goto out;
0241 }
0242 else
0243 {
0244 ret = 1;
0245 txinfo->transaction_state = TX_ACTIVE;
0246
0247 atmi_xa_deserialize_xid((unsigned char *)G_atmi_tls->G_atmi_xa_curtx.txinfo->tmxid,
0248 &G_atmi_tls->xid);
0249
0250
0251
0252 if (G_atmi_tls->G_atmi_xa_curtx.txinfo->tmtxflags & TMTXFLAGS_IS_ABORT_ONLY)
0253 {
0254
0255 txinfo->transaction_state = TX_ROLLBACK_ONLY;
0256 }
0257 else
0258 {
0259
0260 if (NULL==(p_ub=atmi_xa_call_tm_generic(ATMI_XA_STATUS, EXFALSE, EXFAIL,
0261 G_atmi_tls->G_atmi_xa_curtx.txinfo, 0L, EXFAIL)))
0262 {
0263 int tperr = tperrno;
0264 NDRX_LOG(log_error, "Tran info failed with: %d", tperr);
0265
0266 if (TPEMATCH==tperr)
0267 {
0268 NDRX_LOG(log_debug, "Not matched by TM -> TX_TIMEOUT_ROLLBACK_ONLY");
0269 txinfo->transaction_state = TX_TIMEOUT_ROLLBACK_ONLY;
0270
0271
0272 G_atmi_tls->G_atmi_xa_curtx.txinfo->tmtxflags |=TMTXFLAGS_IS_ABORT_ONLY;
0273 }
0274 else
0275 {
0276
0277 ret = TX_FAIL;
0278 }
0279 goto out;
0280 }
0281
0282
0283
0284
0285
0286 if (EXSUCCEED!=Bget(p_ub, TMTXSTAGE, 0, (char *)&txstage, 0L))
0287 {
0288 NDRX_LOG(log_error, "Failed to get TMTXSTAGE from tmsrv: %s",
0289 Bstrerror(Berror));
0290 ret = TX_FAIL;
0291 goto out;
0292 }
0293
0294
0295 NDRX_LOG(log_debug, "txstage=%hd", txstage);
0296 if (txstage >= XA_TX_STAGE_ABORTING && txstage <=XA_TX_STAGE_ABORTING)
0297 {
0298 NDRX_LOG(log_warn, "TM is rolling back..!");
0299 txinfo->transaction_state = TX_ROLLBACK;
0300 }
0301 }
0302 }
0303
0304 out:
0305
0306 if (NULL!=p_ub)
0307 {
0308 tpfree((char *)p_ub);
0309 }
0310
0311 return ret;
0312 }
0313
0314
0315
0316
0317
0318 expublic int tx_open(void)
0319 {
0320 int ret;
0321
0322 ret = tpopen();
0323
0324 ret = tx_map_error1(__func__, ret, EXFALSE);
0325
0326 return ret;
0327 }
0328
0329
0330
0331
0332
0333 expublic int tx_rollback(void)
0334 {
0335 int ret, ret2;
0336
0337 ret = tpabort(0L);
0338
0339 ret = tx_map_error1(__func__, ret, EXFALSE);
0340
0341
0342
0343 if (TX_CHAINED==G_atmi_tls->tx_transaction_control)
0344 {
0345 if (TX_PROTOCOL_ERROR == ret || TX_FAIL==ret)
0346
0347 {
0348 NDRX_LOG(log_error, "Fatal error cannot chain tx");
0349 }
0350 else
0351 {
0352 ret2 = tpbegin(G_atmi_tls->tx_transaction_timeout, 0);
0353 ret2 = tx_map_error1("tx_commit next tran begin: ", ret2, EXTRUE);
0354
0355
0356 if (TX_OK!=ret2)
0357 {
0358 ret2 += TX_NO_BEGIN;
0359 }
0360 }
0361
0362 ret = ret2;
0363 }
0364
0365 NDRX_LOG(log_debug, "returns %d", ret);
0366 return ret;
0367 }
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377 expublic int tx_set_commit_return(COMMIT_RETURN cr)
0378 {
0379 int ret = TX_OK;
0380 ATMI_TLS_ENTRY;
0381
0382 if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
0383 {
0384 ret = TX_PROTOCOL_ERROR;
0385 goto out;
0386 }
0387
0388 if (TX_COMMIT_DECISION_LOGGED!=cr &&
0389 TX_COMMIT_COMPLETED!=cr)
0390 {
0391 NDRX_LOG(log_error, "Invalid value: commit return %ld", (long)cr);
0392 ret = TX_EINVAL;
0393 goto out;
0394 }
0395
0396 G_atmi_tls->tx_commit_return = cr;
0397 NDRX_LOG(log_info, "Commit return set to %ld",
0398 (long)G_atmi_tls->tx_commit_return);
0399
0400 out:
0401 return ret;
0402 }
0403
0404
0405
0406
0407
0408
0409
0410 expublic int tx_set_transaction_control(TRANSACTION_CONTROL tc)
0411 {
0412 int ret = TX_OK;
0413 ATMI_TLS_ENTRY;
0414
0415 if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
0416 {
0417 ret = TX_PROTOCOL_ERROR;
0418 goto out;
0419 }
0420
0421 if (TX_UNCHAINED!=tc &&
0422 TX_CHAINED!=tc)
0423 {
0424 NDRX_LOG(log_error, "Invalid value: transaction control %ld", (long)tc);
0425 ret = TX_EINVAL;
0426 goto out;
0427 }
0428
0429 G_atmi_tls->tx_transaction_control = tc;
0430 NDRX_LOG(log_info, "Transaction control set to %ld",
0431 (long)G_atmi_tls->tx_transaction_control);
0432
0433 out:
0434 return ret;
0435 }
0436
0437
0438
0439
0440
0441
0442 expublic int tx_set_transaction_timeout(TRANSACTION_TIMEOUT tt)
0443 {
0444 int ret = TX_OK;
0445 ATMI_TLS_ENTRY;
0446
0447 if (!G_atmi_tls->G_atmi_xa_curtx.is_xa_open)
0448 {
0449 ret = TX_PROTOCOL_ERROR;
0450 goto out;
0451 }
0452
0453 if (tt < 0)
0454 {
0455 NDRX_LOG(log_error, "Invalid value: timeout %ld", (int)tt);
0456 ret = TX_EINVAL;
0457 goto out;
0458 }
0459
0460 G_atmi_tls->tx_transaction_timeout = tt;
0461
0462 NDRX_LOG(log_info, "Transaction timeout out set to %ld",
0463 (long)G_atmi_tls->tx_transaction_timeout);
0464
0465 out:
0466 return ret;
0467 }
0468
0469