blob: 55b03bc66debb9897267808fd0b0f15279ea30fb [file] [log] [blame]
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
//
//-------------------------------------------------------------------
// XARM library
//-------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
// seabed includes
#include "seabed/ms.h"
#include "seabed/pctl.h"
#include "seabed/pevents.h"
#include "seabed/trace.h"
#include "common/sq_common.h"
#include "rm.h"
#include "tmrm.h"
#include "tmmap.h"
#include "tmdeque.h"
#include "tmlogging.h"
#include "dtm/xa.h"
#include "xatmmsg.h"
#include "xatmlib.h"
#include "tmlibmsg.h"
#include "tmregistry.h"
#include "dtm/xarm.h"
#include "xarmapi.h"
// XARM xa_switch structure
xa_switch_t xarm_switch = {
XARM_RM_NAME,
TMNOFLAGS, // Supports association migration, but not
// dynamic registration or asynchronous operations.
0, // 0 should be specified for XARM foreign txn support.
xarm_xa_open,
xarm_xa_close,
xarm_xa_start,
xarm_xa_end,
xarm_xa_rollback,
xarm_xa_prepare,
xarm_xa_commit,
xarm_xa_recover,
xarm_xa_forget,
xarm_xa_complete
};
// Default to XARM. xaTM_initialize will set to tse_switch for TMs.
xa_switch_t *xa_switch = &xarm_switch;
// Define the gv_xaTM object here for the xarm library
extern CxaTM_TM gv_xaTM; // One global xaTM object
// -------------------------------------------------------------------
// xaRM_generic_library
// Purpose - True is returned if the library is working as a standard
// X/Open XARM Library.
// -------------------------------------------------------------------
bool xaRM_generic_library()
{
if (strcmp(xa_switch->name, XARM_RM_NAME) == 0)
return true;
return false;
} //xaRM_generic_library
// ---------------------------------------------------------------------
// xaRM_amIaTM
// Check to see whether the library is running inside a
// TM. If it is, then it is assumed to be connecting to
// a TSE as a subordinate RM.
// This library never runs inside the TM at this time@
// ---------------------------------------------------------------------
bool xaRM_amIaTM()
{
return false;
} // xaRM_amIaTM
// ---------------------------------------------------------------
// xaRM_attach
// Purpose: Attach to Seaquest
// ---------------------------------------------------------------
void xaRM_attach()
{
int argc = 0;
const int argMax = 1024;
char arg[argMax];
char *argp = (char *) &arg;
char **argv = (char **) &argp;
bool lv_shellExec = false;
int32 lv_error = FEOK;
const char lc_name[10] = "";
char * lp_name = (char *) &lc_name;
try
{
memset(arg, 0, argMax);
if(lv_shellExec) {
lv_error = msg_init(&argc, &argv);
}
else {
lv_error = msg_init_attach(&argc, &argv, true, lp_name);
}
if (lv_error)
{
//cerr << "** Error " << lv_error
// << " while attempting to attach to Monitor, exiting." << endl;
//exit(-2);
tm_log_event(DTM_XARM_ATTACH_FAILED, SQ_LOG_CRIT, "DTM_XARM_ATTACH_FAILED", lv_error);
abort();
}
lv_error = msg_mon_process_startup(false);
if (lv_error)
{
//cerr << "** Error " << lv_error
// << " from msg_mon_process_startup, exiting." << endl;
//exit(-3);
tm_log_event(DTM_XARM_STARTUP_FAILED, SQ_LOG_CRIT, "DTM_XARM_STARTUP_FAILED", lv_error);
abort();
}
}
catch (SB_Fatal_Excep lv_except)
{
//cerr << "** Error: unable to attach to Monitor or start Seaquest process, exiting." << endl;
//exit(-1);
abort();
}
} //xaRM_attach
// ---------------------------------------------------------------
// xaRM_init
// Purpose - Initialize the XA TM.
// ---------------------------------------------------------------
int xaRM_init (bool pp_tracing, bool pv_tm_stats, CTmTimer *pp_tmTimer)
{
int lv_error = 0;
union {
XATM_TraceMask lv_traceMask;
int lv_traceMaskInt;
} u;
//initialize trace file
char * lp_traceString = (char *) ms_getenv_str("XARM_TRACE");
char * lp_traceStringEnd;
if (pp_tracing != 0 && lp_traceString)
{
lp_traceStringEnd = lp_traceString + strlen(lp_traceString);
if (lp_traceStringEnd == NULL)
{
//tm_log_event(DTM_XMAPI_INVALID_STRING_SIZE, SQ_LOG_CRIT, "DTM_XMAPI_INVALID_STRING_SIZE");
// Make sure the lp_traceStringEnd pointer points to the null terminator.
abort();
}
//Convert hexadecimal string to int
unsigned long lv_traceMaskul = strtoul(lp_traceString, &lp_traceStringEnd, 16);
u.lv_traceMaskInt = (int) lv_traceMaskul;
}
else
u.lv_traceMask = XATM_TraceOff;
lv_error = gv_xaTM.initialize(u.lv_traceMask, pv_tm_stats, pp_tmTimer);
XATrace((lv_error?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xaRM_init EXIT returning %d\n", lv_error));
return lv_error;
}
// ---------------------------------------------------------------
// xaRM_initialize
// Purpose - Initialize the XARM.
// This function is called by each xarm_xa_* to ensure that the
// initialization has been done. When this library is being used
// as an XARM interface the method can not be called directly as
// it is in the TM.
// The initialized flag can only be false if the library is
// acting as an XARM.
// ---------------------------------------------------------------
int xaRM_initialize ()
{
int lv_error = 0;
bool lv_tm_stats = false; //Ignore tm_stats
// Only proceed the first time this is called.
if (gv_xaTM.initialized())
return lv_error;
else
{
// XARM library only - we are not executing inside Seaquest!
xaRM_attach();
lv_error = xaRM_init(true, lv_tm_stats, NULL);
}
return lv_error;
} //xaRM_initialize
// ---------------------------------------------------------------
// xaRM_setTrace
// Purpose - Set the XARM trace mask to a new value.
// ---------------------------------------------------------------
void xaRM_setTrace(unsigned long pv_mask)
{
union {
XATM_TraceMask lv_traceMask;
int lv_traceMaskInt;
} u;
u.lv_traceMaskInt = (int) pv_mask;
gv_xaTM.traceMask(u.lv_traceMask);
XATrace(XATM_TraceAPIExit,("XARM: xaRM_setTrace EXIT : New trace mask %uld\n",
gv_xaTM.traceMask()));
}
// ---------------------------------------------------------------
// xarm_open
// Purpose - open an RM
// This routine checks the parameters, instantiates a CxaTM_RM
// object, and invokes its open method which causes the xa_open
// message to be sent to the RM.
// Asynchronous xa_open() is not supported.
//
// Return Codes:
// XA_OK Normal completion.
// XAER_ASYNC Async opens not supported yet.
// XAER_RMFAIL Error while opening RM.
// XAER_INVAL Invalid parameter.
// XAER_PROTO xa_open() called against an open RM.
// ---------------------------------------------------------------
int xarm_open (char *info, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
CxaTM_RM *lp_RM;
// Validate parameters
if ((!info) || (rmid < 0))
{
XATrace(XATM_TraceAPIError,("XARM: xa_open failed with XAER_INVAL (invalid parameter)\n"));
return XAER_INVAL;
}
XATrace(XATM_TraceXAAPI,("XARM: xa_open ENTRY info=%s, rmid=%d, flags=0x" PFLLX "\n",
info, rmid, flags));
// Currently no flags are supported for TSE xa_open
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_open failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
// Instantiate an RM object and open the RM.
// There is one RM object per open RM.
lv_xaError = gv_xaTM.newRM(rmid, &lp_RM);
if (lp_RM == NULL)
{
tm_log_event(DTM_XMAPI_INVALID_RM_OBJ, SQ_LOG_CRIT, "DTM_XMAPI_INVALID_RM_OBJ");
XATrace(XATM_TraceAPIError,("XARM: xa_open failed - Invalid RM object\n"));
abort(); //Program logic error
}
if (lv_xaError < XA_OK)
{
XATrace(XATM_TraceAPIError,("XARM: xa_open failed to instantiate new RM with %s\n",
XAtoa(lv_xaError)));
}
else
{
lv_xaError = lp_RM->open(info, flags);
// Tear down the RM object if there was an error
if (lv_xaError < XA_OK)
{
XATrace(XATM_TraceAPIError,("XARM: xa_open failed to open RM with %s\n",
XAtoa(lv_xaError)));
gv_xaTM.deleteRM(lp_RM);
}
}
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_open EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_open EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
} //xarm_open
// -------------------------------------------------------
// xarm_close
// Purpose - close an RM, them remove from the rm map
// ------------------------------------------------------
int xarm_close (char *info, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xa_close ENTRY info=%s, rmid=%d, flags=0x" PFLLX "\n",
info, rmid, flags));
// At shutdown time, info is used by the lead TM to send the "SHUTDOWN" string to the RMs
if (rmid < 0)
{
XATrace(XATM_TraceAPIError,("XARM: xa_close failed with XAER_INVAL (rmid < 0)\n"));
return XAER_INVAL;
}
// Currently no flags are supported for xa_close
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_close failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
if (!lp_RM)
{
lv_xaError = XAER_RMFAIL;
XATrace(XATM_TraceAPIError,("XARM: xa_close failed with XAER_RMFAIL\n"));
}
else
{
lv_xaError = lp_RM->close(info, flags);
// delete the RM once we receive the reply from the RM.
}
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_close EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_close EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
} //xarm_close
// -----------------------------------------------------
// xarm_start
// Purpose - send an xa_start message
// -----------------------------------------------------
int xarm_start (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xa_start ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
// Validate xid and rmid
if ((!xid) || (rmid < 0))
{
XATrace(XATM_TraceAPIError,("XARM: xa_start failed with XAER_INVAL (invalid parameter)\n"));
return XAER_INVAL;
}
// Validate flags
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_start failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
if (xaRM_generic_library() && flags &&
((flags & TMNOWAIT) ||
(!(flags & TMJOIN) && !(flags & TMRESUME))))
{
XATrace(XATM_TraceAPIError,("XARM: xa_start failed with XAER_INVAL (invalid flags)\n"));
return XAER_INVAL;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
// Return an error if the RM wasn't found
if (!lp_RM)
lv_xaError = XAER_RMFAIL;
else
lv_xaError = lp_RM->start(xid, flags);
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_start EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_start EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
} //xarm_start
// ------------------------------------------------------
// xarm_end
// Purpose - send xa_end message
// ------------------------------------------------------
int xarm_end (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xa_end ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
// validate xid and rmid
if ((!xid) || (rmid < 0))
{
XATrace(XATM_TraceAPIError,("XARM: xa_end failed with XAER_INVAL (invalid parameter)\n"));
return XAER_INVAL;
}
// validate flags
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_end failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
if (xaRM_generic_library() && flags &&
(!(flags & TMSUSPEND) && !(flags & TMMIGRATE) &&
!(flags & TMSUCCESS) && !(flags & TMFAIL)))
{
XATrace(XATM_TraceAPIError,("XARM: xa_end failed with XAER_INVAL (invalid flags)\n"));
return XAER_INVAL;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
// Return an error if the RM wasn't found
if (!lp_RM)
lv_xaError = XAER_RMFAIL;
else
lv_xaError = lp_RM->end(xid, flags);
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_end EXIT returning %s.\n", XAtoa(lv_xaError)));
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_end EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_end EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
} //xarm_end
// -----------------------------------------------------
// xarm_prepare
// Purpose - send xa_prepare message
// ----------------------------------------------------
int xarm_prepare (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xa_prepare ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
// validate xid and rmid
if ((!xid) || (rmid < 0))
{
XATrace(XATM_TraceAPIError,("XARM: xa_prepare failed with XAER_INVAL (invalid parameter)\n"));
return XAER_INVAL;
}
// validate flags
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_prepare failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
// Return an error if the RM wasn't found
if (!lp_RM)
{
lv_xaError = XAER_RMFAIL;
XATrace(XATM_TraceAPIError,("XARM: xa_prepare failed with XAER_RMFAIL\n"));
}
else
lv_xaError = lp_RM->prepare(xid, flags);
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_prepare EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_prepare EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
} //xarm_prepare
// ---------------------------------------------------
// xarm_rollback
// Purpose - send xa_rollback message
// ---------------------------------------------------
int xarm_rollback (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xa_rollback ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
// validate xid and rmid
if ((!xid) || (rmid < 0))
{
XATrace(XATM_TraceAPIError,("XARM: xa_rollback failed with XAER_INVAL (invalid parameter)\n"));
return XAER_INVAL;
}
// validate flags
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_rollback failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
// Return an error if the RM wasn't found
if (!lp_RM)
{
lv_xaError = XAER_RMFAIL;
XATrace(XATM_TraceAPIError,("XARM: xa_rollback failed with XAER_RMFAIL\n"));
}
else
lv_xaError = lp_RM->rollback(xid, flags);
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_rollback EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_rollback EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
} //xarm_rollback
// -----------------------------------------------
// xarm_commit
// Purpose - send xa_commit message
// -----------------------------------------------
int xarm_commit (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xa_commit ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
// validate xid and rmid
if ((!xid) || (rmid < 0))
{
XATrace(XATM_TraceAPIError,("XARM: xa_commit failed with XAER_INVAL (invalid parameter)\n"));
return XAER_INVAL;
}
// validate flags
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_commit failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
// Return an error if the RM wasn't found
if (!lp_RM)
{
lv_xaError = XAER_RMFAIL;
XATrace(XATM_TraceAPIError,("XARM: xa_commit failed with XAER_RMFAIL\n"));
}
else
lv_xaError = lp_RM->commit(xid, flags);
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_commit EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_commit EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
} //xarm_commit
// ----------------------------------------------
// xarm_forget
// Purpose - send xa_forget message
// ----------------------------------------------
int xarm_forget (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xa_forget ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
// validate xid and rmid
if ((!xid) || (rmid < 0))
{
XATrace(XATM_TraceAPIError,("XARM: xa_forget failed with XAER_INVAL (invalid parameter)\n"));
return XAER_INVAL;
}
// validate flags
if (!xaRM_generic_library() && (flags & TMASYNC))
{
XATrace(XATM_TraceAPIError,("XARM: xa_forget failed with XAER_ASYNC\n"));
return XAER_ASYNC;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
// Return an error if the RM wasn't found
if (!lp_RM)
{
lv_xaError = XAER_RMFAIL;
XATrace(XATM_TraceAPIError,("XARM: xa_forget failed with XAER_RMFAIL\n"));
}
else
lv_xaError = lp_RM->forget(xid, flags);
if (lv_xaError <= XA_OK)
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_forget EXIT returning %s.\n", XAtoa(lv_xaError)));
}
else
{
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_forget EXIT TMASYNC returning handle %d.\n", lv_xaError));
}
return lv_xaError;
}
// ----------------------------------------------------------
// xarm_recover
// Purpose - send xa_recovery message
// This is currently a dummy routine, left in to fill the
// xa_switch structure out correctly.
// -----------------------------------------------------------
int xarm_recover (XID *xids, int64 count, int rmid, int64 flags)
{
//int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xarm_recover ENTRY UNEXPECTED! rmid=%d, flags=0x" PFLLX
", count=" PFLL ".\n", rmid, flags, count));
return XAER_INVAL;
} //xarm_recover
// ---------------------------------------------------------------
// xarm_recover_send
// Purpose - Send an xa_recover request to a specific RM.
// node defaults to -1, system recovery.
// Returns:
// XA_OK Successful
// XA_INVAL Invalid parameter
// XA_RMFAIL Couldn't find the RM in the RM object list.
// others Returned by CxaTM_RM::recover_send.
// -----------------------------------------------------------------
int xarm_recover_send(int pv_rmid, int64 pv_count, int64 pv_flags,
int pv_index, int pv_node, bool pv_dead_tm)
{
int lv_xaError = XA_OK;
XATrace(XATM_TraceXAAPI,("XARM: xarm_recover_send ENTRY rmid=%d, flags=0x" PFLLX
", count=" PFLL ", node=%d\n", pv_rmid, pv_flags, pv_count, pv_node));
// validate parameters
if ((pv_rmid < 0) || (pv_count <= 0) || (pv_node >= MAX_NODES))
{
XATrace(XATM_TraceAPIError,("XARM: xarm_recover_send failed with XAER_INVAL "
"(invalid parameter)\n"));
return XAER_INVAL;
}
// validate flags
if (!(pv_flags & TMSTARTRSCAN) && !(pv_flags & TMENDRSCAN) &&
(pv_flags != TMNOFLAGS) && (pv_flags != TMRESENDRSCAN) &&
(pv_flags != TMRMFAILRSCAN))
{
XATrace(XATM_TraceAPIError,("XARM: xarm_recover_send failed with XAER_INVAL "
"(invalid flag specified)\n"));
return XAER_INVAL;
}
CxaTM_RM *lp_RM = gv_xaTM.getRM(pv_rmid);
// Return an error if the RM wasn't found
if (!lp_RM)
return XAER_RMFAIL;
//Lock the RM to make sure only one xa_recover can be sent to an RM at a time.
//It will be unlocked in xarm_recover_waitReply.
lp_RM->lock();
lv_xaError = lp_RM->recoverSend(pv_count, pv_flags, pv_node, pv_dead_tm, pv_index);
XATrace(XATM_TraceAPIExitError,
("XARM: xarm_recover_send EXIT returning error %s.\n",
XAtoa(lv_xaError)));
return lv_xaError;
} //xarm_recover_send
// ---------------------------------------------------------------
// xarm_recover_waitReply
// Purpose - Wait for the next xa_recover reply to arrive.
// All parameters are retrieved from the xa_recover reply.
// pp_rmid Output
// Rmid for the RM sending this xa_recover reply. Initialized
// to -1 to avoid confusion over whether we set it.
// pp_xids Output
// Points to a buffer allocated by the caller.
// xarm_recover_waitReply copies the XIDs from the message
// into this buffer and then returns the message object to
// the pool.
// pp_count Input/Output.
// Contains the maximum number of XIDs allocated in pp_xids
// on input. On output it contains the actual number of
// XIDs returned in pp_xids.
// pp_end Output
// True indicates this is the last buffer to be returned.
// False indicates there are more XIDs to come and xa_recover
// must be re-sent.
//
// pp_index Output
// Index to be sent to the TSE on the next xa_recover (if
// applicable)
// pv_rm_wait_time input
// Time in 10 millisecond intervals that we will wait for a
// LDONE completion from the RM.
//
// pp_int_error output
// Seabed error
// -----------------------------------------------------------------
int xarm_recover_waitReply(int *pp_rmid, XID *pp_xids, int64 *pp_count,
bool *pp_end, int *pp_index, int pv_rm_wait_time,
int *pp_int_error)
{
char la_buf[DTM_STRING_BUF_SIZE];
static short lv_ret = BSRETYPE_NOWORK; //Persists across calls!
short lv_ret2;
int lv_xaError = XA_OK;
short la_results[6];
int64 lv_count = 0;
BMS_SRE_LDONE lv_sre;
short lv_event = 0;
int32 lv_type = -1;
bool lv_retryLink = false;
if (!pp_rmid || !pp_xids || !pp_count || *pp_count <= 0 || !pp_end || !pp_index || !pp_int_error)
{
XATrace(XATM_TraceAPIError,("XARM: xarm_recover_waitReply failed with XAER_INVAL "
"(invalid parameter or bad address)\n"));
return XAER_INVAL;
}
if(pp_rmid != NULL) {
*pp_rmid = -1; //Initialize
XATrace(XATM_TraceXAAPI,("XARM: xarm_recover_waitReply ENTRY rmid %d, count "
PFLL ", end %d, RM wait time %d.\n",
*pp_rmid, *pp_count, *pp_end, pv_rm_wait_time));
}
// Initialize return values
*pp_rmid=0;
*pp_end=false;
*pp_index=0;
*pp_int_error = FEOK;
do
{
lv_retryLink = false;
// Wait for the next LDONE completion
// We don't want to wait if we haven't processed all the LDONE
// completions since the last wait.
if (lv_ret != BSRETYPE_LDONE)
{
lv_event = XWAIT(LDONE, pv_rm_wait_time);
// Timeout break and exit.
if (lv_event == 0)
{
// EMS DTM_XATM_COMPLETEALL_FAILED
sprintf(la_buf, "Timed out after %d msec waiting for RM reply, "
"returning XAER_RMFAIL.\n", pv_rm_wait_time);
tm_log_event(DTM_XATM_XA_RECOVER_TIMEOUT, SQ_LOG_WARNING,
"DTM_XATM_XA_RECOVER_TIMEOUT", FETIMEDOUT,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,pv_rm_wait_time);
XATrace(XATM_TraceError,("XARM: xarm_recover_waitReply %s", la_buf));
*pp_count = 0;
lv_xaError = XAER_RMFAIL;
break;
}
}
lv_ret = BMSG_LISTEN_((short *)&lv_sre, BLISTEN_ALLOW_LDONEM, 0);
if (lv_ret == BSRETYPE_LDONE)
{
*pp_rmid = lv_sre.sre_linkTag;
CxaTM_RM *lp_RM = gv_xaTM.getRM(*pp_rmid);
// Check the RM is valid
if (!lp_RM)
{
// EMS DTM_XATM_RECOVER_FAILED_UNEXP_TAG
tm_log_event(DTM_XATM_RECOVER_FAILED_UNEXP_TAG, SQ_LOG_CRIT, "DTM_XATM_RECOVER_FAILED_UNEXP_TAG");
XATrace(XATM_TraceError,("XARM: xarm_recover_waitReply ERROR Listen "
"completed for unexpected tag (rmid), returning "
"XAER_RMFAIL.\n"));
abort(); //Critical fault - fast fail
}
// Find the associated message object
CxaTM_RMMessage *lp_msg = (CxaTM_RMMessage *) lp_RM->msgList()->get(lv_sre.sre_msgId);
if (lp_msg == NULL)
{
tm_log_event(DTM_XATMLIB_INVALID_RM_MSG, SQ_LOG_CRIT, "DTM_XATMLIB_INVALID_RM_MSG");
XATrace(XATM_TraceError, ("XARM: xarm_recover_waitReply ERROR. rmid=%d, "
"msgid=%d not found in RM outstanding message list.\n",
*pp_rmid, lv_sre.sre_msgId));
abort(); //Critical fault - fast fail
}
else
{
lv_ret2 = BMSG_BREAK_(lp_msg->msgid(), la_results, lp_RM->getRmPhandle());
*pp_int_error = lv_ret2;
XATrace(XATM_TraceSpecial, ("XARM: xarm_recover_waitReply BMSG_BREAK_ completed "
"with %d, msgid %d, rmid %d, sendAttempts %d\n",
lv_ret2, lp_msg->msgid(), lp_RM->getRmid(), lp_msg->sendAttempts()));
// If break returns an error we retry the link - resend the message to the RM.
lv_retryLink = lp_msg->checkError(lv_ret2, &lv_xaError, false /*no soft retry*/);
if (lv_retryLink == false)
{
lv_type = lp_msg->getRmReplyType();
// Check the reply
if (lv_xaError || lv_type != TM_DP2_SQ_XA_RECOVER_REPLY)
{
XATrace(XATM_TraceError,("XARM: xarm_recover_waitReply ERROR rmid=%d replied "
"to message type %d with XA error %s\n",
*pp_rmid, lv_type, XAtoa(lv_xaError)));
// Only report errors, not warnings
if (lv_xaError < XA_OK)
tm_log_event(DTM_XATM_RECOVER_FAILED_UNEXP_REPLY, SQ_LOG_WARNING,
"DTM_XATM_RECOVER_FAILED_UNEXP_REPLY",lv_xaError,*pp_rmid,-1,-1,
-1,lv_xaError,-1,-1,-1,-1,-1,-1,-1,lv_type);
}
else
{ /////////////////////////////////////////////////////
// deal with valid responses here //
/////////////////////////////////////////////////////
*pp_end = lp_msg->Rsp()->u.iv_recover.iv_end;
*pp_index = lp_msg->Rsp()->u.iv_recover.iv_recovery_index;
lv_count = (int64) lp_msg->Rsp()->u.iv_recover.iv_count;
// Check that the RM didn't return more XIDs than we allocated
// buffer space for.
if (lv_count <= *pp_count)
*pp_count = lv_count; // return count
else
{
tm_log_event(DTM_XATM_RECOVER_FAILED_PROG_ERROR, SQ_LOG_CRIT,
"DTM_XATM_RECOVER_FAILED_PROG_ERROR",-1,*pp_rmid);
XATrace(XATM_TraceError,("XARM: xarm_recover_waitReply PROGRAMMING ERROR: RM %d returned "
" too many XIDs!\n", *pp_rmid));
abort();
}
memcpy(pp_xids, (XID *) &(lp_msg->Rsp()->u.iv_recover.iv_xid), (lv_count*sizeof(XID)));
} ////////////////////////////////////////////////////
// End dealing with responses //
////////////////////////////////////////////////////
// Now we can clean up the message object
if (lp_RM)
{
gv_xaTM.release_RMmsg(lp_msg);
lp_RM->unlock();
}
} // Don't retry, so we have a reply or error to process
else
{
// delay, retry link, loop back and wait for another LDONE completion
if (lp_RM)
{
if (lp_msg)
{
// We reuse the RM message object, so only remove it from the RMs msgList.
lp_msg->release_from_RMmsgList();
lv_retryLink = lp_msg->retrySend();
// Initialize return values back since we don't have a reply to process and we will return XA_OK
XATrace(XATM_TraceError,("XARM: xarm_recover_waitReply Warning resetting return values since had to retry send.\n"));
*pp_count=0;
*pp_end=false;
*pp_index=0;
*pp_int_error = FEOK;
}
lp_RM->unlock();
}
lv_retryLink = false;
} //retry link
} // msg found
} // LDONE
else // not LDONE
{
XATrace(XATM_TraceSpecial,("XARM: xarm_recover_waitReply : Listen completed with "
"return code: %d, waiting for next LDONE.\n", lv_ret));
}
} while ((lv_ret != BSRETYPE_LDONE && lv_xaError == XA_OK) || lv_retryLink == true);
XATrace(XATM_TraceExit,("XARM: xarm_recover_waitReply EXIT rmid=%d, count=" PFLL
" end=%d, index=%d, returning error %s.\n", *pp_rmid, *pp_count, *pp_end,
*pp_index, XAtoa(lv_xaError)));
return lv_xaError;
} //xarm_recover_waitReply
// -----------------------------------------------------------
// xarm_complete
// Purpose - send xa_complete message
// ----------------------------------------------------------
int xarm_complete (int *handle, int *ret, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
// intel compiler warnings 869
ret = ret;
handle = handle;
XATrace(XATM_TraceExit,("XARM: xa_complete ENTRY rmid=%d, flags=0x" PFLLX "\n",
rmid, flags));
XATrace(XATM_TraceAPIError,("XARM: xa_complete currently not supported!\n"));
// TODO - implement routine
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_complete EXIT returning %s.\n", XAtoa(lv_xaError)));
return lv_xaError;
} //xarm_complete
// ---------------------------------------------------------------------
// xarm_complete_one
// Purpose - This function is called by xa_* APIs to perform a waited
// completion for the method when the library is acting as a standard
// XARM implementation. This is similar to complete_all, but we wait
// for one reply from the associated TM.
// Parameters:
// rmid is the identifier for the RM with an outstanding request.
// handle is the handle for completion of a no-waited operation.
// 0 indicates any completion for the RM will be returned.
// Returns the XA return code indicating the outcome of the xa_* request.
// If the rmid or handle don't match those passed to xarm_complete_one then
// an error is returned.
// ---------------------------------------------------------------------
int xarm_complete_one(int pv_rmid, int *pp_handle)
{
short la_results[6];
long lv_ret;
long lv_ret2;
BMS_SRE_LDONE lv_sre;
char la_buf[DTM_STRING_BUF_SIZE];
int lv_xaError = XA_OK;
bool lv_retryLink = false;
XATrace(XATM_TraceXAAPI,("XARM: xarm_complete_one ENTRY, rmid(%d), handle(%d).\n",
pv_rmid, *pp_handle));
CxaTM_RM *lp_RM = gv_xaTM.getRM(pv_rmid);
if (!lp_RM)
{
// EMS DTM_XATM_COMPLETEONE_FAILED
sprintf(la_buf, "rmid %d was not found.\n", pv_rmid);
tm_log_write(DTM_XATM_COMPLETEONE_FAILED, SQ_LOG_CRIT, la_buf);
XATrace(XATM_TraceError,("XARM: xarm_complete_one %s", la_buf));
abort();
}
// Check that there is at least one message outstanding.
if (lp_RM->msgList()->size() == 0)
{
// EMS DTM_XATM_COMPLETEONE_FAILED
sprintf(la_buf, "rmid %d has no outstanding messages.\n", pv_rmid);
tm_log_write(DTM_XATM_COMPLETEONE_FAILED, SQ_LOG_CRIT, la_buf);
XATrace(XATM_TraceError,("XARM: xarm_complete_one %s", la_buf));
abort();
}
// Wait forever for a completion
XWAIT(LDONE, -1);
// It's possible for us to have multiple outstanding requests
// to the same RM (XARM, so DTM TM process) complete.
do
{
lv_ret = BMSG_LISTEN_((short *) &lv_sre, BLISTEN_ALLOW_LDONEM, 0);
if (lv_ret == BSRETYPE_LDONE)
{
// The sre_linkTag contains the RMID.
int lv_rmid = (int) lv_sre.sre_linkTag; //intentional truncation on 64 bit patforms.
XATrace(XATM_TraceDetail, ("XARM: xarm_complete_one rmid=%d, msgid=%d\n",
lv_rmid, lv_sre.sre_msgId));
//TODO: need to wait for the reply associated with the
// specified pp_handle (msgid) to arrive, saving any other
// completions.
if ((lv_rmid != pv_rmid) ||
(*pp_handle != 0 && lv_sre.sre_msgId != *pp_handle))
{
// EMS DTM_XATM_COMPLETEONE_FAILED
sprintf(la_buf, "Listen completed for unknown tag. This "
"should match the rmid and handle passed in. Expected "
"rmid %d, handle %d, but Listen completed for rmid %d, "
"handle %d.\n",
pv_rmid, *pp_handle, lv_rmid, lv_sre.sre_msgId);
tm_log_write(DTM_XATM_COMPLETEONE_FAILED, SQ_LOG_CRIT, la_buf);
XATrace(XATM_TraceError,("XARM: xarm_complete_one: %s\n", la_buf));
abort();
}
// Look up message in RMs outstanding messages list
CxaTM_RMMessage *lp_msg = (CxaTM_RMMessage *) lp_RM->msgList()->get(lv_sre.sre_msgId);
if (lp_msg == NULL)
{
// EMS DTM_XATM_COMPLETEONE_FAILED
sprintf(la_buf, "ERROR. rmid=%d, msgid=%d not found in RM "
"outstanding message list.\n",
lv_rmid, lv_sre.sre_msgId);
tm_log_write(DTM_XATM_COMPLETEONE_FAILED, SQ_LOG_CRIT, la_buf);
XATrace(XATM_TraceError,("XARM: xarm_complete_one: %s\n", la_buf));
abort();
}
else
{
lv_xaError = XA_OK;
lp_RM->lock(); //Lock the RM to make sure no one else can change the msgList before we do.
lv_ret2 = BMSG_BREAK_(lp_msg->msgid(),
la_results,
lp_RM->getRmPhandle());
XATrace(XATM_TraceSpecial, ("XARM: xarm_complete_one BMSG_BREAK_ completed with %ld, msgid %d, rmid %d, sendAttempts %d\n",
lv_ret2, lp_msg->msgid(), lp_RM->getRmid(), lp_msg->sendAttempts()));
// If break returns an error we retry the link - resend the message to the
// RM.
lv_retryLink = lp_msg->checkError(lv_ret2, &lv_xaError);
if (lv_retryLink == false)
{
/////////////////////////////////////////////////////
// deal with response here //
/////////////////////////////////////////////////////
int32 lv_type = lp_msg->getRmReplyType();
if (lv_xaError != XA_OK)
{
XATrace(XATM_TraceError,("XARM: xarm_complete_one rmid=%d replied "
"to message type %d with XA error %s\n",
lv_rmid, lv_type,
XAtoa(lv_xaError)));
}
// release the message object
if (lp_RM != NULL)
{
gv_xaTM.release_RMmsg(lp_msg);
lp_RM->unlock();
}
} ////////////////////////////////////////////////////
// End dealing with response //
////////////////////////////////////////////////////
else
{
// delay, retry link, loop back and wait for another LDONE completion
if (lp_RM)
{
if (lp_msg)
{
// We reuse the RM message object, so only remove it from the RMs msgList.
lp_msg->release_from_RMmsgList();
lv_retryLink = lp_msg->retrySend();
}
lp_RM->unlock();
}
lv_retryLink = false;
}
} // else found message object, call BREAK
} //if LDONE
else
{
XATrace(XATM_TraceError, ("XARM: xarm_complete_one ERROR: Listen didn't "
"return LDONE! rmid=%d, Listen returned=%ld\n",
pv_rmid, lv_ret));
}
} while (lv_ret == BSRETYPE_LDONE);
XATrace(XATM_TraceXAAPI,("XARM: xarm_complete_one EXIT rmid %d, handle %d, returning %s.\n",
pv_rmid, *pp_handle, XAtoa(lv_xaError)));
return lv_xaError;
} // xarm_complete_one
// ---------------------------------------------------------------
// xarm_xa_open
// Purpose - Send xa_open message to a DTM TM process. This
// is a waited call to xa_open in the XARM Library.
// This routine checks the parameters, instantiates a CxaTM_RM
// object, and invokes its open method which causes the xa_open
// message to be sent to the RM.
// If TMASYNC was specified in the xa_open flags, then xa_open
// returns a handle which is passed back to the caller.
// Currently only one asynchronous operation is supported per
// RM.
//
// Return Codes:
// XA_OK Normal completion.
// XAER_ASYNC This RM already has an outstanding async
// operation.
// XAER_RMFAIL Error while opening RM.
// XAER_INVAL Invalid parameter.
// XAER_PROTO xa_open() called against an open RM.
// ---------------------------------------------------------------
int xarm_xa_open (char *info, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_open ENTRY info=%s, rmid=%d, flags=0x" PFLLX "\n",
info, rmid, flags));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_open(info, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
return lv_xaError;
} // xarm_xa_open
// -------------------------------------------------------
// xarm_xa_close
// Purpose - Send an xa_close message to the a DTM TM
// process to close an RM, them remove from the rm map
// ------------------------------------------------------
int xarm_xa_close (char *info, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_close ENTRY info=%s, rmid=%d, flags=0x" PFLLX "\n",
info, rmid, flags));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_close(info, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
// Delete the RM
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
if (!lp_RM)
{
lv_xaError = XAER_RMFAIL;
XATrace(XATM_TraceAPIError,("XARM: xa_close failed with XAER_RMFAIL\n"));
}
else
gv_xaTM.deleteRM(lp_RM);
return lv_xaError;
} // xarm_xa_close
// -----------------------------------------------------
// xarm_xa_start
// Purpose - send an xa_start message to a DTM TM
// process to start a transaction branch.
// -----------------------------------------------------
int xarm_xa_start (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_start ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_start(xid, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
return lv_xaError;
} // xarm_xa_start
// ------------------------------------------------------
// xarm_xa_end
// Purpose - send xa_end message to a DTM TM
// process to end association with a transaction branch.
// ------------------------------------------------------
int xarm_xa_end (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_end ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_end(xid, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
return lv_xaError;
} // xarm_xa_end
// -----------------------------------------------------
// xarm_xa_prepare
// Purpose - send xa_prepare message to a DTM TM
// process to prepare a transaction branch.
// ----------------------------------------------------
int xarm_xa_prepare (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_prepare ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_prepare(xid, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
return lv_xaError;
} // xarm_xa_prepare
// ---------------------------------------------------
// xarm_xa_rollback
// Purpose - send xa_rollback message to a DTM TM
// process to abort a transaction branch.
// ---------------------------------------------------
int xarm_xa_rollback (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_rollback ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_rollback(xid, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
return lv_xaError;
} // xarm_xa_rollback
// -----------------------------------------------
// xarm_xa_commit
// Purpose - send xa_commit message to a DTM TM
// process to commit a transaction branch.
// -----------------------------------------------
int xarm_xa_commit (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_commit ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_commit(xid, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
return lv_xaError;
} // xarm_xa_commit
// ----------------------------------------------
// xarm_xa_forget
// Purpose - send xa_forget message to a DTM TM
// process to forget a transaction branch.
// ----------------------------------------------
int xarm_xa_forget (XID *xid, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_handle = 0;
XATrace(XATM_TraceXAAPI,("XARM: xa_forget ENTRY rmid=%d, flags=0x" PFLLX ", xid=%s\n",
rmid, flags, XIDtoa(xid)));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_forget(xid, rmid, flags);
// Wait for reply.
if (lv_xaError == XA_OK)
lv_xaError = xarm_complete_one(rmid, &lv_handle);
return lv_xaError;
} // xarm_xa_forget
// ----------------------------------------------------------
// xarm_xa_recover
// Purpose - send xa_recovery message to a DTM TM process.
// Not changing the interface to add the index as
// that is a proprietary extension.
// -----------------------------------------------------------
int xarm_xa_recover (XID *xids, int64 count, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
int lv_rmid;
int64 lv_count = count;
bool lv_end = true;
int lv_index=0;
int lv_int_error = 0;
XATrace(XATM_TraceXAAPI,("XARM: xarm_xa_recover ENTRY UNEXPECTED! rmid=%d, flags=0x" PFLLX
", count=" PFLL ".\n", rmid, flags, count));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
lv_xaError = xarm_recover_send(rmid, count, flags, -1, 0, -1);
lv_xaError = xarm_recover_waitReply(&lv_rmid, xids, &lv_count, &lv_end, &lv_index, -1, &lv_int_error);
if (lv_xaError == XA_OK)
return lv_count;
else
return lv_xaError;
} // xarm_xa_recover
// -----------------------------------------------------------
// xarm_xa_complete
// Purpose - send xa_complete message to the DTM TM process
// to complete an outstanding request which was initiated
// using TMASYNC.
// All TSE RM messages are asynchronous, but the completion
// is handled differently to the XA standard, so xa_complete
// is implemented differently here.
// handle is actually the message id for the Seabed message.
// ----------------------------------------------------------
int xarm_xa_complete (int *handle, int *ret, int rmid, int64 flags)
{
int lv_xaError = XA_OK;
// intel compiler warnings 869
XATrace(XATM_TraceExit,("XARM: xa_complete ENTRY rmid=%d, flags=0x"
PFLLX ", handle=%d\n", rmid, flags, *handle));
lv_xaError = xaRM_initialize();
if (lv_xaError != XA_OK)
return lv_xaError;
CxaTM_RM *lp_RM = gv_xaTM.getRM(rmid);
if (!lp_RM)
{
XATrace(XATM_TraceError,("XARM: xa_complete rmid %d was not found.\n", rmid));
lv_xaError = XAER_INVAL;
}
else
{
if (flags & TMMULTIPLE)
*handle = 0;
lv_xaError = xarm_complete_one(rmid, handle);
if (lv_xaError >= 0)
{
*ret = lv_xaError;
lv_xaError = XA_OK;
}
}
XATrace((lv_xaError?XATM_TraceAPIExitError:XATM_TraceAPIExit),
("XARM: xa_complete EXIT returning %s, handle=%d, ret=%s, rmid=%d.\n",
XAtoa(lv_xaError), *handle,
XAtoa(*ret), rmid));
return lv_xaError;
} // xarm_xa_complete