zookeeper 1.4.4-java → 1.4.6-java

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.
@@ -0,0 +1 @@
1
+ zookeeper
@@ -0,0 +1 @@
1
+ ruby-1.9.3-p429
data/.gitignore CHANGED
@@ -15,3 +15,5 @@ coverage
15
15
  *.swp
16
16
  *.swo
17
17
 
18
+ .ruby-gemset
19
+ .ruby-version
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@
2
2
  notifications:
3
3
  email:
4
4
  - slyphon@gmail.com
5
+ - eric@5stops.com
5
6
 
6
7
  # pull in releaseops submodule
7
8
  before_install:
data/CHANGELOG CHANGED
@@ -1,3 +1,26 @@
1
+
2
+ v1.4.6
3
+
4
+ * Fix two issues with dealing with unresponsive zookeeper servers
5
+ that would prevent the client from properly recovering the session
6
+ (including one in the Apache ZooKeeper C library — see ZOOKEEPER-1756
7
+ for more details)
8
+ * Reduce the chances of seeing Zookeeper::Exceptions::NotConnected
9
+ exceptions by only submitting new commands if we are connected
10
+ * Prevent commands from being queued to be sent to the server if the
11
+ session has expired which will solve most cases involving the
12
+ Zookeeper::Exceptions::ContinuationTimeoutError exception
13
+ * Upgrade the Apache ZooKeeper C library to 3.4.5 (client is backward
14
+ compatible with 3.3 servers). The Java library has not been updated.
15
+ * Cleanup complaints from compiler for uninitialized variable access
16
+
17
+ v1.4.5
18
+
19
+ * Allow passing :session_id and :session_password options #42 (thanks to avalanche123)
20
+ * Fix permissions constants #46, #47, #48 (thanks to jaeho-kim)
21
+ * Allow JRuby to read nil values #44 (thanks to reidmorrison)
22
+
23
+
1
24
  v1.4.4 fix build under FreeBSD (h/t: stass)
2
25
 
3
26
  * https://github.com/slyphon/zookeeper/pull/40
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
@@ -8,7 +8,7 @@ group :test do
8
8
  gem "rspec" , "~> 2.11"
9
9
  gem 'eventmachine', '1.0.0'
10
10
  gem 'evented-spec', '~> 0.9.0'
11
- gem 'zk-server', '~> 1.0'
11
+ gem 'zk-server', '~> 1.0', :git => 'https://github.com/zk-ruby/zk-server.git'
12
12
  end
13
13
 
14
14
  # ffs, :platform appears to be COMLETELY BROKEN so we just DO THAT HERE
data/README.markdown CHANGED
@@ -1,10 +1,10 @@
1
1
  # zookeeper #
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/slyphon/zookeeper.png?branch=master)](http://travis-ci.org/slyphon/zookeeper)
3
+ [![Build Status](https://secure.travis-ci.org/zk-ruby/zookeeper.png?branch=master)](http://travis-ci.org/zk-ruby/zookeeper)
4
4
 
5
5
  An interface to the Zookeeper cluster coordination server.
6
6
 
7
- For a higher-level interface with a more convenient API and features such as locks, have a look at [ZK](https://github.com/slyphon/zk).
7
+ For a higher-level interface with a more convenient API and features such as locks, have a look at [ZK](https://github.com/zk-ruby/zk).
8
8
 
9
9
  ## Fork Safety! ##
10
10
 
data/Rakefile CHANGED
@@ -25,6 +25,7 @@ if File.exists?(release_ops_path)
25
25
 
26
26
  namespace :zk do
27
27
  namespace :gems do
28
+ desc "Build gems to prepare for a release. Requires TAG="
28
29
  task :build do
29
30
  require 'tmpdir'
30
31
 
@@ -41,14 +42,15 @@ if File.exists?(release_ops_path)
41
42
  sh "git co #{tag} && git reset --hard && git clean -fdx"
42
43
 
43
44
  ENV['JAVA_GEM'] = nil
44
- sh "rvm 1.8.7 do gem build zookeeper.gemspec"
45
- sh "rvm 1.8.7 do env JAVA_GEM=1 gem build zookeeper.gemspec"
45
+ sh "gem build zookeeper.gemspec"
46
+ sh "env JAVA_GEM=1 gem build zookeeper.gemspec"
46
47
 
47
48
  mv FileList['*.gem'], orig_dir
48
49
  end
49
50
  end
50
51
  end
51
52
 
53
+ desc "Release gems that have been built"
52
54
  task :push do
53
55
  gems = FileList['*.gem']
54
56
  raise "No gemfiles to push!" if gems.empty?
@@ -90,8 +92,17 @@ namespace :build do
90
92
 
91
93
  Rake::Task['build'].invoke
92
94
  end
95
+
96
+ task :clobber do
97
+ cd 'ext' do
98
+ sh 'rake clobber'
99
+ end
100
+
101
+ Rake::Task['build'].invoke
102
+ end
93
103
  end
94
104
 
105
+ desc "Build C component"
95
106
  task :build do
96
107
  cd 'ext' do
97
108
  sh "rake"
data/ext/Rakefile CHANGED
@@ -1,10 +1,6 @@
1
1
  require 'rbconfig'
2
2
 
3
- LIB_ZK_SO = 'lib/libzookeeper_mt_gem.la'
4
-
5
- TARBALL = FileList['zkc-*.tar.gz'].first
6
-
7
- raise "Where is the zkc tarball!?" unless TARBALL
3
+ ZKRB_WRAPPER = %w[zkrb_wrapper.c zkrb_wrapper.h]
8
4
 
9
5
  namespace :zkrb do
10
6
  task :clean do
@@ -17,49 +13,29 @@ namespace :zkrb do
17
13
  end
18
14
 
19
15
  task :clobber => :clean do
20
- rm_rf %w[Makefile c lib bin include ._c]
16
+ rm_rf %w[Makefile c lib bin include ._c] + ZKRB_WRAPPER
21
17
  end
22
18
  end
23
19
 
24
- task :clean => 'zkrb:clean'
25
- task :clobber => 'zkrb:clobber'
26
-
27
- GENERATE_GVL_CODE_RB = 'generate_gvl_code.rb'
28
-
29
- # file 'c' do
30
- # if tarball = Dir['zkc-*.tar.gz'].first
31
- # sh "tar -zxf #{tarball}"
32
- # else
33
- # raise "couldn't find the tarball! wtf?!"
34
- # end
35
- # end
36
-
37
- file 'c' => TARBALL do
38
- sh "tar -zxf #{TARBALL}"
39
- sh "patch -p0 < patch-zookeeper"
40
- end
41
-
42
- file GENERATE_GVL_CODE_RB => 'c'
20
+ task :clean => 'zkrb:clean'
21
+ task :clobber => 'zkrb:clobber'
22
+ task :wrappers => ZKRB_WRAPPER
23
+ task :default => :build
43
24
 
44
- file 'zkrb_wrapper.c' => GENERATE_GVL_CODE_RB do
25
+ file 'zkrb_wrapper.c' => 'generate_gvl_code.rb' do
45
26
  sh "ruby generate_gvl_code.rb code"
46
27
  end
47
28
 
48
- file 'zkrb_wrapper.h' => GENERATE_GVL_CODE_RB do
29
+ file 'zkrb_wrapper.h' => 'generate_gvl_code.rb' do
49
30
  sh "ruby generate_gvl_code.rb headers"
50
31
  end
51
32
 
52
- ZKRB_WRAPPER = %w[zkrb_wrapper.c zkrb_wrapper.h]
53
-
54
- task :wrappers => ZKRB_WRAPPER
55
-
56
33
  file 'Makefile' do
57
34
  sh "ruby extconf.rb"
58
35
  end
59
36
 
60
- task :build => [ZKRB_WRAPPER, 'Makefile'].flatten do
37
+ task :build => [ 'Makefile', :wrappers ] do
61
38
  sh 'make'
62
39
  end
63
40
 
64
- task :default => :build
65
41
 
data/ext/c_zookeeper.rb CHANGED
@@ -17,7 +17,7 @@ class CZookeeper
17
17
  include Exceptions
18
18
  include Logger
19
19
 
20
- DEFAULT_SESSION_TIMEOUT_MSEC = 10000
20
+ DEFAULT_RECEIVE_TIMEOUT_MSEC = 10000
21
21
 
22
22
  class GotNilEventException < StandardError; end
23
23
 
@@ -65,7 +65,7 @@ class CZookeeper
65
65
  # the actual C data is stashed in this ivar. never *ever* touch this
66
66
  @_data = nil
67
67
 
68
- @_session_timeout_msec = DEFAULT_SESSION_TIMEOUT_MSEC
68
+ @_receive_timeout_msec = opts[:receive_timeout_msec] || DEFAULT_RECEIVE_TIMEOUT_MSEC
69
69
 
70
70
  @mutex = Monitor.new
71
71
 
@@ -89,7 +89,7 @@ class CZookeeper
89
89
 
90
90
  logger.info { "initiating connection to #{@host}" }
91
91
 
92
- zkrb_init(@host)#, :zkc_log_level => log_level)
92
+ zkrb_init(@host, opts)#, :zkc_log_level => log_level)
93
93
 
94
94
  start_event_thread
95
95
 
@@ -120,6 +120,14 @@ class CZookeeper
120
120
  state == ZOO_ASSOCIATING_STATE
121
121
  end
122
122
 
123
+ def unhealthy?
124
+ @_closed || @_shutting_down || is_unrecoverable
125
+ end
126
+
127
+ def healthy?
128
+ !unhealthy?
129
+ end
130
+
123
131
  def close
124
132
  return if closed?
125
133
 
@@ -183,11 +191,11 @@ class CZookeeper
183
191
  while true
184
192
  if timeout
185
193
  now = Time.now
186
- break if (@state == ZOO_CONNECTED_STATE) || @_shutting_down || @_closed || (now > time_to_stop)
194
+ break if (@state == ZOO_CONNECTED_STATE) || unhealthy? || (now > time_to_stop)
187
195
  delay = time_to_stop.to_f - now.to_f
188
196
  @state_cond.wait(delay)
189
197
  else
190
- break if (@state == ZOO_CONNECTED_STATE) || @_shutting_down || @_closed
198
+ break if (@state == ZOO_CONNECTED_STATE) || unhealthy?
191
199
  @state_cond.wait
192
200
  end
193
201
  end
@@ -201,7 +209,7 @@ class CZookeeper
201
209
  # blocks the caller until result has returned
202
210
  def submit_and_block(meth, *args)
203
211
  @mutex.synchronize do
204
- raise Exceptions::NotConnected if @_shutting_down
212
+ raise Exceptions::NotConnected if unhealthy?
205
213
  end
206
214
 
207
215
  cnt = Continuation.new(meth, *args)
@@ -257,8 +265,11 @@ class CZookeeper
257
265
  event_thread_await_running
258
266
 
259
267
  # this is the main loop
260
- until (@_shutting_down or @_closed or is_unrecoverable)
261
- submit_pending_calls if @reg.anything_to_do?
268
+ while healthy?
269
+ if @reg.anything_to_do? && connected?
270
+ submit_pending_calls
271
+ end
272
+
262
273
  zkrb_iterate_event_loop
263
274
  iterate_event_delivery
264
275
  end
@@ -269,7 +280,7 @@ class CZookeeper
269
280
  if @_shutting_down and not (@_closed or is_unrecoverable)
270
281
  logger.debug { "we're in shutting down state, there are #{@reg.in_flight.length} in_flight completions" }
271
282
 
272
- until @reg.in_flight.empty? or is_unrecoverable or @_closed
283
+ until @reg.in_flight.empty? or @_closed or is_unrecoverable
273
284
  zkrb_iterate_event_loop
274
285
  iterate_event_delivery
275
286
  logger.debug { "there are #{@reg.in_flight} in_flight completions left" }
data/ext/event_lib.c CHANGED
@@ -21,7 +21,7 @@ slyphon@gmail.com
21
21
  */
22
22
 
23
23
  #include "ruby.h"
24
- #include "c-client-src/zookeeper.h"
24
+ #include "zookeeper/zookeeper.h"
25
25
  #include <errno.h>
26
26
  #include <stdio.h>
27
27
  #include <stdlib.h>
@@ -321,7 +321,7 @@ VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
321
321
 
322
322
  switch (event->type) {
323
323
  case ZKRB_DATA: {
324
- zkrb_debug("zkrb_event_to_ruby ZKRB_DATA\n");
324
+ zkrb_debug("zkrb_event_to_ruby ZKRB_DATA");
325
325
  struct zkrb_data_completion *data_ctx = event->completion.data_completion;
326
326
  if (ZKRBDebugging) zkrb_print_stat(data_ctx->stat);
327
327
  rb_hash_aset(hash, GET_SYM("data"), data_ctx->data ? rb_str_new(data_ctx->data, data_ctx->data_len) : Qnil);
@@ -329,39 +329,39 @@ VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
329
329
  break;
330
330
  }
331
331
  case ZKRB_STAT: {
332
- zkrb_debug("zkrb_event_to_ruby ZKRB_STAT\n");
332
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STAT");
333
333
  struct zkrb_stat_completion *stat_ctx = event->completion.stat_completion;
334
334
  rb_hash_aset(hash, GET_SYM("stat"), stat_ctx->stat ? zkrb_stat_to_rarray(stat_ctx->stat) : Qnil);
335
335
  break;
336
336
  }
337
337
  case ZKRB_STRING: {
338
- zkrb_debug("zkrb_event_to_ruby ZKRB_STRING\n");
338
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STRING");
339
339
  struct zkrb_string_completion *string_ctx = event->completion.string_completion;
340
340
  rb_hash_aset(hash, GET_SYM("string"), string_ctx->value ? rb_str_new2(string_ctx->value) : Qnil);
341
341
  break;
342
342
  }
343
343
  case ZKRB_STRINGS: {
344
- zkrb_debug("zkrb_event_to_ruby ZKRB_STRINGS\n");
344
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STRINGS");
345
345
  struct zkrb_strings_completion *strings_ctx = event->completion.strings_completion;
346
346
  rb_hash_aset(hash, GET_SYM("strings"), strings_ctx->values ? zkrb_string_vector_to_ruby(strings_ctx->values) : Qnil);
347
347
  break;
348
348
  }
349
349
  case ZKRB_STRINGS_STAT: {
350
- zkrb_debug("zkrb_event_to_ruby ZKRB_STRINGS_STAT\n");
350
+ zkrb_debug("zkrb_event_to_ruby ZKRB_STRINGS_STAT");
351
351
  struct zkrb_strings_stat_completion *strings_stat_ctx = event->completion.strings_stat_completion;
352
352
  rb_hash_aset(hash, GET_SYM("strings"), strings_stat_ctx->values ? zkrb_string_vector_to_ruby(strings_stat_ctx->values) : Qnil);
353
353
  rb_hash_aset(hash, GET_SYM("stat"), strings_stat_ctx->stat ? zkrb_stat_to_rarray(strings_stat_ctx->stat) : Qnil);
354
354
  break;
355
355
  }
356
356
  case ZKRB_ACL: {
357
- zkrb_debug("zkrb_event_to_ruby ZKRB_ACL\n");
357
+ zkrb_debug("zkrb_event_to_ruby ZKRB_ACL");
358
358
  struct zkrb_acl_completion *acl_ctx = event->completion.acl_completion;
359
359
  rb_hash_aset(hash, GET_SYM("acl"), acl_ctx->acl ? zkrb_acl_vector_to_ruby(acl_ctx->acl) : Qnil);
360
360
  rb_hash_aset(hash, GET_SYM("stat"), acl_ctx->stat ? zkrb_stat_to_rarray(acl_ctx->stat) : Qnil);
361
361
  break;
362
362
  }
363
363
  case ZKRB_WATCHER: {
364
- zkrb_debug("zkrb_event_to_ruby ZKRB_WATCHER\n");
364
+ zkrb_debug("zkrb_event_to_ruby ZKRB_WATCHER");
365
365
  struct zkrb_watcher_completion *watcher_ctx = event->completion.watcher_completion;
366
366
  rb_hash_aset(hash, GET_SYM("type"), INT2FIX(watcher_ctx->type));
367
367
  rb_hash_aset(hash, GET_SYM("state"), INT2FIX(watcher_ctx->state));
@@ -377,8 +377,8 @@ VALUE zkrb_event_to_ruby(zkrb_event_t *event) {
377
377
  }
378
378
 
379
379
  void zkrb_print_stat(const struct Stat *s) {
380
- fprintf(stderr, "stat {\n");
381
380
  if (s != NULL) {
381
+ fprintf(stderr, "stat {\n");
382
382
  fprintf(stderr, "\t czxid: %"PRId64"\n", s->czxid); // PRId64 defined in inttypes.h
383
383
  fprintf(stderr, "\t mzxid: %"PRId64"\n", s->mzxid);
384
384
  fprintf(stderr, "\t ctime: %"PRId64"\n", s->ctime);
@@ -390,10 +390,10 @@ void zkrb_print_stat(const struct Stat *s) {
390
390
  fprintf(stderr, "\t dataLength: %d\n", s->dataLength);
391
391
  fprintf(stderr, "\t numChildren: %d\n", s->numChildren);
392
392
  fprintf(stderr, "\t pzxid: %"PRId64"\n", s->pzxid);
393
+ fprintf(stderr, "}\n");
393
394
  } else {
394
- fprintf(stderr, "\tNULL\n");
395
+ fprintf(stderr, "stat { NULL }\n");
395
396
  }
396
- fprintf(stderr, "}\n");
397
397
  }
398
398
 
399
399
  zkrb_calling_context *zkrb_calling_context_alloc(int64_t req_id, zkrb_queue_t *queue) {
@@ -436,7 +436,7 @@ void zkrb_state_callback(
436
436
  zhandle_t *zh, int type, int state, const char *path, void *calling_ctx) {
437
437
 
438
438
  zkrb_debug("ZOOKEEPER_C_STATE WATCHER "
439
- "type = %d, state = %d, path = %p, value = %s\n",
439
+ "type = %d, state = %d, path = %p, value = %s",
440
440
  type, state, (void *) path, path ? path : "NULL");
441
441
 
442
442
  /* save callback context */
@@ -466,7 +466,7 @@ void zkrb_data_callback(
466
466
  int rc, const char *value, int value_len, const struct Stat *stat, const void *calling_ctx) {
467
467
 
468
468
  zkrb_debug("ZOOKEEPER_C_DATA WATCHER "
469
- "rc = %d (%s), value = %s, len = %d\n",
469
+ "rc = %d (%s), value = %s, len = %d",
470
470
  rc, zerror(rc), value ? value : "NULL", value_len);
471
471
 
472
472
  /* copy data completion */
@@ -494,7 +494,7 @@ void zkrb_data_callback(
494
494
  void zkrb_stat_callback(
495
495
  int rc, const struct Stat *stat, const void *calling_ctx) {
496
496
  zkrb_debug("ZOOKEEPER_C_STAT WATCHER "
497
- "rc = %d (%s)\n", rc, zerror(rc));
497
+ "rc = %d (%s)", rc, zerror(rc));
498
498
 
499
499
  struct zkrb_stat_completion *sc = zk_malloc(sizeof(struct zkrb_stat_completion));
500
500
  sc->stat = NULL;
@@ -512,7 +512,7 @@ void zkrb_string_callback(
512
512
  int rc, const char *string, const void *calling_ctx) {
513
513
 
514
514
  zkrb_debug("ZOOKEEPER_C_STRING WATCHER "
515
- "rc = %d (%s)\n", rc, zerror(rc));
515
+ "rc = %d (%s)", rc, zerror(rc));
516
516
 
517
517
  struct zkrb_string_completion *sc = zk_malloc(sizeof(struct zkrb_string_completion));
518
518
  sc->value = NULL;
@@ -530,7 +530,7 @@ void zkrb_string_callback(
530
530
  void zkrb_strings_callback(
531
531
  int rc, const struct String_vector *strings, const void *calling_ctx) {
532
532
  zkrb_debug("ZOOKEEPER_C_STRINGS WATCHER "
533
- "rc = %d (%s), calling_ctx = %p\n", rc, zerror(rc), calling_ctx);
533
+ "rc = %d (%s), calling_ctx = %p", rc, zerror(rc), calling_ctx);
534
534
 
535
535
  /* copy string vector */
536
536
  struct zkrb_strings_completion *sc = zk_malloc(sizeof(struct zkrb_strings_completion));
@@ -547,7 +547,7 @@ void zkrb_strings_callback(
547
547
  void zkrb_strings_stat_callback(
548
548
  int rc, const struct String_vector *strings, const struct Stat *stat, const void *calling_ctx) {
549
549
  zkrb_debug("ZOOKEEPER_C_STRINGS_STAT WATCHER "
550
- "rc = %d (%s), calling_ctx = %p\n", rc, zerror(rc), calling_ctx);
550
+ "rc = %d (%s), calling_ctx = %p", rc, zerror(rc), calling_ctx);
551
551
 
552
552
  struct zkrb_strings_stat_completion *sc = zk_malloc(sizeof(struct zkrb_strings_stat_completion));
553
553
  sc->stat = NULL;
@@ -565,7 +565,7 @@ void zkrb_strings_stat_callback(
565
565
 
566
566
  void zkrb_void_callback(int rc, const void *calling_ctx) {
567
567
  zkrb_debug("ZOOKEEPER_C_VOID WATCHER "
568
- "rc = %d (%s)\n", rc, zerror(rc));
568
+ "rc = %d (%s)", rc, zerror(rc));
569
569
 
570
570
  ZKH_SETUP_EVENT(queue, event);
571
571
  event->rc = rc;
@@ -577,7 +577,7 @@ void zkrb_void_callback(int rc, const void *calling_ctx) {
577
577
 
578
578
  void zkrb_acl_callback(
579
579
  int rc, struct ACL_vector *acls, struct Stat *stat, const void *calling_ctx) {
580
- zkrb_debug("ZOOKEEPER_C_ACL WATCHER rc = %d (%s)\n", rc, zerror(rc));
580
+ zkrb_debug("ZOOKEEPER_C_ACL WATCHER rc = %d (%s)", rc, zerror(rc));
581
581
 
582
582
  struct zkrb_acl_completion *ac = zk_malloc(sizeof(struct zkrb_acl_completion));
583
583
  ac->acl = NULL;
data/ext/event_lib.h CHANGED
@@ -2,7 +2,7 @@
2
2
  #define ZKRB_EVENT_LIB_H
3
3
 
4
4
  #include "ruby.h"
5
- #include "c-client-src/zookeeper.h"
5
+ #include "zookeeper/zookeeper.h"
6
6
  #include <errno.h>
7
7
  #include <stdio.h>
8
8
  #include <stdlib.h>
data/ext/extconf.rb CHANGED
@@ -3,10 +3,11 @@ require 'rbconfig'
3
3
  require 'fileutils'
4
4
 
5
5
  HERE = File.expand_path(File.dirname(__FILE__))
6
- BUNDLE = Dir.glob("zkc-*.tar.gz").first
7
- ZKPATCH = "patch-zookeeper"
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")
8
9
 
9
- BUNDLE_PATH = File.join(HERE, 'c')
10
+ BUNDLE_PATH = File.join(HERE, ZKC_VERSION, 'c')
10
11
 
11
12
  $EXTRA_CONF = ''
12
13
 
@@ -58,8 +59,10 @@ Dir.chdir(HERE) do
58
59
  puts "Building zkc."
59
60
 
60
61
  unless File.exists?('c')
61
- puts(cmd = "tar xzf #{BUNDLE} 2>&1 && patch -p0 < #{ZKPATCH} 2>&1")
62
- raise "'#{cmd}' failed" unless system(cmd)
62
+ safe_sh "tar xzf #{BUNDLE} 2>&1"
63
+ PATCHES.each do |patch|
64
+ safe_sh "patch -p0 < #{patch} 2>&1"
65
+ end
63
66
  end
64
67
 
65
68
  # clean up stupid apple rsrc fork bullshit