【TcaplusDB知识库】读取数据示例(TDR表)

2022-04-11 00:00:00 业务 请求 初始化 目标 日志

前提
成功创建:集群,表格组,PLAYERONLINECNT表

PLAYERONLINECNT表描述文件table_test.xml如下:

<?xml version="1.0" encoding="GBK" standalone="yes" ?>
<metalib name="tcaplus_tb" tagsetversion="1" version="1">
<struct name="PLAYERONLINECNT" version="1" primarykey="TimeStamp,GameSvrID" splittablekey="TimeStamp">
<entry name="TimeStamp" type="uint32" desc="单位为分钟" />
<entry name="GameSvrID" type="string" size="64" />
<entry name="GameAppID" type="string" size="64" desc="gameapp id" />
<entry name="OnlineCntIOS" type="uint32" defaultvalue="0" desc="ios在线人数" />
<entry name="OnlineCntAndroid" type="uint32" defaultvalue="0" desc="android在线人数" />
<entry name="BinaryLen" type="smalluint" defaultvalue="1" desc="数据来源数据长度;长度为0时,忽略来源检查"/>
<entry name="binary" type="tinyint" desc="二进制" count= "1000" refer="BinaryLen" />
<entry name="binary2" type="tinyint" desc="二进制2" count= "1000" refer="BinaryLen" />
<entry name="strstr" type="string" size="64" desc="字符串"/>
<index name="index_id" column="TimeStamp"/>
</struct>
</metalib>

定义配置参数
// 目标业务的tcapdir地址
static const char DIR_URL_ARRAY[][TCAPLUS_MAX_STRING_LENGTH] =
{
"tcp://10.191.***.99:9999",
"tcp://10.191.***.88:9999"
};
// 目标业务的tcapdir 地址个数
static const int32_t DIR_URL_COUNT = 2;

// 目标业务的集群ID
static const int32_t APP_ID = 3;
// 目标业务的表格组ID
static const int32_t ZONE_ID = 1;
// 目标业务的业务密码
static const char * SIGNATURE = "*******";
// 目标业务的表名 PLAYERONLINECNT
static const char * TABLE_NAME = "PLAYERONLINECNT";

初始化TcaplusAPI日志句柄
日志配置文件:tlogconf.xml

//TCaplus service 日志类
TcaplusService::TLogger* g_pstTlogger;
LPTLOGCATEGORYINST g_pstLogHandler;
LPTLOGCTX g_pstLogCtx;
int32_t InitLog()
{
// 日志配置文件的路径
const char* sLogConfFile = "tlogconf.xml";
// 日志类名
const char* sCategoryName = "mytest";
//从配置文件初始化日志句柄
g_pstLogCtx = tlog_init_from_file(sLogConfFile);
if (NULL == g_pstLogCtx)
{
fprintf(stderr, "tlog_init_from_file failed.\n");
return -1;
}
// 获取日志类
g_pstLogHandler = tlog_get_category(g_pstLogCtx, sCategoryName);
if (NULL == g_pstLogHandler)
{
fprintf(stderr, "tlog_get_category(mytest) failed.\n");
return -2;
}
// 初始化日志句柄
g_pstTlogger = new TcaplusService::TLogger(g_pstLogHandler);
if (NULL == g_pstTlogger)
{
fprintf(stderr, "TcaplusService::TLogger failed.\n");
return -3;
}

return 0;
}

初始化TcaplusAPI客户端
//TCaplus service API的客户端主类
TcaplusService::TcaplusServer g_stTcapSvr;
//表的meta信息
extern unsigned char g_szMetalib_tcaplus_tb[];
LPTDRMETA g_szTableMeta = NULL;
int32_t InitServiceAPI()
{
// 初始化
int32_t iRet = g_stTcapSvr.Init(g_pstTlogger, /*module_id*/0, /*app id*/APP_ID, /*zone id*/ZONE_ID, /*signature*/SIGNATURE);
if (0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "g_stTcapSvr.Init failed, iRet: %d.", iRet);
return iRet;
}

// 添加目录服务器
for (int32_t i = 0; i< DIR_URL_COUNT; i++)
{
iRet = g_stTcapSvr.AddDirServerAddress(DIR_URL_ARRAY[i]);
if (0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "g_stTcapSvr.AddDirServerAddress(%s) failed, iRet: %d.", DIR_URL_ARRAY[i], iRet);
return iRet;
}
}

// 取得表的meta描述
g_szTableMeta = tdr_get_meta_by_name((LPTDRMETALIB)g_szMetalib_tcaplus_tb, TABLE_NAME);
if(NULL == g_szTableMeta)
{
tlog_error(g_pstLogHandler, 0, 0,"tdr_get_meta_by_name(%s) failed.", TABLE_NAME);
return -1;
}

// 注册数据表(连接dir服务器,认证,获取表路由),10s超时
iRet = g_stTcapSvr.RegistTable(TABLE_NAME, g_szTableMeta, /*timeout_ms*/10000);
if(0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "g_stTcapSvr.RegistTable(%s) failed, iRet: %d.", TABLE_NAME, iRet);
return iRet;
}

// 连接表对应的所有tcaplus proxy服务器
iRet = g_stTcapSvr.ConnectAll(/*timeout_ms*/10000, 0);
if(0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "g_stTcapSvr.ConnectAll failed, iRet: %d.", iRet);
return iRet;
}

return 0;
}

通过API发送Get请求
int32_t SendGetRequest()
{
// 请求对象类
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;
}

//初始化请求对象
int iRet = pstRequest->Init(TCAPLUS_API_GET_REQ, NULL, 0, 0, 0, 0);
if(0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "pstRequest->Init(TCAPLUS_API_GET_REQ) failed, iRet: %d.", iRet);
return iRet;
}

//为请求添加表记录
TcaplusService::TcaplusServiceRecord* pstRecord = pstRequest->AddRecord();
if (NULL == pstRecord)
{
tlog_error(g_pstLogHandler, 0, 0, "pstRequest->AddRecord() failed.");
return -1;
}

PLAYERONLINECNT stPLAYERONLINECNT;
memset(&stPLAYERONLINECNT, 0, sizeof(stPLAYERONLINECNT));

// 设置查询的key信息
stPLAYERONLINECNT.dwTimeStamp = 1;
snprintf(stPLAYERONLINECNT.szGameSvrID, sizeof(stPLAYERONLINECNT.szGameSvrID), "%s", "mysvrid");

// 设置基于TDR描述设置record数据
iRet = pstRecord->SetData(&stPLAYERONLINECNT, sizeof(stPLAYERONLINECNT));
if(0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "pstRecord->SetData() failed, iRet: %d.", iRet);
return iRet;
}

// 发送请求消息包
iRet= g_stTcapSvr.SendRequest(pstRequest);
if(0 != iRet)
{
tlog_error(g_pstLogHandler, 0, 0, "g_stTcapSvr.SendRequest failed, iRet: %d.", iRet);
return iRet;
}
return 0;
}

通过API接收响应
int RecvResp(TcaplusServiceResponse*& response)
{
//此处阻塞收包,每次阻塞1ms,收5000次
unsigned int sleep_us = 1000;
unsigned int sleep_count = 5000;
do
{
usleep(sleep_us);
response = NULL;
int ret = g_stTcapSvr.RecvResponse(response);
if (ret < 0)
{
tlog_error(g_pstLogHandler, 0, 0, "tcaplus_server.RecvResponse failed. ret:%d", ret);
return ret;
}

//收到一个响应包
if (1 == ret)
{
break;
}
} while ((--sleep_count) > 0);

//5s超时
if (0 == sleep_count)
{
tlog_error(g_pstLogHandler, 0, 0, "tcaplus_server.RecvResponse wait timeout.");
return -1;
}
return 0;
}

示例
main.cpp

int main(void) {
//初始化日志
int ret = InitLog();
if (ret != 0)
{
printf("init log failed\n");
return -1;
}

//初始化API客户端
ret = InitServiceAPI();
if ( ret != 0)
{
printf("init InitServiceAPI failed\n");
return -1;
}

//发送请求
ret = SendGetRequest();
if (0 != ret)
{
printf("SendGetRequest failed\n");
return -1;
}

//接收响应
TcaplusServiceResponse* response = NULL;
ret = RecvResp(response);
if (0 != ret)
{
printf("RecvResp failed\n");
return -1;
}

//获取操作的结果,0表示成功
int32_t result = response->GetResult();
if (0 != result)
{
printf("the result is %d\n", result);
return -1;
}

//获取响应中记录
//batch命令可能一个响应中有多条记录
int count = 0;
const TcaplusService::TcaplusServiceRecord* const_record = NULL;
while((count++) < response->GetRecordCount())
{
//读取记录
const_record = NULL;
printf("--- --- %3d --- ---\n", count - 1);
ret = response->FetchRecord(const_record);
if(0 != ret)
{
printf("FetchRecord() ret:%d\n", ret);
continue;
}

//将记录赋值给结构体
PLAYERONLINECNT stPLAYERONLINECNT;
memset(&stPLAYERONLINECNT, 0, sizeof(stPLAYERONLINECNT));
ret = const_record->GetData(&stPLAYERONLINECNT, sizeof(stPLAYERONLINECNT));
if(0 != ret)
{
printf("const_record->GetData() failed, ret: %d.", ret);
continue;
}

//打印结构体中的值
printf("struct dwTimeStamp %d szGameSvrID %s szGameAppID %s dwOnlineCntIOS %d dwOnlineCntAndroid %d \n",
stPLAYERONLINECNT.dwTimeStamp,
stPLAYERONLINECNT.szGameSvrID,
stPLAYERONLINECNT.szGameAppID,
stPLAYERONLINECNT.dwOnlineCntIOS,
stPLAYERONLINECNT.dwOnlineCntAndroid);
}
return 0;
}

TcaplusDB是腾讯出品的分布式NoSQL数据库,存储和调度的代码完全自研。具备缓存+落地融合架构、PB级存储、毫秒级时延、无损水平扩展和复杂数据结构等特性。同时具备丰富的生态、便捷的迁移、极低的运维成本和五个九高可用等特点。客户覆盖游戏、互联网、政务、金融、制造和物联网等领域。

相关文章