zookeeper 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/ext/c_zookeeper.rb CHANGED
@@ -156,7 +156,7 @@ class CZookeeper
156
156
 
157
157
  def state
158
158
  return ZOO_CLOSED_STATE if closed?
159
- zkrb_state
159
+ submit_and_block(:state)
160
160
  end
161
161
 
162
162
  # this implementation is gross, but i don't really see another way of doing it
@@ -176,13 +176,21 @@ class CZookeeper
176
176
  connected?
177
177
  end
178
178
 
179
-
180
179
  private
181
180
  # submits a job for processing
182
181
  # blocks the caller until result has returned
183
182
  def submit_and_block(meth, *args)
184
183
  cnt = Continuation.new(meth, *args)
185
- @reg.synchronized { |r| r.pending << cnt }
184
+ @reg.lock
185
+ begin
186
+ if meth == :state
187
+ @reg.pending.unshift(cnt)
188
+ else
189
+ @reg.pending << cnt
190
+ end
191
+ ensure
192
+ @reg.unlock rescue nil
193
+ end
186
194
  wake_event_loop!
187
195
  cnt.value
188
196
  end
@@ -232,10 +240,8 @@ class CZookeeper
232
240
 
233
241
  # this is the main loop
234
242
  until (@_shutting_down or @_closed or is_unrecoverable)
235
- submit_pending_calls if @reg.pending?
236
- # log_realtime("zkrb_iterate_event_loop") do
237
- zkrb_iterate_event_loop # XXX: check rc here
238
- # end
243
+ submit_pending_calls if @reg.anything_to_do?
244
+ zkrb_iterate_event_loop
239
245
  iterate_event_delivery
240
246
  end
241
247
 
@@ -260,31 +266,20 @@ class CZookeeper
260
266
  end
261
267
 
262
268
  def submit_pending_calls
263
- # this is ok, because the calling thread only ever *adds* to this hash,
264
- # and the keys are always unique
269
+ calls = @reg.next_batch()
265
270
 
266
- pending = nil
271
+ return if calls.empty?
267
272
 
268
- @reg.lock
269
- begin
270
- pending, @reg.pending = @reg.pending, []
271
- ensure
272
- @reg.unlock
273
- end
274
-
275
- return if pending.empty?
276
-
277
- logger.debug { "#{self.class}##{__method__} " }
278
-
279
- while cntn = pending.shift
280
- cntn.submit(self)
281
- @reg.in_flight[cntn.req_id] = cntn # in_flight is only ever touched by us
273
+ while cntn = calls.shift
274
+ cntn.submit(self) # this delivers state check results (and does other stuff)
275
+ if req_id = cntn.req_id # state checks will not have a req_id
276
+ @reg.in_flight[req_id] = cntn # in_flight is only ever touched by us
277
+ end
282
278
  end
283
279
  end
284
280
 
285
281
  def wake_event_loop!
286
- logger.debug { "#{self.class}##{__method__}" }
287
- @pipe_write && @pipe_write.write("\001")
282
+ @pipe_write && @pipe_write.write('1')
288
283
  end
289
284
 
290
285
  def iterate_event_delivery
data/ext/common.h CHANGED
@@ -1,7 +1,17 @@
1
1
  #ifndef ZKRB_COMMON_H
2
2
  #define ZKRB_COMMON_H
3
3
 
4
+ #include "ruby.h"
5
+
4
6
  //#define THREADED
5
7
  #undef THREADED // we are linking against the zookeeper_st lib, this is crucial
6
8
 
9
+ #ifndef RB_GC_GUARD_PTR
10
+ #define RB_GC_GUARD_PTR(V) (V);
11
+ #endif
12
+ #ifndef RB_GC_GUARD
13
+ #define RB_GC_GUARD(V) (V);
14
+ #endif
15
+
16
+
7
17
  #endif /* ZKRB_COMMON_H */
data/ext/zkrb.c CHANGED
@@ -56,6 +56,13 @@
56
56
  *
57
57
  * NOTE: This file depends on exception classes defined in lib/zookeeper/exceptions.rb
58
58
  *
59
+ * -------
60
+ *
61
+ * @rectalogic: any time you create a ruby value in C, and so there are no
62
+ * references to it in the VM except for your variable, and you then call into
63
+ * the VM (allowing a GC), and your reference is on the stack, then it needs to
64
+ * be volatile
65
+ *
59
66
  */
60
67
 
61
68
  #include "ruby.h"
@@ -269,7 +276,7 @@ static VALUE method_zkrb_init(int argc, VALUE* argv, VALUE self) {
269
276
  zoo_set_debug_level(FIX2INT(log_level));
270
277
  }
271
278
 
272
- VALUE data;
279
+ volatile VALUE data;
273
280
  zkrb_instance_data_t *zk_local_ctx;
274
281
  data = Data_Make_Struct(CZookeeper, zkrb_instance_data_t, 0, free_zkrb_instance_data, zk_local_ctx);
275
282
 
@@ -665,13 +672,12 @@ static VALUE method_zkrb_get_next_event(VALUE self, VALUE blocking) {
665
672
  check_debug(!is_closed(self), "we're closed in the middle of method_zkrb_get_next_event, bailing");
666
673
 
667
674
  zkrb_event_t *event = zkrb_dequeue(zk->queue, 1);
668
-
669
- /* Wait for an event using rb_thread_select() on the queue's pipe */
675
+
670
676
  if (event == NULL) {
671
677
  if (NIL_P(blocking) || (blocking == Qfalse)) {
672
678
  goto error;
673
679
  }
674
- else {
680
+ else {
675
681
  // if we're shutting down, don't enter this section, we don't want to block
676
682
  check_debug(!is_shutting_down(self), "method_zkrb_get_next_event, we're shutting down, don't enter blocking section");
677
683
 
@@ -707,7 +713,7 @@ static VALUE method_zkrb_get_next_event(VALUE self, VALUE blocking) {
707
713
  // the single threaded version of this call. will go away when we do direct
708
714
  // event delivery (soon)
709
715
  static VALUE method_zkrb_get_next_event_st(VALUE self) {
710
- VALUE rval = Qnil;
716
+ volatile VALUE rval = Qnil;
711
717
 
712
718
  if (is_closed(self)) {
713
719
  zkrb_debug("we are closed, not gonna try to get an event");
@@ -8,6 +8,10 @@ module Zookeeper
8
8
 
9
9
  # for keeping track of which continuations are pending, and which ones have
10
10
  # been submitted and are awaiting a repsonse
11
+ #
12
+ # `state_check` are high-priority checks that query the connection about
13
+ # its current state, they always run before other continuations
14
+ #
11
15
  class Registry < Struct.new(:pending, :in_flight)
12
16
  extend Forwardable
13
17
 
@@ -23,15 +27,26 @@ module Zookeeper
23
27
  begin
24
28
  yield self
25
29
  ensure
26
- @mutex.unlock
30
+ @mutex.unlock rescue nil
27
31
  end
28
32
  end
29
33
 
30
34
  # does not lock the mutex, returns true if there are pending jobs
31
- def pending?
32
- !self.pending.empty?
35
+ def anything_to_do?
36
+ !pending.empty?
33
37
  end
34
- end
38
+
39
+ # returns the pending continuations, resetting the list
40
+ # this method is synchronized
41
+ def next_batch()
42
+ @mutex.lock
43
+ begin
44
+ pending.slice!(0,pending.length)
45
+ ensure
46
+ @mutex.unlock rescue nil
47
+ end
48
+ end
49
+ end # Registry
35
50
 
36
51
  # *sigh* what is the index in the *args array of the 'callback' param
37
52
  CALLBACK_ARG_IDX = {
@@ -43,6 +58,7 @@ module Zookeeper
43
58
  :get_acl => 2,
44
59
  :set_acl => 3,
45
60
  :get_children => 2,
61
+ :state => 0,
46
62
  }
47
63
 
48
64
  # maps the method name to the async return hash keys it should use to
@@ -111,9 +127,10 @@ module Zookeeper
111
127
  def submit(czk)
112
128
  rc, *_ = czk.__send__(:"zkrb_#{@meth}", *async_args)
113
129
 
114
- if user_callback? or (rc != ZOK) # if this is an async call, or we failed to submit it
115
- @rval = [rc] # create the repsonse
116
- deliver! # wake the caller and we're out
130
+ # if this is an state call, async call, or we failed to submit it
131
+ if (@meth == :state) or user_callback? or (rc != ZOK)
132
+ @rval = [rc] # create the repsonse
133
+ deliver! # wake the caller and we're out
117
134
  end
118
135
  end
119
136
 
@@ -121,11 +138,16 @@ module Zookeeper
121
138
  @args.first
122
139
  end
123
140
 
141
+ def state_call?
142
+ @meth == :state
143
+ end
144
+
124
145
  protected
125
146
 
126
147
  # an args array with the only difference being that if there's a user
127
148
  # callback provided, we don't handle delivering the end result
128
149
  def async_args
150
+ return [] if @meth == :state # special-case :P
129
151
  ary = @args.dup
130
152
 
131
153
  logger.debug { "async_args, meth: #{meth} ary: #{ary.inspect}, #{callback_arg_idx}" }
@@ -147,7 +169,7 @@ module Zookeeper
147
169
  begin
148
170
  @cond.signal
149
171
  ensure
150
- @mutex.unlock
172
+ @mutex.unlock rescue nil
151
173
  end
152
174
  end
153
175
  end # Base
@@ -1,4 +1,4 @@
1
1
  module Zookeeper
2
- VERSION = '1.1.1'
2
+ VERSION = '1.1.2'
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: 17
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 1
9
- - 1
10
- version: 1.1.1
9
+ - 2
10
+ version: 1.1.2
11
11
  platform: ruby
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-15 00:00:00 Z
23
+ date: 2012-05-17 00:00:00 Z
24
24
  dependencies:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: backports