zookeeper 1.1.0-java → 1.1.1-java

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,17 @@
1
+ v1.1.1 Cleanup after code review (h/t @eric)
2
+
3
+ * While hunting down this bug: https://bugs.ruby-lang.org/issues/6438
4
+ Eric Lindvall made a number of helpful catches.
5
+
6
+ * Reduce syscall overhead by not using an unnecessary pipe in the event_lib.c
7
+ implementation
8
+
9
+ * More careful use of rb_raise, don't longjmp past necessary free() calls.
10
+
11
+ * More careful malloc in the get() implementation (we need to allocate 1MB
12
+ to hold the data in a znode, but only in the SYNC cases).
13
+
14
+
1
15
  v1.1.0 Rewrite C backend to use zookeeper_st, the async library
2
16
 
3
17
  * In order to ensure fork safety, a rewrite of the backend was necessary.
data/ext/event_lib.c CHANGED
@@ -21,7 +21,6 @@ slyphon@gmail.com
21
21
  */
22
22
 
23
23
  #include "ruby.h"
24
- #include "event_lib.h"
25
24
  #include "c-client-src/zookeeper.h"
26
25
  #include <errno.h>
27
26
  #include <stdio.h>
@@ -30,82 +29,59 @@ slyphon@gmail.com
30
29
  #include <unistd.h>
31
30
  #include <inttypes.h>
32
31
  #include "common.h"
32
+ #include "event_lib.h"
33
33
  #include "dbg.h"
34
34
 
35
+ #ifndef THREADED
36
+ #define USE_XMALLOC
37
+ #endif
38
+
35
39
  #define GET_SYM(str) ID2SYM(rb_intern(str))
36
40
 
37
41
  int ZKRBDebugging;
38
42
 
39
- #ifdef THREADED
40
-
43
+ #if THREADED
41
44
  pthread_mutex_t zkrb_q_mutex = PTHREAD_MUTEX_INITIALIZER;
45
+ #endif
42
46
 
43
47
  inline static int global_mutex_lock() {
44
- int rv = pthread_mutex_lock(&zkrb_q_mutex);
48
+ int rv=0;
49
+ #if THREADED
50
+ rv = pthread_mutex_lock(&zkrb_q_mutex);
45
51
  if (rv != 0) log_err("global_mutex_lock error");
52
+ #endif
46
53
  return rv;
47
54
  }
48
55
 
49
56
  inline static int global_mutex_unlock() {
50
- int rv = pthread_mutex_unlock(&zkrb_q_mutex);
57
+ int rv=0;
58
+ #if THREADED
59
+ rv = pthread_mutex_unlock(&zkrb_q_mutex);
51
60
  if (rv != 0) log_err("global_mutex_unlock error");
61
+ #endif
52
62
  return rv;
53
63
  }
54
64
 
55
- void atfork_prepare() {
56
- global_mutex_lock();
57
- }
58
-
59
- void atfork_parent() {
60
- global_mutex_unlock();
61
- }
62
-
63
- void atfork_child() {
64
- global_mutex_unlock();
65
- }
66
-
67
- // set up handlers to make sure the thread being forked holds the lock at the
68
- // time the process is copied, then immediately unlock the mutex in both parent
69
- // and children
70
- /*pthread_atfork(atfork_prepare, atfork_parent, atfork_child);*/
71
-
72
- // delegates to the system malloc (we can't use xmalloc in the threaded case,
73
- // as we can't touch the interpreter)
74
-
75
- inline static void* zk_malloc(size_t size) {
76
- return malloc(size);
77
- }
78
-
79
- inline static void zk_free(void *ptr) {
80
- free(ptr);
81
- }
82
-
83
- #else
84
-
85
- inline static int global_mutex_lock() {
86
- return 0;
87
- }
88
-
89
- inline static int global_mutex_unlock() {
90
- return 0;
91
- }
92
-
93
65
  // we can use the ruby xmalloc/xfree that will raise errors
94
66
  // in the case of a failure to allocate memory, and can cycle
95
67
  // the garbage collector in some cases.
96
68
 
97
69
  inline static void* zk_malloc(size_t size) {
70
+ #ifdef USE_XMALLOC
98
71
  return xmalloc(size);
72
+ #else
73
+ return malloc(size);
74
+ #endif
99
75
  }
100
76
 
101
77
  inline static void zk_free(void *ptr) {
78
+ #ifdef USE_XMALLOC
102
79
  xfree(ptr);
80
+ #else
81
+ free(ptr);
82
+ #endif
103
83
  }
104
84
 
105
-
106
- #endif /* THREADED */
107
-
108
-
109
85
  void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
110
86
  if (q == NULL) {
111
87
  zkrb_debug("zkrb_enqueue, queue ptr was NULL");
@@ -125,13 +101,15 @@ void zkrb_enqueue(zkrb_queue_t *q, zkrb_event_t *elt) {
125
101
  q->tail->event = NULL;
126
102
  q->tail->next = NULL;
127
103
 
128
- ssize_t ret = write(q->pipe_write, "0", 1); /* Wake up Ruby listener */
129
-
130
104
  global_mutex_unlock();
131
105
 
132
- if (ret < 0) {
106
+ #if THREADED
107
+ ssize_t ret = write(q->pipe_write, "0", 1); /* Wake up Ruby listener */
108
+
109
+ if (ret < 0)
133
110
  log_err("write to queue (%p) pipe failed!\n", q);
134
- }
111
+ #endif
112
+
135
113
  }
136
114
 
137
115
  // NOTE: the zkrb_event_t* returned *is* the same pointer that's part of the
@@ -182,8 +160,10 @@ void zkrb_signal(zkrb_queue_t *q) {
182
160
 
183
161
  global_mutex_lock();
184
162
 
163
+ #if THREADED
185
164
  if (!write(q->pipe_write, "0", 1)) /* Wake up Ruby listener */
186
165
  log_err("zkrb_signal: write to pipe failed, could not wake");
166
+ #endif
187
167
 
188
168
  global_mutex_unlock();
189
169
  }
@@ -200,10 +180,12 @@ zkrb_event_ll_t *zkrb_event_ll_t_alloc(void) {
200
180
  }
201
181
 
202
182
  zkrb_queue_t *zkrb_queue_alloc(void) {
203
- int pfd[2];
204
183
  zkrb_queue_t *rq = NULL;
205
184
 
185
+ #if THREADED
186
+ int pfd[2];
206
187
  check(pipe(pfd) == 0, "creating the signal pipe failed");
188
+ #endif
207
189
 
208
190
  rq = zk_malloc(sizeof(zkrb_queue_t));
209
191
  check_mem(rq);
@@ -214,8 +196,11 @@ zkrb_queue_t *zkrb_queue_alloc(void) {
214
196
  check_mem(rq->head);
215
197
 
216
198
  rq->tail = rq->head;
199
+
200
+ #if THREADED
217
201
  rq->pipe_read = pfd[0];
218
202
  rq->pipe_write = pfd[1];
203
+ #endif
219
204
 
220
205
  return rq;
221
206
 
@@ -233,8 +218,11 @@ void zkrb_queue_free(zkrb_queue_t *queue) {
233
218
  }
234
219
 
235
220
  zk_free(queue->head);
221
+
222
+ #if THREADED
236
223
  close(queue->pipe_read);
237
224
  close(queue->pipe_write);
225
+ #endif
238
226
 
239
227
  zk_free(queue);
240
228
  }
@@ -268,21 +256,26 @@ void zkrb_event_free(zkrb_event_t *event) {
268
256
  case ZKRB_STRINGS: {
269
257
  struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
270
258
  int k;
271
- if (strings_ctx->values)
272
- for (k = 0; k < strings_ctx->values->count; ++k) zk_free(strings_ctx->values->data[k]);
273
- zk_free(strings_ctx->values);
259
+ if (strings_ctx->values) {
260
+ for (k = 0; k < strings_ctx->values->count; ++k) {
261
+ zk_free(strings_ctx->values->data[k]);
262
+ }
263
+ zk_free(strings_ctx->values);
264
+ }
274
265
  zk_free(strings_ctx);
275
266
  break;
276
267
  }
277
268
  case ZKRB_STRINGS_STAT: {
278
269
  struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
279
270
  int k;
280
- if (strings_stat_ctx->values)
281
- for (k = 0; k < strings_stat_ctx->values->count; ++k) zk_free(strings_stat_ctx->values->data[k]);
282
- zk_free(strings_stat_ctx->values);
271
+ if (strings_stat_ctx->values) {
272
+ for (k = 0; k < strings_stat_ctx->values->count; ++k) {
273
+ zk_free(strings_stat_ctx->values->data[k]);
274
+ }
275
+ zk_free(strings_stat_ctx->values);
276
+ }
283
277
 
284
- if (strings_stat_ctx->stat)
285
- zk_free(strings_stat_ctx->stat);
278
+ if (strings_stat_ctx->stat) zk_free(strings_stat_ctx->stat);
286
279
  zk_free(strings_stat_ctx);
287
280
  break;
288
281
  }
data/ext/zkrb.c CHANGED
@@ -107,16 +107,22 @@ typedef enum {
107
107
  } zkrb_call_type;
108
108
 
109
109
  inline static const char* call_type_to_str(zkrb_call_type ct) {
110
+ const char *rv = NULL;
110
111
  switch (ct) {
111
112
  case SYNC:
112
- return "SYNC";
113
+ rv="SYNC";
114
+ break;
113
115
  case ASYNC:
114
- return "ASYNC";
116
+ rv="ASYNC";
117
+ break;
115
118
  case SYNC_WATCH:
116
- return "SYNC_WATCH";
119
+ rv="SYNC_WATCH";
120
+ break;
117
121
  case ASYNC_WATCH:
118
- return "ASYNC_WATCH";
122
+ rv="ASYNC_WATCH";
123
+ break;
119
124
  }
125
+ return rv;
120
126
  }
121
127
 
122
128
  inline static void assert_valid_params(VALUE reqid, VALUE path) {
@@ -167,6 +173,17 @@ static void hexbufify(char *dest, const char *src, int len) {
167
173
  }
168
174
  }
169
175
 
176
+ inline static int we_are_forked(zkrb_instance_data_t *zk) {
177
+ int rv=0;
178
+
179
+ if ((!!zk) && (zk->orig_pid != getpid())) {
180
+ rv=1;
181
+ }
182
+
183
+ return rv;
184
+ }
185
+
186
+
170
187
  static int destroy_zkrb_instance(zkrb_instance_data_t* zk) {
171
188
  int rv = ZOK;
172
189
 
@@ -177,23 +194,23 @@ static int destroy_zkrb_instance(zkrb_instance_data_t* zk) {
177
194
  /* Note that after zookeeper_close() returns, ZK handle is invalid */
178
195
  zkrb_debug("obj_id: %lx, calling zookeeper_close", zk->object_id);
179
196
 
180
- if (zk->orig_pid != getpid()) {
197
+ if (we_are_forked(zk)) {
181
198
  zkrb_debug("FORK DETECTED! orig_pid: %d, current pid: %d, "
182
199
  "using socket-closing hack before zookeeper_close", zk->orig_pid, getpid());
183
200
 
184
201
  int fd = ((int *)zk->zh)[0]; // nasty, brutish, and wonderfully effective hack (see above)
185
202
  close(fd);
203
+
186
204
  }
187
205
 
188
206
  rv = zookeeper_close(zk->zh);
189
207
 
190
- zkrb_debug("obj_id: %lx, zookeeper_close returned %d", zk->object_id, rv);
208
+ zkrb_debug("obj_id: %lx, zookeeper_close returned %d, calling context: %p", zk->object_id, rv, ctx);
191
209
  zkrb_calling_context_free((zkrb_calling_context *) ctx);
192
210
  }
193
211
 
194
212
  zk->zh = NULL;
195
213
 
196
- // [wickman] TODO: fire off warning if queue is not empty
197
214
  if (zk->queue) {
198
215
  zkrb_debug("obj_id: %lx, freeing queue pointer: %p", zk->object_id, zk->queue);
199
216
  zkrb_queue_free(zk->queue);
@@ -222,7 +239,7 @@ static void print_zkrb_instance_data(zkrb_instance_data_t* ptr) {
222
239
 
223
240
  inline static void zkrb_debug_clientid_t(const clientid_t *cid) {
224
241
  int pass_len = sizeof(cid->passwd);
225
- int hex_len = 2 * pass_len;
242
+ int hex_len = 2 * pass_len + 1;
226
243
  char buf[hex_len];
227
244
  hexbufify(buf, cid->passwd, pass_len);
228
245
 
@@ -230,8 +247,8 @@ inline static void zkrb_debug_clientid_t(const clientid_t *cid) {
230
247
  }
231
248
 
232
249
  static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
233
- VALUE hostPort;
234
- VALUE options;
250
+ VALUE hostPort=Qnil;
251
+ VALUE options=Qnil;
235
252
 
236
253
  rb_scan_args(argc, argv, "11", &hostPort, &options);
237
254
 
@@ -249,7 +266,7 @@ static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
249
266
  zoo_set_debug_level(0); // no log messages
250
267
  } else {
251
268
  Check_Type(log_level, T_FIXNUM);
252
- zoo_set_debug_level((int)log_level);
269
+ zoo_set_debug_level(FIX2INT(log_level));
253
270
  }
254
271
 
255
272
  VALUE data;
@@ -270,12 +287,12 @@ static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
270
287
 
271
288
  zk_local_ctx->zh =
272
289
  zookeeper_init(
273
- RSTRING_PTR(hostPort),
274
- zkrb_state_callback,
275
- session_timeout_msec(self),
276
- &zk_local_ctx->myid,
277
- ctx,
278
- 0);
290
+ RSTRING_PTR(hostPort), // const char *host
291
+ zkrb_state_callback, // watcher_fn
292
+ session_timeout_msec(self), // recv_timeout
293
+ &zk_local_ctx->myid, // cilentid_t
294
+ ctx, // void *context
295
+ 0); // flags
279
296
 
280
297
  zkrb_debug("method_zkrb_init, zk_local_ctx: %p, zh: %p, queue: %p, calling_ctx: %p",
281
298
  zk_local_ctx, zk_local_ctx->zh, zk_local_ctx->queue, ctx);
@@ -399,12 +416,14 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
399
416
  if (data != Qnil) Check_Type(data, T_STRING);
400
417
  Check_Type(flags, T_FIXNUM);
401
418
  const char *data_ptr = (data == Qnil) ? NULL : RSTRING_PTR(data);
402
- size_t data_len = (data == Qnil) ? -1 : RSTRING_LEN(data);
419
+ ssize_t data_len = (data == Qnil) ? -1 : RSTRING_LEN(data);
403
420
 
404
421
  struct ACL_vector *aclptr = NULL;
405
422
  if (acls != Qnil) { aclptr = zkrb_ruby_to_aclvector(acls); }
406
423
  char realpath[16384];
407
424
 
425
+ int invalid_call_type=0;
426
+
408
427
  int rc;
409
428
  switch (call_type) {
410
429
 
@@ -420,7 +439,7 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
420
439
  break;
421
440
 
422
441
  default:
423
- raise_invalid_call_type_err(call_type);
442
+ invalid_call_type=1;
424
443
  break;
425
444
  }
426
445
 
@@ -429,6 +448,8 @@ static VALUE method_create(VALUE self, VALUE reqid, VALUE path, VALUE data, VALU
429
448
  free(aclptr);
430
449
  }
431
450
 
451
+ if (invalid_call_type) raise_invalid_call_type_err(call_type);
452
+
432
453
  output = rb_ary_new();
433
454
  rb_ary_push(output, INT2FIX(rc));
434
455
  if (IS_SYNC(call_type) && rc == ZOK) {
@@ -472,9 +493,13 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
472
493
  int data_len = MAX_ZNODE_SIZE;
473
494
  struct Stat stat;
474
495
 
475
- char * data = xmalloc(MAX_ZNODE_SIZE); /* ugh */
496
+ char * data = NULL;
497
+ if (IS_SYNC(call_type)) {
498
+ data = malloc(MAX_ZNODE_SIZE); /* ugh */
499
+ memset(data, 0, sizeof(data));
500
+ }
476
501
 
477
- int rc;
502
+ int rc, invalid_call_type=0;
478
503
 
479
504
  switch (call_type) {
480
505
 
@@ -500,7 +525,8 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
500
525
  break;
501
526
 
502
527
  default:
503
- raise_invalid_call_type_err(call_type);
528
+ invalid_call_type=1;
529
+ goto cleanup;
504
530
  break;
505
531
  }
506
532
 
@@ -514,7 +540,9 @@ static VALUE method_get(VALUE self, VALUE reqid, VALUE path, VALUE async, VALUE
514
540
  rb_ary_push(output, zkrb_stat_to_rarray(&stat));
515
541
  }
516
542
 
517
- xfree(data);
543
+ cleanup:
544
+ free(data);
545
+ if (invalid_call_type) raise_invalid_call_type_err(call_type);
518
546
  return output;
519
547
  }
520
548
 
@@ -527,9 +555,9 @@ static VALUE method_set(VALUE self, VALUE reqid, VALUE path, VALUE data, VALUE a
527
555
  if (data != Qnil) Check_Type(data, T_STRING);
528
556
 
529
557
  const char *data_ptr = (data == Qnil) ? NULL : RSTRING_PTR(data);
530
- size_t data_len = (data == Qnil) ? -1 : RSTRING_LEN(data);
558
+ ssize_t data_len = (data == Qnil) ? -1 : RSTRING_LEN(data);
531
559
 
532
- int rc;
560
+ int rc=ZOK;
533
561
  switch (call_type) {
534
562
 
535
563
  #ifdef THREADED
@@ -561,7 +589,7 @@ static VALUE method_set_acl(VALUE self, VALUE reqid, VALUE path, VALUE acls, VAL
561
589
 
562
590
  struct ACL_vector * aclptr = zkrb_ruby_to_aclvector(acls);
563
591
 
564
- int rc;
592
+ int rc=ZOK, invalid_call_type=0;
565
593
  switch (call_type) {
566
594
 
567
595
  #ifdef THREADED
@@ -575,13 +603,15 @@ static VALUE method_set_acl(VALUE self, VALUE reqid, VALUE path, VALUE acls, VAL
575
603
  break;
576
604
 
577
605
  default:
578
- raise_invalid_call_type_err(call_type);
606
+ invalid_call_type=1;
579
607
  break;
580
608
  }
581
609
 
582
610
  deallocate_ACL_vector(aclptr);
583
611
  free(aclptr);
584
612
 
613
+ if (invalid_call_type) raise_invalid_call_type_err(call_type);
614
+
585
615
  return INT2FIX(rc);
586
616
  }
587
617
 
@@ -592,7 +622,7 @@ static VALUE method_get_acl(VALUE self, VALUE reqid, VALUE path, VALUE async) {
592
622
  struct ACL_vector acls;
593
623
  struct Stat stat;
594
624
 
595
- int rc;
625
+ int rc=ZOK;
596
626
  switch (call_type) {
597
627
 
598
628
  #ifdef THREADED
@@ -692,12 +722,14 @@ static VALUE method_zkrb_get_next_event_st(VALUE self) {
692
722
  rval = zkrb_event_to_ruby(event);
693
723
  zkrb_event_free(event);
694
724
 
725
+ #if THREADED
695
726
  int fd = zk->queue->pipe_read;
696
727
 
697
728
  // we don't care in this case. this is just until i can remove the self
698
729
  // pipe from the queue
699
730
  char b[128];
700
731
  while(read(fd, b, sizeof(b)) == sizeof(b)){}
732
+ #endif
701
733
  }
702
734
 
703
735
  return rval;
@@ -721,7 +753,6 @@ inline static int get_self_pipe_read_fd(VALUE self) {
721
753
  #endif
722
754
  }
723
755
 
724
-
725
756
  static VALUE method_zkrb_iterate_event_loop(VALUE self) {
726
757
  FETCH_DATA_PTR(self, zk);
727
758
 
@@ -730,7 +761,7 @@ static VALUE method_zkrb_iterate_event_loop(VALUE self) {
730
761
 
731
762
  int fd=0, interest=0, events=0, rc=0, maxfd=0;
732
763
  struct timeval tv;
733
-
764
+
734
765
  zookeeper_interest(zk->zh, &fd, &interest, &tv);
735
766
 
736
767
  if (fd != -1) {
@@ -767,9 +798,12 @@ static VALUE method_zkrb_iterate_event_loop(VALUE self) {
767
798
 
768
799
  // we got woken up by the self-pipe
769
800
  if (FD_ISSET(pipe_r_fd, &rfds)) {
770
- // flush the pipe (from mt_adaptor.c)
801
+ // one event has awoken us, so we clear one event from the pipe
771
802
  char b[1];
772
- read(pipe_r_fd, b, 1); // one event has awoken us, so we clear one event from the pipe
803
+
804
+ if (read(pipe_r_fd, b, 1) < 0) {
805
+ rb_raise(rb_eRuntimeError, "read from pipe failed: %s", clean_errno());
806
+ }
773
807
  }
774
808
 
775
809
  rc = zookeeper_process(zk->zh, events);
@@ -793,18 +827,11 @@ static VALUE method_has_events(VALUE self) {
793
827
  return rb_event;
794
828
  }
795
829
 
796
-
797
- // wake up the event loop, used when shutting down
798
- #if 0
799
- static VALUE method_wake_event_loop_bang(VALUE self) {
800
- FETCH_DATA_PTR(self, zk);
801
-
802
- zkrb_debug_inst(self, "Waking event loop: %p", zk->queue);
803
- zkrb_signal(zk->queue);
804
-
830
+ static VALUE method_zoo_set_log_level(VALUE self, VALUE level) {
831
+ Check_Type(level, T_FIXNUM);
832
+ zoo_set_debug_level(FIX2INT(level));
805
833
  return Qnil;
806
- };
807
- #endif
834
+ }
808
835
 
809
836
  static VALUE method_close_handle(VALUE self) {
810
837
  FETCH_DATA_PTR(self, zk);
@@ -846,12 +873,6 @@ static VALUE method_recv_timeout(VALUE self) {
846
873
  return INT2NUM(zoo_recv_timeout(zk->zh));
847
874
  }
848
875
 
849
- /*static VALUE method_client_id(VALUE self) {*/
850
- /* FETCH_DATA_PTR(self, zk);*/
851
- /* const clientid_t *id = zoo_client_id(zk->zh);*/
852
- /* return UINT2NUM(id->client_id);*/
853
- /*}*/
854
-
855
876
  // returns a CZookeeper::ClientId object with the values set for session_id and passwd
856
877
  static VALUE method_client_id(VALUE self) {
857
878
  FETCH_DATA_PTR(self, zk);
@@ -859,7 +880,7 @@ static VALUE method_client_id(VALUE self) {
859
880
  const clientid_t *cid = zoo_client_id(zk->zh);
860
881
 
861
882
  if (strlen(cid->passwd) != 16) {
862
- zkrb_debug("passwd is not null-termniated");
883
+ zkrb_debug("passwd is not null-terminated");
863
884
  } else {
864
885
  hexbufify(buf, cid->passwd, 16);
865
886
  zkrb_debug("password in hex is: %s", buf);
@@ -910,6 +931,8 @@ static void zkrb_define_methods(void) {
910
931
  rb_define_method(CZookeeper, "zkrb_set_acl", method_set_acl, 5);
911
932
  rb_define_method(CZookeeper, "zkrb_get_acl", method_get_acl, 3);
912
933
 
934
+ rb_define_singleton_method(CZookeeper, "zoo_set_log_level", method_zoo_set_log_level, 1);
935
+
913
936
  DEFINE_METHOD(client_id, 0);
914
937
  DEFINE_METHOD(close_handle, 0);
915
938
  DEFINE_METHOD(deterministic_conn_order, 1);
@@ -1,4 +1,4 @@
1
1
  module Zookeeper
2
- VERSION = '1.1.0'
2
+ VERSION = '1.1.1'
3
3
  DRIVER_VERSION = '3.3.5'
4
4
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zookeeper
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 0
10
- version: 1.1.0
9
+ - 1
10
+ version: 1.1.1
11
11
  platform: java
12
12
  authors:
13
13
  - Phillip Pearson
@@ -20,7 +20,7 @@ autorequire:
20
20
  bindir: bin
21
21
  cert_chain: []
22
22
 
23
- date: 2012-05-14 00:00:00 Z
23
+ date: 2012-05-15 00:00:00 Z
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: backports
@@ -186,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
186
186
  requirements: []
187
187
 
188
188
  rubyforge_project:
189
- rubygems_version: 1.8.15
189
+ rubygems_version: 1.8.24
190
190
  signing_key:
191
191
  specification_version: 3
192
192
  summary: Apache ZooKeeper driver for Rubies