in sql-odbc/src/opensearchenlist/msdtc_enlist.cpp [1006:1171]
RETCODE static EnlistInDtc_1pipe(void *conn, ITransaction *pTra,
ITransactionDispenser *pDtc, int method) {
CSTR func = "EnlistInDtc_1pipe";
static IDtcToXaHelperSinglePipe *pHelper = NULL;
ITransactionResourceAsync *pRes = NULL;
IAsyncES *asdum;
HRESULT res;
DWORD dwRMCookie;
XID xid;
const char *xalibname = GetXaLibName();
const char *xalibpath = GetXaLibPath();
int recovLvl;
char errmsg[256];
char reason[128];
if (!pHelper) {
res = pDtc->QueryInterface(IID_IDtcToXaHelperSinglePipe,
(void **)&pHelper);
if (res != S_OK || !pHelper) {
mylog("DtcToXaHelperSingelPipe get error %d\n", res);
pHelper = NULL;
return SQL_ERROR;
}
}
res = (NULL != (asdum = new IAsyncES)) ? S_OK : E_FAIL;
if (S_OK != res) {
mylog("CoCreateInstance error %d\n", res);
return SQL_ERROR;
}
recovLvl = EsDtc_is_recovery_available(conn, reason, sizeof(reason));
switch (method) {
case DTC_CHECK_BEFORE_LINK:
if (0 == recovLvl) {
snprintf(errmsg, sizeof(errmsg),
"%s is unavailable in distributed transactions",
reason);
EsDtc_set_error(conn, errmsg, func);
return SQL_ERROR;
}
}
/*mylog("dllname=%s dsn=%s\n", xalibname, conn->connInfo.dsn); res = 0;*/
char dtcname[1024];
EsDtc_create_connect_string(conn, dtcname, sizeof(dtcname));
bool confirmedRegkey = false, confirmingLink = false, xarmerr = false;
char error_header[64];
while (true) {
res = pHelper->XARMCreate(dtcname, (char *)xalibname, &dwRMCookie);
mylog("XARMcreate error code=%x (%d %d)\n", res, confirmedRegkey,
confirmingLink);
xarmerr = true;
if (!confirmingLink)
snprintf(error_header, sizeof(error_header),
"XARMcreate error code=%x", res);
switch (res) {
case S_OK:
if (confirmingLink) {
switch (recovLvl) {
case 0:
snprintf(errmsg, sizeof(errmsg),
"%s:%s is currently unavailable in "
"distributed transactions",
error_header, reason);
break;
case -1:
snprintf(
errmsg, sizeof(errmsg),
"%s:Possibly you connect to the database whose "
"authentication method is %s or ident",
error_header, reason);
break;
case 1:
snprintf(
errmsg, sizeof(errmsg),
"%s:Are you trying to connect to the database "
"whose authentication method is ident?",
error_header);
break;
}
} else
xarmerr = false;
break;
case XACT_E_XA_TX_DISABLED:
snprintf(errmsg, sizeof(errmsg),
"%s:Please enable XA transaction in MSDTC security "
"configuration",
error_header);
break;
case XACT_E_TMNOTAVAILABLE:
snprintf(errmsg, sizeof(errmsg),
"%s:Please start Distributed Transaction Coordinator "
"service",
error_header);
break;
case E_FAIL:
if (!confirmedRegkey) {
int retcode = regkeyCheck(xalibname, xalibpath);
confirmedRegkey = true;
if (retcode > 0)
continue;
}
switch (method) {
case DTC_CHECK_RM_CONNECTION:
if (!confirmingLink) {
confirmingLink = true;
strcat(dtcname, ";" KEYWORD_DTC_CHECK "=0");
continue;
}
default:
snprintf(errmsg, sizeof(errmsg),
"%s:Failed to link with DTC service. Please "
"look at the log of Event Viewer etc.",
error_header);
}
break;
case XACT_E_CONNECTION_DOWN:
snprintf(errmsg, sizeof(errmsg),
"%s:Lost connection with DTC transaction "
"manager\nMSDTC has some trouble?",
error_header);
break;
default:
snprintf(errmsg, sizeof(errmsg), "%s\n", error_header);
break;
}
break;
}
if (xarmerr) {
EsDtc_set_error(conn, errmsg, func);
return SQL_ERROR;
}
res = pHelper->ConvertTridToXID((DWORD *)pTra, dwRMCookie, &xid);
if (res != S_OK) {
mylog("ConvertTridToXid error %d\n", res);
return SQL_ERROR;
}
{
char esxid[258];
XidToText(xid, esxid);
mylog("ConvertTridToXID -> %s\n", esxid);
}
asdum->SetXid(&xid);
/* Create an IAsyncES instance by myself */
/* DLLGetClassObject(GUID_IAsyncES, IID_ITransactionResourceAsync, (void **)
* &asdum); */
asdum->SetHelper(pHelper, dwRMCookie);
res = pHelper->EnlistWithRM(dwRMCookie, pTra, asdum, &asdum->enlist);
if (res != S_OK) {
mylog("EnlistWithRM error %d\n", res);
pHelper->ReleaseRMCookie(dwRMCookie, TRUE);
return SQL_ERROR;
}
mylog("asdum=%p start transaction\n", asdum);
asdum->SetConnection(conn);
LIFELOCK_ACQUIRE;
EsDtc_set_async(conn, asdum);
LIFELOCK_RELEASE;
return SQL_SUCCESS;
}