[PB表][C++ SDK]查询表记录总数
1. 接口说明
查询表记录总数(example路径:examples/tcaplus/C++_pb2_asyncmode_simpletable/SingleOperation/get_count)
2. 版本要求
无特殊要求,所有版本都提供了该接口。
3. 准备工作
参见准备工作文档,完成使用该接口前的准备工作,并创建如下PB Generic表,并使用PB工具转换为C++代码。
syntax = "proto2";
package myTcaplusTable;
import "tcaplusservice.optionv1.proto";
message tb_online {
option(tcaplusservice.tcaplus_primary_key) = "openid,tconndid,timekey";
required int32 openid = 1; //QQ Uin
required int32 tconndid = 2;
required string timekey = 3;
required string gamesvrid = 4;
optional int32 logintime = 5 [default = 1];
repeated int64 lockid = 6 [packed = true]; //repeated类型字段使用packed关键字修饰
optional pay_info pay = 7;
message pay_info {
optional uint64 total_money = 1;
optional uint64 pay_times = 2;
}
}
准备工作完成后,将会获得以下信息,这些信息在使用SDK时会被用到:
- 目录服务器地址列表
- 业务ID
- 业务访问密码
- 游戏区ID
- 数据表名
4. 示例代码
4.1 异步调用示例代码
示例代码的基本执行过程:
- 定义表配置参数;
- 创建客户端;
- 定义回调函数,处理响应;
- 发送请求;
- example框架;
第1,2,5步是所有示例的通用代码,重点关注第3步和第4步,发送请求和响应处理的回调函数
4.1.1 定义数据库表配置参数(代码路径:examples/tcaplus/C++_common_for_pb/common.h)
主要设置表的相关配置参数,在代码文件的头部
// 目标业务的tcapdir地址
static const char DIR_URL_ARRAY[][TCAPLUS_MAX_STRING_LENGTH] =
{
"tcp://10.191.***.99:9999"
};
// 目标业务的tcapdir 地址个数
static const int32_t DIR_URL_COUNT = 1;
// 目标业务的集群ID
static const int32_t APP_ID = 3;
// 目标业务的表格组ID
static const int32_t ZONE_ID = 1;
// 目标业务的业务密码
static const char * SIGNATURE = "*******";
// 目标业务的表名 tb_online
static const char * TABLE_NAME = "tb_online";
4.1.2 创建SDK客户端(代码路径:examples/tcaplus/C++_common_for_pb/common.h)
通过日志配置文件tlogconf.xml创建日志句柄,用于SDK的日志打印;通过该代码创建一个Tcaplus客户端,该客户端只允许单线程使用,多线程模型可以在每个线程上初始化一个客户端实例
//Tcaplus PB API客户端
TcaplusAsyncPbApi g_stAsyncApi;
int32_t InitAsyncPbApi()
{
//PB API配置
ClientOptions cfg;
cfg.app_id = APP_ID;
cfg.zones.push_back(ZONE_ID);
strcpy(cfg.signature, SIGNATURE);
for (int32_t i = 0; i < DIR_URL_COUNT; i++)
{
cfg.dirs.push_back(DIR_URL_ARRAY[i]);
}
//访问的PB表
cfg.tables.push_back(TABLE_NAME);
//日志配置
strncpy(cfg.log_cfg, "tlogconf.xml", sizeof(cfg.log_cfg));
//初始化连接超时时间5s
cfg.timeout = 5000;
//初始化连接
int32_t iRet = g_stAsyncApi.Init(cfg);
if (0 != iRet)
{
cout << "ERROR: g_stAsyncApi.Init failed, log cfg: " << cfg.log_cfg << ", iRet: " << iRet << "." << endl;
return iRet;
}
return iRet;
}
4.1.3 定义回调函数,处理响应(代码路径:examples/tcaplus/C++_pb2_asyncmode_simpletable/SingleOperation/get_count/main.cpp)
class CommonCallback : public TcaplusPbCallback
{
public:
CommonCallback()
{
cout << "Init CommonCallback." << endl;
}
~CommonCallback()
{
cout << "Fini ~CommonCallback." << endl;
}
int OnRecv(int64_t &count)
{
g_dwTotalRevNum++;
printf("count: %d\n",(int)count);
return 0;
}
int OnError(int64_t &count)
{
g_dwTotalRevNum++;
cout<<"error"<<endl;
return 0;
}
int OnTimeout(const std::vector< ::google::protobuf::Message *> &msgs)
{
cout<<"timeout"<<endl;
return 0;
}
int OnFinish(const NS_TCAPLUS_PROTOBUF_API::MsgParam ¶m)
{
cout << "OnFinish: " << param.m_nOperation << " req: " << param.m_vecMsgs.size() << endl;
return 0;
}
};
4.1.4 发送请求(代码路径:examples/tcaplus/C++_pb2_asyncmode_simpletable/SingleOperation/get_count/main.cpp)
使用客户端发送请求
void SendRequest(struct schedule * S, void* arg)
{
static CommonCallback cb;
int32_t iRet = g_stAsyncApi.GetCount("tb_online", &cb);
if (iRet != TcapErrCode::GEN_ERR_SUC)
{
cout << "ERROR, Error iRet = " << iRet << endl;
}
}
4.1.5 example异步框架(代码路径:examples/tcaplus/C++_common_for_pb/common.h)
通过实现回调函数的三个函数指针,proc主框架会调用相应的函数发送请求,接收响应和超时处理,该框架所有例子通用
int32_t main(int32_t argc, char* argv[])
{
int32_t iRet = 0;
//初始化
iRet = InitAsync("tlogconf.xml");
if (0 != iRet)
{
cout << "ERROR: Init failed, iRet: " << iRet << ", please check the tcaplus_pb.log for detail." << endl;
return iRet;
}
//设置回调函数
g_stPbCallbackFunctions.pfnSendRequest = SendRequest;
iRet = ProcAsync();
if (0 != iRet)
{
cout << "ERROR: ProcAsync failed, iRet: " << iRet << ", please check the tcaplus_pb.log for detail." << endl;
return iRet;
}
FinishAsync();
return 0;
}
// 初始化pb api
int32_t InitAsync(const char* log_conf)
{
int32_t iRet = 0;
iRet = InitAsyncPbApi(log_conf);
if (0 != iRet)
{
cout << "ERROR: InitCoroutinePbApi failed, iRet: " << iRet << "." << endl;
return iRet;
}
return iRet;
}
//************************************************************************
// Method: FinishAsync
// Returns:
// Qualifier: 函数退出时处理逻辑
//*************************************************************************/
void FinishAsync()
{
cout << "g_stAsyncApi finish!" << endl;
g_stAsyncApi.Fini();
google::protobuf::ShutdownProtobufLibrary();
}
//************************************
// Method: ProcAsync
// Returns: int32_t
// Qualifier: 处理函数
//************************************
int32_t ProcAsync()
{
int32_t iRet = 0;
// 本例子中使用变量iSendRequestCount是控制发包的数量
int32_t iSendRequestCount = 0;
do
{
if (iSendRequestCount < TOTAL_SEND_RECV_NUM)
{
if(NULL == g_stPbCallbackFunctions.pfnSendRequest)
{
cout << "ERROR: g_stPbCallbackFunctions.pfnSendRequest is NULL, so will finish example." << endl;
break;
}
int32_t iUin = iSendRequestCount;
g_stPbCallbackFunctions.pfnSendRequest(NULL, (void *)&iUin);
iSendRequestCount++;
}
// 更新,接收回包
g_stAsyncApi.UpdateNetwork();
usleep(TCAPLUS_SLEEEP_US);
} while (g_dwTotalRevNum != TOTAL_SEND_RECV_NUM);
cout << "end mytest, please check the mytest.log for detail." << endl;
return 0;
}
5. 常见问题
详见错误码含义和处理方法。