// the single threaded version of this call. will go away when we do direct // event delivery (soon) static VALUE method_zkrb_get_next_event_st(VALUE self) { volatile VALUE rval = Qnil; if (is_closed(self)) { zkrb_debug("we are closed, not gonna try to get an event"); return Qnil; } FETCH_DATA_PTR(self, zk); zkrb_event_t *event = zkrb_dequeue(zk->queue, 0); if (event != NULL) { rval = zkrb_event_to_ruby(event); zkrb_event_free(event); #if THREADED int fd = zk->queue->pipe_read; // we don't care in this case. this is just until i can remove the self // pipe from the queue char b[128]; while(read(fd, b, sizeof(b)) == sizeof(b)){} #endif } return rval; }
static VALUE method_set_watcher(VALUE self, VALUE new_watcher) { FETCH_DATA_PTR(self, zk); #warning [emaland] needs to be tested/implemented return Qnil; // watcher_fn old_watcher = zoo_set_watcher(zk->zh, new_watcher); // return old_watcher; }
static VALUE method_is_unrecoverable(VALUE self) { FETCH_DATA_PTR(self, zk); if(is_unrecoverable(zk->zh) == ZINVALIDSTATE) return Qtrue; return Qfalse; }
static VALUE method_has_events(VALUE self) { VALUE rb_event; FETCH_DATA_PTR(self, zk); rb_event = zkrb_peek(zk->queue) != NULL ? Qtrue : Qfalse; return rb_event; }
// wake up the event loop, used when shutting down static VALUE method_wake_event_loop_bang(VALUE self) { FETCH_DATA_PTR(self, zk); zkrb_signal(zk->queue); return Qnil; };
static VALUE method_close(VALUE self) { int rc; FETCH_DATA_PTR(self, zk); /* Note that after zookeeper_close() returns, ZK handle is invalid */ rc = destroy_zkrb_instance(zk); return INT2FIX(rc); }
// wake up the event loop, used when shutting down static VALUE method_wake_event_loop_bang(VALUE self) { FETCH_DATA_PTR(self, zk); zkrb_debug_inst(self, "Waking event loop: %p", zk->queue); zkrb_signal(zk->queue); return Qnil; };
static VALUE method_exists(VALUE self, VALUE path, VALUE watch) { struct Stat stat; Check_Type(path, T_STRING); FETCH_DATA_PTR(self, zk); check_errors(zoo_exists(zk->zh, RSTRING(path)->ptr, (watch != Qfalse && watch != Qnil), &stat)); return array_from_stat(&stat); }
static VALUE method_delete(VALUE self, VALUE path, VALUE version) { Check_Type(path, T_STRING); Check_Type(version, T_FIXNUM); FETCH_DATA_PTR(self, zk); check_errors(zoo_delete(zk->zh, RSTRING(path)->ptr, FIX2INT(version))); return Qtrue; }
// this method is *only* called asynchronously static VALUE method_sync(VALUE self, VALUE reqid, VALUE path) { int rc = ZOK; // don't use STANDARD_PREAMBLE here b/c we don't need to determine call_type assert_valid_params(reqid, path); FETCH_DATA_PTR(self, zk); rc = zkrb_call_zoo_async(zk->zh, RSTRING_PTR(path), zkrb_string_callback, CTX_ALLOC(zk, reqid)); return INT2FIX(rc); }
static VALUE method_add_auth(VALUE self, VALUE reqid, VALUE scheme, VALUE cert) { int rc = ZOK; Check_Type(scheme, T_STRING); Check_Type(cert, T_STRING); FETCH_DATA_PTR(self, zk); rc = zkrb_call_zoo_add_auth(zk->zh, RSTRING_PTR(scheme), RSTRING_PTR(cert), RSTRING_LEN(cert), zkrb_void_callback, CTX_ALLOC(zk, reqid)); return INT2FIX(rc); }
// returns a CZookeeper::ClientId object with the values set for session_id and passwd static VALUE method_client_id(VALUE self) { FETCH_DATA_PTR(self, zk); const clientid_t *cid = zoo_client_id(zk->zh); VALUE session_id = LL2NUM(cid->client_id); VALUE passwd = rb_str_new2(cid->passwd); VALUE client_id_obj = rb_class_new_instance(0, RARRAY_PTR(rb_ary_new()), ZookeeperClientId); rb_funcall(client_id_obj, rb_intern("session_id="), 1, session_id); rb_funcall(client_id_obj, rb_intern("passwd="), 1, passwd); return client_id_obj; }
static VALUE method_get_next_event(VALUE self, VALUE blocking) { // dbg.h check_debug(!is_closed(self), "we are closed, not trying to get event"); char buf[64]; FETCH_DATA_PTR(self, zk); for (;;) { check_debug(!is_closed(self), "we're closed in the middle of method_get_next_event, bailing"); zkrb_event_t *event = zkrb_dequeue(zk->queue, 1); /* Wait for an event using rb_thread_select() on the queue's pipe */ if (event == NULL) { if (NIL_P(blocking) || (blocking == Qfalse)) { goto error; } else { // if we're shutting down, don't enter this section, we don't want to block check_debug(!is_shutting_down(self), "method_get_next_event, we're shutting down, don't enter blocking section"); int fd = zk->queue->pipe_read; ssize_t bytes_read = 0; // wait for an fd to become readable, opposite of rb_thread_fd_writable rb_thread_wait_fd(fd); // clear all bytes here, we'll catch all the events on subsequent calls // (until we run out of events) bytes_read = read(fd, buf, sizeof(buf)); if (bytes_read == -1) { rb_raise(rb_eRuntimeError, "read failed: %d", errno); } zkrb_debug_inst(self, "read %zd bytes from the queue (%p)'s pipe", bytes_read, zk->queue); continue; } } VALUE hash = zkrb_event_to_ruby(event); zkrb_event_free(event); return hash; } error: return Qnil; }
static VALUE method_get_acl(VALUE self, VALUE path) { FETCH_DATA_PTR(self, zk); Check_Type(path, T_STRING); // ZOOAPI int zoo_get_acl(zhandle_t *zh, const char *path, struct ACL_vector *acl, // struct Stat *stat); struct ACL_vector acl; struct Stat stat; check_errors(zoo_get_acl(zk->zh, RSTRING(path)->ptr, &acl, &stat)); VALUE result = rb_ary_new(); rb_ary_push(result, acl_vector_to_ruby(&acl)); rb_ary_push(result, stat_to_ruby(&stat)); return result; }
static VALUE method_create(VALUE self, VALUE path, VALUE value, VALUE flags) { char realpath[10240]; Check_Type(path, T_STRING); Check_Type(value, T_STRING); Check_Type(flags, T_FIXNUM); FETCH_DATA_PTR(self, zk); check_errors(zoo_create(zk->zh, RSTRING(path)->ptr, RSTRING(value)->ptr, RSTRING(value)->len, &ZOO_OPEN_ACL_UNSAFE, FIX2INT(flags), realpath, sizeof(realpath))); return rb_str_new2(realpath); }
static VALUE method_get(VALUE self, VALUE path) { char data[1024]; int data_len = sizeof(data); struct Stat stat; memset(data, 0, sizeof(data)); Check_Type(path, T_STRING); FETCH_DATA_PTR(self, zk); check_errors(zoo_get(zk->zh, RSTRING(path)->ptr, 0, data, &data_len, &stat)); return rb_ary_new3(2, rb_str_new(data, data_len), array_from_stat(&stat)); }
static VALUE method_get_children(VALUE self, VALUE path) { struct String_vector strings; int i; VALUE output; Check_Type(path, T_STRING); FETCH_DATA_PTR(self, zk); check_errors(zoo_get_children(zk->zh, RSTRING(path)->ptr, 0, &strings)); output = rb_ary_new(); for (i = 0; i < strings.count; ++i) { rb_ary_push(output, rb_str_new2(strings.data[i])); } return output; }
static VALUE method_get_next_event(VALUE self, VALUE blocking) { char buf[64]; FETCH_DATA_PTR(self, zk); for (;;) { // we use the is_running(self) method here because it allows us to have a // ruby-land semaphore that we can also use in the java extension // if (is_closed(self) || !is_running(self)) { zkrb_debug_inst(self, "is_closed(self): %d, is_running(self): %d, method_get_next_event is exiting loop", is_closed(self), is_running(self)); return Qnil; // this case for shutdown } zkrb_event_t *event = zkrb_dequeue(zk->queue, 1); /* Wait for an event using rb_thread_select() on the queue's pipe */ if (event == NULL) { if (NIL_P(blocking) || (blocking == Qfalse)) { return Qnil; // no event for us } else { int fd = zk->queue->pipe_read; ssize_t bytes_read = 0; // wait for an fd to become readable, opposite of rb_thread_fd_writable rb_thread_wait_fd(fd); bytes_read = read(fd, buf, sizeof(buf)); if (bytes_read == -1) { rb_raise(rb_eRuntimeError, "read failed: %d", errno); } zkrb_debug_inst(self, "read %zd bytes from the queue (%p)'s pipe", bytes_read, zk->queue); continue; } } VALUE hash = zkrb_event_to_ruby(event); zkrb_event_free(event); return hash; } }
static VALUE method_close_handle(VALUE self) { FETCH_DATA_PTR(self, zk); if (ZKRBDebugging) { zkrb_debug_inst(self, "CLOSING_ZK_INSTANCE"); print_zkrb_instance_data(zk); } // this is a value on the ruby side we can check to see if destroy_zkrb_instance // has been called rb_iv_set(self, "@_closed", Qtrue); /* Note that after zookeeper_close() returns, ZK handle is invalid */ int rc = destroy_zkrb_instance(zk); zkrb_debug("destroy_zkrb_instance returned: %d", rc); return INT2FIX(rc); }
static VALUE method_get_next_event(VALUE self) { char buf[64]; zkrb_event_t *event ; int fd; fd_set rset; VALUE hash ; FETCH_DATA_PTR(self, zk); for (;;) { // we use the is_running(self) method here because it allows us to have a // ruby-land semaphore that we can also use in the java extension // if (!is_running(self)) { /* fprintf(stderr, "method_get_next_event: running is false, returning nil\n");*/ return Qnil; // this case for shutdown } event = zkrb_dequeue(zk->queue, 1); /* Wait for an event using rb_thread_select() on the queue's pipe */ if (event == NULL) { fd = zk->queue->pipe_read; FD_ZERO(&rset); FD_SET(fd, &rset); if (rb_thread_select(fd + 1, &rset, NULL, NULL, NULL) == -1) rb_raise(rb_eRuntimeError, "select failed: %d", errno); if (read(fd, buf, sizeof(buf)) == -1) rb_raise(rb_eRuntimeError, "read failed: %d", errno); continue; } hash = zkrb_event_to_ruby(event); zkrb_event_free(event); return hash; } }
static VALUE method_set(int argc, VALUE* argv, VALUE self) { VALUE v_path, v_data, v_version; int real_version = -1; FETCH_DATA_PTR(self, zk); rb_scan_args(argc, argv, "21", &v_path, &v_data, &v_version); Check_Type(v_path, T_STRING); Check_Type(v_data, T_STRING); Check_Type(v_version, T_FIXNUM); if(!NIL_P(v_version)) real_version = FIX2INT(v_version); check_errors(zoo_set(zk->zh, RSTRING(v_path)->ptr, RSTRING(v_data)->ptr, RSTRING(v_data)->len, FIX2INT(v_version))); return Qtrue; }
static VALUE method_recv_timeout(VALUE self) { FETCH_DATA_PTR(self, zk); return INT2NUM(zoo_recv_timeout(zk->zh)); }
static VALUE method_zkrb_state(VALUE self) { FETCH_DATA_PTR(self, zk); return INT2NUM(zoo_state(zk->zh)); }
static VALUE method_close(VALUE self) { FETCH_DATA_PTR(self, zk); check_errors(zookeeper_close(zk->zh)); return Qtrue; }
static VALUE method_client_id(VALUE self) { const clientid_t *id ; FETCH_DATA_PTR(self, zk); id = zoo_client_id(zk->zh); return UINT2NUM(id->client_id); }
static VALUE method_zkrb_iterate_event_loop(VALUE self) { FETCH_DATA_PTR(self, zk); fd_set rfds, wfds, efds; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); int fd=0, interest=0, events=0, rc=0, maxfd=0; struct timeval tv; zookeeper_interest(zk->zh, &fd, &interest, &tv); if (fd != -1) { if (interest & ZOOKEEPER_READ) { FD_SET(fd, &rfds); } else { FD_CLR(fd, &rfds); } if (interest & ZOOKEEPER_WRITE) { FD_SET(fd, &wfds); } else { FD_CLR(fd, &wfds); } } else { fd = 0; } // add our self-pipe to the read set, allow us to wake up in case our attention is needed int pipe_r_fd = get_self_pipe_read_fd(self); FD_SET(pipe_r_fd, &rfds); maxfd = (pipe_r_fd > fd) ? pipe_r_fd : fd; rc = rb_thread_select(maxfd+1, &rfds, &wfds, &efds, &tv); if (rc > 0) { if (FD_ISSET(fd, &rfds)) { events |= ZOOKEEPER_READ; } if (FD_ISSET(fd, &wfds)) { events |= ZOOKEEPER_WRITE; } // we got woken up by the self-pipe if (FD_ISSET(pipe_r_fd, &rfds)) { // one event has awoken us, so we clear one event from the pipe char b[1]; if (read(pipe_r_fd, b, 1) < 0) { rb_raise(rb_eRuntimeError, "read from pipe failed: %s", clean_errno()); } } rc = zookeeper_process(zk->zh, events); } else if (rc == 0) { zkrb_debug("timed out waiting for descriptor to be ready"); } else { log_err("select returned: %d", rc); } return INT2FIX(rc); }
static VALUE method_set_debug_level(VALUE self, VALUE level) { FETCH_DATA_PTR(self, zk); Check_Type(level, T_FIXNUM); zoo_set_debug_level(FIX2INT(level)); return Qnil; }