- Enduro/X 7.0.12 소스빌드 이미지(-DENABLE_POSTGRES=ON, libndrxxaecpg XA 스위치) - docker-compose: postgres(max_prepared_transactions=100) + endurox app - ECPG XA 서비스 3종: ACQUIRE→RECONCILE→SETTLE (tpservice + EXEC SQL) - 클라이언트 tpbegin/tpcall체인/tpcommit → tmsrv 2PC(prepare/commit) 원자 커밋 - 검증: 서비스 AVAIL, 커밋 row(status=S) psql 확인, 롤백 시 무잔존, pg_prepared_xacts=0 - 규명된 런타임 요건: sysctl fs.mqueue.*, ulimit msgqueue/nofile, XA open-str JSON - docs/architecture.md, README, service-catalog 설계 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
86 lines
2.6 KiB
C
86 lines
2.6 KiB
C
/*
|
|
* acqdrv - acquiring driver client.
|
|
*
|
|
* Starts ONE global transaction (tpbegin), fires the ACQUIRE -> RECONCILE ->
|
|
* SETTLE chain via a single tpcall("ACQUIRE"), then tpcommit (or tpabort when
|
|
* the 4th arg is "abort", to prove XA rollback).
|
|
*
|
|
* Usage: acqdrv [merchant] [amount] [bizdate YYYY-MM-DD] [abort]
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <atmi.h>
|
|
#include <ubf.h>
|
|
#include "acq.fd.h"
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
const char *merch = (argc > 1) ? argv[1] : "M0001";
|
|
long amount = (argc > 2) ? atol(argv[2]) : 1000000; /* 10,000.00 */
|
|
const char *bizdate = (argc > 3) ? argv[3] : "2026-07-19";
|
|
int do_abort = (argc > 4 && strcmp(argv[4], "abort") == 0);
|
|
|
|
UBFH *b;
|
|
long rlen = 0;
|
|
long pid = 0, fee = 0, net = 0, sid = 0;
|
|
char st[16] = "";
|
|
BFLDLEN l;
|
|
|
|
if (tpinit(NULL) < 0) {
|
|
fprintf(stderr, "tpinit FAIL: %s\n", tpstrerror(tperrno));
|
|
return 1;
|
|
}
|
|
if (tpopen() < 0) {
|
|
fprintf(stderr, "tpopen FAIL: %s\n", tpstrerror(tperrno));
|
|
return 1;
|
|
}
|
|
|
|
b = (UBFH *)tpalloc("UBF", NULL, 4096);
|
|
if (b == NULL) {
|
|
fprintf(stderr, "tpalloc FAIL: %s\n", tpstrerror(tperrno));
|
|
return 1;
|
|
}
|
|
Bchg(b, T_MERCHANT, 0, (char *)merch, 0L);
|
|
Bchg(b, T_AMOUNT, 0, (char *)&amount, 0L);
|
|
Bchg(b, T_BIZDATE, 0, (char *)bizdate, 0L);
|
|
|
|
if (tpbegin(60, 0) < 0) {
|
|
fprintf(stderr, "tpbegin FAIL: %s\n", tpstrerror(tperrno));
|
|
return 1;
|
|
}
|
|
|
|
if (tpcall("ACQUIRE", (char *)b, 0L, (char **)&b, &rlen, 0L) < 0) {
|
|
fprintf(stderr, "tpcall(ACQUIRE) FAIL: %s\n", tpstrerror(tperrno));
|
|
tpabort(0);
|
|
return 1;
|
|
}
|
|
|
|
Bget(b, T_PURCHASE_ID, 0, (char *)&pid, 0L);
|
|
Bget(b, T_FEE, 0, (char *)&fee, 0L);
|
|
Bget(b, T_NET, 0, (char *)&net, 0L);
|
|
Bget(b, T_SETTLE_ID, 0, (char *)&sid, 0L);
|
|
l = sizeof(st); Bget(b, T_STATUS, 0, st, &l);
|
|
|
|
if (do_abort) {
|
|
if (tpabort(0) < 0) {
|
|
fprintf(stderr, "tpabort FAIL: %s\n", tpstrerror(tperrno));
|
|
return 1;
|
|
}
|
|
printf(">>> ROLLBACK: global tx aborted. purchase_id=%ld should NOT persist "
|
|
"(merch=%s amount=%ld)\n", pid, merch, amount);
|
|
} else {
|
|
if (tpcommit(0) < 0) {
|
|
fprintf(stderr, "tpcommit FAIL: %s\n", tpstrerror(tperrno));
|
|
tpabort(0);
|
|
return 1;
|
|
}
|
|
printf(">>> COMMIT OK: purchase_id=%ld merch=%s amount=%ld fee=%ld net=%ld "
|
|
"settlement_id=%ld status=%s\n", pid, merch, amount, fee, net, sid, st);
|
|
}
|
|
|
|
tpfree((char *)b);
|
|
tpclose();
|
|
tpterm();
|
|
return 0;
|
|
}
|