zk-server 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ --color
2
+ --require ./spec/support/logging_progress_bar_formatter.rb
3
+ --format Motionbox::LoggingProgressBarFormatter
4
+
data/.dotfiles/rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.3@zk-server --create
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .rvmrc
19
+ zookeeper/
data/.yardopts ADDED
@@ -0,0 +1,9 @@
1
+ --protected
2
+ --no-private
3
+ --tag hidden_example:Hidden
4
+ --hide-tag hidden_example
5
+ --markup markdown
6
+ -
7
+ MIT_LICENSE
8
+ README.md
9
+
data/Gemfile ADDED
@@ -0,0 +1,21 @@
1
+ source :rubygems
2
+
3
+ gem 'zk', :path => '~/zk'
4
+
5
+
6
+
7
+ group :development do
8
+ gem 'pry'
9
+ end
10
+
11
+ group :docs do
12
+ gem 'yard', '~> 0.7.5'
13
+
14
+ platform :mri_19 do
15
+ gem 'redcarpet'
16
+ end
17
+ end
18
+
19
+
20
+ # Specify your gem's dependencies in zk-server.gemspec
21
+ gemspec
data/MIT_LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (C) 2012 by Hewlett Packard Development Company, L.P.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # ZK::Server
2
+
3
+ Sets up and runs a ZooKeeper standalone server process. Intended for use during testing of zookeeper-related code. The following are the design goals:
4
+
5
+ * Easy to configure and run
6
+ * Never ever leaks a process (barring impossible circumstances)
7
+
8
+
9
+ ## Usage
10
+
11
+ Example usage:
12
+
13
+ ```
14
+ server = ZK::Server.new do |config|
15
+ config.client_port = 21811
16
+ config.enable_jmx = true
17
+ config.force_sync = false
18
+ end
19
+
20
+ server.run
21
+
22
+ # do a bunch of stuff (like run your specs)
23
+
24
+ server.shutdown
25
+ ```
26
+
27
+ For full options, see [ZK::Server::Config](http://rubydoc.info/github/slyphon/zk-server/master/ZK/Server/Config)
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ namespace :yard do
2
+ task :clean do
3
+ rm_rf '.yardoc'
4
+ end
5
+
6
+ task :server => :clean do
7
+ sh "yard server --reload"
8
+ end
9
+ end
10
+
11
+ task :clean => 'yard:clean'
12
+
13
+
@@ -0,0 +1,138 @@
1
+ module ZK
2
+ module Server
3
+ class Config
4
+ DEFAULT_JVM_FLAGS = %w[
5
+ -server
6
+ -Xmx256m
7
+ -Dzookeeper.serverCnxnFactory=org.apache.zookeeper.server.NettyServerCnxnFactory
8
+ ].freeze
9
+
10
+ # the com.sun.managemnt.jmxremote.port arg will be filled in dynamically
11
+ # based on the {#jmx_port} value
12
+ #
13
+ DEFAULT_JMX_ARGS = %w[
14
+ -Dcom.sun.management.jmxremote=true
15
+ -Dcom.sun.management.jmxremote.local.only=false
16
+ -Dcom.sun.management.jmxremote.authenticate=false
17
+ -Dcom.sun.management.jmxremote.ssl=false
18
+ ].freeze
19
+
20
+ ZOO_MAIN = 'org.apache.zookeeper.server.quorum.QuorumPeerMain'.freeze
21
+
22
+ # The top level directory we will store all of our data under. used as the
23
+ # basis for all other path generation. Defaults to `File.join(Dir.getwd, 'zookeeper')`
24
+ attr_accessor :base_dir
25
+
26
+ # a hash that will be used to provide extra values for the zoo.cfg file.
27
+ # keys are written as-is to the file, so they should be camel-cased.
28
+ #
29
+ # dataDir will be set relative to {#base_dir} and clientPort will either use
30
+ # the default of 2181, or can be adjusted by {#client_port=}
31
+ #
32
+ attr_accessor :zoo_cfg_hash
33
+
34
+ # what port should the server listen on for connections? (default 2181)
35
+ attr_accessor :client_port
36
+ alias port client_port
37
+ alias port= client_port=
38
+
39
+ # maximum number of client connections (defaults to 100)
40
+ attr_accessor :max_client_cnxns
41
+
42
+ # defaults to 2000
43
+ attr_accessor :tick_time
44
+
45
+ # from the [admin guide](http://zookeeper.apache.org/doc/r3.3.5/zookeeperAdmin.html)
46
+ #
47
+ # > ZooKeeper logs transactions to a transaction log. After snapCount
48
+ # > transactions are written to a log file a snapshot is started and a new
49
+ # > transaction log file is created. The default snapCount is 100,000.
50
+ #
51
+ # For testing, to speed up disk IO, I generally set this to 1_000_000 and
52
+ # force_sync to false. YMMV, understand what this does before messing with it
53
+ # if you care about your data.
54
+ #
55
+ # default: unset
56
+ attr_accessor :snap_count
57
+
58
+ # This value can make testing go faster, as zookeeper doesn't have to issue
59
+ # an fsync() call for each snapshot write. It is however DANGEROUS if you
60
+ # care about the data. (I set it to false for running tests)
61
+ #
62
+ # default: no value set
63
+ attr_accessor :force_sync
64
+
65
+ # if truthy, will enable jmx (defaults to false)
66
+ # note that our defualt jmx config has all security and auth turned off
67
+ # if you want to customize this, then use jvm_flags and set this to false
68
+ attr_accessor :enable_jmx
69
+
70
+ # default jmx port is 22222
71
+ attr_accessor :jmx_port
72
+
73
+ # array to which additional JVM flags should be added
74
+ #
75
+ # default is {DEEFAULT_JVM_FLAGS}
76
+ attr_accessor :jvm_flags
77
+
78
+ def initialize(opts={})
79
+ @base_dir = File.join(Dir.getwd, 'zookeeper')
80
+ @zoo_cfg_hash = {}
81
+ @tick_time = 2000
82
+ @client_port = 2181
83
+ @snap_count = nil
84
+ @force_sync = nil
85
+ @jmx_port = 22222
86
+ @enable_jmx = false
87
+ @jvm_flags = DEFAULT_JVM_FLAGS.dup
88
+
89
+ @max_client_cnxns = 100
90
+
91
+ opts.each { |k,v| __send__(:"#{k}=", v) }
92
+ end
93
+
94
+ # @private
95
+ def zoo_cfg_path
96
+ File.join(base_dir, 'zoo.cfg')
97
+ end
98
+
99
+ # @private
100
+ def log4j_props_path
101
+ File.join(base_dir, 'log4j.properties')
102
+ end
103
+
104
+ # @private
105
+ def log_dir
106
+ File.join(base_dir, 'log')
107
+ end
108
+
109
+ # @private
110
+ def stdio_redirect_path
111
+ File.join(log_dir, 'zookeeper.out')
112
+ end
113
+
114
+ # @private
115
+ def data_dir
116
+ File.join(base_dir, 'data')
117
+ end
118
+
119
+ # @private
120
+ def classpath
121
+ @classpath ||= [Server.zk_jar_path, Server.log4j_jar_path, base_dir]
122
+ end
123
+
124
+ # @private
125
+ def command_args
126
+ cmd = [Server.java_binary_path]
127
+ cmd += %W[-Dzookeeper.log.dir=#{log_dir} -Dzookeeper.root.logger=INFO,CONSOLE]
128
+ if enable_jmx
129
+ cmd += DEFAULT_JMX_ARGS
130
+ cmd << "-Dcom.sun.management.jmxremote.port=#{jmx_port}"
131
+ end
132
+ cmd += jvm_flags
133
+ cmd += %W[-cp #{classpath.join(':')} #{ZOO_MAIN} #{zoo_cfg_path}]
134
+ end
135
+ end
136
+ end
137
+ end
138
+
@@ -0,0 +1,17 @@
1
+ # DEFAULT: console appender only
2
+ log4j.rootLogger=INFO, ROLLINGFILE
3
+
4
+ # Add ROLLINGFILE to rootLogger to get log file output
5
+ # Log DEBUG level and above messages to a log file
6
+ log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender
7
+ log4j.appender.ROLLINGFILE.Threshold=DEBUG
8
+ log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/zookeeper.log
9
+
10
+ # Max log file size of 10MB
11
+ log4j.appender.ROLLINGFILE.MaxFileSize=10MB
12
+ # uncomment the next line to limit number of backup files
13
+ #log4j.appender.ROLLINGFILE.MaxBackupIndex=10
14
+
15
+ log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
16
+ log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} - %-5p [%t:%C{1}@%L] - %m%n
17
+
@@ -0,0 +1,198 @@
1
+ module ZK
2
+ module Server
3
+ # This encapsulates the logic of running the zookeeper server, as a sub-process.
4
+ # It is intended that it will be stopped and started with the process that starts it.
5
+ # We are not going to do daemonized process management.
6
+ #
7
+ # By default, we will create a directory in the current working directory called 'zk-server'
8
+ # to store our data under (configurable).
9
+ #
10
+ class Process
11
+ include ZK::Logging
12
+ extend Forwardable
13
+ include FileUtils::Verbose
14
+
15
+ def_delegators :config,
16
+ :base_dir, :data_dir, :log4j_props_path, :log_dir, :command_args,
17
+ :tick_time, :snap_count, :force_sync, :zoo_cfg_hash, :client_port,
18
+ :max_client_cnxns, :stdio_redirect_path, :zoo_cfg_path
19
+
20
+ # the {Config} object that will be used to configure this Process
21
+ attr_accessor :config
22
+
23
+ attr_reader :exit_status
24
+
25
+ # how long should we wait for the child to start responding to 'ruok'?
26
+ attr_accessor :child_startup_timeout
27
+
28
+ def initialize(opts={})
29
+ @child_startup_timeout = opts.delete(:child_startup_timeout, 5)
30
+ @run_called = false
31
+ @config = Config.new(opts)
32
+ @exit_watching_thread = nil
33
+
34
+ @pid = nil
35
+ @exit_status = nil
36
+
37
+ @mutex = Monitor.new
38
+ @exit_cond = @mutex.new_cond
39
+ end
40
+
41
+ # removes all files related to this instance
42
+ # runs {#shutdown} first
43
+ def clobber!
44
+ shutdown
45
+ FileUtils.rm_rf(base_dir)
46
+ end
47
+
48
+ # true if the process was started and is still running
49
+ def running?
50
+ spawned? and !@exit_status and !!::Process.kill(0, @pid)
51
+ rescue Errno::ESRCH
52
+ false
53
+ end
54
+
55
+ # have we started the child process?
56
+ def spawned?
57
+ !!@pid
58
+ end
59
+
60
+ # shutdown the child, wait for it to exit, ensure it is dead
61
+ def shutdown
62
+ if @pid
63
+ return if @exit_status
64
+
65
+ @mutex.synchronize do
66
+ %w[HUP TERM KILL].each do |signal|
67
+ logger.debug { "sending #{signal} to #{@pid}" }
68
+
69
+ begin
70
+ ::Process.kill(signal, @pid)
71
+ rescue Errno::ESRCH
72
+ break
73
+ end
74
+
75
+ if @exit_status or @exit_cond.wait(5)
76
+ logger.debug { "process exited" }
77
+ break
78
+ end
79
+ end
80
+ end
81
+
82
+ logger.debug { "@exit_status: #{@exit_status}" }
83
+ end
84
+ true
85
+ end
86
+
87
+ # can we connect to the server, issue an 'ruok', and receive an 'imok'?
88
+ def ping?
89
+ TCPSocket.open('localhost', client_port) do |sock|
90
+ sock.puts('ruok')
91
+ sock.read == 'imok'
92
+ end
93
+ rescue
94
+ false
95
+ end
96
+
97
+ # the pid of our child process
98
+ def pid
99
+ @pid
100
+ end
101
+
102
+ # start the child, using the {#config}. we create the files necessary,
103
+ # fork the child, and wait 5s for the child to start responding to pings
104
+ #
105
+ #
106
+ # @return [false,true] false if run has already been called on this instance
107
+ # true if we hav
108
+ def run
109
+ return false if @run_called
110
+ @run_called = true
111
+
112
+ create_files!
113
+ fork_and_exec!
114
+ spawn_exit_watching_thread
115
+
116
+ unless wait_until_ping
117
+ raise "Oh noes! something went wrong!" unless running?
118
+ end
119
+
120
+ at_exit { self.shutdown }
121
+
122
+ true
123
+ end
124
+
125
+ protected
126
+ def wait_until_ping(timeout=5)
127
+ times_up = timeout ? Time.now + timeout : 0
128
+ while Time.now < times_up
129
+ return true if ping?
130
+ end
131
+ false
132
+ end
133
+
134
+ def spawn_exit_watching_thread
135
+ @exit_watching_thread ||= Thread.new do
136
+ _, @exit_status = ::Process.wait2(@pid)
137
+ @mutex.synchronize do
138
+ @exit_cond.broadcast
139
+ end
140
+ end
141
+ end
142
+
143
+ # wait for up to timeout seconds to pass, polling for completion
144
+ # returns nil if the process didn't exit
145
+ def wait_for_pid(timeout=2)
146
+ times_up = timeout ? Time.now + timeout : 0
147
+
148
+ while Time.now < times_up
149
+ pid, stat = ::Process.wait2(@pid, ::Process::WNOHANG)
150
+ return stat if stat
151
+ sleep(0.01)
152
+ end
153
+
154
+ nil
155
+ end
156
+
157
+ def fork_and_exec!
158
+ @pid ||= (
159
+ args = command_args()
160
+ args << {:err => [:child, :out], :out => [stdio_redirect_path, File::APPEND|File::CREAT|File::WRONLY]}
161
+ spawn({}, *command_args)
162
+ )
163
+ end
164
+
165
+ def create_files!
166
+ mkdir_p base_dir
167
+ mkdir_p data_dir
168
+ write_zoo_cfg!
169
+ write_log4j_properties!
170
+ end
171
+
172
+ def write_log4j_properties!
173
+ unless File.exists?(log4j_props_path)
174
+ cp Server.default_log4j_props_path, log4j_props_path
175
+ end
176
+ end
177
+
178
+ def write_zoo_cfg!
179
+ File.open(zoo_cfg_path, 'w') do |fp|
180
+ fp.puts <<-EOS
181
+ tickTime=#{tick_time}
182
+ dataDir=#{data_dir}
183
+ clientPort=#{client_port}
184
+ maxClientCnxns=#{max_client_cnxns}
185
+ EOS
186
+
187
+ fp.puts("forceSync=#{force_sync}") if force_sync
188
+ fp.puts("snapCount=#{snap_count}") if snap_count
189
+ zoo_cfg_hash.each do |k,v|
190
+ fp.puts("#{k}=#{v}")
191
+ end
192
+
193
+ fp.fsync
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
@@ -0,0 +1,5 @@
1
+ module ZK
2
+ module Server
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/lib/zk-server.rb ADDED
@@ -0,0 +1,81 @@
1
+ # Yes, i know, this is arguably bad form, but i'm actually going to use bundler
2
+ # as an API
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'fileutils'
6
+ require 'forwardable'
7
+ require 'logger'
8
+ require 'socket'
9
+
10
+ Bundler.require
11
+
12
+ require 'zk'
13
+
14
+ #ZK.logger = Logger.new($stderr).tap { |l| l.level = Logger::DEBUG }
15
+
16
+ module ZK
17
+ module Server
18
+ ZK_JAR_GEM = 'slyphon-zookeeper_jar'
19
+ LOG4J_GEM = 'slyphon-log4j'
20
+
21
+ # Create a new {ZK::Server::Process} instance. if a block is given
22
+ # then yield the {Config} object to the block
23
+ #
24
+ # @yield [Config] server config instance if block given
25
+ def self.new(opts={})
26
+ Server::Process.new(opts).tap do |server|
27
+ yield server.config if block_given?
28
+ end
29
+ end
30
+
31
+ def self.zk_jar_path
32
+ # in future revisions of the zookeeper jar, we'll make it easier to get
33
+ # at this information without needing rubygems and bundler to get at it,
34
+ # but for now this is the best way
35
+
36
+ @zk_jar_path ||= get_jar_paths_from_gem(ZK_JAR_GEM).first
37
+ end
38
+
39
+ def self.log4j_jar_path
40
+ @log4j_jar_path ||= get_jar_paths_from_gem(LOG4J_GEM).first
41
+ end
42
+
43
+ def self.get_jar_paths_from_gem(gem_name)
44
+ glob = "#{get_spec_for(gem_name).lib_dirs_glob}/**/*.jar"
45
+
46
+ Dir[glob].tap do |ary|
47
+ raise "gem #{gem_name} did not contain any jars (using glob: #{glob.inspect})" if ary.empty?
48
+ end
49
+ end
50
+
51
+ def self.get_spec_for(gem_name)
52
+ not_found = proc do
53
+ raise "could not locate the #{gem_name} Gem::Specification! wtf?!"
54
+ end
55
+
56
+ Bundler.load.specs.find(not_found) { |s| s.name == gem_name }
57
+ end
58
+
59
+ def self.java_binary_path=(path)
60
+ @java_binary_path = path
61
+ end
62
+
63
+ def self.java_binary_path
64
+ @java_binary_path ||= which('java')
65
+ end
66
+
67
+ def self.which(bin_name)
68
+ if_none = proc { "Could not find #{bin_name} in PATH: #{ENV['PATH'].inspect}" }
69
+ ENV['PATH'].split(':').map{|n| File.join(n, bin_name) }.find(if_none) {|x| File.executable?(x) }
70
+ end
71
+
72
+ def self.default_log4j_props_path
73
+ File.expand_path('../zk-server/log4j.properties', __FILE__)
74
+ end
75
+ end
76
+ end
77
+
78
+ require 'zk-server/version'
79
+ require 'zk-server/config'
80
+ require 'zk-server/process'
81
+
data/zk-server.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/zk-server/version', __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.authors = ["Jonathan D. Simms"]
6
+ s.email = ["slyphon@gmail.com"]
7
+ s.description = %q{runs a standalone zookeeper server}
8
+ s.summary = s.description + "\n"
9
+ s.homepage = ""
10
+
11
+ s.add_runtime_dependency 'bundler', '~> 1.1.3'
12
+ s.add_runtime_dependency 'zk', '>= 1.0.0'
13
+ s.add_runtime_dependency 'slyphon-log4j', '= 1.2.15'
14
+ s.add_runtime_dependency 'slyphon-zookeeper_jar', '~> 3.3.5'
15
+
16
+ s.files = `git ls-files`.split($\)
17
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
19
+ s.name = "zk-server"
20
+ s.require_paths = ["lib"]
21
+ s.version = ZK::Server::VERSION
22
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: zk-server
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Jonathan D. Simms
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-02 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: bundler
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ hash: 21
29
+ segments:
30
+ - 1
31
+ - 1
32
+ - 3
33
+ version: 1.1.3
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: zk
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 23
45
+ segments:
46
+ - 1
47
+ - 0
48
+ - 0
49
+ version: 1.0.0
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: slyphon-log4j
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - "="
59
+ - !ruby/object:Gem::Version
60
+ hash: 1
61
+ segments:
62
+ - 1
63
+ - 2
64
+ - 15
65
+ version: 1.2.15
66
+ type: :runtime
67
+ version_requirements: *id003
68
+ - !ruby/object:Gem::Dependency
69
+ name: slyphon-zookeeper_jar
70
+ prerelease: false
71
+ requirement: &id004 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ hash: 1
77
+ segments:
78
+ - 3
79
+ - 3
80
+ - 5
81
+ version: 3.3.5
82
+ type: :runtime
83
+ version_requirements: *id004
84
+ description: runs a standalone zookeeper server
85
+ email:
86
+ - slyphon@gmail.com
87
+ executables: []
88
+
89
+ extensions: []
90
+
91
+ extra_rdoc_files: []
92
+
93
+ files:
94
+ - .dotfiles/rspec-logging
95
+ - .dotfiles/rvmrc
96
+ - .gitignore
97
+ - .yardopts
98
+ - Gemfile
99
+ - MIT_LICENSE
100
+ - README.md
101
+ - Rakefile
102
+ - lib/zk-server.rb
103
+ - lib/zk-server/config.rb
104
+ - lib/zk-server/log4j.properties
105
+ - lib/zk-server/process.rb
106
+ - lib/zk-server/version.rb
107
+ - zk-server.gemspec
108
+ homepage: ""
109
+ licenses: []
110
+
111
+ post_install_message:
112
+ rdoc_options: []
113
+
114
+ require_paths:
115
+ - lib
116
+ required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ hash: 3
122
+ segments:
123
+ - 0
124
+ version: "0"
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ requirements: []
135
+
136
+ rubyforge_project:
137
+ rubygems_version: 1.8.15
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: runs a standalone zookeeper server
141
+ test_files: []
142
+