zookeeper-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Roman Kashitsyn <romankashi...@gmail.com>
Subject Watcher lifecycle in libzookeeper_mt
Date Wed, 08 Jul 2015 21:31:13 GMT
Hi all!

I'm trying to figure out how to manage zookeeper watchers lifetime in C
client. I am using libzookeeper version 3.4.6:

ZOO_INFO@log_env@712: Client environment:zookeeper.version=zookeeper C
client 3.4.6
ZOO_INFO@log_env@723: Client environment:os.name=Linux
ZOO_INFO@log_env@724: Client environment:os.arch=3.14.25-2

The problem is that zookeeper_close() doesn't trigger watchers. I free data
allocated for watchers on watcher invocation, but it doesn't work on
session termination.

Am I supposed to track pending watchers myself, remember the invoked
watchers and free data associated with non-triggered watches?

I tried to find an answer in zkpython, but it looks like it follows the
same pattern as me.

Consider the following scenario:

1. Connect to a zk server
2. Check if a node exists and add a watcher
3. Close session

The watcher added on step 2 is not going to be called if the node is left
untouched.

For example, the following test program (zktest.c) prints just

Session state changed: Connected
Exists invoked, RC = 0
Closing session
Exiting

Leaving no chance to free data (potentially) associated with exists
watcher. Is it a bug or a feature?

// beginning of zktest.c
// build with: make LDFLAGS='-pthread -lzookeeper_mt' zktest

#include <zookeeper/zookeeper.h>
#include <stdio.h>
#include <pthread.h>
#include <assert.h>

int completed;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;

const char *state_to_string(int type) {
  if (type == ZOO_EXPIRED_SESSION_STATE)
    return "Expired";
  if (type == ZOO_AUTH_FAILED_STATE)
    return "Auth";
  if (type == ZOO_CONNECTING_STATE)
    return "Connecting";
  if (type == ZOO_ASSOCIATING_STATE)
    return "Associating";
  if (type == ZOO_CONNECTED_STATE)
    return "Connected";
  return "Unknown";
}

void print_event(zhandle_t *zh, int type, int state, const char *path,
                 void *data) {
  if (type == ZOO_SESSION_EVENT) {
    printf("Session state changed: %s\n", state_to_string(state));
    if (state == ZOO_CONNECTED_STATE) {
      pthread_cond_broadcast(&condvar);
    }
  } else {
    printf("Other zk event: %d on %s\n", type, path);
  }
}

void exists_watcher(zhandle_t *zh, int type, int state, const char *path,
                    void *data) {
  printf("[Exists watcher] ");
  print_event(zh, type, state, path, data);
}

void on_exists(int rc, const struct Stat *stat, const void *data) {
  printf("Exists invoked, RC = %d\n", rc);
  pthread_mutex_lock(&mutex);
  completed = 1;
  pthread_cond_broadcast(&condvar);
  pthread_mutex_unlock(&mutex);
}

int main() {
  zhandle_t *handle =
      zookeeper_init("localhost:2181", print_event, 1000, 0, 0, 0);
  assert(handle != NULL);

  pthread_mutex_lock(&mutex);
  while (zoo_state(handle) != ZOO_CONNECTED_STATE) {
    pthread_cond_wait(&condvar, &mutex);
  }
  pthread_mutex_unlock(&mutex);

  int rc =
      zoo_awexists(handle, "/zookeeper", exists_watcher, NULL, on_exists,
0);
  assert(rc == ZOK);

  pthread_mutex_lock(&mutex);
  while (!completed) {
    pthread_cond_wait(&condvar, &mutex);
  }
  pthread_mutex_unlock(&mutex);

  printf("Closing session\n");
  rc = zookeeper_close(handle);
  assert(rc == ZOK);
  printf("Exiting\n");
  return 0;
}

// end of zktest.c

Thanks in advance,
Roman

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message