Невозможно загрузить данные в Zookeeper программно

Я установил Zookeeper на моем Ubuntu машина. Я запускаю его в режиме кластера с тремя 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;
}

Я думал, этот код должен создать /testworker «Папка» внутри Zookeeper, однако, это не так — ls / Команда не показывает изменений. Одна интересная вещь, на которую я должен обратить внимание, это то, что моя программа никогда не вызывает create_completion обратный вызов (я проверил это с cout). Поэтому, возможно, мне понадобятся некоторые специальные флаги и специальные строки компиляции для моей программы. Теперь я скомпилировал его так:

$ g++ -o test test.cpp -I /...path_to_include_folder/ -L /..path_to_lib_folder/ -lzookeeper_mt

РЕДАКТИРОВАТЬ

Я немного исследовал проблему и обнаружил, что функции обратного вызова вообще не вызываются. Например, init функция, которая запускает сеанс, не вызывает main_watcher Перезвоните. Это почему?

РЕДАКТИРОВАТЬ

Я проверил это немного больше. Оказалось, что zookeeper_init (который называется внутри моего init функция) возвращает 0 в качестве значения errno и помимо этого устанавливает zh (который является обработчиком zookeeper типа static zhandle_t *) до некоторой стоимости, так zh не является null и так, согласно документация, init функция должна быть в порядке (даже если она не вызывает процедуру обратного вызова). Так что действительно странно, что у меня нет сообщений об ошибках в консоли, и я не получаю флаги ошибок со стандартными методами 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

Решение

У вас есть две ошибки в коде.

1. В этой строке static int server_id; , Должно быть static clientid_t server_id;

2. И ваша функция инициализации должна быть

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(); должен быть закомментирован.

И другое. Смотрите новую версию главный. Я добавил бесконечный цикл.

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;
}
1

Другие решения

При создании ZNode вам необходимо указать основной ACL (Access Control List) — вот базовый пример создания 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%llx\n", _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

0

По вопросам рекламы [email protected]