无法以编程方式上传数据到Zookeeper
Unable to upload data to Zookeeper programmatically
我已经在我的Ubuntu
机器上安装了Zookeeper
。我在集群模式下运行它,有三个z1
, z2
和z3
实例。当我用bin/zkCli.sh -server 127.0.0.1:2181,127.0.0.1:2182,...
连接到它并执行ls /
时,我看到一些列表,比如节点或数据(我不确定术语)。现在我想要的是用标准C++
client
以编程方式上传一些数据。为了实现这一点,我有一堆函数,包括init
,其中,我猜,开始一个会话,create
函数,它内部调用zoo_acreate
和一个空的(为了简单起见)回调函数create_complete
。
上面提到的最后两个函数是这样的:
void create(const char * path,
const char * value) {
zoo_acreate(zh,
path,
value,
0,
&ZOO_OPEN_ACL_UNSAFE,
0,
create_completion,
NULL);
}
void create_completion (int rc, const char *value, const void *data) {
// empty at this moment
}
然而,当我试图使用这些函数来上传一些数据到zookeeper时,我没有得到任何结果——实际上,没有错误,但同时没有数据。我使用这些函数的方式如下:
int main(){
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort); // as a result of invoking this function
// I see in the console some logs, including this message:
// Initiating client connection, host=127.0.0.1:2181,....
create("/testworker", "");
return 0;
}
我认为,这段代码应该在Zookeeper中创建一个/testworker
"文件夹",然而,它没有- ls /
命令显示没有更改。我应该指出的一件有趣的事情是,似乎我的程序从未调用create_completion
回调(我用cout
检查了它)。所以,我可能需要一些特殊的标志和一些特殊的编译字符串为我的程序。我现在编译它的方式是:
$ g++ -o test test.cpp -I /...path_to_include_folder/ -L /..path_to_lib_folder/ -lzookeeper_mt
编辑
我稍微调查了一下这个问题,发现回调函数根本没有被调用。例如,启动会话的init
函数不调用main_watcher
callback。为什么呢?
编辑
我又调查了一下。事实证明,zookeeper_init
(在我的init
函数中调用)返回0
作为errno
的值,此外它还将zh
(这是static zhandle_t *
类型的zookeeper处理程序)设置为某些值,因此zh
不是null
,因此,根据文档,init
函数应该是ok的(即使它不触发回调例程)。因此,很奇怪的是,我在控制台上没有错误消息,也没有得到标准zookeeper方法的错误标志,但回调和数据上传仍然不起作用。有什么问题,我怎么调试它?
编辑
这是我的一个小例子的完整源代码:
#include <iostream>
#include "proto.h"
#include "zookeeper.h"
#include "zookeeper_log.h"
#include "recordio.h"
#include "zookeeper.jute.h"
#include "zookeeper_version.h"
#include "errno.h"
using namespace std;
static char *hostPort;
static zhandle_t * zh;
static int connected = 0;
static int expired = 0;
static int server_id;
static struct String_vector * workers = NULL;
static struct String_vector * tasks = NULL;
void create(const char *, const char *);
void create_completion(int, const char *, const void *);
void main_watcher(zhandle_t *zkh,
int type,
int state,
const char *path,
void* context)
{
// cout << "HELLO FROM WATCHER " << endl; // Not printed when I remove comment. Why???
if(type == ZOO_SESSION_EVENT){
if(state == ZOO_CONNECTED_STATE){
connected = 1;
}
else if(state == ZOO_AUTH_FAILED_STATE){
connected = 0;
}
else if(state == ZOO_EXPIRED_SESSION_STATE){
expired = 1;
connected = 0;
zookeeper_close(zkh);
}
}
}
int init(char* hostPort){
srand(time(NULL));
server_id = rand();
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
zh = zookeeper_init(hostPort, main_watcher, 15000, 0, 0, 0);
return errno;
}
void create_completion(int rc, const char *value, const void * data){
// empty at this moment for simplicity
}
void create(const char * path, const char * value){
zoo_acreate(zh, path, value, 0, &ZOO_OPEN_ACL_UNSAFE, 0,
create_completion, NULL);
}
int main(){
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort);
create("/testworkers", ""); // Do not see this "folder" /testworkers in Zookeeper. Why???
return 0;
}
编辑
这真让我抓狂。我花了几天时间读了一本关于C++
连接器到Zookeeper
的书,没有结果,我刚刚拿了第一个Python
连接器,花了不超过1.5分钟就完成了。但那不是我想要的。我想看看我怎么能做这个琐碎的事情在C++
-编译,连接和创建。仅此而已。
编辑
我用-DTHREADED
选项编译了我的程序,但无济于事。尽管如此,zoo_acreate
并没有创建任何东西。它不产生错误消息,不产生警告,不返回错误标志,也不提供任何结果。真奇怪的图书馆。
代码中有两个错误。
1。在这个字符串中,static int server_id;
。必须为static clientid_t server_id;
2。init函数必须是
int init(char* hostPort)
{
//srand(time(NULL));
//server_id = rand();
zoo_set_debug_level(ZOO_LOG_LEVEL_INFO);
zh = zookeeper_init(hostPort, main_watcher, 15000, &server_id, 0, 0);
return errno;
}
请注意zookeeper_init
,函数srand(time(NULL));
和server_id = rand();
必须被注释掉。
还有别的。参见main的新版本。我添加了无限循环
int main()
{
hostPort = (char *)("127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183");
init(hostPort);
create("/testworkers", ""); // Do not see this "folder" /testworkers in Zookeeper. Why???
while(1)
{
sleep(1);
}
return 0;
}
在创建ZNode时,您需要声明基本的ACL(访问控制列表)—下面是创建ZNode的一个基本示例:
static zhandle_t *zh;
static clientid_t myid;
char buffer[512];
struct ACL CREATE_ONLY_ACL[] = {{ZOO_PERM_ALL, ZOO_ANYONE_ID_UNSAFE}};
struct ACL_vector CREATE_ONLY = {1, CREATE_ONLY_ACL};
zh = zookeeper_init("localhost:2181", watcher, 1000, 0, 0, 0);
int rc = zoo_create(zh,"/xyz","value", 5, &CREATE_ONLY, ZOO_EPHEMERAL, buffer, sizeof(buffer)-1);
if (rc) {
fprintf(stdout, "Error %d, %s for %s [%d] - could NOT create /xyz n", rc, zerror(rc), __FILE__, __LINE__);
}
else
cout << "Created /xyc znode" << endl;
// Watcher function -- basic handling
void watcher(zhandle_t *zzh, int type, int state, const char *path, void* context)
{
fprintf(stdout, "Watcher %s state = %s", type2String(type), state2String(state));
if (path && strlen(path) > 0) {
fprintf(stderr, " for path %s", path);
}
fprintf(stdout, "n");
if (type == ZOO_SESSION_EVENT) {
if (state == ZOO_CONNECTED_STATE) {
const clientid_t *id = zoo_client_id(zzh);
if (myid.client_id == 0 || myid.client_id != id->client_id) {
myid = *id;
fprintf(stdout, "Got a new session id: 0x%llxn", _LL_CAST_ myid.client_id);
}
} else if (state == ZOO_AUTH_FAILED_STATE) {
fprintf(stdout, "Authentication failure. Shutting down...n");
zookeeper_close(zzh);
zh=0;
} else if (state == ZOO_EXPIRED_SESSION_STATE) {
fprintf(stdout, "Session expired. Shutting down...n");
zookeeper_close(zzh);
zh=0;
}
}
}
这将创建一个znode -然而它将在客户端关闭时消失,因为它具有ZOO_EPHEMERAL访问权限,如果您希望它在客户端断开连接后存在,那么您需要更改为不同的ACL
- 防止主数据类型C++的隐式转换
- 用于访问容器<T>数据成员的正确 API
- 嵌套在类中时无法设置成员数据
- 使用流处理接收到的数据
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 在cuda线程之间共享大量常量数据
- C++将文本文件中的数据读取到结构数组中
- 如何在C++中序列化结构数据
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 通过套接字[TCP]传输数据 如何在C / C ++中打包多个整数并使用send() recv()传输数据
- 在c代码之间共享数据的最佳方式
- 链表,反向函数,数据结构
- 数据成员SFINAE的C++17测试:gcc vs clang
- C++浮点数据类型和字符串数据类型无法子到模板函数中
- 如何对点云数据进行排序
- 从矢量<无符号字符>转换为字符* 包括垃圾数据
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- 无法以编程方式上传数据到Zookeeper