#include "stdafx.h" #include "SpBase.h" #include "SpMisc.h" #include "SpModule.h" #include "SpEntity.h" #include "SpTransactionContext.h" #include "sp_ses.h" #include SpTransactionContext::SpTransactionContext(sp_ses_uas_t *uas, int info, int method_id, int method_sig, int timeout, iobuffer_t **p_pkt, int tsx_id) : m_pkt(NULL), m_tsx(NULL) { int rc; sp_tsx_uas_callback cb; cb.on_destroy = NULL; cb.user_data = this; rc = sp_tsx_uas_create(uas, tsx_id, &cb, &m_tsx); if (rc == 0) { m_info = info; m_method_id = method_id; m_method_sig = method_sig; m_timeout = timeout; m_expire_time = timeout < 0 ? -1 : ((int)GetTickCount() + timeout); if (p_pkt) { m_pkt = *p_pkt; *p_pkt = NULL; } } } SpTransactionContext::~SpTransactionContext() { if (m_pkt) iobuffer_dec_ref(m_pkt); if (m_tsx) { sp_tsx_uas_close(m_tsx); sp_tsx_uas_destroy(m_tsx); } } bool SpTransactionContext::IsOneWayCall() { return !!m_info; } DWORD SpTransactionContext::GetRequestID() { if (m_tsx) { return (DWORD)sp_tsx_uas_get_id(m_tsx); } else { return -1; } } ErrorCodeEnum SpTransactionContext::GetReceiveBuffer(DWORD &dwMessageID, DWORD &dwMessageSignature, CAutoBuffer &Buffer) { if (m_pkt) { dwMessageID = (DWORD)m_method_id; dwMessageSignature = (DWORD)m_method_sig; int size = iobuffer_get_length(m_pkt); Buffer.Init(size); if (size > 0) { memcpy(&Buffer[0], iobuffer_data(m_pkt, 0), size); } return Error_Succeed; } else { return Error_Unexpect; } } ErrorCodeEnum SpTransactionContext::SendAnswer(CAutoBuffer Buffer, bool bEnd) { if (m_info) { return Error_Bug; } else { iobuffer_t *ans_pkt = iobuffer_create(-1, -1); int rc; int v; v = (int)Error_Succeed; iobuffer_write(ans_pkt, IOBUF_T_I4, &v, 0); // sys error v = 0; iobuffer_write(ans_pkt, IOBUF_T_I4, &v, 0); // user error CSimpleString str = ""; v = Buffer.GetCount(); if (v > 0) iobuffer_write(ans_pkt, IOBUF_T_BUF, &Buffer[0], v); rc = sp_tsx_uas_answer(m_tsx, !!bEnd, &ans_pkt); if (ans_pkt) iobuffer_dec_ref(ans_pkt); return SpTranslateError(rc); } } ErrorCodeEnum SpTransactionContext::SendAnswer(ErrorCodeEnum eSysError, DWORD dwUserError, CSimpleString str) { if (m_info) { return Error_Bug; } else { iobuffer_t *ans_pkt = iobuffer_create(-1, -1); int rc; int v; v = (int)eSysError; iobuffer_write(ans_pkt, IOBUF_T_I4, &v, 0); // sys error iobuffer_write(ans_pkt, IOBUF_T_I4, &dwUserError, 0); // user error iobuffer_write(ans_pkt, IOBUF_T_STR, str.GetData(), str.GetLength()); rc = sp_tsx_uas_answer(m_tsx, 1, &ans_pkt); if (ans_pkt) iobuffer_dec_ref(ans_pkt); return SpTranslateError(rc); } } DWORD SpTransactionContext::GetExpireLeftTime() { if (m_tsx) { // because the machine will restart every day, so use int for time ticks storage is ok! if (m_expire_time == -1) { return m_expire_time; } else { int now = (int)GetTickCount(); return m_expire_time > now ? (m_expire_time - now) : 0; } } else { return -1; } } ErrorCodeEnum SpTransactionContext::GetLinkContext(linkContext& curLink) { if (m_pkt) { char bussinessId[LINKINFO_BUSSID_LEN + 1]; char traceId[LINKINFO_TRACEID_LEN + 1]; char spanId[LINKINFO_SPANID_LEN + 1]; char parentSpanId[LINKINFO_PARENTSPANID_LEN + 1]; ZeroMemory(bussinessId, sizeof(bussinessId)); ZeroMemory(traceId, sizeof(traceId)); ZeroMemory(spanId, sizeof(spanId)); ZeroMemory(parentSpanId, sizeof(parentSpanId)); iobuffer_get_linkInfo(m_pkt, bussinessId, traceId, spanId, parentSpanId); curLink.bussinessId = bussinessId; curLink.traceId = traceId; curLink.spanId = spanId; curLink.parentSpanId = parentSpanId; } return Error_Succeed; } ErrorCodeEnum SpTransactionContext::GetExpireTime(DWORD &dwWholeTime,DWORD &dwLeftTime) { if (m_tsx) { if (m_expire_time == -1) { dwWholeTime = dwLeftTime = 0xffffffff; } else { int now = (int)GetTickCount(); dwWholeTime = m_timeout; dwLeftTime = m_expire_time > now ? (m_expire_time - now) : 0; } return Error_Succeed; } else { return Error_Unexpect; } } ErrorCodeEnum SpTransactionContext::SetExpireTime( DWORD dwMS ) { return Error_NotImpl; } // // SpMUITransactionContext // ErrorCodeEnum SpMUITransactionContext::SendAnswer( ErrorCodeEnum eErrorCode, DWORD dwUserError, CSimpleString str) { if (m_op == OP_START) { m_pEntity->FinishStart(eErrorCode); } else if (m_op == OP_PAUSE) { m_pEntity->FinishPause(eErrorCode); } else if (m_op == OP_SELFTEST) { m_pEntity->FinishSelfTest(eErrorCode, dwUserError); } else if (m_op == OP_CONTINUE) { m_pEntity->FinishContinue(eErrorCode); } else if (m_op == OP_CLOSE) { m_pEntity->FinishClose(eErrorCode); } //TODO: always return Error_Unexpect ?? return Error_Unexpect; }