zookeeper-ng 1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +7 -0
  2. data/.ctags_paths +1 -0
  3. data/.dotfiles/ruby-gemset +1 -0
  4. data/.dotfiles/ruby-version +1 -0
  5. data/.dotfiles/rvmrc +2 -0
  6. data/.gitignore +19 -0
  7. data/.gitmodules +3 -0
  8. data/.travis.yml +25 -0
  9. data/CHANGELOG +395 -0
  10. data/Gemfile +30 -0
  11. data/Guardfile +8 -0
  12. data/LICENSE +23 -0
  13. data/Manifest +29 -0
  14. data/README.markdown +85 -0
  15. data/Rakefile +121 -0
  16. data/cause-abort.rb +117 -0
  17. data/ext/.gitignore +6 -0
  18. data/ext/Rakefile +41 -0
  19. data/ext/c_zookeeper.rb +398 -0
  20. data/ext/common.h +17 -0
  21. data/ext/dbg.h +53 -0
  22. data/ext/depend +5 -0
  23. data/ext/event_lib.c +740 -0
  24. data/ext/event_lib.h +175 -0
  25. data/ext/extconf.rb +103 -0
  26. data/ext/generate_gvl_code.rb +321 -0
  27. data/ext/patches/zkc-3.3.5-network.patch +24 -0
  28. data/ext/patches/zkc-3.4.5-fetch-and-add.patch +16 -0
  29. data/ext/patches/zkc-3.4.5-logging.patch +41 -0
  30. data/ext/patches/zkc-3.4.5-out-of-order-ping.patch +163 -0
  31. data/ext/patches/zkc-3.4.5-overflow.patch +11 -0
  32. data/ext/patches/zkc-3.4.5-yosemite-htonl-fix.patch +102 -0
  33. data/ext/zkc-3.4.5.tar.gz +0 -0
  34. data/ext/zkrb.c +1075 -0
  35. data/ext/zkrb_wrapper.c +775 -0
  36. data/ext/zkrb_wrapper.h +350 -0
  37. data/ext/zkrb_wrapper_compat.c +15 -0
  38. data/ext/zkrb_wrapper_compat.h +11 -0
  39. data/ext/zookeeper_base.rb +256 -0
  40. data/java/java_base.rb +503 -0
  41. data/lib/zookeeper.rb +115 -0
  42. data/lib/zookeeper/acls.rb +44 -0
  43. data/lib/zookeeper/callbacks.rb +108 -0
  44. data/lib/zookeeper/client.rb +30 -0
  45. data/lib/zookeeper/client_methods.rb +282 -0
  46. data/lib/zookeeper/common.rb +122 -0
  47. data/lib/zookeeper/common/queue_with_pipe.rb +110 -0
  48. data/lib/zookeeper/compatibility.rb +138 -0
  49. data/lib/zookeeper/constants.rb +97 -0
  50. data/lib/zookeeper/continuation.rb +223 -0
  51. data/lib/zookeeper/core_ext.rb +58 -0
  52. data/lib/zookeeper/em_client.rb +55 -0
  53. data/lib/zookeeper/exceptions.rb +135 -0
  54. data/lib/zookeeper/forked.rb +19 -0
  55. data/lib/zookeeper/latch.rb +34 -0
  56. data/lib/zookeeper/logger.rb +39 -0
  57. data/lib/zookeeper/logger/forwarding_logger.rb +84 -0
  58. data/lib/zookeeper/monitor.rb +19 -0
  59. data/lib/zookeeper/rake_tasks.rb +165 -0
  60. data/lib/zookeeper/request_registry.rb +153 -0
  61. data/lib/zookeeper/stat.rb +21 -0
  62. data/lib/zookeeper/version.rb +4 -0
  63. data/notes.txt +14 -0
  64. data/scripts/upgrade-1.0-sed-alike.rb +46 -0
  65. data/spec/c_zookeeper_spec.rb +51 -0
  66. data/spec/chrooted_connection_spec.rb +83 -0
  67. data/spec/compatibilty_spec.rb +8 -0
  68. data/spec/default_watcher_spec.rb +41 -0
  69. data/spec/em_spec.rb +51 -0
  70. data/spec/ext/zookeeper_base_spec.rb +19 -0
  71. data/spec/forked_connection_spec.rb +124 -0
  72. data/spec/latch_spec.rb +24 -0
  73. data/spec/log4j.properties +17 -0
  74. data/spec/shared/all_success_return_values.rb +10 -0
  75. data/spec/shared/connection_examples.rb +1077 -0
  76. data/spec/spec_helper.rb +61 -0
  77. data/spec/support/00_logging.rb +38 -0
  78. data/spec/support/10_spawn_zookeeper.rb +24 -0
  79. data/spec/support/progress_formatter.rb +15 -0
  80. data/spec/support/zookeeper_spec_helpers.rb +96 -0
  81. data/spec/zookeeper_spec.rb +24 -0
  82. data/zookeeper.gemspec +38 -0
  83. data/zoomonkey/duplicates +3 -0
  84. data/zoomonkey/zoomonkey.rb +194 -0
  85. metadata +157 -0
data/ext/event_lib.h ADDED
@@ -0,0 +1,175 @@
1
+ #ifndef ZKRB_EVENT_LIB_H
2
+ #define ZKRB_EVENT_LIB_H
3
+
4
+ #include "ruby.h"
5
+ #include "zookeeper/zookeeper.h"
6
+ #include <errno.h>
7
+ #include <stdio.h>
8
+ #include <stdlib.h>
9
+ #include <unistd.h>
10
+
11
+ #define ZK_TRUE 1
12
+ #define ZK_FALSE 0
13
+ #define ZKRB_GLOBAL_REQ -1
14
+
15
+ // (slyphon): this RC value does not conflict with any of the ZOO_ERRORS
16
+ // but need to find a better way of formalizing and defining this stuff
17
+ #define ZKRB_ERR_REQ -2
18
+ #define ZKRB_ERR_RC -15
19
+
20
+ #ifndef RSTRING_LEN
21
+ # define RSTRING_LEN(x) RSTRING(x)->len
22
+ #endif
23
+ #ifndef RSTRING_PTR
24
+ # define RSTRING_PTR(x) RSTRING(x)->ptr
25
+ #endif
26
+ #ifndef RARRAY_LEN
27
+ # define RARRAY_LEN(x) RARRAY(x)->len
28
+ #endif
29
+
30
+ extern int ZKRBDebugging;
31
+ extern pthread_mutex_t zkrb_q_mutex;
32
+
33
+ struct zkrb_data_completion {
34
+ char *data;
35
+ int data_len;
36
+ struct Stat *stat;
37
+ };
38
+
39
+ struct zkrb_stat_completion {
40
+ struct Stat *stat;
41
+ };
42
+
43
+ struct zkrb_void_completion {
44
+ };
45
+
46
+ struct zkrb_string_completion {
47
+ char *value;
48
+ };
49
+
50
+ struct zkrb_strings_completion {
51
+ struct String_vector *values;
52
+ };
53
+
54
+ struct zkrb_strings_stat_completion {
55
+ struct String_vector *values;
56
+ struct Stat *stat;
57
+ };
58
+
59
+ struct zkrb_acl_completion {
60
+ struct ACL_vector *acl;
61
+ struct Stat *stat;
62
+ };
63
+
64
+ struct zkrb_watcher_completion {
65
+ int type;
66
+ int state;
67
+ char *path;
68
+ };
69
+
70
+ typedef struct {
71
+ int64_t req_id;
72
+ int rc;
73
+
74
+ enum {
75
+ ZKRB_DATA = 0,
76
+ ZKRB_STAT = 1,
77
+ ZKRB_VOID = 2,
78
+ ZKRB_STRING = 3,
79
+ ZKRB_STRINGS = 4,
80
+ ZKRB_STRINGS_STAT = 5,
81
+ ZKRB_ACL = 6,
82
+ ZKRB_WATCHER = 7
83
+ } type;
84
+
85
+ union {
86
+ struct zkrb_data_completion *data_completion;
87
+ struct zkrb_stat_completion *stat_completion;
88
+ struct zkrb_void_completion *void_completion;
89
+ struct zkrb_string_completion *string_completion;
90
+ struct zkrb_strings_completion *strings_completion;
91
+ struct zkrb_strings_stat_completion *strings_stat_completion;
92
+ struct zkrb_acl_completion *acl_completion;
93
+ struct zkrb_watcher_completion *watcher_completion;
94
+ } completion;
95
+ } zkrb_event_t;
96
+
97
+ struct zkrb_event_ll {
98
+ zkrb_event_t *event;
99
+ struct zkrb_event_ll *next;
100
+ };
101
+
102
+ typedef struct zkrb_event_ll zkrb_event_ll_t;
103
+
104
+ typedef struct {
105
+ zkrb_event_ll_t *head;
106
+ zkrb_event_ll_t *tail;
107
+ int pipe_read;
108
+ int pipe_write;
109
+ pid_t orig_pid;
110
+ } zkrb_queue_t;
111
+
112
+ zkrb_queue_t * zkrb_queue_alloc(void);
113
+ void zkrb_queue_free(zkrb_queue_t *queue);
114
+ zkrb_event_t * zkrb_event_alloc(void);
115
+ void zkrb_event_free(zkrb_event_t *ptr);
116
+
117
+ void zkrb_enqueue(zkrb_queue_t *queue, zkrb_event_t *elt);
118
+ zkrb_event_t * zkrb_peek(zkrb_queue_t *queue);
119
+ zkrb_event_t * zkrb_dequeue(zkrb_queue_t *queue, int need_lock);
120
+ void zkrb_signal(zkrb_queue_t *queue);
121
+
122
+ void zkrb_print_stat(const struct Stat *s);
123
+
124
+ typedef struct {
125
+ int64_t req_id;
126
+ zkrb_queue_t *queue;
127
+ } zkrb_calling_context;
128
+
129
+ void zkrb_print_calling_context(zkrb_calling_context *ctx);
130
+ zkrb_calling_context *zkrb_calling_context_alloc(int64_t req_id, zkrb_queue_t *queue);
131
+ void zkrb_calling_context_free(zkrb_calling_context *ctx);
132
+
133
+ /*
134
+ default process completions that get queued into the ruby client event queue
135
+ */
136
+
137
+ void zkrb_state_callback(
138
+ zhandle_t *zh, int type, int state, const char *path, void *calling_ctx);
139
+
140
+ void zkrb_data_callback(
141
+ int rc, const char *value, int value_len, const struct Stat *stat, const void *calling_ctx);
142
+
143
+ void zkrb_stat_callback(
144
+ int rc, const struct Stat *stat, const void *calling_ctx);
145
+
146
+ void zkrb_string_callback(
147
+ int rc, const char *string, const void *calling_ctx);
148
+
149
+ void zkrb_strings_callback(
150
+ int rc, const struct String_vector *strings, const void *calling_ctx);
151
+
152
+ void zkrb_strings_stat_callback(
153
+ int rc, const struct String_vector *strings, const struct Stat* stat, const void *calling_ctx);
154
+
155
+ void zkrb_void_callback(
156
+ int rc, const void *calling_ctx);
157
+
158
+ void zkrb_acl_callback(
159
+ int rc, struct ACL_vector *acls, struct Stat *stat, const void *calling_ctx);
160
+
161
+ VALUE zkrb_event_to_ruby(zkrb_event_t *event);
162
+ VALUE zkrb_acl_to_ruby(struct ACL *acl);
163
+ VALUE zkrb_acl_vector_to_ruby(struct ACL_vector *acl_vector);
164
+ VALUE zkrb_id_to_ruby(struct Id *id);
165
+ VALUE zkrb_string_vector_to_ruby(struct String_vector *string_vector);
166
+ VALUE zkrb_stat_to_rarray(const struct Stat *stat);
167
+ VALUE zkrb_stat_to_rhash(const struct Stat* stat);
168
+
169
+ struct ACL_vector * zkrb_ruby_to_aclvector(VALUE acl_ary);
170
+ struct ACL_vector * zkrb_clone_acl_vector(struct ACL_vector * src);
171
+ struct String_vector * zkrb_clone_string_vector(const struct String_vector * src);
172
+ struct ACL zkrb_ruby_to_acl(VALUE rubyacl);
173
+ struct Id zkrb_ruby_to_id(VALUE rubyid);
174
+
175
+ #endif /* ZKRB_EVENT_LIB_H */
data/ext/extconf.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'mkmf'
2
+ require 'rbconfig'
3
+ require 'fileutils'
4
+
5
+ HERE = File.expand_path(File.dirname(__FILE__))
6
+ BUNDLE = Dir.glob("zkc-*.tar.gz").sort.last
7
+ ZKC_VERSION = BUNDLE[/(zkc-.*?)\.tar.gz$/, 1]
8
+ PATCHES = Dir.glob("patches/#{ZKC_VERSION}*.patch")
9
+
10
+ BUNDLE_PATH = File.join(HERE, ZKC_VERSION, 'c')
11
+
12
+ $EXTRA_CONF = ''
13
+
14
+ # CLANG!!!! jeez, if apple would only *stop* "thinking different"
15
+ if cc = RbConfig::CONFIG['CC'] && cc =~ /^gcc/
16
+ $CC = cc
17
+ $EXTRA_CONF = "#{$EXTRA_CONF} CC=#{$CC}"
18
+ end
19
+
20
+ $CFLAGS = "#{$CFLAGS}".gsub("$(cflags)", "").gsub("-arch ppc", "")
21
+ $LDFLAGS = "#{$LDFLAGS}".gsub("$(ldflags)", "").gsub("-arch ppc", "")
22
+ $CXXFLAGS = " -std=gnu++98 #{$CFLAGS}"
23
+ $CPPFLAGS = $ARCH_FLAG = ""
24
+
25
+ if RUBY_VERSION == '1.8.7'
26
+ $CFLAGS << ' -DZKRB_RUBY_187'
27
+ end
28
+
29
+ ZK_DEBUG = (ENV['DEBUG'] or ARGV.any? { |arg| arg == '--debug' })
30
+ ZK_DEV = ENV['ZK_DEV']
31
+ DEBUG_CFLAGS = " -O0 -ggdb3 -DHAVE_DEBUG -fstack-protector-all"
32
+
33
+ if ZK_DEBUG
34
+ $stderr.puts "*** Setting debug flags. ***"
35
+ $EXTRA_CONF = "#{$EXTRA_CONF} --enable-debug"
36
+ $CFLAGS.gsub!(/ -O[^0] /, ' ')
37
+ $CFLAGS << DEBUG_CFLAGS
38
+ end
39
+
40
+ $includes = " -I#{HERE}/include"
41
+ $libraries = " -L#{HERE}/lib -L#{RbConfig::CONFIG['libdir']}"
42
+ $CFLAGS = "#{$includes} #{$libraries} #{$CFLAGS}"
43
+ $LDFLAGS = "#{$libraries} #{$LDFLAGS}"
44
+ $LIBPATH = ["#{HERE}/lib"]
45
+ $DEFLIBPATH = []
46
+
47
+ def safe_sh(cmd)
48
+ puts cmd
49
+ system(cmd)
50
+ unless $?.exited? and $?.success?
51
+ raise "command failed! #{cmd}"
52
+ end
53
+ end
54
+
55
+ Dir.chdir(HERE) do
56
+ if File.exist?("lib")
57
+ puts "Zkc already built; run 'rake clobber' in ext/ first if you need to rebuild."
58
+ else
59
+ puts "Building zkc."
60
+
61
+ unless File.exists?('c')
62
+ safe_sh "tar xzf #{BUNDLE} 2>&1"
63
+ PATCHES.each do |patch|
64
+ safe_sh "patch -p0 < #{patch} 2>&1"
65
+ end
66
+ end
67
+
68
+ # clean up stupid apple rsrc fork bullshit
69
+ FileUtils.rm_f(Dir['**/._*'].select{|p| test(?f, p)})
70
+
71
+ Dir.chdir(BUNDLE_PATH) do
72
+ configure = "./configure --prefix=#{HERE} --with-pic --without-cppunit --disable-dependency-tracking #{$EXTRA_CONF} 2>&1"
73
+ configure = "env CFLAGS='#{DEBUG_CFLAGS}' #{configure}" if ZK_DEBUG
74
+
75
+ safe_sh(configure)
76
+ safe_sh("make 2>&1")
77
+ safe_sh("make install 2>&1")
78
+ end
79
+
80
+ system("rm -rf #{BUNDLE_PATH}") unless ZK_DEBUG or ZK_DEV
81
+ end
82
+ end
83
+
84
+ # Absolutely prevent the linker from picking up any other zookeeper_mt
85
+ Dir.chdir("#{HERE}/lib") do
86
+ %w[st mt].each do |stmt|
87
+ %w[a la dylib].each do |ext|
88
+ origin_lib_name = "libzookeeper_#{stmt}.#{ext}"
89
+ dest_lib_name = "libzookeeper_#{stmt}_gem.#{ext}"
90
+ system("cp -f #{origin_lib_name} #{dest_lib_name}") if File.exists?(origin_lib_name)
91
+ end
92
+ end
93
+ end
94
+
95
+ # -lm must come after lzookeeper_st_gem to ensure proper link
96
+ $LIBS << " -lzookeeper_st_gem -lm"
97
+
98
+ have_func('rb_thread_blocking_region')
99
+ have_func('rb_thread_fd_select')
100
+
101
+ $CFLAGS << ' -Wall' if ZK_DEV
102
+ create_makefile 'zookeeper_c'
103
+
@@ -0,0 +1,321 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ =begin
4
+ the idea here is to take each zoo_* function declaration in the header file, and turn it into
5
+ a calling arguments struct, a wrapper function and a macro for packing the values.
6
+
7
+ so for:
8
+
9
+ ZOOAPI int zoo_acreate(zhandle_t *zh, const char *path, const char *value,
10
+ int valuelen, const struct ACL_vector *acl, int flags,
11
+ string_completion_t completion, const void *data);
12
+
13
+ we want
14
+
15
+ typedef struct {
16
+ zhandle_t *zh;
17
+ const char *path;
18
+ const char *value;
19
+ int valuelen;
20
+ const struct ACL_vector *acl;
21
+ int flags;
22
+ string_completion_t completion;
23
+ const void *data;
24
+ } zkrb_zoo_acreate_args_t;
25
+
26
+ static VALUE zkrb_gvl_zoo_acreate(void *data) {
27
+ zkrb_zoo_acreate_args_t *a = (zkrb_zoo_acreate_args_t *)data;
28
+
29
+ a->rc = zoo_acreate(a->zh, a->path, a->value, a->valuelen, a->acl, a->flags, a->completion, a->data);
30
+
31
+ return Qnil;
32
+ }
33
+
34
+ static int zkrb_call_zoo_acreate(zhandle_t *zh, const char *path, const char *value,
35
+ int valuelen, const struct ACL_vector *acl, int flags,
36
+ string_completion_t completion, const void *data) {
37
+
38
+ zkrb_zoo_acreate_args_t args = {
39
+ .rc = ZKRB_FAIL,
40
+ .zh = zh,
41
+ .path = path,
42
+ .value = value,
43
+ .valuelen = valuelen,
44
+ .acl = acl,
45
+ .flags = flags,
46
+ .completion = completion,
47
+ .data = data
48
+ };
49
+
50
+ zkrb_thread_blocking_region(zkrb_gvl_zoo_acreate, (void *)&args);
51
+
52
+ return args.rc;
53
+ }
54
+
55
+ =end
56
+
57
+ REGEXP = /^ZOOAPI int (zoo_[^(]+)\(([^)]+)\);$/m
58
+
59
+ require 'forwardable'
60
+ require 'stringio'
61
+
62
+ THIS_DIR = File.expand_path('..', __FILE__)
63
+
64
+ ZKRB_WRAPPER_H_PATH = File.expand_path('../zkrb_wrapper.h', __FILE__)
65
+ ZKRB_WRAPPER_C_PATH = File.expand_path('../zkrb_wrapper.c', __FILE__)
66
+
67
+ # the struct that holds the call args for zoo_fn_name
68
+ class CallStruct
69
+ attr_reader :zoo_fn_name, :typed_args, :name
70
+
71
+ def initialize(zoo_fn_name, typed_args)
72
+ @zoo_fn_name, @typed_args = zoo_fn_name, typed_args
73
+ @name = "zkrb_#{zoo_fn_name}_args_t"
74
+ end
75
+
76
+ def body
77
+ @body ||= (
78
+ lines = ["typedef struct {"]
79
+ lines += typed_args.map{|n| " #{n};"}
80
+ lines << " int rc;"
81
+ lines << "} #{name};"
82
+ lines.join("\n")
83
+ )
84
+ end
85
+ end
86
+
87
+ module MemberNames
88
+ def member_names
89
+ @member_names ||= typed_args.map { |n| n.split(/[ *]/).last }
90
+ end
91
+ end
92
+
93
+ # the zkrb_gvl_zoo_* function
94
+ class WrapperFunction
95
+ extend Forwardable
96
+ include MemberNames
97
+
98
+ PREFIX = 'zkrb_gvl'
99
+
100
+ def_delegators :struct, :typed_args
101
+
102
+ attr_reader :struct, :name, :zoo_fn_name
103
+
104
+ def initialize(zoo_fn_name, struct)
105
+ @zoo_fn_name = zoo_fn_name
106
+ @struct = struct
107
+ @name = "#{PREFIX}_#{zoo_fn_name}"
108
+ end
109
+
110
+ def fn_signature
111
+ @fn_signature ||= "static VALUE #{name}(void *data)"
112
+ end
113
+
114
+ def body
115
+ @body ||= (
116
+ lines = ["#{fn_signature} {"]
117
+ lines << " #{struct.name} *a = (#{struct.name} *)data;"
118
+
119
+ funcall = " a->rc = #{zoo_fn_name}("
120
+ funcall << member_names.map { |m| "a->#{m}" }.join(', ')
121
+ funcall << ');'
122
+
123
+ lines << funcall
124
+
125
+ lines << " return Qnil;"
126
+ lines << "}"
127
+ lines.join("\n")
128
+ )
129
+ end
130
+ end
131
+
132
+ # the zkrb_call_zoo_* function
133
+ class CallingFunction
134
+ extend Forwardable
135
+ include MemberNames
136
+
137
+ PREFIX = 'zkrb_call'
138
+
139
+ def_delegators :struct, :typed_args
140
+
141
+ attr_reader :struct, :wrapper_fn, :zoo_fn_name, :name
142
+
143
+ def initialize(zoo_fn_name, struct, wrapper_fn)
144
+ @zoo_fn_name, @struct, @wrapper_fn = zoo_fn_name, struct, wrapper_fn
145
+
146
+ @name = "#{PREFIX}_#{zoo_fn_name}"
147
+ end
148
+
149
+ def fn_signature
150
+ @fn_signature ||= "int #{name}(#{typed_args.join(', ')})"
151
+ end
152
+
153
+ def initializer_lines
154
+ @initializer_lines ||= member_names.map { |n| " .#{n} = #{n}" }.join(",\n")
155
+ end
156
+
157
+ def top
158
+ <<-EOS
159
+ // wrapper that calls #{zoo_fn_name} via #{wrapper_fn.name} inside rb_thread_blocking_region
160
+ #{fn_signature} {
161
+ #{struct.name} args = {
162
+ .rc = ZKRB_FAIL,
163
+ #{initializer_lines}
164
+ };
165
+ EOS
166
+ end
167
+
168
+ def rb_thread_blocking_region_call
169
+ " zkrb_thread_blocking_region(#{wrapper_fn.name}, (void *)&args);"
170
+ end
171
+
172
+ def bottom
173
+ <<-EOS
174
+
175
+ return args.rc;
176
+ }
177
+ EOS
178
+ end
179
+
180
+ def body
181
+ @body ||= [top, rb_thread_blocking_region_call, bottom].join("\n")
182
+ end
183
+ end
184
+
185
+ class GeneratedCode < Struct.new(:structs, :wrapper_fns, :calling_fns)
186
+ def initialize(*a)
187
+ super
188
+
189
+ self.structs ||= []
190
+ self.wrapper_fns ||= []
191
+ self.calling_fns ||= []
192
+ end
193
+
194
+ def self.from_zookeeper_h(text)
195
+ new.tap do |code|
196
+ while true
197
+ break unless text =~ REGEXP
198
+ text = $~.post_match
199
+
200
+ zoo_fn_name, argstr = $1
201
+ argstr = $2
202
+
203
+ typed_args = argstr.split(',').map(&:strip)
204
+
205
+ # gah, fix up functions which have a void_completion_t with no name assigned
206
+ if idx = typed_args.index('void_completion_t')
207
+ typed_args[idx] = 'void_completion_t completion'
208
+ end
209
+
210
+ struct = CallStruct.new(zoo_fn_name, typed_args)
211
+ wrapper_fn = WrapperFunction.new(zoo_fn_name, struct)
212
+ calling_fn = CallingFunction.new(zoo_fn_name, struct, wrapper_fn)
213
+
214
+ code.structs << struct
215
+ code.wrapper_fns << wrapper_fn
216
+ code.calling_fns << calling_fn
217
+ end
218
+ end
219
+ end
220
+ end
221
+
222
+ def render_header_file(code)
223
+ StringIO.new('zkrb_wrapper.h', 'w').tap do |fp|
224
+ fp.puts <<-EOS
225
+ #ifndef ZKRB_WRAPPER_H
226
+ #define ZKRB_WRAPPER_H
227
+ #if 0
228
+
229
+ AUTOGENERATED BY #{File.basename(__FILE__)}
230
+
231
+ #endif
232
+
233
+ #include "ruby.h"
234
+ #include "zookeeper/zookeeper.h"
235
+ #include "zkrb_wrapper_compat.h"
236
+ #include "dbg.h"
237
+
238
+ #define ZKRB_FAIL -1
239
+
240
+ EOS
241
+
242
+ code.structs.each do |struct|
243
+ fp.puts(struct.body)
244
+ fp.puts
245
+ end
246
+
247
+ code.calling_fns.each do |cf|
248
+ fp.puts "#{cf.fn_signature};"
249
+ end
250
+
251
+ fp.puts <<-EOS
252
+
253
+ #endif /* ZKRB_WRAPPER_H */
254
+ EOS
255
+
256
+ end.string
257
+ end
258
+
259
+ def render_c_file(code)
260
+ StringIO.new('zkrb_wrapper.c', 'w').tap do |fp|
261
+ fp.puts <<-EOS
262
+ /*
263
+
264
+ Autogenerated boilerplate wrappers around zoo_* function calls necessary for using
265
+ rb_thread_blocking_region to release the GIL when calling native code.
266
+
267
+ generated by ext/#{File.basename(__FILE__)}
268
+
269
+ */
270
+
271
+ #include "ruby.h"
272
+ #include "zkrb_wrapper.h"
273
+ #include <errno.h>
274
+ #include <stdio.h>
275
+ #include <stdlib.h>
276
+
277
+ EOS
278
+
279
+ code.wrapper_fns.zip(code.calling_fns) do |wrap_fn, call_fn|
280
+ fp.puts "#{wrap_fn.body}\n\n"
281
+ fp.puts "#{call_fn.body}\n\n"
282
+ end
283
+
284
+ end.string
285
+ end
286
+
287
+
288
+ def help!
289
+ $stderr.puts "usage: #{File.basename(__FILE__)} {all|headers|code}"
290
+ exit 1
291
+ end
292
+
293
+ def main
294
+ help! if ARGV.empty?
295
+ opts = []
296
+
297
+ zookeeper_h_path = Dir[File.join(THIS_DIR, "**/zookeeper.h")].first
298
+
299
+ raise "Could not locate zookeeper.h!" unless zookeeper_h_path
300
+
301
+ text = File.read(zookeeper_h_path)
302
+ code = GeneratedCode.from_zookeeper_h(text)
303
+
304
+ cmd = ARGV.first
305
+
306
+ help! unless %w[headers all code].include?(cmd)
307
+
308
+ if %w[headers all].include?(cmd)
309
+ $stderr.puts "writing #{ZKRB_WRAPPER_H_PATH}"
310
+ File.open(ZKRB_WRAPPER_H_PATH, 'w') { |fp| fp.write(render_header_file(code)) }
311
+ end
312
+
313
+ if %w[code all].include?(cmd)
314
+ $stderr.puts "writing #{ZKRB_WRAPPER_C_PATH}"
315
+ File.open(ZKRB_WRAPPER_C_PATH, 'w') { |fp| fp.write(render_c_file(code)) }
316
+ end
317
+
318
+ end
319
+
320
+ main
321
+