- 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>
88 lines
2.5 KiB
Text
88 lines
2.5 KiB
Text
/*
|
|
* RECONCILE (대사) - ECPG XA service.
|
|
*
|
|
* Marks the purchase matched (status='M'), writes a ledger recon entry, then
|
|
* tpcall()s SETTLE - all inside the caller's global transaction.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <atmi.h>
|
|
#include <ubf.h>
|
|
#include <userlog.h>
|
|
#include <ndebug.h>
|
|
#include "acq.fd.h"
|
|
|
|
void RECONCILE(TPSVCINFO *p);
|
|
|
|
int tpsvrinit(int argc, char **argv)
|
|
{
|
|
if (tpopen() < 0) {
|
|
userlog("reconcile: tpopen FAIL: %s", tpstrerror(tperrno));
|
|
return -1;
|
|
}
|
|
if (tpadvertise("RECONCILE", RECONCILE) < 0) {
|
|
userlog("reconcile: tpadvertise(RECONCILE) FAIL: %s", tpstrerror(tperrno));
|
|
return -1;
|
|
}
|
|
userlog("reconcile: RECONCILE advertised, RM opened");
|
|
return 0;
|
|
}
|
|
|
|
void tpsvrdone(void)
|
|
{
|
|
tpclose();
|
|
userlog("reconcile: tpsvrdone");
|
|
}
|
|
|
|
void RECONCILE(TPSVCINFO *p)
|
|
{
|
|
UBFH *b = (UBFH *)p->data;
|
|
long net = 0;
|
|
char bizdate[16] = "";
|
|
BFLDLEN len;
|
|
long rlen = 0;
|
|
|
|
EXEC SQL BEGIN DECLARE SECTION;
|
|
long h_pid;
|
|
long h_net;
|
|
char h_bizdate[16];
|
|
EXEC SQL END DECLARE SECTION;
|
|
|
|
if (Bget(b, T_PURCHASE_ID, 0, (char *)&h_pid, 0L) < 0) {
|
|
userlog("RECONCILE: missing T_PURCHASE_ID: %s", Bstrerror(Berror));
|
|
tpreturn(TPFAIL, 0, p->data, 0L, 0L);
|
|
return;
|
|
}
|
|
Bget(b, T_NET, 0, (char *)&net, 0L);
|
|
len = sizeof(bizdate);
|
|
Bget(b, T_BIZDATE, 0, bizdate, &len);
|
|
h_net = net;
|
|
strncpy(h_bizdate, bizdate, sizeof(h_bizdate) - 1); h_bizdate[sizeof(h_bizdate) - 1] = 0;
|
|
|
|
/* This is a distinct XA branch (own DB connection); it writes only its own
|
|
* recon evidence row and does NOT touch the purchase row (which belongs to
|
|
* the ACQUIRE branch and is not yet committed / not visible here). */
|
|
EXEC SQL INSERT INTO ledger (ledger_id, purchase_id, entry_type, amount, biz_date)
|
|
VALUES (nextval('ledger_seq'), :h_pid, 'RECON', :h_net, :h_bizdate);
|
|
if (sqlca.sqlcode < 0) {
|
|
userlog("RECONCILE: INSERT ledger FAIL [%d] %s",
|
|
sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc);
|
|
tpreturn(TPFAIL, 0, p->data, 0L, 0L);
|
|
return;
|
|
}
|
|
|
|
Bchg(b, T_STATUS, 0, "M", 0L);
|
|
|
|
userlog("RECONCILE pid=%ld matched -> SETTLE", h_pid);
|
|
|
|
if (tpcall("SETTLE", (char *)b, 0L, (char **)&b, &rlen, 0L) < 0) {
|
|
userlog("RECONCILE: tpcall(SETTLE) FAIL: %s", tpstrerror(tperrno));
|
|
tpreturn(TPFAIL, 0, (char *)b, 0L, 0L);
|
|
return;
|
|
}
|
|
|
|
tpreturn(TPSUCCESS, 0, (char *)b, 0L, 0L);
|
|
}
|
|
|
|
/* vim: set ts=4 sw=4 et smartindent: */
|