zookeeper-ng 1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.ctags_paths +1 -0
- data/.dotfiles/ruby-gemset +1 -0
- data/.dotfiles/ruby-version +1 -0
- data/.dotfiles/rvmrc +2 -0
- data/.gitignore +19 -0
- data/.gitmodules +3 -0
- data/.travis.yml +25 -0
- data/CHANGELOG +395 -0
- data/Gemfile +30 -0
- data/Guardfile +8 -0
- data/LICENSE +23 -0
- data/Manifest +29 -0
- data/README.markdown +85 -0
- data/Rakefile +121 -0
- data/cause-abort.rb +117 -0
- data/ext/.gitignore +6 -0
- data/ext/Rakefile +41 -0
- data/ext/c_zookeeper.rb +398 -0
- data/ext/common.h +17 -0
- data/ext/dbg.h +53 -0
- data/ext/depend +5 -0
- data/ext/event_lib.c +740 -0
- data/ext/event_lib.h +175 -0
- data/ext/extconf.rb +103 -0
- data/ext/generate_gvl_code.rb +321 -0
- data/ext/patches/zkc-3.3.5-network.patch +24 -0
- data/ext/patches/zkc-3.4.5-fetch-and-add.patch +16 -0
- data/ext/patches/zkc-3.4.5-logging.patch +41 -0
- data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
- data/ext/patches/zkc-3.4.5-overflow.patch +11 -0
- data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
- data/ext/zkc-3.4.5.tar.gz +0 -0
- data/ext/zkrb.c +1075 -0
- data/ext/zkrb_wrapper.c +775 -0
- data/ext/zkrb_wrapper.h +350 -0
- data/ext/zkrb_wrapper_compat.c +15 -0
- data/ext/zkrb_wrapper_compat.h +11 -0
- data/ext/zookeeper_base.rb +256 -0
- data/java/java_base.rb +503 -0
- data/lib/zookeeper.rb +115 -0
- data/lib/zookeeper/acls.rb +44 -0
- data/lib/zookeeper/callbacks.rb +108 -0
- data/lib/zookeeper/client.rb +30 -0
- data/lib/zookeeper/client_methods.rb +282 -0
- data/lib/zookeeper/common.rb +122 -0
- data/lib/zookeeper/common/queue_with_pipe.rb +110 -0
- data/lib/zookeeper/compatibility.rb +138 -0
- data/lib/zookeeper/constants.rb +97 -0
- data/lib/zookeeper/continuation.rb +223 -0
- data/lib/zookeeper/core_ext.rb +58 -0
- data/lib/zookeeper/em_client.rb +55 -0
- data/lib/zookeeper/exceptions.rb +135 -0
- data/lib/zookeeper/forked.rb +19 -0
- data/lib/zookeeper/latch.rb +34 -0
- data/lib/zookeeper/logger.rb +39 -0
- data/lib/zookeeper/logger/forwarding_logger.rb +84 -0
- data/lib/zookeeper/monitor.rb +19 -0
- data/lib/zookeeper/rake_tasks.rb +165 -0
- data/lib/zookeeper/request_registry.rb +153 -0
- data/lib/zookeeper/stat.rb +21 -0
- data/lib/zookeeper/version.rb +4 -0
- data/notes.txt +14 -0
- data/scripts/upgrade-1.0-sed-alike.rb +46 -0
- data/spec/c_zookeeper_spec.rb +51 -0
- data/spec/chrooted_connection_spec.rb +83 -0
- data/spec/compatibilty_spec.rb +8 -0
- data/spec/default_watcher_spec.rb +41 -0
- data/spec/em_spec.rb +51 -0
- data/spec/ext/zookeeper_base_spec.rb +19 -0
- data/spec/forked_connection_spec.rb +124 -0
- data/spec/latch_spec.rb +24 -0
- data/spec/log4j.properties +17 -0
- data/spec/shared/all_success_return_values.rb +10 -0
- data/spec/shared/connection_examples.rb +1077 -0
- data/spec/spec_helper.rb +61 -0
- data/spec/support/00_logging.rb +38 -0
- data/spec/support/10_spawn_zookeeper.rb +24 -0
- data/spec/support/progress_formatter.rb +15 -0
- data/spec/support/zookeeper_spec_helpers.rb +96 -0
- data/spec/zookeeper_spec.rb +24 -0
- data/zookeeper.gemspec +38 -0
- data/zoomonkey/duplicates +3 -0
- data/zoomonkey/zoomonkey.rb +194 -0
- metadata +157 -0
data/ext/c_zookeeper.rb
ADDED
@@ -0,0 +1,398 @@
|
|
1
|
+
Zookeeper.require_lib(
|
2
|
+
'zookeeper/logger',
|
3
|
+
'zookeeper/common',
|
4
|
+
'zookeeper/constants',
|
5
|
+
'zookeeper/exceptions' # zookeeper_c depends on exceptions defined in here
|
6
|
+
)
|
7
|
+
|
8
|
+
Zookeeper.require_root 'ext/zookeeper_c'
|
9
|
+
|
10
|
+
# require File.expand_path('../zookeeper_c', __FILE__)
|
11
|
+
|
12
|
+
module Zookeeper
|
13
|
+
# NOTE: this class extending (opening) the class defined in zkrb.c
|
14
|
+
class CZookeeper
|
15
|
+
include Forked
|
16
|
+
include Constants
|
17
|
+
include Exceptions
|
18
|
+
include Logger
|
19
|
+
|
20
|
+
DEFAULT_RECEIVE_TIMEOUT_MSEC = 10000
|
21
|
+
|
22
|
+
class GotNilEventException < StandardError; end
|
23
|
+
|
24
|
+
attr_accessor :original_pid
|
25
|
+
|
26
|
+
# assume we're at debug level
|
27
|
+
def self.get_debug_level
|
28
|
+
@debug_level ||= ZOO_LOG_LEVEL_INFO
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.set_debug_level(value)
|
32
|
+
@debug_level = value
|
33
|
+
set_zkrb_debug_level(value)
|
34
|
+
end
|
35
|
+
|
36
|
+
# wrap these calls in our sync->async special sauce
|
37
|
+
%w[get set exists create delete get_acl set_acl get_children add_auth].each do |sym|
|
38
|
+
class_eval(<<-EOS, __FILE__, __LINE__+1)
|
39
|
+
def #{sym}(*args)
|
40
|
+
submit_and_block(:#{sym}, *args)
|
41
|
+
end
|
42
|
+
EOS
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(host, event_queue, opts={})
|
46
|
+
@host = host
|
47
|
+
@event_queue = event_queue
|
48
|
+
|
49
|
+
# keep track of the pid that created us
|
50
|
+
update_pid!
|
51
|
+
|
52
|
+
# used by the C layer. CZookeeper sets this to true when the init method
|
53
|
+
# has completed. once this is set to true, it stays true.
|
54
|
+
#
|
55
|
+
# you should grab the @mutex before messing with this flag
|
56
|
+
@_running = nil
|
57
|
+
|
58
|
+
# This is set to true after destroy_zkrb_instance has been called and all
|
59
|
+
# CZookeeper state has been cleaned up
|
60
|
+
@_closed = false # also used by the C layer
|
61
|
+
|
62
|
+
# set by the ruby side to indicate we are in shutdown mode used by method_get_next_event
|
63
|
+
@_shutting_down = false
|
64
|
+
|
65
|
+
# the actual C data is stashed in this ivar. never *ever* touch this
|
66
|
+
@_data = nil
|
67
|
+
|
68
|
+
@_receive_timeout_msec = opts[:receive_timeout_msec] || DEFAULT_RECEIVE_TIMEOUT_MSEC
|
69
|
+
|
70
|
+
@mutex = Monitor.new
|
71
|
+
|
72
|
+
# used to signal that we're running
|
73
|
+
@running_cond = @mutex.new_cond
|
74
|
+
|
75
|
+
# used to signal we've received the connected event
|
76
|
+
@state_mutex = Monitor.new
|
77
|
+
@state_cond = @state_mutex.new_cond
|
78
|
+
|
79
|
+
# the current state of the connection
|
80
|
+
@state = ZOO_CLOSED_STATE
|
81
|
+
|
82
|
+
@pipe_read, @pipe_write = IO.pipe
|
83
|
+
|
84
|
+
@event_thread = nil
|
85
|
+
|
86
|
+
# hash of in-flight Continuation instances
|
87
|
+
@reg = Continuation::Registry.new
|
88
|
+
|
89
|
+
log_level = ENV['ZKC_DEBUG'] ? ZOO_LOG_LEVEL_DEBUG : ZOO_LOG_LEVEL_ERROR
|
90
|
+
|
91
|
+
logger.info { "initiating connection to #{@host}" }
|
92
|
+
|
93
|
+
zkrb_init(@host, opts)#, :zkc_log_level => log_level)
|
94
|
+
|
95
|
+
start_event_thread
|
96
|
+
|
97
|
+
logger.debug { "init returned!" }
|
98
|
+
end
|
99
|
+
|
100
|
+
def closed?
|
101
|
+
@mutex.synchronize { !!@_closed }
|
102
|
+
end
|
103
|
+
|
104
|
+
def running?
|
105
|
+
@mutex.synchronize { !!@_running }
|
106
|
+
end
|
107
|
+
|
108
|
+
def shutting_down?
|
109
|
+
@mutex.synchronize { !!@_shutting_down }
|
110
|
+
end
|
111
|
+
|
112
|
+
def connected?
|
113
|
+
state == ZOO_CONNECTED_STATE
|
114
|
+
end
|
115
|
+
|
116
|
+
def connecting?
|
117
|
+
state == ZOO_CONNECTING_STATE
|
118
|
+
end
|
119
|
+
|
120
|
+
def associating?
|
121
|
+
state == ZOO_ASSOCIATING_STATE
|
122
|
+
end
|
123
|
+
|
124
|
+
def close
|
125
|
+
return if closed?
|
126
|
+
|
127
|
+
fn_close = proc do
|
128
|
+
if !@_closed and @_data
|
129
|
+
logger.debug { "CALLING CLOSE HANDLE!!" }
|
130
|
+
close_handle
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if forked?
|
135
|
+
fn_close.call
|
136
|
+
else
|
137
|
+
stop_event_thread
|
138
|
+
@mutex.synchronize(&fn_close)
|
139
|
+
end
|
140
|
+
|
141
|
+
[@pipe_read, @pipe_write].each { |io| io.close unless io.closed? }
|
142
|
+
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
|
146
|
+
# call this to stop the event loop, you can resume with the
|
147
|
+
# resume method
|
148
|
+
#
|
149
|
+
# requests may still be added during this time, but they will not be
|
150
|
+
# processed until you call resume
|
151
|
+
def pause_before_fork_in_parent
|
152
|
+
logger.debug { "##{__method__}" }
|
153
|
+
@mutex.synchronize { stop_event_thread }
|
154
|
+
end
|
155
|
+
|
156
|
+
# call this if 'pause' was previously called to start the event loop again
|
157
|
+
def resume_after_fork_in_parent
|
158
|
+
logger.debug { "##{__method__}" }
|
159
|
+
|
160
|
+
@mutex.synchronize do
|
161
|
+
@_shutting_down = nil
|
162
|
+
start_event_thread
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def state
|
167
|
+
return ZOO_CLOSED_STATE if closed?
|
168
|
+
@state_mutex.synchronize { @state }
|
169
|
+
end
|
170
|
+
|
171
|
+
# this implementation is gross, but i don't really see another way of doing it
|
172
|
+
# without more grossness
|
173
|
+
#
|
174
|
+
# returns true if we're connected, false if we're not
|
175
|
+
#
|
176
|
+
# if timeout is nil, we never time out, and wait forever for CONNECTED state
|
177
|
+
#
|
178
|
+
def wait_until_connected(timeout=10)
|
179
|
+
time_to_stop = timeout ? Time.now + timeout : nil
|
180
|
+
|
181
|
+
return false unless wait_until_running(timeout)
|
182
|
+
|
183
|
+
@state_mutex.synchronize do
|
184
|
+
while true
|
185
|
+
if timeout
|
186
|
+
now = Time.now
|
187
|
+
break if (@state == ZOO_CONNECTED_STATE) || unhealthy? || (now > time_to_stop)
|
188
|
+
delay = time_to_stop.to_f - now.to_f
|
189
|
+
@state_cond.wait(delay)
|
190
|
+
else
|
191
|
+
break if (@state == ZOO_CONNECTED_STATE) || unhealthy?
|
192
|
+
@state_cond.wait
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
connected?
|
198
|
+
end
|
199
|
+
|
200
|
+
private
|
201
|
+
# This method is NOT SYNCHRONIZED!
|
202
|
+
#
|
203
|
+
# you must hold the @mutex lock while calling this method
|
204
|
+
def unhealthy?
|
205
|
+
@_closed || @_shutting_down || is_unrecoverable
|
206
|
+
end
|
207
|
+
|
208
|
+
# This method is NOT SYNCHRONIZED!
|
209
|
+
#
|
210
|
+
# you must hold the @mutex lock while calling this method
|
211
|
+
def healthy?
|
212
|
+
!unhealthy?
|
213
|
+
end
|
214
|
+
|
215
|
+
# submits a job for processing
|
216
|
+
# blocks the caller until result has returned
|
217
|
+
def submit_and_block(meth, *args)
|
218
|
+
@mutex.synchronize do
|
219
|
+
raise Exceptions::NotConnected if unhealthy?
|
220
|
+
end
|
221
|
+
|
222
|
+
cnt = Continuation.new(meth, *args)
|
223
|
+
@reg.synchronize do |r|
|
224
|
+
if meth == :state
|
225
|
+
r.state_check << cnt
|
226
|
+
else
|
227
|
+
r.pending << cnt
|
228
|
+
end
|
229
|
+
end
|
230
|
+
wake_event_loop!
|
231
|
+
cnt.value
|
232
|
+
end
|
233
|
+
|
234
|
+
# this method is part of the reopen/close code, and is responsible for
|
235
|
+
# shutting down the dispatch thread.
|
236
|
+
#
|
237
|
+
# this method must be EXTERNALLY SYNCHRONIZED!
|
238
|
+
#
|
239
|
+
# @event_thread will be nil when this method exits
|
240
|
+
#
|
241
|
+
def stop_event_thread
|
242
|
+
if @event_thread
|
243
|
+
logger.debug { "##{__method__}" }
|
244
|
+
shut_down!
|
245
|
+
wake_event_loop!
|
246
|
+
@event_thread.join
|
247
|
+
@event_thread = nil
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# starts the event thread running if not already started
|
252
|
+
# returns false if already running
|
253
|
+
def start_event_thread
|
254
|
+
return false if @event_thread
|
255
|
+
@event_thread = Thread.new(&method(:event_thread_body))
|
256
|
+
end
|
257
|
+
|
258
|
+
# will wait until the client has entered the running? state
|
259
|
+
# or until timeout seconds have passed.
|
260
|
+
#
|
261
|
+
# returns true if we're running, false if we timed out
|
262
|
+
def wait_until_running(timeout=5)
|
263
|
+
@mutex.synchronize do
|
264
|
+
return true if @_running
|
265
|
+
@running_cond.wait(timeout)
|
266
|
+
!!@_running
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
def event_thread_body
|
271
|
+
Thread.current.abort_on_exception = true
|
272
|
+
logger.debug { "##{__method__} starting event thread" }
|
273
|
+
|
274
|
+
event_thread_await_running
|
275
|
+
|
276
|
+
# this is the main loop
|
277
|
+
while healthy?
|
278
|
+
if @reg.anything_to_do? && connected?
|
279
|
+
submit_pending_calls
|
280
|
+
end
|
281
|
+
|
282
|
+
zkrb_iterate_event_loop
|
283
|
+
iterate_event_delivery
|
284
|
+
end
|
285
|
+
|
286
|
+
# ok, if we're exiting the event loop, and we still have a valid connection
|
287
|
+
# and there's still completions we're waiting to hear about, then we
|
288
|
+
# should pump the handle before leaving this loop
|
289
|
+
if @_shutting_down and not (@_closed or is_unrecoverable)
|
290
|
+
logger.debug { "we're in shutting down state, there are #{@reg.in_flight.length} in_flight completions" }
|
291
|
+
|
292
|
+
until @reg.in_flight.empty? or @_closed or is_unrecoverable
|
293
|
+
zkrb_iterate_event_loop
|
294
|
+
iterate_event_delivery
|
295
|
+
logger.debug { "there are #{@reg.in_flight} in_flight completions left" }
|
296
|
+
end
|
297
|
+
|
298
|
+
logger.debug { "finished completions" }
|
299
|
+
end
|
300
|
+
|
301
|
+
# anything left over after all that gets the finger
|
302
|
+
remaining = @reg.next_batch + @reg.in_flight.values
|
303
|
+
|
304
|
+
logger.debug { "there are #{remaining.length} completions to awaken" }
|
305
|
+
|
306
|
+
@reg.in_flight.clear
|
307
|
+
|
308
|
+
while cb = remaining.shift
|
309
|
+
cb.shutdown!
|
310
|
+
end
|
311
|
+
rescue ShuttingDownException
|
312
|
+
logger.error { "event thread saw @_shutting_down, bailing without entering loop" }
|
313
|
+
ensure
|
314
|
+
logger.debug { "##{__method__} exiting" }
|
315
|
+
end
|
316
|
+
|
317
|
+
def submit_pending_calls
|
318
|
+
calls = @reg.next_batch()
|
319
|
+
|
320
|
+
return if calls.empty?
|
321
|
+
|
322
|
+
while cntn = calls.shift
|
323
|
+
cntn.submit(self) # this delivers state check results (and does other stuff)
|
324
|
+
if req_id = cntn.req_id # state checks will not have a req_id
|
325
|
+
@reg.in_flight[req_id] = cntn # in_flight is only ever touched by us
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def wake_event_loop!
|
331
|
+
@pipe_write && @pipe_write.write('1')
|
332
|
+
end
|
333
|
+
|
334
|
+
def iterate_event_delivery
|
335
|
+
while hash = zkrb_get_next_event_st()
|
336
|
+
logger.debug { "##{__method__} got #{hash.inspect} " }
|
337
|
+
|
338
|
+
if (hash[:req_id] == ZKRB_GLOBAL_CB_REQ) && (hash[:type] == -1)
|
339
|
+
ev_state = hash[:state]
|
340
|
+
|
341
|
+
@state_mutex.synchronize do
|
342
|
+
if @state != ev_state
|
343
|
+
@state = ev_state
|
344
|
+
@state_cond.broadcast
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
cntn = @reg.in_flight.delete(hash[:req_id])
|
350
|
+
|
351
|
+
if cntn and not cntn.user_callback? # this is one of "our" continuations
|
352
|
+
cntn.call(hash) # so we handle delivering it
|
353
|
+
next # and skip handing it to the dispatcher
|
354
|
+
end
|
355
|
+
|
356
|
+
# otherwise, the event was a session event (ZKRB_GLOBAL_CB_REQ)
|
357
|
+
# or a user-provided callback
|
358
|
+
@event_queue.push(hash)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def event_thread_await_running
|
363
|
+
logger.debug { "event_thread waiting until running: #{@_running}" }
|
364
|
+
|
365
|
+
@mutex.synchronize do
|
366
|
+
@running_cond.wait_until { @_running or @_shutting_down }
|
367
|
+
logger.debug { "event_thread running: #{@_running}" }
|
368
|
+
|
369
|
+
raise ShuttingDownException if @_shutting_down
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
# use this method to set the @_shutting_down flag to true
|
374
|
+
def shut_down!
|
375
|
+
logger.debug { "##{__method__}" }
|
376
|
+
|
377
|
+
@mutex.synchronize do
|
378
|
+
@_shutting_down = true
|
379
|
+
# ollie ollie oxen all home free!
|
380
|
+
@running_cond.broadcast
|
381
|
+
end
|
382
|
+
|
383
|
+
@state_mutex.synchronize do
|
384
|
+
@state_cond.broadcast
|
385
|
+
end
|
386
|
+
end
|
387
|
+
|
388
|
+
# called by underlying C code to signal we're running
|
389
|
+
def zkc_set_running_and_notify!
|
390
|
+
logger.debug { "##{__method__}" }
|
391
|
+
|
392
|
+
@mutex.synchronize do
|
393
|
+
@_running = true
|
394
|
+
@running_cond.broadcast
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
data/ext/common.h
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#ifndef ZKRB_COMMON_H
|
2
|
+
#define ZKRB_COMMON_H
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
//#define THREADED
|
7
|
+
#undef THREADED // we are linking against the zookeeper_st lib, this is crucial
|
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
|
+
|
17
|
+
#endif /* ZKRB_COMMON_H */
|
data/ext/dbg.h
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#ifndef __dbg_h__
|
2
|
+
#define __dbg_h__
|
3
|
+
|
4
|
+
// ALL GLORY TO THE Zed A. Shaw
|
5
|
+
// http://c.learncodethehardway.org/book/learn-c-the-hard-waych21.html#x26-10500021
|
6
|
+
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <errno.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
#ifdef NDEBUG
|
12
|
+
#define debug(M, ...)
|
13
|
+
#else
|
14
|
+
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
15
|
+
#endif
|
16
|
+
|
17
|
+
#define clean_errno() (errno == 0 ? "None" : strerror(errno))
|
18
|
+
|
19
|
+
#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
20
|
+
|
21
|
+
#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
|
22
|
+
|
23
|
+
#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
|
24
|
+
|
25
|
+
// acts to assert that A is true
|
26
|
+
#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
27
|
+
|
28
|
+
// like check, but provide an explicit goto label name
|
29
|
+
#define check_goto(A, L, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto L; }
|
30
|
+
|
31
|
+
// like check, but implicit jump to 'unlock' label
|
32
|
+
#define check_unlock(A, M, ...) check_goto(A, unlock, M, ##__VA_ARGS__)
|
33
|
+
|
34
|
+
#define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }
|
35
|
+
|
36
|
+
#define check_mem(A) check((A), "Out of memory.")
|
37
|
+
|
38
|
+
// checks the condition A, if not true, logs the message M given using zkrb_debug
|
39
|
+
// then does a goto to the label L
|
40
|
+
#define check_debug_goto(A, L, M, ...) if(!(A)) { zkrb_debug(M, ##__VA_ARGS__); errno=0; goto L; }
|
41
|
+
|
42
|
+
// check_debug_goto with implicit 'unlock' label
|
43
|
+
#define check_debug_unlock(A, M, ...) check_debug_goto(A, unlock, M, ##__VA_ARGS__)
|
44
|
+
|
45
|
+
// like check_debug_goto, but the label is implicitly 'error'
|
46
|
+
#define check_debug(A, M, ...) check_debug_goto(A, error, M, ##__VA_ARGS__)
|
47
|
+
|
48
|
+
#define zkrb_debug(M, ...) if (ZKRBDebugging) fprintf(stderr, "DEBUG %p:%s:%d: " M "\n", (void *)pthread_self(), __FILE__, __LINE__, ##__VA_ARGS__)
|
49
|
+
#define zkrb_debug_inst(O, M, ...) zkrb_debug("obj_id: %lx, " M, FIX2LONG(rb_obj_id(O)), ##__VA_ARGS__)
|
50
|
+
|
51
|
+
// __dbg_h__
|
52
|
+
#endif
|
53
|
+
|