slyphon-zookeeper 0.1.0-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.
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ *.o
3
+ *.so
4
+ *~
5
+ *.log
6
+ Makefile
7
+ pkg
8
+ zookeeper.gemspec
data/CHANGELOG ADDED
@@ -0,0 +1,23 @@
1
+ v0.4.3 Fix a handful of memory-related bugs, fix SIGSEGV on master change,
2
+ reduce latency of event handling, fix compilation on OSX.
3
+
4
+ v0.4.2 Add options to Zookeeper#initialize, silence most Zookeeper logs.
5
+
6
+ v0.4.1 Upgrade to ZooKeeper 3.3.2
7
+
8
+ v0.4.0. More attr-readers (StarvingMarvin) and 1.9 compatibility (tsuraan)
9
+
10
+ v0.3.2. Handle close, closed connections and expired sessions a little more gracefully.
11
+
12
+ v0.3.1. ACL bugfix.
13
+
14
+ v0.3.0. Wickman's rewrite, breaks dependencies from myelin/emaland port.
15
+
16
+ v0.2.2. Fix compatibility with stock Leopard fat-binary Ruby.
17
+
18
+ v0.2.1. No more camelcase classname.
19
+
20
+ v0.2. Bundle C dependencies, like memcached.gem.
21
+
22
+ v0.1. First release.
23
+
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ (The MIT License)
2
+
3
+ Copyright (C) 2008 Phillip Pearson
4
+ Copyright (C) 2010 Twitter, Inc.
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ 'Software'), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Manifest ADDED
@@ -0,0 +1,33 @@
1
+ CHANGELOG
2
+ Gemfile
3
+ LICENSE
4
+ Manifest
5
+ README
6
+ Rakefile
7
+ Session.vim
8
+ examples/cloud_config.rb
9
+ ext/extconf.rb
10
+ ext/zkc-3.3.2.tar.gz
11
+ ext/zookeeper_base.rb
12
+ ext/zookeeper_c.c
13
+ ext/zookeeper_lib.c
14
+ ext/zookeeper_lib.h
15
+ java/zookeeper_base.rb
16
+ lib/zookeeper.rb
17
+ lib/zookeeper/acls.rb
18
+ lib/zookeeper/callbacks.rb
19
+ lib/zookeeper/common.rb
20
+ lib/zookeeper/constants.rb
21
+ lib/zookeeper/exceptions.rb
22
+ lib/zookeeper/stat.rb
23
+ spec/log4j.properties
24
+ spec/spec_helper.rb
25
+ spec/zookeeper_spec.rb
26
+ tags
27
+ test/test_basic.rb
28
+ test/test_callback1.rb
29
+ test/test_close.rb
30
+ test/test_esoteric.rb
31
+ test/test_watcher1.rb
32
+ test/test_watcher2.rb
33
+ zookeeper.gemspec
data/README ADDED
@@ -0,0 +1,42 @@
1
+ zookeeper
2
+
3
+ An interface to the Zookeeper distributed configuration server.
4
+
5
+ == License
6
+
7
+ Copyright 2008 Phillip Pearson, and 2010 Twitter, Inc. Licensed under the
8
+ MIT License. See the included LICENSE file. Portions copyright 2008-2010
9
+ the Apache Software Foundation, licensed under the Apache 2 license, and
10
+ used with permission.
11
+
12
+ == Install
13
+
14
+ sudo gem install zookeeper
15
+
16
+ == Usage
17
+
18
+ Connect to a server:
19
+
20
+ require 'rubygems'
21
+ require 'zookeeper'
22
+ z = Zookeeper.new("localhost:2181")
23
+ z.get_children(:path => "/")
24
+
25
+ == Idioms
26
+
27
+ The following methods are initially supported:
28
+ get
29
+ set
30
+ get_children
31
+ stat
32
+ create
33
+ delete
34
+ get_acl
35
+ set_acl
36
+
37
+ All support async callbacks. get, get_children and stat support both
38
+ watchers and callbacks.
39
+
40
+ Calls take a dictionary of parameters. With the exception of set_acl, the
41
+ only required parameter is :path. Each call returns a dictionary with at
42
+ minimum two keys :req_id and :rc.
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'echoe'
2
+
3
+ Echoe.new("zookeeper") do |p|
4
+ p.author = "Phillip Pearson, Eric Maland, Evan Weaver, Brian Wickman"
5
+ p.project = "fauna"
6
+ p.summary = "An interface to the Zookeeper distributed configuration server."
7
+ p.url = "https://github.com/twitter/zookeeper"
8
+ p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
9
+ p.clean_pattern += ["ext/lib", "ext/include", "ext/c", "ext/bin", "ext/conftest.dSYM"]
10
+ p.rdoc_pattern = /README|TODO|LICENSE|CHANGELOG|BENCH|COMPAT|zookeeper_c.c|zookeeper.rb/
11
+ end
12
+
13
+ namespace :mb do
14
+ task :build_gems do
15
+ sh "gem build slyphon-zookeeper.gemspec"
16
+ ENV['JAVA_GEM'] = '1'
17
+ sh "gem build slyphon-zookeeper.gemspec"
18
+ end
19
+ end
@@ -0,0 +1,125 @@
1
+ require "rubygems"
2
+ require "zookeeper"
3
+
4
+ # A basic cloud-based YAML config library. Ruby Zookeeper client example.
5
+ #
6
+ # If you pass in a file as 'zk:/foo.yml/blah' it will go out to zookeeper.
7
+ # Otherwise the file is assumed to be local. The yml file will get parsed
8
+ # and cached locally, and keys after the .yml get interpreted as keys into
9
+ # the YAML.
10
+ #
11
+ # e.g. get(zk:/config/service.yml/key1/key2/key3..) =>
12
+ # zk.get(:path => /config/service.yml)
13
+ # yaml <= YAML.parse(data)
14
+ # yaml[key1][key2][key3]...
15
+ #
16
+ # If keys are unspecified, it returns the parsed YAML as one big object
17
+ #
18
+ # TODO if staleness is set to 0, read in YAML immediately before next
19
+ # get(...)
20
+
21
+ class CloudConfig
22
+ class NodeNotFound < StandardError; end
23
+ class BadPathError < StandardError; end
24
+
25
+ DEFAULT_SERVERS = "localhost:2181"
26
+
27
+ def initialize(zkservers = DEFAULT_SERVERS, staleness = 15) # maximum allowed staleness in seconds
28
+ @staleness = staleness
29
+ @lock = Mutex.new
30
+ @zkservers = DEFAULT_SERVERS
31
+
32
+ # cache
33
+ @data = {}
34
+ @zkcb = Zookeeper::WatcherCallback.new { dirty_callback(@zkcb.context) }
35
+ @zk = nil
36
+ end
37
+
38
+ def get(node)
39
+ filename, keys = extract_filename(node)
40
+
41
+ # read(filename) is potentially a zk call, so do not hold the lock during the read
42
+ if @lock.synchronize { !@data.has_key?(filename) }
43
+ d = YAML.load(read(filename))
44
+ @lock.synchronize { @data[filename] = d }
45
+ end
46
+
47
+ # synchronized b/c we potentially have a background thread updating data nodes from zk
48
+ # if keys is empty, return the whole file, otherwise roll up the keys
49
+ @lock.synchronize {
50
+ keys.empty? ? @data[filename] : keys.inject(@data[filename]) { |hash, key| hash[key] }
51
+ }
52
+ end
53
+
54
+ # todo:
55
+ # factor get-and-watch into a different subsystem (so you can have
56
+ # polling stat() ops on local filesystem.)
57
+ def read(yaml)
58
+ # read yaml file and register watcher. if watcher fires, set up
59
+ # background thread to do read and update data.
60
+ if yaml.match(/^zk:/)
61
+ @zk ||= init_zk
62
+ yaml = yaml['zk:'.length..-1] # strip off zk: from zk:/config/path.yml
63
+ resp = get_and_register(yaml)
64
+
65
+ if resp[:rc] != Zookeeper::ZOK
66
+ @zk.unregister_watcher(resp[:req_id])
67
+ raise NodeNotFound
68
+ end
69
+
70
+ resp[:data]
71
+ else
72
+ raise NodeNotFound unless File.exists?(yaml)
73
+ File.read(yaml)
74
+ end
75
+ end
76
+
77
+ def extract_filename(node)
78
+ path_elements = node.split("/")
79
+
80
+ yamlindex = path_elements.map{ |x| x.match("\.yml$") != nil }.index(true)
81
+ raise BadPathError unless yamlindex
82
+
83
+ yamlname = path_elements[0..yamlindex].join '/'
84
+ yamlkeys = path_elements[(yamlindex+1)..-1]
85
+
86
+ return yamlname, yamlkeys
87
+ end
88
+
89
+ private
90
+ def init_zk
91
+ Zookeeper.new(@zkservers)
92
+ end
93
+
94
+ def get_and_register(znode)
95
+ @zk.get(:path => znode, :watcher => @zkcb,
96
+ :watcher_context => { :path => znode,
97
+ :wait => rand(@staleness) })
98
+ end
99
+
100
+ def dirty_callback(context)
101
+ path = context[:path]
102
+ wait = context[:wait]
103
+
104
+ # Fire off a background update that waits a randomized period of time up
105
+ # to @staleness seconds.
106
+ Thread.new do
107
+ sleep wait
108
+ background_update(path)
109
+ end
110
+ end
111
+
112
+ def background_update(zkpath)
113
+ # do a synchronous get/register a new watcher
114
+ resp = get_and_register(zkpath)
115
+ if resp[:rc] != Zookeeper::ZOK
116
+ # puts "Unable to read #{zkpath} from Zookeeper!" @logger.error
117
+ zk.unregister_watcher(resp[:req_id])
118
+ else
119
+ # puts "Updating data."
120
+ d = YAML.load(resp[:data])
121
+ @lock.synchronize { @data["zk:#{zkpath}"] = d }
122
+ end
123
+ end
124
+ end
125
+
data/ext/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ bin
2
+ include
3
+ lib
4
+ *.bundle
5
+
data/ext/extconf.rb ADDED
@@ -0,0 +1,56 @@
1
+
2
+ require 'mkmf'
3
+ require 'rbconfig'
4
+
5
+ HERE = File.expand_path(File.dirname(__FILE__))
6
+ BUNDLE = Dir.glob("zkc-*.tar.gz").first
7
+ BUNDLE_PATH = "c"
8
+
9
+ $CFLAGS = "#{RbConfig::CONFIG['CFLAGS']} #{$CFLAGS}".gsub("$(cflags)", "").gsub("-arch ppc", "")
10
+ $LDFLAGS = "#{RbConfig::CONFIG['LDFLAGS']} #{$LDFLAGS}".gsub("$(ldflags)", "").gsub("-arch ppc", "")
11
+ $CXXFLAGS = " -std=gnu++98 #{$CFLAGS}"
12
+ $CPPFLAGS = $ARCH_FLAG = $DLDFLAGS = ""
13
+
14
+ if ENV['DEBUG']
15
+ puts "Setting debug flags."
16
+ $CFLAGS << " -O0 -ggdb3 -DHAVE_DEBUG"
17
+ $EXTRA_CONF = " --enable-debug"
18
+ $CFLAGS.gsub!(/ -O[^0] /, ' ')
19
+ end
20
+
21
+ $includes = " -I#{HERE}/include"
22
+ $libraries = " -L#{HERE}/lib -L#{RbConfig::CONFIG['libdir']}"
23
+ $CFLAGS = "#{$includes} #{$libraries} #{$CFLAGS}"
24
+ $LDFLAGS = "#{$libraries} #{$LDFLAGS}"
25
+ $LIBPATH = ["#{HERE}/lib"]
26
+ $DEFLIBPATH = []
27
+
28
+ Dir.chdir(HERE) do
29
+ if File.exist?("lib")
30
+ puts "Zkc already built; run 'rake clean' first if you need to rebuild."
31
+ else
32
+ puts "Building zkc."
33
+ puts(cmd = "tar xzf #{BUNDLE} 2>&1")
34
+ raise "'#{cmd}' failed" unless system(cmd)
35
+
36
+ Dir.chdir(BUNDLE_PATH) do
37
+ puts(cmd = "env CC=gcc CXX=g++ CFLAGS='-fPIC #{$CFLAGS}' LDFLAGS='-fPIC #{$LDFLAGS}' ./configure --prefix=#{HERE} --without-cppunit --disable-dependency-tracking #{$EXTRA_CONF} 2>&1")
38
+ raise "'#{cmd}' failed" unless system(cmd)
39
+ puts(cmd = "make CXXFLAGS='#{$CXXFLAGS}' CFLAGS='-fPIC #{$CFLAGS}' LDFLAGS='-fPIC #{$LDFLAGS}' || true 2>&1")
40
+ raise "'#{cmd}' failed" unless system(cmd)
41
+ puts(cmd = "make install || true 2>&1")
42
+ raise "'#{cmd}' failed" unless system(cmd)
43
+ end
44
+
45
+ system("rm -rf #{BUNDLE_PATH}") unless ENV['DEBUG'] or ENV['DEV']
46
+ end
47
+ end
48
+
49
+ # Absolutely prevent the linker from picking up any other zookeeper_mt
50
+ Dir.chdir("#{HERE}/lib") do
51
+ system("cp -f libzookeeper_mt.a libzookeeper_mt_gem.a")
52
+ system("cp -f libzookeeper_mt.la libzookeeper_mt_gem.la")
53
+ end
54
+ $LIBS << " -lzookeeper_mt_gem"
55
+
56
+ create_makefile 'zookeeper_c'
Binary file
@@ -0,0 +1,117 @@
1
+ # The low-level wrapper-specific methods for the C lib
2
+ # subclassed by the top-level Zookeeper class
3
+ class ZookeeperBase < CZookeeper
4
+ include ZookeeperCommon
5
+ include ZookeeperCallbacks
6
+ include ZookeeperConstants
7
+ include ZookeeperExceptions
8
+ include ZookeeperACLs
9
+ include ZookeeperStat
10
+
11
+
12
+ ZKRB_GLOBAL_CB_REQ = -1
13
+
14
+ # debug levels
15
+ ZOO_LOG_LEVEL_ERROR = 1
16
+ ZOO_LOG_LEVEL_WARN = 2
17
+ ZOO_LOG_LEVEL_INFO = 3
18
+ ZOO_LOG_LEVEL_DEBUG = 4
19
+
20
+ def reopen(timeout = 10, watcher=nil)
21
+ watcher ||= @default_watcher
22
+
23
+ @req_mutex.synchronize do
24
+ # flushes all outstanding watcher reqs.
25
+ @watcher_req = {}
26
+ set_default_global_watcher(&watcher)
27
+ end
28
+
29
+ init(@host)
30
+
31
+ if timeout > 0
32
+ time_to_stop = Time.now + timeout
33
+ until state == Zookeeper::ZOO_CONNECTED_STATE
34
+ break if Time.now > time_to_stop
35
+ sleep 0.1
36
+ end
37
+ end
38
+
39
+ state
40
+ end
41
+
42
+ def initialize(host, timeout = 10, watcher=nil)
43
+ @watcher_reqs = {}
44
+ @completion_reqs = {}
45
+ @req_mutex = Monitor.new
46
+ @current_req_id = 1
47
+ @host = host
48
+
49
+ watcher ||= get_default_global_watcher
50
+
51
+ @_running = nil # used by the C layer
52
+ reopen(timeout, watcher)
53
+ return nil unless connected?
54
+ setup_dispatch_thread!
55
+ end
56
+
57
+ # if either of these happen, the user will need to renegotiate a connection via reopen
58
+ def assert_open
59
+ raise ZookeeperException::SessionExpired if state == ZOO_EXPIRED_SESSION_STATE
60
+ raise ZookeeperException::ConnectionClosed unless connected?
61
+ end
62
+
63
+ def connected?
64
+ state == ZOO_CONNECTED_STATE
65
+ end
66
+
67
+ def connecting?
68
+ state == ZOO_CONNECTING_STATE
69
+ end
70
+
71
+ def associating?
72
+ state == ZOO_ASSOCIATING_STATE
73
+ end
74
+
75
+ def close
76
+ @_running = false;
77
+ wake_event_loop!
78
+
79
+ @dispatcher.join
80
+
81
+ super
82
+ end
83
+
84
+ # set the watcher object/proc that will receive all global events (such as session/state events)
85
+ def set_default_global_watcher(&block)
86
+ @req_mutex.synchronize do
87
+ @default_watcher = block # save this here for reopen() to use
88
+ @watcher_reqs[ZKRB_GLOBAL_CB_REQ] = { :watcher => @default_watcher, :watcher_context => nil }
89
+ end
90
+ end
91
+
92
+ protected
93
+ def running?
94
+ false|@_running
95
+ end
96
+
97
+ def setup_dispatch_thread!
98
+ @dispatcher = Thread.new do
99
+ while running?
100
+ begin # calling user code, so protect ourselves
101
+ dispatch_next_callback
102
+ rescue Exception => e
103
+ $stderr.puts "Error in dispatch thread, #{e.class}: #{e.message}\n" << e.backtrace.map{|n| "\t#{n}"}.join("\n")
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # TODO: Make all global puts configurable
110
+ def get_default_global_watcher
111
+ Proc.new { |args|
112
+ logger.debug { "Ruby ZK Global CB called type=#{event_by_value(args[:type])} state=#{state_by_value(args[:state])}" }
113
+ true
114
+ }
115
+ end
116
+ end
117
+