2015-09-14 5 views
1

Я установил 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.Невозможно загрузить данные в Zookeeper программно

последних двух упомянутых функций выглядит следующим образом:

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 
} 

Однако, когда я пытаюсь использовать эти функции для того, чтобы загрузить некоторые данные зоопарка, я не получаю никакого результата - на самом деле, без ошибок, но при в то же время нет данных. Способ я использую эти функции это одна:

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 

EDIT

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

EDIT

Я invastigated это немного больше. Оказалось, что zookeeper_init (который вызывается внутри моей init функции) возвращает 0 как значение errno и к тому же он устанавливает zh (который является Zookeeper обработчик типа static zhandle_t *) до некоторого значения, так zh не null и так, по до documentation, init функция должна быть в порядке (даже если она не вызывает процедуру обратного вызова). Поэтому действительно странно, что у меня нет сообщений об ошибках в консоли, и я не получаю флаги ошибок со стандартными методами zookeeper, но все же обратные вызовы и загрузка данных не работают. Что не так с этим и как я могу его отладить?

EDIT

Это полный исходный код моего крошечного примера:

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

EDIT

Это действительно заставляет меня с ума.Я провел несколько дней, прочитав книгу по разъему C++ до Zookeeper и не получил никакого результата, и я только что взял первый разъем Python, потратив не более 1,5 минут и сделал это. Но это не то, что я хочу. Я хочу посмотреть, как я могу сделать эту тривиальную вещь в C++ - компилировать, подключать и создавать. Больше ничего.

EDIT

я составил свою программу с -DTHREADED вариант, но безрезультатно. Тем не менее, zoo_acreate ничего не создает. Он не создает сообщений об ошибках, он не создает предупреждений, он не возвращает флаги ошибок и не дает никакого результата. Действительно странная библиотека.

+0

zoo_acreate() имеет возвращаемое значение. Возможно, это не удалось, и код возврата подскажет вам, почему. – nos

+0

Спасибо! Я проверю этот код сейчас. – Jacobian

+0

Я проверил его. 'zoo_acreate' возвращает' 0' в моем примере. – Jacobian

ответ

1

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

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

2.And ваш инициализационный FUNC должен быть

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; 
} 
+0

Спасибо, Олег! Я проверю его в течение часа, и если он сработает, я буду рад поделиться с вами некоторой кармой. =) – Jacobian

+0

И можете ли вы поделиться тем, откуда взялись эти знания? Содержимое книги «ZooKeeper» устарело, и поэтому единственный способ выяснить, как сделать все на C++, - это глубоко погрузиться в исходный код библиотеки Zookeeper? – Jacobian

+0

@Jacobian Сначала проверьте мои исправления. –

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%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

Смежные вопросы