// -------------------------------------------------------------- // CxaTM_RMMessage::send_rm // Purpose - send the message to the RM // Caller may lock. // -------------------------------------------------------------- int CxaTM_RMMessage::send_rm() { short lv_ret = -1; int lv_xaError = XA_OK; XATrace(XATM_TraceExit, ("XATM: CxaTM_RMMessage::send_rm ENTRY. msgid=%d, retries=%d/%d.\n", iv_msgid, sendAttempts(), RM()->maxSendRetries())); lock(); // Make sure that this CxaTM_RMMessage object doesn't already have a link outstanding if (msgid()) { tm_log_event(DTM_XATM_SENDTORM_FAILED, SQ_LOG_CRIT, "DTM_XATM_SENDTORM_FAILED", -1, RM()->getRmid(), -1, -1, msgid()); XATrace(XATM_TraceError, ("XATM: CxaTM_RMMessage::send_rm : XATM Message object " "already has a link outstanding, msgid %d\n", msgid())); abort(); } if (iv_reqLen > RM_MAX_DATA || iv_rspLen > RM_MAX_DATA) { // EMS DTM_XATM_SENDTORM_FAILED tm_log_event(DTM_XATM_SENDTORM_FAILED2, SQ_LOG_CRIT, "DTM_XATM_SENDTORM_FAILED2", -1,RM()->getRmid(),-1,-1,-1,XAER_RMFAIL,-1,-1,-1,-1,-1,-1,-1, RM_MAX_DATA,iv_reqLen,iv_rspLen); XATrace(XATM_TraceError, ("XATM: CxaTM_RMMessage::send_rm : " " Request or reply buffer too large, returning XAER_RMFAIL.\n")); lv_xaError = XAER_RMFAIL; } else { inc_sendAttempts(); lv_ret = link(); } if (lv_ret) { // EMS DTM_XATM_SENDTORM_FAILED tm_log_event(DTM_XATM_SENDTORM_FAILED, SQ_LOG_CRIT, "DTM_XATM_SENDTORM_FAILED", lv_ret, ip_RM->getRmid()); lv_xaError = XAER_RMFAIL; } unlock(); XATrace((lv_xaError?XATM_TraceExitError:XATM_TraceExit), ("XATM: CxaTM_RMMessage::send_rm EXIT returning %s, BMSG_LINK_ returned %d, msgid=%d, retries=%d/%d.\n", XAtoa(lv_xaError), lv_ret, iv_msgid, sendAttempts(), RM()->maxSendRetries())); return lv_xaError; } //CxaTM_RMMessage::send_rm
void message_filter::remove_filter(u16 const & msg_type, u32 const & msg_subtype) { msg_type_subtype_t msgid(msg_type, msg_subtype); filters_map_t::iterator tmp_iter = m_filters.find(msgid); R_ASSERT2(tmp_iter != m_filters.end(), "message filter not found"); m_filters.erase(tmp_iter); }
// -------------------------------------------------------------- // CxaTM_RMMessage::can_we_retrySend // Purpose - Determines whether we can retry the send to an RM. // Returns: // true - retry the send to an RM // false - do not retry the send. This could be because we got an // error on the send or we've exceeded the retries. // pp_xaError output: // XA_OK if the retry was successful, or // XAER_RMFAIL if retries exceeded. // XAER_* Any error returned by RM()->send_rm(). // -------------------------------------------------------------- bool CxaTM_RMMessage::can_we_retrySend(int *pp_xaError) { bool lv_success = false; XATrace(XATM_TraceExit, ("XATM: CxaTM_RMMessage::can_we_retrySend ENTRY RM %d, XA error=%d.\n", RM()->getRmid(), *pp_xaError)); lock(); if (sendAttempts() >= RM()->maxSendRetries()) { XATrace(XATM_TraceError,("XATM: CxaTM_RMMessage::can_we_retrySend rmid=%d, " "msgid=%d, sendAttempts=%d. Retries exceeded.\n", RM()->getRmid(), msgid(), sendAttempts())); *pp_xaError = XAER_RMFAIL; } else if (*pp_xaError == XA_RETRY) lv_success = true; unlock(); XATrace(XATM_TraceExit, ("XATM: CxaTM_RMMessage::can_we_retrySend EXIT RM %d, XA error=%d, returning %d.\n", RM()->getRmid(), *pp_xaError, lv_success)); return lv_success; } //CxaTM_RMMessage::can_we_retrySend
void message_filter::filter(u16 const & msg_type, u32 const & msg_subtype, msg_type_subtype_func_t const & found_func) { msg_type_subtype_t msgid(msg_type, msg_subtype); R_ASSERT2(m_filters.find(msgid) == m_filters.end(), "message filter already exist"); m_filters.insert(std::make_pair(msgid, found_func)); }
// -------------------------------------------------------------- // CxaTM_RM::checkError // Check the error returned by BMSG_BREAK_ and determine whether // to retry the LINK. // If break returns an error we retry the link - resend the // message to the RM. // We don't need to cancel/abandon the message. If Seabed // returned an error it already abandoned it. // pv_breakError - return code from BMSG_BREAK_. // pp_xaError will contain the XA error code on return. // pv_softRetry - true (default) Will retry true (retry link) if an // XA_RETRY occurs. This happens if a // FEPATHDOWN, FENOLCB, or an XA_RETRY occur. // false Will return retry = false if one of these // errors occurs. This allows the XA_RETRY to // be passed up to the next level for xa_recover. // pv_transid only used for event messages (error reporting). // return code // true = retry link. // false = Don't retry. Retries exceeded or error is not // retryable. // -------------------------------------------------------------- bool CxaTM_RMMessage::checkError(short pv_breakError, int *pp_xaError, bool pv_softRetry, int64 pv_transid) { bool lv_retryLink = false; *pp_xaError = XA_OK; char la_buf[DTM_STRING_BUF_SIZE]; CTmTxKey lv_txn = (CTmTxKey) pv_transid; XATrace(XATM_TraceExit, ("XATM: CxaTM_RMMessage::checkError ENTRY txn ID (%d,%d) msgid=%d, breakError=%d, " "rmid=%d, softRetry=%d.\n", lv_txn.node(), lv_txn.seqnum(), iv_msgid, pv_breakError, RM()->getRmid(), pv_softRetry)); lock(); // For XARM clients connecting to a DTM TM, we always retry the error. // DTM TMs don't run as process pairs, but we are attempting to send to // a specific node which might go down and switch to a spare. Also the // TSE might switch to it's backup. // If it's a retryable error (FEPATHDOWN (201) or FEOWNERSHIP (200)) or // FENOLCB (30) from a TSE then we'll retry. if ((tm_XARM_generic_library() && pv_breakError) || pv_breakError == FEPATHDOWN || pv_breakError == FEOWNERSHIP || pv_breakError == FENOLCB ) { // Retry sending the request to the RM. This is used to deal with failovers. if (ip_RM->inc_totalRetries()) { sprintf(la_buf, "Retrying send to RM. BMSG_BREAK_ failed for Txn ID (%d,%d) with " "error %d, rmid=%d, msgid=%d, retries=%d/%d\n", lv_txn.node(), lv_txn.seqnum(), pv_breakError, RM()->getRmid(), msgid(), sendAttempts(), RM()->maxSendRetries()); tm_log_event(DTM_TM_INFO_MSGBRK_FAIL3, SQ_LOG_WARNING, "DTM_TM_INFO_MSGBRK_FAIL3", pv_breakError, RM()->getRmid(),lv_txn.node(),lv_txn.seqnum(), msgid(),-1,-1,-1, sendAttempts(),-1,-1,-1,-1,-1,-1,-1,RM()->getRMnameDetail()); XATrace(XATM_TraceError,("XATM: CxaTM_RMMessage::checkError : %s", la_buf)); } if ((pv_breakError == FEPATHDOWN) || (pv_breakError == FENOLCB)) *pp_xaError = XA_RETRY; lv_retryLink = can_we_retrySend(pp_xaError); } else { if (pv_breakError == FEOK) { *pp_xaError = getRmError(); if (*pp_xaError != XA_OK) { XATrace(XATM_TraceDetail,("XATM: CxaTM_RMMessage::checkError : " "XA error %s encountered.\n", XAtoa(*pp_xaError))); // If the RM responds XA_RETRY, we retry as for a break error, but allow // this to retry forever. if (*pp_xaError == XA_RETRY) { lv_retryLink = can_we_retrySend(pp_xaError); clear_sendAttempts(); } } } else { sprintf(la_buf, "RM connection error. txn ID (%d,%d) BMSG_BREAK_ failed with " "error %d, rmid=%d, msgid=%d, retries=%d/%d\n", lv_txn.node(), lv_txn.seqnum(), pv_breakError, RM()->getRmid(), msgid(), sendAttempts(), RM()->maxSendRetries()); tm_log_event(DTM_TM_INFO_MSGBRK_FAIL4, SQ_LOG_WARNING, "DTM_TM_INFO_MSGBRK_FAIL4",pv_breakError, RM()->getRmid(), lv_txn.node(),lv_txn.seqnum(),msgid(),-1,-1,-1, sendAttempts(), -1,-1,-1,-1,-1,-1,-1,RM()->getRMnameDetail()); XATrace(XATM_TraceError,("XATM: CxaTM_RMMessage::checkError : %s", la_buf)); *pp_xaError = XAER_RMFAIL; } } unlock(); if (!pv_softRetry && *pp_xaError == XA_RETRY) lv_retryLink = false; XATrace(XATM_TraceExit, ("XATM: CxaTM_RMMessage::checkError EXIT txn ID (%d,%d) msgid=%d, returning " "retryLink=%d, xaError=%s.\n", lv_txn.node(), lv_txn.seqnum(), msgid(), lv_retryLink, XAtoa(*pp_xaError))); return lv_retryLink; } //CxaTM_RMMessage::checkError
// -------------------------------------------------------------- // CxaTM_RMMessage::release_from_RMmsgList // Purpose: Release this meesage from the RMs msgList. // -------------------------------------------------------------- void CxaTM_RMMessage::release_from_RMmsgList() { // Remove the message from the RMs message list but reuse it for the retry RM()->msgList()->remove(msgid()); msgid(0); } //CxaTM_RMMessage::release_from_RMmsgList
void client(int clinx, char *name, long id, int inx) { int ferr; int lerr; bool ok; int match; Util_AA<int> msgid(MAX_SENDS); Util_AA<char> recv_buffer(MAX_SENDS * BUFSIZ); Util_AA<short> recv_buffer3(MAX_SENDS * BUFSIZ); RT results; int send; Util_AA<char> send_buffer(MAX_SENDS * BUFSIZ); Util_AA<short> send_buffer2(MAX_SENDS * BUFSIZ); int send_len; MS_SRE_LDONE sre_ldone; for (send = 0; send < MAX_SENDS; send++) { sprintf(&send_buffer.ip_v[send * BUFSIZ], "hello, greetings from %s, name=%s, id=%ld, inx=%d, send=%d", my_name, name, id, inx, send); while (clinx >= 0) { strcat(&send_buffer.ip_v[send * BUFSIZ], "!"); clinx--; } send_len = (int) strlen(&send_buffer.ip_v[send * BUFSIZ]) + 1; ferr = XMSG_LINK_(TPT_REF(phandle), // phandle &msgid.ip_v[send], // msgid &send_buffer2.ip_v[send * BUFSIZ], // reqctrl (ushort) (inx & 1), // reqctrlsize &recv_buffer3.ip_v[send * BUFSIZ], // replyctrl 1, // replyctrlmax &send_buffer.ip_v[send * BUFSIZ], // reqdata (ushort) send_len, // reqdatasize &recv_buffer.ip_v[send * BUFSIZ], // replydata BUFSIZ, // replydatamax (SB_Tag_Type) // linkertag &send_buffer.ip_v[send * BUFSIZ], 0, // pri 0, // xmitclass XMSG_LINK_LDONEQ); // linkopts util_check("XMSG_LINK_", ferr); } for (send = 0; send < MAX_SENDS;) { lerr = XWAIT(LDONE, -1); TEST_CHK_WAITIGNORE(lerr); for (;;) { lerr = XMSG_LISTEN_((short *) &sre_ldone, // sre 0, // listenopts 0); // listenertag if (lerr == XSRETYPE_NOWORK) break; send++; assert(lerr == XSRETYPE_LDONE); ok = false; for (match = 0; match < MAX_SENDS; match++) { if (sre_ldone.sre_linkTag == (SB_Tag_Type) &send_buffer.ip_v[match * BUFSIZ]) { ok = true; break; } } assert(ok); ferr = XMSG_BREAK_(msgid.ip_v[match], results.u.s, TPT_REF(phandle)); util_check("XMSG_BREAK_", ferr); assert(results.u.t.ctrl_size == (uint) (inx & 1)); assert(results.u.t.data_size > (strlen(&send_buffer.ip_v[match * BUFSIZ]) + 14)); assert(results.u.t.errm == RT_DATA_RCVD); // data printf("%s\n", &recv_buffer.ip_v[match * BUFSIZ]); } } }