Package Splitting Problems of Response Package
Due to factors such as the size limit of the TCP network buffer, when the response packet exceeds 256KB, the tcaplus backend will trigger packet splitting.But ensure that subcontracting does not split a single record (regardless of its size). For example, if the three records of the response package are 10KB, 251KB, and 1MB, they will be returned in two packages, namely (10KB, 251KB) and (1MB).
1. Split Package Command Word
Generally, command words returned by multiple packets (reading multiple records at once, or writing multiple records at once while setting ResultFlag to return old records) may trigger subcontracting, so it is necessary to determine the subcontracting scenario
- BatchGet,batch query,Over 256KB must be splited
- BatchUpdate、BatchReplace、BatchDelete,Batch modification or deletion, when setting the flag to return old records, will return the batch of old records,Default not to split
- GetByPartKey,Return batch records through local index queries,Over 256KB must be splited
- UpdateByPartKey,DeleteByPartKey,Will return updated or deleted keys,Over 256KB must be splited
- ListGetAll,Query all records under the List Key in the List table,Default not to split
- ListGetBatch,List Table Query Batch Records under List Key,Default not to split
- ListReplaceBatch、ListDeletBatch、ListAddAfterBatchWhen modifying or deleting batch elements under ListKey and setting the flag to return old records, the batch of old records will be returned,Default not to split
- Global index query, when the table is configured with a global index, batch records can be returned through SQL queries,Over 256KB must be splited
Anyway, it's easy to remember:
- To split package, request displays the call pstRequest ->SetMultiResponseFlag (1);
- Do not split package, request displays the call pstRequest ->SetMultiResponseFlag (0)// BatchGet GetByPartKey UpdateByPartKey DeleteByPartKey global index query, inevitably subcontracting, invalid setting
2. Split Package processing
Special handling is required for command words returned by Splitting
- Request processing requires setting the Allow Split flag when sending a request. Some requests do not have a Split flag set by default, so users need to manually call Allow Splitting. Otherwise, packets exceeding 256k will be lost (excluding those that must be Splited)
TcaplusService::TcaplusServiceRequest* pstRequest = g_stTcapSvr.GetRequest(TABLE_NAME);
if (NULL == pstRequest)
{
tlog_error(g_pstLogHandler, 0, 0, "g_stTcapSvr.GetRequest(%s) failed.", TABLE_NAME);
return -1;
}
int32_t iRet = pstRequest->Init(TCAPLUS_API_BATCH_GET_REQ, NULL, 0, 0, 0, 0);
if(0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "pstRequest->Init(TCAPLUS_API_BATCH_GET_REQ) failed, iRet: %d.", iRet);
return iRet;
}
//Asynchronous ID can be set and the response will be brought back
uint64_t asyncId = 99;
pstRequest->SetAsyncID(asyncId);
//Request sets the Splitting flag after init, 1 allows Split , otherwise it is not allowed
pstRequest->SetMultiResponseFlag(1);
- Response processing. Due to the asynchronous mode of the C++API, users typically use asynchronous IDs to correspond responses and requests one by one. For response processing in splitting scenarios, it is necessary to determine whether the request for this ID has been completed through the tag in the response (HaveMoreResPkgs, whether there are any split packages)
uint64_t asyncId = pstTcapRspRcved->GetAsynID();
int32_t dwResult = pstTcapRspRcved->GetResult();
// Response failed
if( 0 != dwResult)
{
//The task with this asynchronous ID has failed, and you can directly handle the failure
//For example, deleting the asynchronous ID from the waiting queue
return;
}
//Successfully responded, read the record in the response
int32_t dwRecordCount = pstTcapRspRcved->GetRecordCount();//Obtain the number of records in the result
const TcaplusServiceRecord * pstTcapRecord = NULL;
int32_t dwCount = 0;
while(dwCount++ < dwRecordCount)
{
int32_t iRet = pstTcapRspRcved->FetchRecord(pstTcapRecord);
if(0 != iRet || NULL == pstTcapRecord)
{
printf( "FetchRecord failed, iRet: %d \n", iRet);
continue;
}
PLAYERONLINECNT stPLAYERONLINECNT;
memset(&stPLAYERONLINECNT, 0, sizeof(stPLAYERONLINECNT));
// Obtain record data based on TDR description
iRet = pstTcapRecord->GetData(&stPLAYERONLINECNT, sizeof(stPLAYERONLINECNT));
if(0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "GetData failed, iRet: %d .", iRet);
return -4;
}
//Business processing this record stPLAYERONLINECNT
}
//Subsequent package judgment
if (1 == pstTcapRspRcved->HaveMoreResPkgs())
{
//Note that this does not mean that the task for the asynchronous ID has been completed!!!
//Triggered subcontracting, there are subsequent packages, continue to receive packages, waiting for the next response
}
else
{
//There are no further packages available. The task for this asynchronous ID has been completed
//For example, the task with that ID can be completed from the waiting queue
}