Я установил 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. В этой строке 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;
}
При создании 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