use system thin for native compilation
9
Gemfile
|
@ -1,9 +1,8 @@
|
|||
source "http://gemcutter.org"
|
||||
bin_path "vendor/bin"
|
||||
disable_rubygems
|
||||
disable_system_gems
|
||||
# disable_rubygems
|
||||
# disable_system_gems
|
||||
|
||||
gem "thin"
|
||||
gem "shotgun"
|
||||
gem "templater"
|
||||
gem "sprockets"
|
||||
|
@ -14,7 +13,11 @@ gem "yui-compressor"
|
|||
gem "haml"
|
||||
gem "compass"
|
||||
gem "smusher"
|
||||
gem "compass-slickmap"
|
||||
gem "maruku"
|
||||
gem "markaby"
|
||||
|
||||
gem "jeweler"
|
||||
gem "rspec"
|
||||
gem "rdoc"
|
||||
gem "sdoc"
|
||||
|
|
28
Rakefile
|
@ -13,20 +13,20 @@ begin
|
|||
gem.rubyforge_project = "middleman"
|
||||
gem.executables = %w(mm-init mm-build mm-server)
|
||||
gem.add_dependency("thin")
|
||||
gem.add_dependency("shotgun")
|
||||
gem.add_dependency("templater")
|
||||
gem.add_dependency("sprockets")
|
||||
gem.add_dependency("sinatra")
|
||||
gem.add_dependency("sinatra-content-for")
|
||||
gem.add_dependency("rack-test")
|
||||
gem.add_dependency("yui-compressor")
|
||||
gem.add_dependency("smusher")
|
||||
gem.add_dependency("haml", ">=2.1.0")
|
||||
gem.add_dependency("compass")
|
||||
gem.add_development_dependency("rdoc")
|
||||
gem.add_development_dependency("rspec")
|
||||
gem.add_development_dependency("sdoc")
|
||||
gem.add_development_dependency("cucumber")
|
||||
# gem.add_dependency("shotgun")
|
||||
# gem.add_dependency("templater")
|
||||
# gem.add_dependency("sprockets")
|
||||
# gem.add_dependency("sinatra")
|
||||
# gem.add_dependency("sinatra-content-for")
|
||||
# gem.add_dependency("rack-test")
|
||||
# gem.add_dependency("yui-compressor")
|
||||
# gem.add_dependency("smusher")
|
||||
# gem.add_dependency("haml", ">=2.1.0")
|
||||
# gem.add_dependency("compass")
|
||||
# gem.add_development_dependency("rdoc")
|
||||
# gem.add_development_dependency("rspec")
|
||||
# gem.add_development_dependency("sdoc")
|
||||
# gem.add_development_dependency("cucumber")
|
||||
|
||||
# Ignore vendored files
|
||||
gem.files = gem.files.exclude("vendor/*")
|
||||
|
|
|
@ -52,6 +52,7 @@ require 'shotgun'
|
|||
config = File.join(File.dirname(__FILE__), '..', 'lib', 'middleman', 'config.ru')
|
||||
app = Shotgun.new(config, lambda { |inner_app| Middleman::Base })
|
||||
|
||||
require 'rubygems'
|
||||
require 'thin'
|
||||
Thin::Logging.silent = true
|
||||
|
||||
|
|
3
vendor/bin/jeweler
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/bin/ruby
|
||||
require File.join(File.dirname(__FILE__), "../gems/environment")
|
||||
load File.join(File.dirname(__FILE__), "../gems/gems/jeweler-1.3.0/bin/jeweler")
|
2
vendor/bin/thin → vendor/bin/maruku
vendored
|
@ -1,3 +1,3 @@
|
|||
#!/Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/bin/ruby
|
||||
require File.join(File.dirname(__FILE__), "../gems/environment")
|
||||
load File.join(File.dirname(__FILE__), "../gems/gems/thin-1.2.5/bin/thin")
|
||||
load File.join(File.dirname(__FILE__), "../gems/gems/maruku-0.6.0/bin/maruku")
|
3
vendor/bin/marutex
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/bin/ruby
|
||||
require File.join(File.dirname(__FILE__), "../gems/environment")
|
||||
load File.join(File.dirname(__FILE__), "../gems/gems/maruku-0.6.0/bin/marutex")
|
3
vendor/bin/rubyforge
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/bin/ruby
|
||||
require File.join(File.dirname(__FILE__), "../gems/environment")
|
||||
load File.join(File.dirname(__FILE__), "../gems/gems/rubyforge-2.0.3/bin/rubyforge")
|
BIN
vendor/gems/cache/compass-slickmap-0.2.1.gem
vendored
Normal file
BIN
vendor/gems/cache/gemcutter-0.1.7.gem
vendored
Normal file
BIN
vendor/gems/cache/git-1.2.5.gem
vendored
Normal file
BIN
vendor/gems/cache/jeweler-1.3.0.gem
vendored
Normal file
BIN
vendor/gems/cache/json_pure-1.2.0.gem
vendored
Normal file
BIN
vendor/gems/cache/markaby-0.5.gem
vendored
Normal file
BIN
vendor/gems/cache/maruku-0.6.0.gem
vendored
Normal file
BIN
vendor/gems/cache/net-scp-1.0.2.gem
vendored
Normal file
BIN
vendor/gems/cache/net-ssh-2.0.15.gem
vendored
Normal file
BIN
vendor/gems/cache/rubyforge-2.0.3.gem
vendored
Normal file
BIN
vendor/gems/cache/syntax-1.0.0.gem
vendored
Normal file
173
vendor/gems/environment.rb
vendored
|
@ -3,37 +3,43 @@ module Bundler
|
|||
file = File.expand_path(__FILE__)
|
||||
dir = File.dirname(file)
|
||||
|
||||
ENV["GEM_HOME"] = dir
|
||||
ENV["GEM_PATH"] = dir
|
||||
ENV["PATH"] = "#{dir}/../bin:#{ENV["PATH"]}"
|
||||
ENV["RUBYOPT"] = "-r#{file} #{ENV["RUBYOPT"]}"
|
||||
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/builder-2.1.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/builder-2.1.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/polyglot-0.2.9/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/polyglot-0.2.9/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/treetop-1.4.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/treetop-1.4.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/term-ansicolor-1.0.4/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/term-ansicolor-1.0.4/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/syntax-1.0.0/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/syntax-1.0.0/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/maruku-0.6.0/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/maruku-0.6.0/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/extlib-0.9.13/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/extlib-0.9.13/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/highline-1.5.1/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/highline-1.5.1/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/diff-lcs-1.1.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/diff-lcs-1.1.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/cucumber-0.4.4/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/cucumber-0.4.4/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/templater-1.0.0/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/templater-1.0.0/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/eventmachine-0.12.10/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/eventmachine-0.12.10/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/daemons-1.0.10/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/daemons-1.0.10/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/net-ssh-2.0.15/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/net-ssh-2.0.15/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/haml-2.2.13/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/haml-2.2.13/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/net-scp-1.0.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/net-scp-1.0.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json_pure-1.2.0/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json_pure-1.2.0/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/gemcutter-0.1.7/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/gemcutter-0.1.7/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rubyforge-2.0.3/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rubyforge-2.0.3/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/git-1.2.5/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/git-1.2.5/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/jeweler-1.3.0/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/jeweler-1.3.0/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/ext/json/ext")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/json-1.2.0/ext")
|
||||
|
@ -44,12 +50,18 @@ module Bundler
|
|||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rake-0.8.7/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sprockets-1.0.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sprockets-1.0.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/builder-2.1.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/builder-2.1.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/cucumber-0.4.4/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/cucumber-0.4.4/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rspec-1.2.9/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/markaby-0.5/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/markaby-0.5/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/smusher-0.4.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/smusher-0.4.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-1.0.1/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-1.0.1/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/thin-1.2.5/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/thin-1.2.5/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-test-0.5.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rack-test-0.5.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/configuration-1.1.0/bin")
|
||||
|
@ -64,15 +76,109 @@ module Bundler
|
|||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/rdoc-2.4.3/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sdoc-0.2.14.1/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sdoc-0.2.14.1/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-content-for-0.2/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/sinatra-content-for-0.2/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/compass-0.8.17/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/compass-0.8.17/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/yui-compressor-0.9.1/lib")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/compass-slickmap-0.2.1/bin")
|
||||
$LOAD_PATH.unshift File.expand_path("#{dir}/gems/compass-slickmap-0.2.1/lib")
|
||||
|
||||
@gemfile = "#{dir}/../../Gemfile"
|
||||
|
||||
require "rubygems"
|
||||
|
||||
@bundled_specs = {}
|
||||
@bundled_specs["polyglot"] = eval(File.read("#{dir}/specifications/polyglot-0.2.9.gemspec"))
|
||||
@bundled_specs["polyglot"].loaded_from = "#{dir}/specifications/polyglot-0.2.9.gemspec"
|
||||
@bundled_specs["treetop"] = eval(File.read("#{dir}/specifications/treetop-1.4.2.gemspec"))
|
||||
@bundled_specs["treetop"].loaded_from = "#{dir}/specifications/treetop-1.4.2.gemspec"
|
||||
@bundled_specs["term-ansicolor"] = eval(File.read("#{dir}/specifications/term-ansicolor-1.0.4.gemspec"))
|
||||
@bundled_specs["term-ansicolor"].loaded_from = "#{dir}/specifications/term-ansicolor-1.0.4.gemspec"
|
||||
@bundled_specs["syntax"] = eval(File.read("#{dir}/specifications/syntax-1.0.0.gemspec"))
|
||||
@bundled_specs["syntax"].loaded_from = "#{dir}/specifications/syntax-1.0.0.gemspec"
|
||||
@bundled_specs["maruku"] = eval(File.read("#{dir}/specifications/maruku-0.6.0.gemspec"))
|
||||
@bundled_specs["maruku"].loaded_from = "#{dir}/specifications/maruku-0.6.0.gemspec"
|
||||
@bundled_specs["extlib"] = eval(File.read("#{dir}/specifications/extlib-0.9.13.gemspec"))
|
||||
@bundled_specs["extlib"].loaded_from = "#{dir}/specifications/extlib-0.9.13.gemspec"
|
||||
@bundled_specs["highline"] = eval(File.read("#{dir}/specifications/highline-1.5.1.gemspec"))
|
||||
@bundled_specs["highline"].loaded_from = "#{dir}/specifications/highline-1.5.1.gemspec"
|
||||
@bundled_specs["diff-lcs"] = eval(File.read("#{dir}/specifications/diff-lcs-1.1.2.gemspec"))
|
||||
@bundled_specs["diff-lcs"].loaded_from = "#{dir}/specifications/diff-lcs-1.1.2.gemspec"
|
||||
@bundled_specs["templater"] = eval(File.read("#{dir}/specifications/templater-1.0.0.gemspec"))
|
||||
@bundled_specs["templater"].loaded_from = "#{dir}/specifications/templater-1.0.0.gemspec"
|
||||
@bundled_specs["net-ssh"] = eval(File.read("#{dir}/specifications/net-ssh-2.0.15.gemspec"))
|
||||
@bundled_specs["net-ssh"].loaded_from = "#{dir}/specifications/net-ssh-2.0.15.gemspec"
|
||||
@bundled_specs["haml"] = eval(File.read("#{dir}/specifications/haml-2.2.13.gemspec"))
|
||||
@bundled_specs["haml"].loaded_from = "#{dir}/specifications/haml-2.2.13.gemspec"
|
||||
@bundled_specs["net-scp"] = eval(File.read("#{dir}/specifications/net-scp-1.0.2.gemspec"))
|
||||
@bundled_specs["net-scp"].loaded_from = "#{dir}/specifications/net-scp-1.0.2.gemspec"
|
||||
@bundled_specs["json_pure"] = eval(File.read("#{dir}/specifications/json_pure-1.2.0.gemspec"))
|
||||
@bundled_specs["json_pure"].loaded_from = "#{dir}/specifications/json_pure-1.2.0.gemspec"
|
||||
@bundled_specs["gemcutter"] = eval(File.read("#{dir}/specifications/gemcutter-0.1.7.gemspec"))
|
||||
@bundled_specs["gemcutter"].loaded_from = "#{dir}/specifications/gemcutter-0.1.7.gemspec"
|
||||
@bundled_specs["rubyforge"] = eval(File.read("#{dir}/specifications/rubyforge-2.0.3.gemspec"))
|
||||
@bundled_specs["rubyforge"].loaded_from = "#{dir}/specifications/rubyforge-2.0.3.gemspec"
|
||||
@bundled_specs["git"] = eval(File.read("#{dir}/specifications/git-1.2.5.gemspec"))
|
||||
@bundled_specs["git"].loaded_from = "#{dir}/specifications/git-1.2.5.gemspec"
|
||||
@bundled_specs["jeweler"] = eval(File.read("#{dir}/specifications/jeweler-1.3.0.gemspec"))
|
||||
@bundled_specs["jeweler"].loaded_from = "#{dir}/specifications/jeweler-1.3.0.gemspec"
|
||||
@bundled_specs["json"] = eval(File.read("#{dir}/specifications/json-1.2.0.gemspec"))
|
||||
@bundled_specs["json"].loaded_from = "#{dir}/specifications/json-1.2.0.gemspec"
|
||||
@bundled_specs["httpclient"] = eval(File.read("#{dir}/specifications/httpclient-2.1.5.2.gemspec"))
|
||||
@bundled_specs["httpclient"].loaded_from = "#{dir}/specifications/httpclient-2.1.5.2.gemspec"
|
||||
@bundled_specs["rake"] = eval(File.read("#{dir}/specifications/rake-0.8.7.gemspec"))
|
||||
@bundled_specs["rake"].loaded_from = "#{dir}/specifications/rake-0.8.7.gemspec"
|
||||
@bundled_specs["sprockets"] = eval(File.read("#{dir}/specifications/sprockets-1.0.2.gemspec"))
|
||||
@bundled_specs["sprockets"].loaded_from = "#{dir}/specifications/sprockets-1.0.2.gemspec"
|
||||
@bundled_specs["builder"] = eval(File.read("#{dir}/specifications/builder-2.1.2.gemspec"))
|
||||
@bundled_specs["builder"].loaded_from = "#{dir}/specifications/builder-2.1.2.gemspec"
|
||||
@bundled_specs["cucumber"] = eval(File.read("#{dir}/specifications/cucumber-0.4.4.gemspec"))
|
||||
@bundled_specs["cucumber"].loaded_from = "#{dir}/specifications/cucumber-0.4.4.gemspec"
|
||||
@bundled_specs["rspec"] = eval(File.read("#{dir}/specifications/rspec-1.2.9.gemspec"))
|
||||
@bundled_specs["rspec"].loaded_from = "#{dir}/specifications/rspec-1.2.9.gemspec"
|
||||
@bundled_specs["markaby"] = eval(File.read("#{dir}/specifications/markaby-0.5.gemspec"))
|
||||
@bundled_specs["markaby"].loaded_from = "#{dir}/specifications/markaby-0.5.gemspec"
|
||||
@bundled_specs["smusher"] = eval(File.read("#{dir}/specifications/smusher-0.4.2.gemspec"))
|
||||
@bundled_specs["smusher"].loaded_from = "#{dir}/specifications/smusher-0.4.2.gemspec"
|
||||
@bundled_specs["rack"] = eval(File.read("#{dir}/specifications/rack-1.0.1.gemspec"))
|
||||
@bundled_specs["rack"].loaded_from = "#{dir}/specifications/rack-1.0.1.gemspec"
|
||||
@bundled_specs["rack-test"] = eval(File.read("#{dir}/specifications/rack-test-0.5.2.gemspec"))
|
||||
@bundled_specs["rack-test"].loaded_from = "#{dir}/specifications/rack-test-0.5.2.gemspec"
|
||||
@bundled_specs["configuration"] = eval(File.read("#{dir}/specifications/configuration-1.1.0.gemspec"))
|
||||
@bundled_specs["configuration"].loaded_from = "#{dir}/specifications/configuration-1.1.0.gemspec"
|
||||
@bundled_specs["launchy"] = eval(File.read("#{dir}/specifications/launchy-0.3.3.gemspec"))
|
||||
@bundled_specs["launchy"].loaded_from = "#{dir}/specifications/launchy-0.3.3.gemspec"
|
||||
@bundled_specs["shotgun"] = eval(File.read("#{dir}/specifications/shotgun-0.4.gemspec"))
|
||||
@bundled_specs["shotgun"].loaded_from = "#{dir}/specifications/shotgun-0.4.gemspec"
|
||||
@bundled_specs["sinatra"] = eval(File.read("#{dir}/specifications/sinatra-0.9.4.gemspec"))
|
||||
@bundled_specs["sinatra"].loaded_from = "#{dir}/specifications/sinatra-0.9.4.gemspec"
|
||||
@bundled_specs["rdoc"] = eval(File.read("#{dir}/specifications/rdoc-2.4.3.gemspec"))
|
||||
@bundled_specs["rdoc"].loaded_from = "#{dir}/specifications/rdoc-2.4.3.gemspec"
|
||||
@bundled_specs["sdoc"] = eval(File.read("#{dir}/specifications/sdoc-0.2.14.1.gemspec"))
|
||||
@bundled_specs["sdoc"].loaded_from = "#{dir}/specifications/sdoc-0.2.14.1.gemspec"
|
||||
@bundled_specs["yui-compressor"] = eval(File.read("#{dir}/specifications/yui-compressor-0.9.1.gemspec"))
|
||||
@bundled_specs["yui-compressor"].loaded_from = "#{dir}/specifications/yui-compressor-0.9.1.gemspec"
|
||||
@bundled_specs["sinatra-content-for"] = eval(File.read("#{dir}/specifications/sinatra-content-for-0.2.gemspec"))
|
||||
@bundled_specs["sinatra-content-for"].loaded_from = "#{dir}/specifications/sinatra-content-for-0.2.gemspec"
|
||||
@bundled_specs["compass"] = eval(File.read("#{dir}/specifications/compass-0.8.17.gemspec"))
|
||||
@bundled_specs["compass"].loaded_from = "#{dir}/specifications/compass-0.8.17.gemspec"
|
||||
@bundled_specs["compass-slickmap"] = eval(File.read("#{dir}/specifications/compass-slickmap-0.2.1.gemspec"))
|
||||
@bundled_specs["compass-slickmap"].loaded_from = "#{dir}/specifications/compass-slickmap-0.2.1.gemspec"
|
||||
|
||||
def self.add_specs_to_loaded_specs
|
||||
Gem.loaded_specs.merge! @bundled_specs
|
||||
end
|
||||
|
||||
def self.add_specs_to_index
|
||||
@bundled_specs.each do |name, spec|
|
||||
Gem.source_index.add_spec spec
|
||||
end
|
||||
end
|
||||
|
||||
add_specs_to_loaded_specs
|
||||
add_specs_to_index
|
||||
|
||||
def self.require_env(env = nil)
|
||||
context = Class.new do
|
||||
|
@ -129,36 +235,11 @@ module Bundler
|
|||
end
|
||||
end
|
||||
|
||||
$" << "rubygems.rb"
|
||||
module Gem
|
||||
@loaded_stacks = Hash.new { |h,k| h[k] = [] }
|
||||
|
||||
module Kernel
|
||||
def gem(*)
|
||||
# Silently ignore calls to gem, since, in theory, everything
|
||||
# is activated correctly already.
|
||||
def source_index.refresh!
|
||||
super
|
||||
Bundler.add_specs_to_index
|
||||
end
|
||||
end
|
||||
|
||||
# Define all the Gem errors for gems that reference them.
|
||||
module Gem
|
||||
def self.ruby ; "/Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/bin/ruby" ; end
|
||||
class LoadError < ::LoadError; end
|
||||
class Exception < RuntimeError; end
|
||||
class CommandLineError < Exception; end
|
||||
class DependencyError < Exception; end
|
||||
class DependencyRemovalException < Exception; end
|
||||
class GemNotInHomeException < Exception ; end
|
||||
class DocumentError < Exception; end
|
||||
class EndOfYAMLException < Exception; end
|
||||
class FilePermissionError < Exception; end
|
||||
class FormatException < Exception; end
|
||||
class GemNotFoundException < Exception; end
|
||||
class InstallError < Exception; end
|
||||
class InvalidSpecificationException < Exception; end
|
||||
class OperationNotSupportedError < Exception; end
|
||||
class RemoteError < Exception; end
|
||||
class RemoteInstallationCancelled < Exception; end
|
||||
class RemoteInstallationSkipped < Exception; end
|
||||
class RemoteSourceException < Exception; end
|
||||
class VerificationError < Exception; end
|
||||
class SystemExitException < SystemExit; end
|
||||
end
|
||||
|
|
3
vendor/gems/gems/compass-slickmap-0.2.1/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.DS_Store
|
||||
pkg
|
||||
.sass-cache
|
20
vendor/gems/gems/compass-slickmap-0.2.1/Rakefile
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
require 'rubygems'
|
||||
require 'rake'
|
||||
|
||||
begin
|
||||
require 'jeweler'
|
||||
Jeweler::Tasks.new do |gem|
|
||||
gem.name = "compass-slickmap"
|
||||
gem.summary = %Q{An implementation of SlickmapCSS sitemap in Sass}
|
||||
gem.email = "tdreyno@gmail.com"
|
||||
gem.homepage = "http://github.com/tdreyno/compass-slickmap"
|
||||
gem.authors = ["Thomas Reynolds"]
|
||||
gem.rubyforge_project = "compassslickmap"
|
||||
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
||||
gem.add_dependency("compass")
|
||||
end
|
||||
|
||||
Jeweler::RubyforgeTasks.new
|
||||
rescue LoadError
|
||||
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
||||
end
|
1
vendor/gems/gems/compass-slickmap-0.2.1/VERSION
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
0.2.1
|
53
vendor/gems/gems/compass-slickmap-0.2.1/compass-slickmap.gemspec
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
# Generated by jeweler
|
||||
# DO NOT EDIT THIS FILE
|
||||
# Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
|
||||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{compass-slickmap}
|
||||
s.version = "0.2.1"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Thomas Reynolds"]
|
||||
s.date = %q{2009-10-09}
|
||||
s.email = %q{tdreyno@gmail.com}
|
||||
s.files = [
|
||||
".gitignore",
|
||||
"Rakefile",
|
||||
"VERSION",
|
||||
"compass-slickmap.gemspec",
|
||||
"lib/slickmap.rb",
|
||||
"lib/slickmap/compass_plugin.rb",
|
||||
"sass/_slickmap.sass",
|
||||
"templates/project/images/L1-center.png",
|
||||
"templates/project/images/L1-left.png",
|
||||
"templates/project/images/L1-right.png",
|
||||
"templates/project/images/L3-bottom.png",
|
||||
"templates/project/images/L3-center.png",
|
||||
"templates/project/images/L3-li-top.png",
|
||||
"templates/project/images/L3-ul-top.png",
|
||||
"templates/project/images/vertical-line.png",
|
||||
"templates/project/images/white-highlight.png",
|
||||
"templates/project/manifest.rb",
|
||||
"templates/project/sitemap.sass"
|
||||
]
|
||||
s.homepage = %q{http://github.com/tdreyno/compass-slickmap}
|
||||
s.rdoc_options = ["--charset=UTF-8"]
|
||||
s.require_paths = ["lib"]
|
||||
s.rubyforge_project = %q{compassslickmap}
|
||||
s.rubygems_version = %q{1.3.5}
|
||||
s.summary = %q{An implementation of SlickmapCSS sitemap in Sass}
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||
s.add_runtime_dependency(%q<compass>, [">= 0"])
|
||||
else
|
||||
s.add_dependency(%q<compass>, [">= 0"])
|
||||
end
|
||||
else
|
||||
s.add_dependency(%q<compass>, [">= 0"])
|
||||
end
|
||||
end
|
45
vendor/gems/gems/compass-slickmap-0.2.1/lib/slickmap.rb
vendored
Executable file
|
@ -0,0 +1,45 @@
|
|||
require 'base64'
|
||||
require File.join(File.dirname(__FILE__), 'slickmap', 'compass_plugin')
|
||||
|
||||
module Compass::SlickmapImage
|
||||
def slickmap_image(path, mime_type = nil)
|
||||
path = path.value
|
||||
real_path = File.join(File.dirname(__FILE__), "..", "templates", "project", "images", path)
|
||||
url = "url('data:#{compute_mime_type(path,mime_type)};base64,#{data(real_path)}')"
|
||||
Sass::Script::String.new(url)
|
||||
end
|
||||
|
||||
private
|
||||
def compute_mime_type(path, mime_type)
|
||||
return mime_type if mime_type
|
||||
case path
|
||||
when /\.png$/i
|
||||
'image/png'
|
||||
when /\.jpe?g$/i
|
||||
'image/jpeg'
|
||||
when /\.gif$/i
|
||||
'image/gif'
|
||||
when /\.([a-zA-Z]+)$/
|
||||
"image/#{Regexp.last_match(1).downcase}"
|
||||
else
|
||||
raise Compass::Error, "A mime type could not be determined for #{path}, please specify one explicitly."
|
||||
end
|
||||
end
|
||||
|
||||
def data(real_path)
|
||||
if File.readable?(real_path)
|
||||
Base64.encode64(File.read(real_path)).gsub("\n","")
|
||||
else
|
||||
raise Compass::Error, "File not found or cannot be read: #{real_path}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
module ::Sass::Script::Functions
|
||||
include Compass::SlickmapImage
|
||||
end
|
||||
|
||||
class ::Sass::Script::Functions::EvaluationContext
|
||||
include ::Sass::Script::Functions
|
||||
end
|
5
vendor/gems/gems/compass-slickmap-0.2.1/lib/slickmap/compass_plugin.rb
vendored
Executable file
|
@ -0,0 +1,5 @@
|
|||
options = Hash.new
|
||||
options[:stylesheets_directory] = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'sass'))
|
||||
options[:templates_directory] = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'templates'))
|
||||
|
||||
Compass::Frameworks.register('slickmap', options)
|
206
vendor/gems/gems/compass-slickmap-0.2.1/sass/_slickmap.sass
vendored
Normal file
|
@ -0,0 +1,206 @@
|
|||
@import compass/utilities/general/reset.sass
|
||||
|
||||
=slickmap(!body_selector = "body")
|
||||
+global-reset
|
||||
#{!body_selector}
|
||||
+slickmap-body
|
||||
@if !body_selector != "body"
|
||||
+slickmap-defaults
|
||||
@if !body_selector == "body"
|
||||
+slickmap-defaults
|
||||
|
||||
=slickmap-primary-nav
|
||||
margin: 0
|
||||
float: left
|
||||
width: 100%
|
||||
li
|
||||
width: 25%
|
||||
&.col1 li
|
||||
width: 99.9%
|
||||
&.col2 li
|
||||
width: 50.0%
|
||||
&.col3 li
|
||||
width: 33.3%
|
||||
&.col4 li
|
||||
width: 25.0%
|
||||
&.col5 li
|
||||
width: 20.0%
|
||||
&.col6 li
|
||||
width: 16.6%
|
||||
&.col7 li
|
||||
width: 14.2%
|
||||
&.col8 li
|
||||
width: 12.5%
|
||||
&.col9 li
|
||||
width: 11.1%
|
||||
&.col10 li
|
||||
width: 10.0%
|
||||
li
|
||||
ul li
|
||||
width: 100% !important
|
||||
|
||||
a:link:before, a:visited:before
|
||||
color: #78a9c0
|
||||
|
||||
// Second Level
|
||||
li
|
||||
width: 100%
|
||||
clear: left
|
||||
margin-top: 0
|
||||
padding: 10px 0 0 0
|
||||
background= slickmap_image("vertical-line.png") "center" "bottom" "repeat-y"
|
||||
a
|
||||
background-color: #cee3ac
|
||||
border-color: #b8da83
|
||||
&:hover
|
||||
border-color: #94b75f
|
||||
background-color: #e7f1d7
|
||||
&:first-child
|
||||
padding-top: 30px
|
||||
&:last-child
|
||||
background= slickmap_image("vertical-line.png") "center" "bottom" "repeat-y"
|
||||
|
||||
a:link:before, a:visited:before
|
||||
color: #8faf5c
|
||||
|
||||
// Third Level
|
||||
ul
|
||||
margin: 10px 0 0 0
|
||||
width: 100%
|
||||
float: right
|
||||
padding: 9px 0 10px 0
|
||||
background= #fff slickmap_image("L3-ul-top.png") "center" "top" "no-repeat"
|
||||
|
||||
li
|
||||
background= slickmap_image("L3-center.png") "left" "center" "no-repeat"
|
||||
padding: 5px 0
|
||||
a
|
||||
background-color: #fff7aa
|
||||
border-color: #e3ca4b
|
||||
font-size: 12px
|
||||
padding: 5px 0
|
||||
width: 80%
|
||||
float: right
|
||||
&:hover
|
||||
background-color: #fffce5
|
||||
border-color: #d1b62c
|
||||
&:first-child
|
||||
padding: 15px 0 5px 0
|
||||
background= slickmap_image("L3-li-top.png") "left" "center" "no-repeat"
|
||||
&:last-child
|
||||
background= slickmap_image("L3-bottom.png") "left" "center" "no-repeat"
|
||||
a:link:before, a:visited:before
|
||||
color: #ccae14
|
||||
font-size: 9px
|
||||
|
||||
li
|
||||
float: left
|
||||
background= slickmap_image("L1-center.png") "center" "top" "no-repeat"
|
||||
padding: 30px 0
|
||||
margin-top: -30px
|
||||
&:last-child
|
||||
background= slickmap_image("L1-right.png") "center" "top" "no-repeat"
|
||||
a
|
||||
margin: 0 20px 0 0
|
||||
padding: 10px 0
|
||||
display: block
|
||||
font-size: 14px
|
||||
font-weight: bold
|
||||
text-align: center
|
||||
color: black
|
||||
background= #c3eafb slickmap_image("white-highlight.png") "top" "left" "repeat-x"
|
||||
border: 2px solid #b5d9ea
|
||||
-moz-border-radius: 5px
|
||||
-webkit-border-radius: 5px
|
||||
-webkit-box-shadow: rgba(0,0,0,0.5) 2px 2px 2px
|
||||
-moz-box-shadow: rgba(0,0,0,0.5) 2px 2px 2px
|
||||
&:hover
|
||||
background-color: #e2f4fd
|
||||
border-color: #97bdcf
|
||||
|
||||
=slickmap-primary-nav-home
|
||||
display: block
|
||||
float: none
|
||||
background= #fff slickmap_image("L1-left.png") "center" "bottom" "no-repeat"
|
||||
position: relative
|
||||
z-index: 2
|
||||
padding: 0 0 30px 0
|
||||
|
||||
=slickmap-utility-nav
|
||||
float: right
|
||||
max-width: 50%
|
||||
margin-right: 10px
|
||||
li
|
||||
float: left
|
||||
margin-bottom: 10px
|
||||
a
|
||||
margin: 0 10px 0 0
|
||||
padding: 5px 10px
|
||||
display: block
|
||||
border: 2px solid #e3ca4b
|
||||
font-size: 12px
|
||||
font-weight: bold
|
||||
text-align: center
|
||||
color: black
|
||||
background= #fff7aa slickmap_image("white-highlight.png") "top" "left" "repeat-x"
|
||||
-moz-border-radius: 5px
|
||||
-webkit-border-radius: 5px
|
||||
-webkit-box-shadow: rgba(0,0,0,0.5) 2px 2px 2px
|
||||
-moz-box-shadow: rgba(0,0,0,0.5) 2px 2px 2px
|
||||
&:hover
|
||||
background-color: #fffce5
|
||||
border-color: #d1b62c
|
||||
&:link:before, &:visited:before
|
||||
color: #ccae14
|
||||
font-size: 9px
|
||||
margin-bottom: 3px
|
||||
|
||||
// General Styles
|
||||
=slickmap-body
|
||||
background: white
|
||||
color: black
|
||||
padding: 40px
|
||||
font-family: Gotham, Helvetica, Arial, sans-serif
|
||||
font-size: 12px
|
||||
line-height: 1
|
||||
|
||||
=slickmap-defaults
|
||||
.sitemap
|
||||
margin: 0 0 40px 0
|
||||
float: left
|
||||
width: 100%
|
||||
h1
|
||||
font-weight: bold
|
||||
text-transform: uppercase
|
||||
font-size: 20px
|
||||
margin: 0 0 5px 0
|
||||
h2
|
||||
font-family: "Lucida Grande", Verdana, sans-serif
|
||||
font-size: 10px
|
||||
color: #777777
|
||||
margin: 0 0 20px 0
|
||||
a
|
||||
text-decoration: none
|
||||
&:link:before, &:visited:before
|
||||
content: " "attr(href)" "
|
||||
display: block
|
||||
text-transform: uppercase
|
||||
font-size: 10px
|
||||
margin-bottom: 5px
|
||||
word-wrap: break-word
|
||||
ol, ul
|
||||
list-style: none
|
||||
|
||||
//
|
||||
NUMBER OF COLUMNS: Adjust #primaryNav li to set the number
|
||||
of columns required in your site map. The default is
|
||||
4 columns (25%). 5 columns would be 20%, 6 columns would
|
||||
be 16.6%, etc.
|
||||
#primaryNav
|
||||
+slickmap-primary-nav
|
||||
li#home
|
||||
+slickmap-primary-nav-home
|
||||
|
||||
// Utility Navigation
|
||||
#utilityNav
|
||||
+slickmap-utility-nav
|
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/L1-center.png
vendored
Normal file
After Width: | Height: | Size: 300 B |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/L1-left.png
vendored
Normal file
After Width: | Height: | Size: 305 B |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/L1-right.png
vendored
Normal file
After Width: | Height: | Size: 295 B |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/L3-bottom.png
vendored
Normal file
After Width: | Height: | Size: 353 B |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/L3-center.png
vendored
Normal file
After Width: | Height: | Size: 326 B |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/L3-li-top.png
vendored
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/L3-ul-top.png
vendored
Normal file
After Width: | Height: | Size: 201 B |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/vertical-line.png
vendored
Normal file
After Width: | Height: | Size: 152 B |
BIN
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/images/white-highlight.png
vendored
Normal file
After Width: | Height: | Size: 189 B |
10
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/manifest.rb
vendored
Executable file
|
@ -0,0 +1,10 @@
|
|||
image 'images/L1-center.png'
|
||||
image 'images/L1-left.png'
|
||||
image 'images/L1-right.png'
|
||||
image 'images/L3-bottom.png'
|
||||
image 'images/L3-center.png'
|
||||
image 'images/L3-li-top.png'
|
||||
image 'images/L3-ul-top.png'
|
||||
image 'images/vertical-line.png'
|
||||
image 'images/white-highlight.png'
|
||||
stylesheet 'sitemap.sass', :media => "screen, projection"
|
3
vendor/gems/gems/compass-slickmap-0.2.1/templates/project/sitemap.sass
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
@import slickmap.sass
|
||||
|
||||
+slickmap
|
29
vendor/gems/gems/daemons-1.0.10/LICENSE
vendored
|
@ -1,29 +0,0 @@
|
|||
Copyright (c) 2005-2007 Thomas Uehlinger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
This license does not apply to daemonize.rb, which is was written by
|
||||
Travis Whitton und published under the following license:
|
||||
|
||||
The Daemonize extension module is copywrited free software by Travis Whitton
|
||||
<whitton@atlantic.net>. You can redistribute it under the terms specified in
|
||||
the COPYING file of the Ruby distribution.
|
223
vendor/gems/gems/daemons-1.0.10/README
vendored
|
@ -1,223 +0,0 @@
|
|||
= Daemons Version 1.0.10
|
||||
|
||||
(See Releases for release-specific information)
|
||||
|
||||
== What is Daemons?
|
||||
|
||||
Daemons provides an easy way to wrap existing ruby scripts (for example a self-written server)
|
||||
to be <i>run as a daemon</i> and to be <i>controlled by simple start/stop/restart commands</i>.
|
||||
|
||||
If you want, you can also use daemons to <i>run blocks of ruby code in a daemon process</i> and to control
|
||||
these processes from the main application.
|
||||
|
||||
Besides this basic functionality, daemons offers many advanced features like <i>exception backtracing</i>
|
||||
and logging (in case your ruby script crashes) and <i>monitoring</i> and automatic restarting of your processes
|
||||
if they crash.
|
||||
|
||||
Daemons includes the <tt>daemonize.rb</tt> script written by <i>Travis Whitton</i> to do the daemonization
|
||||
process.
|
||||
|
||||
== Basic Usage
|
||||
|
||||
You can use Daemons in four differet ways:
|
||||
|
||||
=== 1. Create wrapper scripts for your server scripts or applications
|
||||
|
||||
Layout: suppose you have your self-written server <tt>myserver.rb</tt>:
|
||||
|
||||
# this is myserver.rb
|
||||
# it does nothing really useful at the moment
|
||||
|
||||
loop do
|
||||
sleep(5)
|
||||
end
|
||||
|
||||
To use <tt>myserver.rb</tt> in a production environment, you need to be able to
|
||||
run <tt>myserver.rb</tt> in the _background_ (this means detach it from the console, fork it
|
||||
in the background, release all directories and file descriptors).
|
||||
|
||||
Just create <tt>myserver_control.rb</tt> like this:
|
||||
|
||||
# this is myserver_control.rb
|
||||
|
||||
require 'rubygems' # if you use RubyGems
|
||||
require 'daemons'
|
||||
|
||||
Daemons.run('myserver.rb')
|
||||
|
||||
And use it like this from the console:
|
||||
|
||||
$ ruby myserver_control.rb start
|
||||
(myserver.rb is now running in the background)
|
||||
$ ruby myserver_control.rb restart
|
||||
(...)
|
||||
$ ruby myserver_control.rb stop
|
||||
|
||||
For testing purposes you can even run <tt>myserver.rb</tt> <i>without forking</i> in the background:
|
||||
|
||||
$ ruby myserver_control.rb run
|
||||
|
||||
An additional nice feature of Daemons is that you can pass <i>additional arguments</i> to the script that
|
||||
should be daemonized by seperating them by two _hyphens_:
|
||||
|
||||
$ ruby myserver_control.rb start -- --file=anyfile --a_switch another_argument
|
||||
|
||||
|
||||
=== 2. Create wrapper scripts that include your server procs
|
||||
|
||||
Layout: suppose you have some code you want to run in the background and control that background process
|
||||
from a script:
|
||||
|
||||
# this is your code
|
||||
# it does nothing really useful at the moment
|
||||
|
||||
loop do
|
||||
sleep(5)
|
||||
end
|
||||
|
||||
To run this code as a daemon create <tt>myproc_control.rb</tt> like this and include your code:
|
||||
|
||||
# this is myproc_control.rb
|
||||
|
||||
require 'rubygems' # if you use RubyGems
|
||||
require 'daemons'
|
||||
|
||||
Daemons.run_proc('myproc.rb') do
|
||||
loop do
|
||||
sleep(5)
|
||||
end
|
||||
end
|
||||
|
||||
And use it like this from the console:
|
||||
|
||||
$ ruby myproc_control.rb start
|
||||
(myproc.rb is now running in the background)
|
||||
$ ruby myproc_control.rb restart
|
||||
(...)
|
||||
$ ruby myproc_control.rb stop
|
||||
|
||||
For testing purposes you can even run <tt>myproc.rb</tt> <i>without forking</i> in the background:
|
||||
|
||||
$ ruby myproc_control.rb run
|
||||
|
||||
=== 3. Control a bunch of daemons from another application
|
||||
|
||||
Layout: you have an application <tt>my_app.rb</tt> that wants to run a bunch of
|
||||
server tasks as daemon processes.
|
||||
|
||||
# this is my_app.rb
|
||||
|
||||
require 'rubygems' # if you use RubyGems
|
||||
require 'daemons'
|
||||
|
||||
task1 = Daemons.call(:multiple => true) do
|
||||
# first server task
|
||||
|
||||
loop {
|
||||
conn = accept_conn()
|
||||
serve(conn)
|
||||
}
|
||||
end
|
||||
|
||||
task2 = Daemons.call do
|
||||
# second server task
|
||||
|
||||
loop {
|
||||
something_different()
|
||||
}
|
||||
end
|
||||
|
||||
# the parent process continues to run
|
||||
|
||||
# we can even control our tasks, for example stop them
|
||||
task1.stop
|
||||
task2.stop
|
||||
|
||||
exit
|
||||
|
||||
=== 4. Daemonize the currently running process
|
||||
|
||||
Layout: you have an application <tt>my_daemon.rb</tt> that wants to run as a daemon
|
||||
(but without the ability to be controlled by daemons via start/stop commands)
|
||||
|
||||
# this is my_daemons.rb
|
||||
|
||||
require 'rubygems' # if you use RubyGems
|
||||
require 'daemons'
|
||||
|
||||
# Initialize the app while we're not a daemon
|
||||
init()
|
||||
|
||||
# Become a daemon
|
||||
Daemons.daemonize
|
||||
|
||||
# The server loop
|
||||
loop {
|
||||
conn = accept_conn()
|
||||
serve(conn)
|
||||
}
|
||||
|
||||
|
||||
<b>For further documentation, refer to the module documentation of Daemons.</b>
|
||||
|
||||
|
||||
== Download and Installation
|
||||
|
||||
*Download*: just go to http://rubyforge.org/projects/daemons/
|
||||
|
||||
Installation *with* RubyGems:
|
||||
$ su
|
||||
# gem install daemons
|
||||
|
||||
Installation *without* RubyGems:
|
||||
$ tar xfz daemons-x.x.x.tar.gz
|
||||
$ cd daemons-x.x.x
|
||||
$ su
|
||||
# ruby setup.rb
|
||||
|
||||
== Documentation
|
||||
|
||||
For further documentation, refer to the module documentation of Daemons (click on Daemons).
|
||||
|
||||
The RDoc documentation is also online at http://daemons.rubyforge.org
|
||||
|
||||
|
||||
== Author
|
||||
|
||||
Written in 2005-2008 by Thomas Uehlinger <mailto:th.uehlinger@gmx.ch>.
|
||||
|
||||
== License
|
||||
|
||||
Copyright (c) 2005-2008 Thomas Uehlinger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
This license does not apply to daemonize.rb, which is was written by
|
||||
Travis Whitton und published under the following license:
|
||||
|
||||
The Daemonize extension module is copywrited free software by Travis Whitton
|
||||
<whitton@atlantic.net>. You can redistribute it under the terms specified in
|
||||
the COPYING file of the Ruby distribution.
|
||||
|
||||
== Feedback and other resources
|
||||
|
||||
At http://rubyforge.org/projects/daemons.
|
84
vendor/gems/gems/daemons-1.0.10/Rakefile
vendored
|
@ -1,84 +0,0 @@
|
|||
require 'rubygems'
|
||||
Gem::manage_gems
|
||||
|
||||
require 'rake/gempackagetask'
|
||||
#require 'rake/testtask'
|
||||
require 'rake/packagetask'
|
||||
require 'rake/rdoctask'
|
||||
|
||||
$LOAD_PATH << './lib'
|
||||
require 'daemons'
|
||||
|
||||
|
||||
PKG_NAME = "daemons"
|
||||
|
||||
PKG_FILES = FileList[
|
||||
"Rakefile", "Releases", "TODO", "README", "LICENSE",
|
||||
"setup.rb",
|
||||
"lib/**/*.rb",
|
||||
#"test/**/*",
|
||||
"examples/**/*"
|
||||
]
|
||||
#PKG_FILES.exclude(%r(^test/tmp/.+))
|
||||
PKG_FILES.exclude(%r(\.pid$))
|
||||
PKG_FILES.exclude(%r(\.log$))
|
||||
|
||||
spec = Gem::Specification.new do |s|
|
||||
s.name = PKG_NAME
|
||||
s.version = Daemons::VERSION
|
||||
s.author = "Thomas Uehlinger"
|
||||
s.email = "th.uehlinger@gmx.ch"
|
||||
s.rubyforge_project = "daemons"
|
||||
s.homepage = "http://daemons.rubyforge.org"
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.summary = "A toolkit to create and control daemons in different ways"
|
||||
s.description = <<-EOF
|
||||
Daemons provides an easy way to wrap existing ruby scripts (for example a self-written server)
|
||||
to be run as a daemon and to be controlled by simple start/stop/restart commands.
|
||||
|
||||
You can also call blocks as daemons and control them from the parent or just daemonize the current
|
||||
process.
|
||||
|
||||
Besides this basic functionality, daemons offers many advanced features like exception
|
||||
backtracing and logging (in case your ruby script crashes) and monitoring and automatic
|
||||
restarting of your processes if they crash.
|
||||
EOF
|
||||
|
||||
#s.files = FileList["{test,lib}/**/*"].exclude("rdoc").to_a
|
||||
s.files = PKG_FILES
|
||||
s.require_path = "lib"
|
||||
s.autorequire = "daemons"
|
||||
s.has_rdoc = true
|
||||
s.extra_rdoc_files = ["README", "Releases", "TODO"]
|
||||
end
|
||||
|
||||
Rake::GemPackageTask.new(spec) do |pkg|
|
||||
pkg.need_tar = true
|
||||
end
|
||||
|
||||
|
||||
#Rake::PackageTask.new("package") do |p|
|
||||
# p.name = PKG_NAME
|
||||
# p.version = Daemons::VERSION
|
||||
# p.need_tar = true
|
||||
# p.need_zip = true
|
||||
# p.package_files = PKG_FILES
|
||||
#end
|
||||
|
||||
|
||||
task :default => [:package]
|
||||
|
||||
|
||||
task :upload do
|
||||
sh "scp -r html/* uehli@rubyforge.org:/var/www/gforge-projects/daemons"
|
||||
end
|
||||
|
||||
|
||||
desc "Create the RDOC html files"
|
||||
rd = Rake::RDocTask.new("rdoc") { |rdoc|
|
||||
rdoc.rdoc_dir = 'html'
|
||||
rdoc.title = "Daemons"
|
||||
rdoc.options << '--line-numbers' << '--inline-source' << '--main' << 'README'
|
||||
rdoc.rdoc_files.include('README', 'TODO', 'Releases')
|
||||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||||
}
|
126
vendor/gems/gems/daemons-1.0.10/Releases
vendored
|
@ -1,126 +0,0 @@
|
|||
= Daemons Release History
|
||||
|
||||
== Release 1.0.10: November 16, 2007
|
||||
|
||||
* By default, we now delete stray pid-files (i.e. pid-files which result for
|
||||
example from a killed daemon) automatically. This function can be deactivated by
|
||||
passing :keep_pid_files => true as an option.
|
||||
* All pid files of :multiple daemons new get deleted correctly upon exit of the daemons (reported by Han Holl).
|
||||
* Use the signal 'KILL' instead of 'TERM' on Windows platforms.
|
||||
* Use exit! in trap('TERM') instead of exit when option :hard_exit is given (thanks to Han Holl).
|
||||
* Did some clarification on the exception log.
|
||||
|
||||
== Release 1.0.9: October 29, 2007
|
||||
|
||||
* fixed a severe bug in the new Pid.running? function: function returned true if the process did not exist (thanks to Jeremy Lawler).
|
||||
|
||||
== Release 1.0.8: September 24, 2007
|
||||
|
||||
* new Pid.running? function. Checking whether a process exists by sending signal '0' (thanks to Dru Nelson).
|
||||
|
||||
== Release 1.0.7: July 7, 2007
|
||||
|
||||
* Patch to fix wrong ARGV when using :exec (in def start_exec: Kernel.exec(script(), *(@app_argv || []))) (thanks to Alex McGuire).
|
||||
|
||||
== Release 1.0.6: Mai 8, 2007
|
||||
|
||||
* New option to pass an ARGV-style array to run and run_proc (thanks to Marc Evans).
|
||||
* Additional patches for '/var/log' (thanks to Marc Evans).
|
||||
|
||||
== Release 1.0.5: February 24, 2007
|
||||
|
||||
* Applied patch that makes daemons to use '/var/log' as logfile
|
||||
directory if you use :dir_mode = :system (thanks to Han Holl).
|
||||
* Daemons should now work with Ruby 1.9 (at least the basic features).
|
||||
|
||||
== Release 1.0.4: January 17, 2007
|
||||
|
||||
* Document the :log_output option (thanks to Andrew Kuklewicz).
|
||||
* Set STDOUT.sync = true when redirecting to a logfile (thanks to Andrew Kuklewicz).
|
||||
* Should now run also correctly when there is no working 'ps ax' on the system (thanks to Daniel Kehoe).
|
||||
|
||||
== Release 1.0.3: November 1, 2006
|
||||
|
||||
* Set the app_name correctly also for the monitor process (thanks to Ilya Novoselov).
|
||||
|
||||
== Release 1.0.2: September 26, 2006
|
||||
|
||||
* Changed the 'ps -ax' call back to 'ps ax'.
|
||||
* Fixed the documentation for the :normal :dir_mode.
|
||||
* As a default for Daemons.run_proc, the pid file is now saved in the current directory.
|
||||
* In :ontop mode for running a proc (this is equal to calling something like 'ruby ctrl_proc.rb run'),
|
||||
the proc now runs directly in the calling script, not in a forked process anymore (thanks to Paul Butcher).
|
||||
* Set $0 to app_name in the daemons (thanks to Ilya Novoselov).
|
||||
|
||||
== Release 1.0.1: August 30, 2006
|
||||
|
||||
* Fixed a regex for parsing the 'ps ax' system call. (thanks to Garance Alistair Drosehn)
|
||||
|
||||
== Release 1.0.0: August 29, 2006
|
||||
|
||||
* Fix the parsing of the 'ps ax' system call. (thanks to Garance Alistair Drosehn)
|
||||
|
||||
== Release 0.4.4: February 14, 2006
|
||||
|
||||
* Several fixes that allow us to use the Daemons::Controller
|
||||
with a proc instead of wrapping a script file. This gives us all the
|
||||
PID file management, monitoring, command line options, etc. without having
|
||||
to specify a path to our script which can be tricky, especially when using
|
||||
RubyGems. (thanks to John-Mason Shackelford)
|
||||
|
||||
== Release 0.4.3: November 29, 2005
|
||||
|
||||
* New Option: You can specify the name of the application with :app_name
|
||||
on calling Daemons.run. This will be used to contruct the name of the pid files
|
||||
and log files. Defaults to the basename of the script. (thanks to Stephen R. Veit)
|
||||
|
||||
* Bugfix: Handle the case where no controller options are given when calling Daemons,
|
||||
just options after "--". (thanks to Stephen R. Veit)
|
||||
|
||||
|
||||
== Release 0.4.2: November 15, 2005
|
||||
|
||||
* Bugfix for problem with :normal pid-file directory mode (pid.rb), fixed (thanks to Stephen R. Veit)
|
||||
|
||||
|
||||
== Release 0.4.1: September 11, 2005
|
||||
|
||||
* Bugfix for 'run' command line mode: didn't work anymore in 0.4.0, fixed
|
||||
|
||||
|
||||
== Release 0.4.0: July 30, 2005
|
||||
|
||||
* Two completely new operation modes:
|
||||
1. Call a block as a daemon (<tt>Daemons.call { my_daemon_code }</tt>)
|
||||
and control it from the parent process.
|
||||
2. Daemonize the currently running process (<tt>Daemons.daemonize</tt>)
|
||||
plus the already existing mode to control your scripts (<tt>Daemons.run("script.rb")</tt>)
|
||||
* Improved documentation (for example "How does the daemonization process work?")
|
||||
* Improved "simulation mode" (<tt>:ontop</tt> option)
|
||||
* Some minor bugfixes
|
||||
|
||||
|
||||
== Release 0.3.0: April 21, 2005
|
||||
|
||||
* New monitor functionality: automatic restarting of your applications if they crash
|
||||
* 'restart' command fixed
|
||||
* '--force' command modifier (please refer to the documentation)
|
||||
* Some more bugfixes and improvements
|
||||
|
||||
|
||||
== Release 0.2.1: Mar 21, 2005
|
||||
|
||||
* Bugfix for a problem with the 'status' command
|
||||
|
||||
|
||||
== Release 0.2.0: Mar 21, 2005
|
||||
|
||||
* Exception backtrace functionality added
|
||||
* Exec functionality added
|
||||
* More examples added
|
||||
* New commands: status, zap
|
||||
|
||||
|
||||
== Release 0.0.1: Feb 8, 2005
|
||||
|
||||
* Initial release
|
6
vendor/gems/gems/daemons-1.0.10/TODO
vendored
|
@ -1,6 +0,0 @@
|
|||
* write the README (2005-02-07) *DONE*
|
||||
* write some real tests (2005-02-08)
|
||||
* document the new options (2005-03-14) *DONE*
|
||||
* start/stop with --force options (2005-04-05)
|
||||
* option to give some console output on start/stop commands (2005-04-05)
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
|
||||
require 'daemons'
|
||||
|
||||
testfile = File.expand_path(__FILE__) + '.log'
|
||||
|
||||
|
||||
# On the first call to <tt<call</tt>, an application group (accessible by <tt>Daemons.group</tt>)
|
||||
# will be created an the options will be kept within, so you only have to specify
|
||||
# <tt>:multiple</tt> once.
|
||||
#
|
||||
|
||||
options = {
|
||||
# :ontop => true,
|
||||
:multiple => true
|
||||
}
|
||||
|
||||
|
||||
Daemons.call(options) do
|
||||
File.open(testfile, 'w') {|f|
|
||||
f.puts "test"
|
||||
}
|
||||
|
||||
loop { puts "1"; sleep 5 }
|
||||
end
|
||||
puts "first task started"
|
||||
|
||||
Daemons.call do
|
||||
loop { puts "2"; sleep 4 }
|
||||
end
|
||||
puts "second task started"
|
||||
|
||||
# NOTE: this process will exit after 5 seconds
|
||||
Daemons.call do
|
||||
puts "3"
|
||||
sleep 5
|
||||
end
|
||||
puts "third task started"
|
||||
|
||||
puts "waiting 20 seconds..."
|
||||
sleep(20)
|
||||
|
||||
# This call would result in an exception as it will try to kill the third process
|
||||
# which has already terminated by that time; but using the 'true' parameter forces the
|
||||
# stop_all procedure.
|
||||
puts "trying to stop all tasks..."
|
||||
Daemons.group.stop_all(true)
|
||||
|
||||
puts "done"
|
|
@ -1,55 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
|
||||
require 'daemons'
|
||||
|
||||
testfile = File.expand_path(__FILE__) + '.log'
|
||||
|
||||
|
||||
# On the first call to <tt<call</tt>, an application group (accessible by <tt>Daemons.group</tt>)
|
||||
# will be created an the options will be kept within, so you only have to specify
|
||||
# <tt>:multiple</tt> once.
|
||||
#
|
||||
|
||||
options = {
|
||||
# :ontop => true,
|
||||
:multiple => true,
|
||||
:monitor => true
|
||||
}
|
||||
|
||||
|
||||
Daemons.call(options) do
|
||||
loop { puts "1"; sleep 20 }
|
||||
end
|
||||
puts "first task started"
|
||||
|
||||
|
||||
# NOTE: this process will exit after 5 seconds
|
||||
Daemons.call do
|
||||
File.open(testfile, 'a') {|f|
|
||||
f.puts "started..."
|
||||
puts "2"
|
||||
|
||||
sleep 5
|
||||
|
||||
f.puts "...exit"
|
||||
}
|
||||
end
|
||||
puts "second task started"
|
||||
|
||||
puts "waiting 100 seconds..."
|
||||
sleep(100)
|
||||
|
||||
# This call would result in an exception as it will try to kill the third process
|
||||
# which has already terminated by that time; but using the 'true' parameter forces the
|
||||
# stop_all procedure.
|
||||
puts "trying to stop all tasks..."
|
||||
Daemons.group.stop_all(true)
|
||||
|
||||
puts "done"
|
|
@ -1,20 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
testfile = File.expand_path(__FILE__) + '.log'
|
||||
|
||||
Daemons.daemonize
|
||||
|
||||
File.open(testfile, 'w') {|f|
|
||||
f.write("test")
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:log_output => true,
|
||||
:backtrace => true
|
||||
}
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver_crashing.rb'), options)
|
|
@ -1,16 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:mode => :exec
|
||||
}
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver.rb'), options)
|
|
@ -1,15 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
}
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver_exiting.rb'), options)
|
|
@ -1,17 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:keep_pid_files => true
|
||||
}
|
||||
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver.rb'), options)
|
|
@ -1,16 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:monitor => true
|
||||
}
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver_crashing.rb'), options)
|
|
@ -1,16 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:multiple => true
|
||||
}
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver.rb'), options)
|
|
@ -1,12 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver.rb'))
|
|
@ -1,16 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:ontop => true
|
||||
}
|
||||
|
||||
Daemons.run(File.join(File.dirname(__FILE__), 'myserver.rb'), options)
|
|
@ -1,43 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
require 'optparse'
|
||||
require 'logger'
|
||||
require 'ostruct'
|
||||
|
||||
|
||||
class MyApp < Logger::Application
|
||||
def initialize(args)
|
||||
super(self.class)
|
||||
@options = OpenStruct.new(:daemonize => true)
|
||||
opts = OptionParser.new do |opts|
|
||||
opts.banner = 'Usage: myapp [options]'
|
||||
opts.separator ''
|
||||
opts.on('-N','--no-daemonize',"Don't run as a daemon") do
|
||||
@options.daemonize = false
|
||||
end
|
||||
end
|
||||
@args = opts.parse!(args)
|
||||
end
|
||||
|
||||
def run
|
||||
Daemons.run_proc('myapp',{:ARGV => @args, :ontop => !@options.daemonize}) do
|
||||
puts "@options.daemonize: #{@options.daemonize}"
|
||||
STDOUT.sync = true
|
||||
loop do
|
||||
print '.'
|
||||
sleep(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
myapp = MyApp.new(ARGV)
|
||||
myapp.run
|
|
@ -1,25 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:multiple => false,
|
||||
:ontop => false,
|
||||
:backtrace => true,
|
||||
:log_output => true,
|
||||
:monitor => true
|
||||
}
|
||||
|
||||
Daemons.run_proc('ctrl_proc.rb', options) do
|
||||
loop do
|
||||
puts 'ping from proc!'
|
||||
sleep(3)
|
||||
end
|
||||
end
|
|
@ -1,101 +0,0 @@
|
|||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
||||
ping from proc!
|
|
@ -1,22 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
options = {
|
||||
:log_output => true,
|
||||
:multiple => true,
|
||||
}
|
||||
|
||||
|
||||
Daemons.run_proc('ctrl_proc_multiple.rb', options) do
|
||||
puts "hello"
|
||||
sleep(5)
|
||||
puts "done"
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
|
||||
hello
|
|
@ -1,17 +0,0 @@
|
|||
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), '../../lib'))
|
||||
|
||||
if File.exist?(File.join(lib_dir, 'daemons.rb'))
|
||||
$LOAD_PATH.unshift lib_dir
|
||||
else
|
||||
begin; require 'rubygems'; rescue ::Exception; end
|
||||
end
|
||||
|
||||
require 'daemons'
|
||||
|
||||
|
||||
Daemons.run_proc('ctrl_proc_simple.rb') do
|
||||
loop do
|
||||
puts 'ping from proc!'
|
||||
sleep(3)
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
|
||||
# This is myserver.rb, an example server that is to be controlled by daemons
|
||||
# and that does nothing really useful at the moment.
|
||||
#
|
||||
# Don't run this script by yourself, it can be controlled by the ctrl*.rb scripts.
|
||||
|
||||
loop do
|
||||
puts 'ping from myserver.rb!'
|
||||
sleep(3)
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
# This is myserver.rb, an example server that is to be controlled by daemons
|
||||
# and that does nothing really useful at the moment.
|
||||
#
|
||||
# Don't run this script by yourself, it can be controlled by the ctrl*.rb scripts.
|
||||
|
||||
loop do
|
||||
puts 'ping from myserver.rb!'
|
||||
puts 'this example server will crash in 3 seconds...'
|
||||
|
||||
sleep(3)
|
||||
|
||||
puts 'CRASH!'
|
||||
raise 'CRASH!'
|
||||
end
|
|
@ -1,30 +0,0 @@
|
|||
/home/uehli/Desktop/daemons-current/examples/myserver_crashing.rb:13: CRASH! (RuntimeError)
|
||||
from /home/uehli/Desktop/daemons-current/examples/myserver_crashing.rb:6:in `loop'
|
||||
from /home/uehli/Desktop/daemons-current/examples/myserver_crashing.rb:6
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons.rb:116:in `load'
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons.rb:116:in `run_via_load'
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons.rb:90:in `start'
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons.rb:359:in `run'
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons.rb:469:in `run'
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons.rb:468:in `call'
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons/cmdline.rb:94:in `catch_exceptions'
|
||||
from /home/uehli/Desktop/daemons-current/lib/daemons.rb:468:in `run'
|
||||
from ctrl_crash.rb:17
|
||||
ping from myserver.rb!
|
||||
this example server will crash in 3 seconds...
|
||||
CRASH!
|
||||
ping from myserver.rb!
|
||||
this example server will crash in 3 seconds...
|
||||
CRASH!
|
||||
/Users/uehli/Projects/daemons-proj/examples/run/myserver_crashing.rb:13: CRASH! (RuntimeError)
|
||||
from /Users/uehli/Projects/daemons-proj/examples/run/myserver_crashing.rb:6:in `loop'
|
||||
from /Users/uehli/Projects/daemons-proj/examples/run/myserver_crashing.rb:6
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons/application.rb:176:in `load'
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons/application.rb:176:in `start_load'
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons/application.rb:257:in `start'
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons/controller.rb:69:in `run'
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons.rb:139:in `run'
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons/cmdline.rb:105:in `call'
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons/cmdline.rb:105:in `catch_exceptions'
|
||||
from /Users/uehli/Projects/daemons-proj/lib/daemons.rb:138:in `run'
|
||||
from ctrl_crash.rb:17
|
|
@ -1,8 +0,0 @@
|
|||
loop do
|
||||
puts 'ping from myserver.rb!'
|
||||
puts 'this example server will exit in 3 seconds...'
|
||||
|
||||
sleep(3)
|
||||
|
||||
Process.exit
|
||||
end
|
283
vendor/gems/gems/daemons-1.0.10/lib/daemons.rb
vendored
|
@ -1,283 +0,0 @@
|
|||
require 'optparse'
|
||||
require 'optparse/time'
|
||||
|
||||
|
||||
require 'daemons/pidfile'
|
||||
require 'daemons/cmdline'
|
||||
require 'daemons/exceptions'
|
||||
require 'daemons/monitor'
|
||||
|
||||
|
||||
require 'daemons/application'
|
||||
require 'daemons/application_group'
|
||||
require 'daemons/controller'
|
||||
|
||||
|
||||
# All functions and classes that Daemons provides reside in this module.
|
||||
#
|
||||
# Daemons is normally invoked by one of the following four ways:
|
||||
#
|
||||
# 1. <tt>Daemons.run(script, options)</tt>:
|
||||
# This is used in wrapper-scripts that are supposed to control other ruby scripts or
|
||||
# external applications. Control is completely passed to the daemons library.
|
||||
# Such wrapper script need to be invoked with command line options like 'start' or 'stop'
|
||||
# to do anything useful.
|
||||
#
|
||||
# 2. <tt>Daemons.run_proc(app_name, options) { (...) }</tt>:
|
||||
# This is used in wrapper-scripts that are supposed to control a proc.
|
||||
# Control is completely passed to the daemons library.
|
||||
# Such wrapper script need to be invoked with command line options like 'start' or 'stop'
|
||||
# to do anything useful.
|
||||
#
|
||||
# 3. <tt>Daemons.call(options) { block }</tt>:
|
||||
# Execute the block in a new daemon. <tt>Daemons.call</tt> will return immediately
|
||||
# after spawning the daemon with the new Application object as a return value.
|
||||
#
|
||||
# 4. <tt>Daemons.daemonize(options)</tt>:
|
||||
# Daemonize the currently runnig process, i.e. the calling process will become a daemon.
|
||||
#
|
||||
# == What does daemons internally do with my daemons?
|
||||
# *or*:: why do my daemons crash when they try to open a file?
|
||||
# *or*:: why can I not see any output from the daemon on the console (when using for example +puts+)?
|
||||
#
|
||||
# From a technical aspect of view, daemons does the following when creating a daemon:
|
||||
#
|
||||
# 1. Forks a child (and exits the parent process, if needed)
|
||||
# 2. Becomes a session leader (which detaches the program from
|
||||
# the controlling terminal).
|
||||
# 3. Forks another child process and exits first child. This prevents
|
||||
# the potential of acquiring a controlling terminal.
|
||||
# 4. Changes the current working directory to "/".
|
||||
# 5. Clears the file creation mask (sets +umask+ to 0000).
|
||||
# 6. Closes file descriptors (reopens +STDOUT+ and +STDERR+ to point to a logfile if
|
||||
# possible).
|
||||
#
|
||||
# So what does this mean for your daemons:
|
||||
# - the current directory is '/'
|
||||
# - you cannot receive any input from the console (for example no +gets+)
|
||||
# - you cannot output anything from the daemons with +puts+/+print+ unless a logfile is used
|
||||
#
|
||||
# == How do PidFiles work? Where are they stored?
|
||||
#
|
||||
# Also, you are maybe interested in reading the documentation for the class PidFile.
|
||||
# There you can find out about how Daemons works internally and how and where the so
|
||||
# called <i>PidFiles</i> are stored.
|
||||
#
|
||||
module Daemons
|
||||
|
||||
VERSION = "1.0.10"
|
||||
|
||||
require 'daemons/daemonize'
|
||||
|
||||
|
||||
# Passes control to Daemons.
|
||||
# This is used in wrapper-scripts that are supposed to control other ruby scripts or
|
||||
# external applications. Control is completely passed to the daemons library.
|
||||
# Such wrapper script should be invoked with command line options like 'start' or 'stop'
|
||||
# to do anything useful.
|
||||
#
|
||||
# +script+:: This is the path to the script that should be run as a daemon.
|
||||
# Please note that Daemons runs this script with <tt>load <script></tt>.
|
||||
# Also note that Daemons cannot detect the directory in which the controlling
|
||||
# script resides, so this has to be either an absolute path or you have to run
|
||||
# the controlling script from the appropriate directory.
|
||||
#
|
||||
# +options+:: A hash that may contain one or more of the options listed below
|
||||
#
|
||||
# === Options:
|
||||
# <tt>:app_name</tt>:: The name of the application. This will be
|
||||
# used to contruct the name of the pid files
|
||||
# and log files. Defaults to the basename of
|
||||
# the script.
|
||||
# <tt>:ARGV</tt>:: An array of strings containing parameters and switches for Daemons.
|
||||
# This includes both parameters for Daemons itself and the controlled scripted.
|
||||
# These are assumed to be separated by an array element '--', .e.g.
|
||||
# ['start', 'f', '--', 'param1_for_script', 'param2_for_script'].
|
||||
# If not given, ARGV (the parameters given to the Ruby process) will be used.
|
||||
# <tt>:dir_mode</tt>:: Either <tt>:script</tt> (the directory for writing the pid files to
|
||||
# given by <tt>:dir</tt> is interpreted relative
|
||||
# to the script location given by +script+) or <tt>:normal</tt> (the directory given by
|
||||
# <tt>:dir</tt> is interpreted as a (absolute or relative) path) or <tt>:system</tt>
|
||||
# (<tt>/var/run</tt> is used as the pid file directory)
|
||||
#
|
||||
# <tt>:dir</tt>:: Used in combination with <tt>:dir_mode</tt> (description above)
|
||||
# <tt>:multiple</tt>:: Specifies whether multiple instances of the same script are allowed to run at the
|
||||
# same time
|
||||
# <tt>:ontop</tt>:: When given (i.e. set to true), stay on top, i.e. do not daemonize the application
|
||||
# (but the pid-file and other things are written as usual)
|
||||
# <tt>:mode</tt>:: <tt>:load</tt> Load the script with <tt>Kernel.load</tt>;
|
||||
# <tt>:exec</tt> Execute the script file with <tt>Kernel.exec</tt>
|
||||
# <tt>:backtrace</tt>:: Write a backtrace of the last exceptions to the file '[app_name].log' in the
|
||||
# pid-file directory if the application exits due to an uncaught exception
|
||||
# <tt>:monitor</tt>:: Monitor the programs and restart crashed instances
|
||||
# <tt>:log_output</tt>:: When given (i.e. set to true), redirect both STDOUT and STDERR to a logfile named '[app_name].output' in the pid-file directory
|
||||
# <tt>:keep_pid_files</tt>:: When given do not delete lingering pid-files (files for which the process is no longer running).
|
||||
# <tt>:hard_exit</tt>:: When given use exit! to end a daemons instead of exit (this will for example
|
||||
# not call at_exit handlers).
|
||||
# -----
|
||||
#
|
||||
# === Example:
|
||||
# options = {
|
||||
# :app_name => "my_app",
|
||||
# :ARGV => ['start', '-f', '--', 'param_for_myscript']
|
||||
# :dir_mode => :script,
|
||||
# :dir => 'pids',
|
||||
# :multiple => true,
|
||||
# :ontop => true,
|
||||
# :mode => :exec,
|
||||
# :backtrace => true,
|
||||
# :monitor => true
|
||||
# }
|
||||
#
|
||||
# Daemons.run(File.join(File.dirname(__FILE__), 'myscript.rb'), options)
|
||||
#
|
||||
def run(script, options = {})
|
||||
options[:script] = script
|
||||
@controller = Controller.new(options, options[:ARGV] || ARGV)
|
||||
|
||||
@controller.catch_exceptions {
|
||||
@controller.run
|
||||
}
|
||||
|
||||
# I don't think anybody will ever use @group, as this location should not be reached under non-error conditions
|
||||
@group = @controller.group
|
||||
end
|
||||
module_function :run
|
||||
|
||||
|
||||
# Passes control to Daemons.
|
||||
# This function does the same as Daemons.run except that not a script but a proc
|
||||
# will be run as a daemon while this script provides command line options like 'start' or 'stop'
|
||||
# and the whole pid-file management to control the proc.
|
||||
#
|
||||
# +app_name+:: The name of the application. This will be
|
||||
# used to contruct the name of the pid files
|
||||
# and log files. Defaults to the basename of
|
||||
# the script.
|
||||
#
|
||||
# +options+:: A hash that may contain one or more of the options listed in the documentation for Daemons.run
|
||||
#
|
||||
# A block must be given to this function. The block will be used as the :proc entry in the options hash.
|
||||
# -----
|
||||
#
|
||||
# === Example:
|
||||
#
|
||||
# Daemons.run_proc('myproc.rb') do
|
||||
# loop do
|
||||
# accept_connection()
|
||||
# read_request()
|
||||
# send_response()
|
||||
# close_connection()
|
||||
# end
|
||||
# end
|
||||
#
|
||||
def run_proc(app_name, options = {}, &block)
|
||||
options[:app_name] = app_name
|
||||
options[:mode] = :proc
|
||||
options[:proc] = block
|
||||
|
||||
# we do not have a script location so the the :script :dir_mode cannot be used, change it to :normal
|
||||
if [nil, :script].include? options[:dir_mode]
|
||||
options[:dir_mode] = :normal
|
||||
options[:dir] = File.expand_path('.')
|
||||
end
|
||||
|
||||
@controller = Controller.new(options, options[:ARGV] || ARGV)
|
||||
|
||||
@controller.catch_exceptions {
|
||||
@controller.run
|
||||
}
|
||||
|
||||
# I don't think anybody will ever use @group, as this location should not be reached under non-error conditions
|
||||
@group = @controller.group
|
||||
end
|
||||
module_function :run_proc
|
||||
|
||||
|
||||
# Execute the block in a new daemon. <tt>Daemons.call</tt> will return immediately
|
||||
# after spawning the daemon with the new Application object as a return value.
|
||||
#
|
||||
# +options+:: A hash that may contain one or more of the options listed below
|
||||
#
|
||||
# +block+:: The block to call in the daemon.
|
||||
#
|
||||
# === Options:
|
||||
# <tt>:multiple</tt>:: Specifies whether multiple instances of the same script are allowed to run at the
|
||||
# same time
|
||||
# <tt>:ontop</tt>:: When given, stay on top, i.e. do not daemonize the application
|
||||
# <tt>:backtrace</tt>:: Write a backtrace of the last exceptions to the file '[app_name].log' in the
|
||||
# pid-file directory if the application exits due to an uncaught exception
|
||||
# -----
|
||||
#
|
||||
# === Example:
|
||||
# options = {
|
||||
# :backtrace => true,
|
||||
# :monitor => true,
|
||||
# :ontop => true
|
||||
# }
|
||||
#
|
||||
# Daemons.call(options) begin
|
||||
# # Server loop:
|
||||
# loop {
|
||||
# conn = accept_conn()
|
||||
# serve(conn)
|
||||
# }
|
||||
# end
|
||||
#
|
||||
def call(options = {}, &block)
|
||||
unless block_given?
|
||||
raise "Daemons.call: no block given"
|
||||
end
|
||||
|
||||
options[:proc] = block
|
||||
options[:mode] = :proc
|
||||
|
||||
@group ||= ApplicationGroup.new('proc', options)
|
||||
|
||||
new_app = @group.new_application(options)
|
||||
new_app.start
|
||||
|
||||
return new_app
|
||||
end
|
||||
module_function :call
|
||||
|
||||
|
||||
# Daemonize the currently runnig process, i.e. the calling process will become a daemon.
|
||||
#
|
||||
# +options+:: A hash that may contain one or more of the options listed below
|
||||
#
|
||||
# === Options:
|
||||
# <tt>:ontop</tt>:: When given, stay on top, i.e. do not daemonize the application
|
||||
# <tt>:backtrace</tt>:: Write a backtrace of the last exceptions to the file '[app_name].log' in the
|
||||
# pid-file directory if the application exits due to an uncaught exception
|
||||
# -----
|
||||
#
|
||||
# === Example:
|
||||
# options = {
|
||||
# :backtrace => true,
|
||||
# :ontop => true
|
||||
# }
|
||||
#
|
||||
# Daemons.daemonize(options)
|
||||
#
|
||||
# # Server loop:
|
||||
# loop {
|
||||
# conn = accept_conn()
|
||||
# serve(conn)
|
||||
# }
|
||||
#
|
||||
def daemonize(options = {})
|
||||
@group ||= ApplicationGroup.new('self', options)
|
||||
|
||||
@group.new_application(:mode => :none).start
|
||||
end
|
||||
module_function :daemonize
|
||||
|
||||
# Return the internal ApplicationGroup instance.
|
||||
def group; @group; end
|
||||
module_function :group
|
||||
|
||||
# Return the internal Controller instance.
|
||||
def controller; @controller; end
|
||||
module_function :controller
|
||||
end
|
|
@ -1,372 +0,0 @@
|
|||
require 'daemons/pidfile'
|
||||
require 'daemons/pidmem'
|
||||
|
||||
|
||||
module Daemons
|
||||
|
||||
class Application
|
||||
|
||||
attr_accessor :app_argv
|
||||
attr_accessor :controller_argv
|
||||
|
||||
# the Pid instance belonging to this application
|
||||
attr_reader :pid
|
||||
|
||||
# the ApplicationGroup the application belongs to
|
||||
attr_reader :group
|
||||
|
||||
# my private options
|
||||
attr_reader :options
|
||||
|
||||
|
||||
SIGNAL = (RUBY_PLATFORM =~ /win32/ ? 'KILL' : 'TERM')
|
||||
|
||||
|
||||
def initialize(group, add_options = {}, pid = nil)
|
||||
@group = group
|
||||
@options = group.options.dup
|
||||
@options.update(add_options)
|
||||
|
||||
@dir_mode = @dir = @script = nil
|
||||
|
||||
unless @pid = pid
|
||||
if dir = pidfile_dir
|
||||
@pid = PidFile.new(dir, @group.app_name, @group.multiple)
|
||||
else
|
||||
@pid = PidMem.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def script
|
||||
@script || @group.script
|
||||
end
|
||||
|
||||
def pidfile_dir
|
||||
Pid.dir(@dir_mode || @group.dir_mode, @dir || @group.dir, @script || @group.script)
|
||||
end
|
||||
|
||||
def output_logfile
|
||||
logdir = options[:dir_mode] == :system ? '/var/log' : pidfile_dir
|
||||
(options[:log_output] && logdir) ? File.join(logdir, @group.app_name + '.output') : nil
|
||||
end
|
||||
|
||||
def logfile
|
||||
logdir = options[:dir_mode] == :system ? '/var/log' : pidfile_dir
|
||||
logdir ? File.join(logdir, @group.app_name + '.log') : nil
|
||||
end
|
||||
|
||||
# this function is only used to daemonize the currently running process (Daemons.daemonize)
|
||||
def start_none
|
||||
unless options[:ontop]
|
||||
Daemonize.daemonize(nil, @group.app_name) #(logfile)
|
||||
else
|
||||
Daemonize.simulate
|
||||
end
|
||||
|
||||
@pid.pid = Process.pid
|
||||
|
||||
|
||||
# We need this to remove the pid-file if the applications exits by itself.
|
||||
# Note that <tt>at_text</tt> will only be run if the applications exits by calling
|
||||
# <tt>exit</tt>, and not if it calls <tt>exit!</tt> (so please don't call <tt>exit!</tt>
|
||||
# in your application!
|
||||
#
|
||||
at_exit {
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
|
||||
# If the option <tt>:backtrace</tt> is used and the application did exit by itself
|
||||
# create a exception log.
|
||||
if options[:backtrace] and not options[:ontop] and not $daemons_sigterm
|
||||
begin; exception_log(); rescue ::Exception; end
|
||||
end
|
||||
|
||||
}
|
||||
|
||||
# This part is needed to remove the pid-file if the application is killed by
|
||||
# daemons or manually by the user.
|
||||
# Note that the applications is not supposed to overwrite the signal handler for
|
||||
# 'TERM'.
|
||||
#
|
||||
trap(SIGNAL) {
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
$daemons_sigterm = true
|
||||
|
||||
if options[:hard_exit]
|
||||
exit!
|
||||
else
|
||||
exit
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def start_exec
|
||||
if options[:backtrace]
|
||||
puts "option :backtrace is not supported with :mode => :exec, ignoring"
|
||||
end
|
||||
|
||||
unless options[:ontop]
|
||||
Daemonize.daemonize(output_logfile, @group.app_name)
|
||||
else
|
||||
Daemonize.simulate(output_logfile)
|
||||
end
|
||||
|
||||
# note that we cannot remove the pid file if we run in :ontop mode (i.e. 'ruby ctrl_exec.rb run')
|
||||
@pid.pid = Process.pid
|
||||
|
||||
ENV['DAEMONS_ARGV'] = @controller_argv.join(' ')
|
||||
# haven't tested yet if this is really passed to the exec'd process...
|
||||
|
||||
|
||||
|
||||
Kernel.exec(script(), *(@app_argv || []))
|
||||
#Kernel.exec(script(), *ARGV)
|
||||
end
|
||||
|
||||
def start_load
|
||||
unless options[:ontop]
|
||||
Daemonize.daemonize(output_logfile, @group.app_name)
|
||||
else
|
||||
Daemonize.simulate(output_logfile)
|
||||
end
|
||||
|
||||
@pid.pid = Process.pid
|
||||
|
||||
|
||||
# We need this to remove the pid-file if the applications exits by itself.
|
||||
# Note that <tt>at_text</tt> will only be run if the applications exits by calling
|
||||
# <tt>exit</tt>, and not if it calls <tt>exit!</tt> (so please don't call <tt>exit!</tt>
|
||||
# in your application!
|
||||
#
|
||||
at_exit {
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
|
||||
# If the option <tt>:backtrace</tt> is used and the application did exit by itself
|
||||
# create a exception log.
|
||||
if options[:backtrace] and not options[:ontop] and not $daemons_sigterm
|
||||
begin; exception_log(); rescue ::Exception; end
|
||||
end
|
||||
|
||||
}
|
||||
|
||||
# This part is needed to remove the pid-file if the application is killed by
|
||||
# daemons or manually by the user.
|
||||
# Note that the applications is not supposed to overwrite the signal handler for
|
||||
# 'TERM'.
|
||||
#
|
||||
trap(SIGNAL) {
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
$daemons_sigterm = true
|
||||
|
||||
if options[:hard_exit]
|
||||
exit!
|
||||
else
|
||||
exit
|
||||
end
|
||||
}
|
||||
|
||||
# Now we really start the script...
|
||||
$DAEMONS_ARGV = @controller_argv
|
||||
ENV['DAEMONS_ARGV'] = @controller_argv.join(' ')
|
||||
|
||||
ARGV.clear
|
||||
ARGV.concat @app_argv if @app_argv
|
||||
|
||||
# TODO: begin - rescue - end around this and exception logging
|
||||
load script()
|
||||
end
|
||||
|
||||
def start_proc
|
||||
return unless p = options[:proc]
|
||||
|
||||
myproc = proc do
|
||||
# We need this to remove the pid-file if the applications exits by itself.
|
||||
# Note that <tt>at_text</tt> will only be run if the applications exits by calling
|
||||
# <tt>exit</tt>, and not if it calls <tt>exit!</tt> (so please don't call <tt>exit!</tt>
|
||||
# in your application!
|
||||
#
|
||||
at_exit {
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
|
||||
# If the option <tt>:backtrace</tt> is used and the application did exit by itself
|
||||
# create a exception log.
|
||||
if options[:backtrace] and not options[:ontop] and not $daemons_sigterm
|
||||
begin; exception_log(); rescue ::Exception; end
|
||||
end
|
||||
|
||||
}
|
||||
|
||||
# This part is needed to remove the pid-file if the application is killed by
|
||||
# daemons or manually by the user.
|
||||
# Note that the applications is not supposed to overwrite the signal handler for
|
||||
# 'TERM'.
|
||||
#
|
||||
trap(SIGNAL) {
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
$daemons_sigterm = true
|
||||
|
||||
if options[:hard_exit]
|
||||
exit!
|
||||
else
|
||||
exit
|
||||
end
|
||||
}
|
||||
|
||||
p.call()
|
||||
end
|
||||
|
||||
unless options[:ontop]
|
||||
@pid.pid = Daemonize.call_as_daemon(myproc, output_logfile, @group.app_name)
|
||||
else
|
||||
Daemonize.simulate(output_logfile)
|
||||
|
||||
@pid.pid = Process.pid
|
||||
|
||||
myproc.call
|
||||
|
||||
# why did we use this??
|
||||
# Thread.new(&options[:proc])
|
||||
|
||||
# why did we use the code below??
|
||||
# unless pid = Process.fork
|
||||
# @pid.pid = pid
|
||||
# Daemonize.simulate(logfile)
|
||||
# options[:proc].call
|
||||
# exit
|
||||
# else
|
||||
# Process.detach(@pid.pid)
|
||||
# end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def start
|
||||
@group.create_monitor(@group.applications[0] || self) unless options[:ontop] # we don't monitor applications in the foreground
|
||||
|
||||
case options[:mode]
|
||||
when :none
|
||||
# this is only used to daemonize the currently running process
|
||||
start_none
|
||||
when :exec
|
||||
start_exec
|
||||
when :load
|
||||
start_load
|
||||
when :proc
|
||||
start_proc
|
||||
else
|
||||
start_load
|
||||
end
|
||||
end
|
||||
|
||||
# def run
|
||||
# if @group.controller.options[:exec]
|
||||
# run_via_exec()
|
||||
# else
|
||||
# run_via_load()
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# def run_via_exec
|
||||
#
|
||||
# end
|
||||
#
|
||||
# def run_via_load
|
||||
#
|
||||
# end
|
||||
|
||||
|
||||
# This is a nice little function for debugging purposes:
|
||||
# In case a multi-threaded ruby script exits due to an uncaught exception
|
||||
# it may be difficult to find out where the exception came from because
|
||||
# one cannot catch exceptions that are thrown in threads other than the main
|
||||
# thread.
|
||||
#
|
||||
# This function searches for all exceptions in memory and outputs them to STDERR
|
||||
# (if it is connected) and to a log file in the pid-file directory.
|
||||
#
|
||||
def exception_log
|
||||
return unless logfile
|
||||
|
||||
require 'logger'
|
||||
|
||||
l_file = Logger.new(logfile)
|
||||
|
||||
# the code below finds the last exception
|
||||
e = nil
|
||||
|
||||
ObjectSpace.each_object {|o|
|
||||
if ::Exception === o
|
||||
e = o
|
||||
end
|
||||
}
|
||||
|
||||
l_file.info "*** below you find the most recent exception thrown, this will be likely (but not certainly) the exception that made the application exit abnormally ***"
|
||||
l_file.error e
|
||||
|
||||
l_file.info "*** below you find all exception objects found in memory, some of them may have been thrown in your application, others may just be in memory because they are standard exceptions ***"
|
||||
|
||||
# this code logs every exception found in memory
|
||||
ObjectSpace.each_object {|o|
|
||||
if ::Exception === o
|
||||
l_file.error o
|
||||
end
|
||||
}
|
||||
|
||||
l_file.close
|
||||
end
|
||||
|
||||
|
||||
def stop
|
||||
if options[:force] and not running?
|
||||
self.zap
|
||||
return
|
||||
end
|
||||
|
||||
# Catch errors when trying to kill a process that doesn't
|
||||
# exist. This happens when the process quits and hasn't been
|
||||
# restarted by the monitor yet. By catching the error, we allow the
|
||||
# pid file clean-up to occur.
|
||||
begin
|
||||
Process.kill(SIGNAL, @pid.pid)
|
||||
rescue Errno::ESRCH => e
|
||||
puts "#{e} #{@pid.pid}"
|
||||
puts "deleting pid-file."
|
||||
end
|
||||
|
||||
# We try to remove the pid-files by ourselves, in case the application
|
||||
# didn't clean it up.
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
|
||||
end
|
||||
|
||||
def zap
|
||||
@pid.cleanup
|
||||
end
|
||||
|
||||
def zap!
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
end
|
||||
|
||||
def show_status
|
||||
running = self.running?
|
||||
|
||||
puts "#{self.group.app_name}: #{running ? '' : 'not '}running#{(running and @pid.exist?) ? ' [pid ' + @pid.pid.to_s + ']' : ''}#{(@pid.exist? and not running) ? ' (but pid-file exists: ' + @pid.pid.to_s + ')' : ''}"
|
||||
end
|
||||
|
||||
# This function implements a (probably too simle) method to detect
|
||||
# whether the program with the pid found in the pid-file is still running.
|
||||
# It just searches for the pid in the output of <tt>ps ax</tt>, which
|
||||
# is probably not a good idea in some cases.
|
||||
# Alternatives would be to use a direct access method the unix process control
|
||||
# system.
|
||||
#
|
||||
def running?
|
||||
if @pid.exist?
|
||||
return Pid.running?(@pid.pid)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,152 +0,0 @@
|
|||
|
||||
module Daemons
|
||||
class ApplicationGroup
|
||||
|
||||
attr_reader :app_name
|
||||
attr_reader :script
|
||||
|
||||
attr_reader :monitor
|
||||
|
||||
#attr_reader :controller
|
||||
|
||||
attr_reader :options
|
||||
|
||||
attr_reader :applications
|
||||
|
||||
attr_accessor :controller_argv
|
||||
attr_accessor :app_argv
|
||||
|
||||
attr_accessor :dir_mode
|
||||
attr_accessor :dir
|
||||
|
||||
# true if the application is supposed to run in multiple instances
|
||||
attr_reader :multiple
|
||||
|
||||
|
||||
def initialize(app_name, options = {})
|
||||
@app_name = app_name
|
||||
@options = options
|
||||
|
||||
if options[:script]
|
||||
@script = File.expand_path(options[:script])
|
||||
end
|
||||
|
||||
#@controller = controller
|
||||
@monitor = nil
|
||||
|
||||
#options = controller.options
|
||||
|
||||
@multiple = options[:multiple] || false
|
||||
|
||||
@dir_mode = options[:dir_mode] || :script
|
||||
@dir = options[:dir] || ''
|
||||
|
||||
@keep_pid_files = options[:keep_pid_files] || false
|
||||
|
||||
#@applications = find_applications(pidfile_dir())
|
||||
@applications = []
|
||||
end
|
||||
|
||||
# Setup the application group.
|
||||
# Currently this functions calls <tt>find_applications</tt> which finds
|
||||
# all running instances of the application and populates the application array.
|
||||
#
|
||||
def setup
|
||||
@applications = find_applications(pidfile_dir())
|
||||
end
|
||||
|
||||
def pidfile_dir
|
||||
PidFile.dir(@dir_mode, @dir, script)
|
||||
end
|
||||
|
||||
def find_applications(dir)
|
||||
pid_files = PidFile.find_files(dir, app_name, ! @keep_pid_files)
|
||||
|
||||
#pp pid_files
|
||||
|
||||
@monitor = Monitor.find(dir, app_name + '_monitor')
|
||||
|
||||
pid_files.reject! {|f| f =~ /_monitor.pid$/}
|
||||
|
||||
return pid_files.map {|f|
|
||||
app = Application.new(self, {}, PidFile.existing(f))
|
||||
setup_app(app)
|
||||
app
|
||||
}
|
||||
end
|
||||
|
||||
def new_application(add_options = {})
|
||||
if @applications.size > 0 and not @multiple
|
||||
if options[:force]
|
||||
@applications.delete_if {|a|
|
||||
unless a.running?
|
||||
a.zap
|
||||
true
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
raise RuntimeException.new('there is already one or more instance(s) of the program running') unless @applications.empty?
|
||||
end
|
||||
|
||||
app = Application.new(self, add_options)
|
||||
|
||||
setup_app(app)
|
||||
|
||||
@applications << app
|
||||
|
||||
return app
|
||||
end
|
||||
|
||||
def setup_app(app)
|
||||
app.controller_argv = @controller_argv
|
||||
app.app_argv = @app_argv
|
||||
end
|
||||
private :setup_app
|
||||
|
||||
def create_monitor(an_app)
|
||||
return if @monitor
|
||||
|
||||
if options[:monitor]
|
||||
@monitor = Monitor.new(an_app)
|
||||
|
||||
@monitor.start(@applications)
|
||||
end
|
||||
end
|
||||
|
||||
def start_all
|
||||
@monitor.stop if @monitor
|
||||
@monitor = nil
|
||||
|
||||
@applications.each {|a|
|
||||
fork {
|
||||
a.start
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def stop_all(force = false)
|
||||
@monitor.stop if @monitor
|
||||
|
||||
@applications.each {|a|
|
||||
if force
|
||||
begin; a.stop; rescue ::Exception; end
|
||||
else
|
||||
a.stop
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
def zap_all
|
||||
@monitor.stop if @monitor
|
||||
|
||||
@applications.each {|a| a.zap}
|
||||
end
|
||||
|
||||
def show_status
|
||||
@applications.each {|a| a.show_status}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,117 +0,0 @@
|
|||
|
||||
module Daemons
|
||||
|
||||
class Optparse
|
||||
|
||||
attr_reader :usage
|
||||
|
||||
def initialize(controller)
|
||||
@controller = controller
|
||||
@options = {}
|
||||
|
||||
@opts = OptionParser.new do |opts|
|
||||
#opts.banner = "Usage: example.rb [options]"
|
||||
opts.banner = ""
|
||||
|
||||
# Boolean switch.
|
||||
# opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
||||
# @options[:verbose] = v
|
||||
# end
|
||||
|
||||
opts.on("-t", "--ontop", "Stay on top (does not daemonize)") do |t|
|
||||
@options[:ontop] = t
|
||||
end
|
||||
|
||||
opts.on("-f", "--force", "Force operation") do |t|
|
||||
@options[:force] = t
|
||||
end
|
||||
|
||||
#opts.separator ""
|
||||
#opts.separator "Specific options:"
|
||||
|
||||
|
||||
opts.separator ""
|
||||
opts.separator "Common options:"
|
||||
|
||||
# No argument, shows at tail. This will print an options summary.
|
||||
# Try it and see!
|
||||
opts.on_tail("-h", "--help", "Show this message") do
|
||||
#puts opts
|
||||
#@usage =
|
||||
controller.print_usage()
|
||||
|
||||
exit
|
||||
end
|
||||
|
||||
# Another typical switch to print the version.
|
||||
opts.on_tail("--version", "Show version") do
|
||||
puts "daemons version #{Daemons::VERSION}"
|
||||
exit
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
@usage = @opts.to_s
|
||||
rescue ::Exception # work around a bug in ruby 1.9
|
||||
@usage = <<END
|
||||
-t, --ontop Stay on top (does not daemonize)
|
||||
-f, --force Force operation
|
||||
|
||||
Common options:
|
||||
-h, --help Show this message
|
||||
--version Show version
|
||||
END
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Return a hash describing the options.
|
||||
#
|
||||
def parse(args)
|
||||
# The options specified on the command line will be collected in *options*.
|
||||
# We set default values here.
|
||||
#options = {}
|
||||
|
||||
|
||||
##pp args
|
||||
@opts.parse(args)
|
||||
|
||||
return @options
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Controller
|
||||
|
||||
def print_usage
|
||||
puts "Usage: #{@app_name} <command> <options> -- <application options>"
|
||||
puts
|
||||
puts "* where <command> is one of:"
|
||||
puts " start start an instance of the application"
|
||||
puts " stop stop all instances of the application"
|
||||
puts " restart stop all instances and restart them afterwards"
|
||||
puts " run start the application and stay on top"
|
||||
puts " zap set the application to a stopped state"
|
||||
puts
|
||||
puts "* and where <options> may contain several of the following:"
|
||||
|
||||
puts @optparse.usage
|
||||
end
|
||||
|
||||
def catch_exceptions(&block)
|
||||
begin
|
||||
block.call
|
||||
rescue CmdException, OptionParser::ParseError => e
|
||||
puts "ERROR: #{e.to_s}"
|
||||
puts
|
||||
print_usage()
|
||||
rescue RuntimeException => e
|
||||
puts "ERROR: #{e.to_s}"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,134 +0,0 @@
|
|||
|
||||
module Daemons
|
||||
class Controller
|
||||
|
||||
attr_reader :app_name
|
||||
|
||||
attr_reader :group
|
||||
|
||||
attr_reader :options
|
||||
|
||||
|
||||
COMMANDS = [
|
||||
'start',
|
||||
'stop',
|
||||
'restart',
|
||||
'run',
|
||||
'zap',
|
||||
'status'
|
||||
]
|
||||
|
||||
def initialize(options = {}, argv = [])
|
||||
@options = options
|
||||
@argv = argv
|
||||
|
||||
# Allow an app_name to be specified. If not specified use the
|
||||
# basename of the script.
|
||||
@app_name = options[:app_name]
|
||||
|
||||
if options[:script]
|
||||
@script = File.expand_path(options[:script])
|
||||
|
||||
@app_name ||= File.split(@script)[1]
|
||||
end
|
||||
|
||||
@app_name ||= 'unknown_application'
|
||||
|
||||
@command, @controller_part, @app_part = Controller.split_argv(argv)
|
||||
|
||||
#@options[:dir_mode] ||= :script
|
||||
|
||||
@optparse = Optparse.new(self)
|
||||
end
|
||||
|
||||
|
||||
# This function is used to do a final update of the options passed to the application
|
||||
# before they are really used.
|
||||
#
|
||||
# Note that this function should only update <tt>@options</tt> and no other variables.
|
||||
#
|
||||
def setup_options
|
||||
#@options[:ontop] ||= true
|
||||
end
|
||||
|
||||
def run
|
||||
@options.update @optparse.parse(@controller_part).delete_if {|k,v| !v}
|
||||
|
||||
setup_options()
|
||||
|
||||
#pp @options
|
||||
|
||||
@group = ApplicationGroup.new(@app_name, @options)
|
||||
@group.controller_argv = @controller_part
|
||||
@group.app_argv = @app_part
|
||||
|
||||
@group.setup
|
||||
|
||||
case @command
|
||||
when 'start'
|
||||
@group.new_application.start
|
||||
when 'run'
|
||||
@options[:ontop] ||= true
|
||||
@group.new_application.start
|
||||
when 'stop'
|
||||
@group.stop_all
|
||||
when 'restart'
|
||||
unless @group.applications.empty?
|
||||
@group.stop_all
|
||||
sleep 1
|
||||
@group.start_all
|
||||
end
|
||||
when 'zap'
|
||||
@group.zap_all
|
||||
when 'status'
|
||||
unless @group.applications.empty?
|
||||
@group.show_status
|
||||
else
|
||||
puts "#{@group.app_name}: no instances running"
|
||||
end
|
||||
when nil
|
||||
raise CmdException.new('no command given')
|
||||
#puts "ERROR: No command given"; puts
|
||||
|
||||
#print_usage()
|
||||
#raise('usage function not implemented')
|
||||
else
|
||||
raise Error.new("command '#{@command}' not implemented")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Split an _argv_ array.
|
||||
# +argv+ is assumed to be in the following format:
|
||||
# ['command', 'controller option 1', 'controller option 2', ..., '--', 'app option 1', ...]
|
||||
#
|
||||
# <tt>command</tt> must be one of the commands listed in <tt>COMMANDS</tt>
|
||||
#
|
||||
# *Returns*: the command as a string, the controller options as an array, the appliation options
|
||||
# as an array
|
||||
#
|
||||
def Controller.split_argv(argv)
|
||||
argv = argv.dup
|
||||
|
||||
command = nil
|
||||
controller_part = []
|
||||
app_part = []
|
||||
|
||||
if COMMANDS.include? argv[0]
|
||||
command = argv.shift
|
||||
end
|
||||
|
||||
if i = argv.index('--')
|
||||
# Handle the case where no controller options are given, just
|
||||
# options after "--" as well (i == 0)
|
||||
controller_part = (i == 0 ? [] : argv[0..i-1])
|
||||
app_part = argv[i+1..-1]
|
||||
else
|
||||
controller_part = argv[0..-1]
|
||||
end
|
||||
|
||||
return command, controller_part, app_part
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -1,263 +0,0 @@
|
|||
#--
|
||||
###############################################################################
|
||||
# daemonize.rb is a slightly modified version of daemonize.rb was #
|
||||
# from the Daemonize Library written by Travis Whitton #
|
||||
# for details, read the notice below #
|
||||
###############################################################################
|
||||
#++
|
||||
#
|
||||
#
|
||||
# =Daemonize Library
|
||||
#
|
||||
# February. 4, 2005 Travis Whitton <whitton@atlantic.net>
|
||||
#
|
||||
# Daemonize allows you to easily modify any existing Ruby program to run
|
||||
# as a daemon. See README.rdoc for more details.
|
||||
#
|
||||
# == How to install
|
||||
# 1. su to root
|
||||
# 2. ruby install.rb
|
||||
# build the docs if you want to
|
||||
# 3. rdoc --main README.rdoc daemonize.rb README.rdoc
|
||||
#
|
||||
# == Copying
|
||||
# The Daemonize extension module is copywrited free software by Travis Whitton
|
||||
# <whitton@atlantic.net>. You can redistribute it under the terms specified in
|
||||
# the COPYING file of the Ruby distribution.
|
||||
#
|
||||
# == WARRANTY
|
||||
# THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
# PURPOSE.
|
||||
#
|
||||
#
|
||||
# ----
|
||||
#
|
||||
# == Purpose
|
||||
#
|
||||
# Daemonize is a module derived from Perl's Proc::Daemon module. This module
|
||||
# allows you to easily modify any existing Ruby program to run as a daemon.
|
||||
# A daemon is a process that runs in the background with no controlling terminal.
|
||||
# Generally servers (like FTP and HTTP servers) run as daemon processes.
|
||||
# Note, do not make the mistake that a daemon == server. Converting a program
|
||||
# to a daemon by hand is a relatively simple process; however, this module will
|
||||
# save you the effort of repeatedly looking up the procedure, and it will also
|
||||
# insure that your programs are daemonized in the safest and most corrects
|
||||
# fashion possible.
|
||||
#
|
||||
# == Procedure
|
||||
#
|
||||
# The Daemonize module does the following:
|
||||
#
|
||||
# Forks a child and exits the parent process.
|
||||
#
|
||||
# Becomes a session leader (which detaches the program from
|
||||
# the controlling terminal).
|
||||
#
|
||||
# Forks another child process and exits first child. This prevents
|
||||
# the potential of acquiring a controlling terminal.
|
||||
#
|
||||
# Changes the current working directory to "/".
|
||||
#
|
||||
# Clears the file creation mask.
|
||||
#
|
||||
# Closes file descriptors.
|
||||
#
|
||||
# == Example usage
|
||||
#
|
||||
# Using the Daemonize module is extremely simple:
|
||||
#
|
||||
# require 'daemonize'
|
||||
#
|
||||
# class TestDaemon
|
||||
# include Daemonize
|
||||
#
|
||||
# def initialize
|
||||
# daemonize()
|
||||
# loop do
|
||||
# # do some work here
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# == Credits
|
||||
#
|
||||
# Daemonize was written by Travis Whitton and is based on Perl's
|
||||
# Proc::Daemonize, which was written by Earl Hood. The above documentation
|
||||
# is also partially borrowed from the Proc::Daemonize POD documentation.
|
||||
|
||||
|
||||
|
||||
module Daemonize
|
||||
VERSION = "0.1.1m"
|
||||
|
||||
# Try to fork if at all possible retrying every 5 sec if the
|
||||
# maximum process limit for the system has been reached
|
||||
def safefork
|
||||
tryagain = true
|
||||
|
||||
while tryagain
|
||||
tryagain = false
|
||||
begin
|
||||
if pid = fork
|
||||
return pid
|
||||
end
|
||||
rescue Errno::EWOULDBLOCK
|
||||
sleep 5
|
||||
tryagain = true
|
||||
end
|
||||
end
|
||||
end
|
||||
module_function :safefork
|
||||
|
||||
|
||||
def simulate(logfile_name = nil)
|
||||
# NOTE: STDOUT and STDERR will not be redirected to the logfile, because in :ontop mode, we normally want to see the output
|
||||
|
||||
Dir.chdir "/" # Release old working directory
|
||||
File.umask 0000 # Insure sensible umask
|
||||
|
||||
# Make sure all file descriptors are closed
|
||||
ObjectSpace.each_object(IO) do |io|
|
||||
unless [STDIN, STDOUT, STDERR].include?(io)
|
||||
begin
|
||||
unless io.closed?
|
||||
io.close
|
||||
end
|
||||
rescue ::Exception
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Free file descriptors and
|
||||
# point them somewhere sensible
|
||||
# STDOUT/STDERR should go to a logfile
|
||||
|
||||
begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
|
||||
end
|
||||
module_function :simulate
|
||||
|
||||
|
||||
def call_as_daemon(block, logfile_name = nil, app_name = nil)
|
||||
rd, wr = IO.pipe
|
||||
|
||||
if tmppid = safefork
|
||||
# parent
|
||||
wr.close
|
||||
pid = rd.read.to_i
|
||||
rd.close
|
||||
|
||||
Process.waitpid(tmppid)
|
||||
|
||||
return pid
|
||||
else
|
||||
# child
|
||||
|
||||
rd.close
|
||||
|
||||
# Detach from the controlling terminal
|
||||
unless sess_id = Process.setsid
|
||||
raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
|
||||
end
|
||||
|
||||
# Prevent the possibility of acquiring a controlling terminal
|
||||
#if oldmode.zero?
|
||||
trap 'SIGHUP', 'IGNORE'
|
||||
exit if pid = safefork
|
||||
#end
|
||||
|
||||
wr.write Process.pid
|
||||
wr.close
|
||||
|
||||
$0 = app_name if app_name
|
||||
|
||||
Dir.chdir "/" # Release old working directory
|
||||
File.umask 0000 # Insure sensible umask
|
||||
|
||||
# Make sure all file descriptors are closed
|
||||
ObjectSpace.each_object(IO) do |io|
|
||||
unless [STDIN, STDOUT, STDERR].include?(io)
|
||||
begin
|
||||
unless io.closed?
|
||||
io.close
|
||||
end
|
||||
rescue ::Exception
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
redirect_io(logfile_name)
|
||||
|
||||
block.call
|
||||
|
||||
exit
|
||||
end
|
||||
end
|
||||
module_function :call_as_daemon
|
||||
|
||||
|
||||
# This method causes the current running process to become a daemon
|
||||
def daemonize(logfile_name = nil, app_name = nil)
|
||||
srand # Split rand streams between spawning and daemonized process
|
||||
safefork and exit # Fork and exit from the parent
|
||||
|
||||
# Detach from the controlling terminal
|
||||
unless sess_id = Process.setsid
|
||||
raise Daemons.RuntimeException.new('cannot detach from controlling terminal')
|
||||
end
|
||||
|
||||
# Prevent the possibility of acquiring a controlling terminal
|
||||
#if oldmode.zero?
|
||||
trap 'SIGHUP', 'IGNORE'
|
||||
exit if pid = safefork
|
||||
#end
|
||||
|
||||
$0 = app_name if app_name
|
||||
|
||||
Dir.chdir "/" # Release old working directory
|
||||
File.umask 0000 # Insure sensible umask
|
||||
|
||||
# Make sure all file descriptors are closed
|
||||
ObjectSpace.each_object(IO) do |io|
|
||||
unless [STDIN, STDOUT, STDERR].include?(io)
|
||||
begin
|
||||
unless io.closed?
|
||||
io.close
|
||||
end
|
||||
rescue ::Exception
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
redirect_io(logfile_name)
|
||||
|
||||
#return oldmode ? sess_id : 0 # Return value is mostly irrelevant
|
||||
return sess_id
|
||||
end
|
||||
module_function :daemonize
|
||||
|
||||
|
||||
# Free file descriptors and
|
||||
# point them somewhere sensible
|
||||
# STDOUT/STDERR should go to a logfile
|
||||
def redirect_io(logfile_name)
|
||||
begin; STDIN.reopen "/dev/null"; rescue ::Exception; end
|
||||
|
||||
if logfile_name
|
||||
begin
|
||||
STDOUT.reopen logfile_name, "a"
|
||||
STDOUT.sync = true
|
||||
rescue ::Exception
|
||||
begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
|
||||
end
|
||||
else
|
||||
begin; STDOUT.reopen "/dev/null"; rescue ::Exception; end
|
||||
end
|
||||
|
||||
begin; STDERR.reopen STDOUT; rescue ::Exception; end
|
||||
STDERR.sync = true
|
||||
end
|
||||
module_function :redirect_io
|
||||
|
||||
end
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
module Daemons
|
||||
|
||||
class Exception < ::RuntimeError
|
||||
end
|
||||
|
||||
class RuntimeException < Exception
|
||||
end
|
||||
|
||||
class CmdException < Exception
|
||||
end
|
||||
|
||||
class Error < Exception
|
||||
end
|
||||
|
||||
class SystemError < Error
|
||||
|
||||
attr_reader :system_error
|
||||
|
||||
def initialize(msg, system_error)
|
||||
super(msg)
|
||||
|
||||
@system_error = system_error
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,127 +0,0 @@
|
|||
|
||||
module Daemons
|
||||
|
||||
require 'daemons/daemonize'
|
||||
|
||||
class Monitor
|
||||
|
||||
def self.find(dir, app_name)
|
||||
pid = PidFile.find_files(dir, app_name, false)[0]
|
||||
|
||||
if pid
|
||||
pid = PidFile.existing(pid)
|
||||
|
||||
unless PidFile.running?(pid.pid)
|
||||
begin; pid.cleanup; rescue ::Exception; end
|
||||
return
|
||||
end
|
||||
|
||||
monitor = self.allocate
|
||||
|
||||
monitor.instance_variable_set(:@pid, pid)
|
||||
|
||||
return monitor
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
def initialize(an_app)
|
||||
@app = an_app
|
||||
@app_name = an_app.group.app_name + '_monitor'
|
||||
|
||||
if an_app.pidfile_dir
|
||||
@pid = PidFile.new(an_app.pidfile_dir, @app_name, false)
|
||||
else
|
||||
@pid = PidMem.new
|
||||
end
|
||||
end
|
||||
|
||||
def watch(applications)
|
||||
sleep(30)
|
||||
|
||||
loop do
|
||||
applications.each {|a|
|
||||
sleep(10)
|
||||
|
||||
unless a.running?
|
||||
a.zap!
|
||||
|
||||
Process.detach(fork { a.start })
|
||||
|
||||
sleep(10)
|
||||
end
|
||||
}
|
||||
|
||||
sleep(30)
|
||||
end
|
||||
end
|
||||
private :watch
|
||||
|
||||
|
||||
def start_with_pidfile(applications)
|
||||
fork do
|
||||
Daemonize.daemonize(nil, @app_name)
|
||||
|
||||
begin
|
||||
@pid.pid = Process.pid
|
||||
|
||||
# at_exit {
|
||||
# begin; @pid.cleanup; rescue ::Exception; end
|
||||
# }
|
||||
|
||||
# This part is needed to remove the pid-file if the application is killed by
|
||||
# daemons or manually by the user.
|
||||
# Note that the applications is not supposed to overwrite the signal handler for
|
||||
# 'TERM'.
|
||||
#
|
||||
# trap('TERM') {
|
||||
# begin; @pid.cleanup; rescue ::Exception; end
|
||||
# exit
|
||||
# }
|
||||
|
||||
watch(applications)
|
||||
rescue ::Exception => e
|
||||
begin
|
||||
File.open(@app.logfile, 'a') {|f|
|
||||
f.puts Time.now
|
||||
f.puts e
|
||||
f.puts e.backtrace.inspect
|
||||
}
|
||||
ensure
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
exit!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
private :start_with_pidfile
|
||||
|
||||
def start_without_pidfile(applications)
|
||||
Thread.new { watch(applications) }
|
||||
end
|
||||
private :start_without_pidfile
|
||||
|
||||
|
||||
def start(applications)
|
||||
return if applications.empty?
|
||||
|
||||
if @pid.kind_of?(PidFile)
|
||||
start_with_pidfile(applications)
|
||||
else
|
||||
start_without_pidfile(applications)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def stop
|
||||
begin; Process.kill(Application::SIGNAL, @pid.pid); rescue ::Exception; end
|
||||
|
||||
# We try to remove the pid-files by ourselves, in case the application
|
||||
# didn't clean it up.
|
||||
begin; @pid.cleanup; rescue ::Exception; end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
101
vendor/gems/gems/daemons-1.0.10/lib/daemons/pid.rb
vendored
|
@ -1,101 +0,0 @@
|
|||
require 'open3'
|
||||
|
||||
|
||||
module Daemons
|
||||
|
||||
class Pid
|
||||
|
||||
def Pid.running?(pid)
|
||||
# Check if process is in existence
|
||||
# The simplest way to do this is to send signal '0'
|
||||
# (which is a single system call) that doesn't actually
|
||||
# send a signal
|
||||
begin
|
||||
Process.kill(0, pid)
|
||||
return true
|
||||
rescue Errno::ESRCH
|
||||
return false
|
||||
rescue ::Exception # for example on EPERM (process exists but does not belong to us)
|
||||
return true
|
||||
#rescue Errno::EPERM
|
||||
# return false
|
||||
end
|
||||
end
|
||||
|
||||
# def Pid.running?(pid, additional = nil)
|
||||
# match_pid = Regexp.new("^\\s*#{pid}\\s")
|
||||
# got_match = false
|
||||
#
|
||||
# #ps_all = IO.popen('ps ax') # the correct syntax is without a dash (-) !
|
||||
# ps_in, ps_out, ps_err = Open3.popen3('ps ax') # the correct syntax is without a dash (-) !
|
||||
#
|
||||
# return true unless ps_out.gets
|
||||
#
|
||||
# begin
|
||||
# ps_out.each { |psline|
|
||||
# next unless psline =~ match_pid
|
||||
# got_match = true
|
||||
# got_match = false if additional and psline !~ /#{additional}/
|
||||
# break
|
||||
# }
|
||||
# ensure
|
||||
# begin; begin; ps_in.close; rescue ::Exception; end; begin; ps_out.close; rescue ::Exception; end; ps_err.close; rescue ::Exception; end
|
||||
# end
|
||||
#
|
||||
# # an alternative would be to use the code below, but I don't know whether this is portable
|
||||
# # `ps axo pid=`.split.include? pid.to_s
|
||||
#
|
||||
# return got_match
|
||||
# end
|
||||
|
||||
|
||||
# Returns the directory that should be used to write the pid file to
|
||||
# depending on the given mode.
|
||||
#
|
||||
# Some modes may require an additionaly hint, others may determine
|
||||
# the directory automatically.
|
||||
#
|
||||
# If no valid directory is found, returns nil.
|
||||
#
|
||||
def Pid.dir(dir_mode, dir, script)
|
||||
# nil script parameter is allowed as long as dir_mode is not :script
|
||||
return nil if dir_mode == :script && script.nil?
|
||||
|
||||
case dir_mode
|
||||
when :normal
|
||||
return File.expand_path(dir)
|
||||
when :script
|
||||
return File.expand_path(File.join(File.dirname(script),dir))
|
||||
when :system
|
||||
return '/var/run'
|
||||
else
|
||||
raise Error.new("pid file mode '#{dir_mode}' not implemented")
|
||||
end
|
||||
end
|
||||
|
||||
# Initialization method
|
||||
def initialize
|
||||
end
|
||||
|
||||
|
||||
# Get method
|
||||
def pid
|
||||
end
|
||||
|
||||
# Set method
|
||||
def pid=(p)
|
||||
end
|
||||
|
||||
# Cleanup method
|
||||
def cleanup
|
||||
end
|
||||
|
||||
# Exists? method
|
||||
def exist?
|
||||
true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
|
@ -1,111 +0,0 @@
|
|||
require 'daemons/pid'
|
||||
|
||||
|
||||
module Daemons
|
||||
|
||||
# === What is a Pid-File?
|
||||
# A <i>Pid-File</i> is a file containing the <i>process identification number</i>
|
||||
# (pid) that is stored in a well-defined location of the filesystem thus allowing other
|
||||
# programs to find out the pid of a running script.
|
||||
#
|
||||
# Daemons needs the pid of the scripts that are currently running in the background
|
||||
# to send them so called _signals_. Daemons uses the +TERM+ signal to tell the script
|
||||
# to exit when you issue a +stop+ command.
|
||||
#
|
||||
# === How does a Pid-File look like?
|
||||
#
|
||||
# Pid-Files generated by Daemons have to following format:
|
||||
# <scriptname>.rb<number>.pid
|
||||
# (Note that <tt><number></tt> is omitted if only one instance of the script can
|
||||
# run at any time)
|
||||
#
|
||||
# Each file just contains one line with the pid as string (for example <tt>6432</tt>).
|
||||
#
|
||||
# === Where are the Pid-Files stored?
|
||||
#
|
||||
# Daemons is configurable to store the Pid-Files relative to three different locations:
|
||||
# 1. in a directory relative to the directory where the script (the one that is supposed to run
|
||||
# as a daemon) resides (<tt>:script</tt> option for <tt>:dir_mode</tt>)
|
||||
# 2. in a directory given by <tt>:dir</tt> (<tt>:normal</tt> option for <tt>:dir_mode</tt>)
|
||||
# 3. in the preconfigured directory <tt>/var/run</tt> (<tt>:system</tt> option for <tt>:dir_mode</tt>)
|
||||
#
|
||||
class PidFile < Pid
|
||||
|
||||
attr_reader :dir, :progname, :multiple, :number
|
||||
|
||||
def PidFile.find_files(dir, progname, delete = false)
|
||||
files = Dir[File.join(dir, "#{progname}*.pid")]
|
||||
|
||||
files.delete_if {|f| not (File.file?(f) and File.readable?(f))}
|
||||
if delete
|
||||
files.delete_if do |f|
|
||||
pid = File.open(f) {|h| h.read}.to_i
|
||||
rsl = ! Pid.running?(pid)
|
||||
if rsl
|
||||
puts "pid-file for killed process #{pid} found (#{f}), deleting."
|
||||
begin; File.unlink(f); rescue ::Exception; end
|
||||
end
|
||||
rsl
|
||||
end
|
||||
end
|
||||
|
||||
return files
|
||||
end
|
||||
|
||||
def PidFile.existing(path)
|
||||
new_instance = PidFile.allocate
|
||||
|
||||
new_instance.instance_variable_set(:@path, path)
|
||||
|
||||
def new_instance.filename
|
||||
return @path
|
||||
end
|
||||
|
||||
return new_instance
|
||||
end
|
||||
|
||||
def initialize(dir, progname, multiple = false)
|
||||
@dir = File.expand_path(dir)
|
||||
@progname = progname
|
||||
@multiple = multiple
|
||||
@number = nil
|
||||
@number = 0 if multiple
|
||||
|
||||
if multiple
|
||||
while File.exist?(filename) and @number < 1024
|
||||
@number += 1
|
||||
end
|
||||
|
||||
if @number == 1024
|
||||
raise RuntimeException('cannot run more than 1024 instances of the application')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def filename
|
||||
File.join(@dir, "#{@progname}#{ @number or '' }.pid")
|
||||
end
|
||||
|
||||
def exist?
|
||||
File.exist? filename
|
||||
end
|
||||
|
||||
def pid=(p)
|
||||
File.open(filename, 'w') {|f|
|
||||
f.puts p #Process.pid
|
||||
}
|
||||
end
|
||||
|
||||
def cleanup
|
||||
File.delete(filename)
|
||||
end
|
||||
|
||||
def pid
|
||||
File.open(filename) {|f|
|
||||
return f.gets.to_i
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
require 'daemons/pid'
|
||||
|
||||
|
||||
module Daemons
|
||||
|
||||
class PidMem < Pid
|
||||
attr_accessor :pid
|
||||
end
|
||||
|
||||
end
|
14
vendor/gems/gems/eventmachine-0.12.10/.gitignore
vendored
|
@ -1,14 +0,0 @@
|
|||
pkg
|
||||
rdoc
|
||||
Makefile
|
||||
|
||||
*.bundle
|
||||
*.dll
|
||||
*.so
|
||||
*.jar
|
||||
*.class
|
||||
*.o
|
||||
*.log
|
||||
*.def
|
||||
*.pdb
|
||||
java/src/.project
|
82
vendor/gems/gems/eventmachine-0.12.10/README
vendored
|
@ -1,82 +0,0 @@
|
|||
= RUBY/EventMachine
|
||||
|
||||
Homepage:: http://rubyeventmachine.com
|
||||
Rubyforge Page:: http://rubyforge.org/projects/eventmachine
|
||||
Google Group:: http://groups.google.com/group/eventmachine
|
||||
Mailing List:: http://rubyforge.org/pipermail/eventmachine-talk
|
||||
RDoc:: http://eventmachine.rubyforge.org
|
||||
IRC:: ##eventmachine on irc.freenode.net
|
||||
Copyright:: (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
||||
Email:: gmail address: garbagecat10
|
||||
|
||||
EventMachine is copyrighted free software made available under the terms
|
||||
of either the GPL or Ruby's License. See the file COPYING for full licensing
|
||||
information.
|
||||
See EventMachine and EventMachine::Connection for documentation and
|
||||
usage examples.
|
||||
|
||||
EventMachine implements a fast, single-threaded engine for arbitrary network
|
||||
communications. It's extremely easy to use in Ruby. EventMachine wraps all
|
||||
interactions with IP sockets, allowing programs to concentrate on the
|
||||
implementation of network protocols. It can be used to create both network
|
||||
servers and clients. To create a server or client, a Ruby program only needs
|
||||
to specify the IP address and port, and provide a Module that implements the
|
||||
communications protocol. Implementations of several standard network protocols
|
||||
are provided with the package, primarily to serve as examples. The real goal
|
||||
of EventMachine is to enable programs to easily interface with other programs
|
||||
using TCP/IP, especially if custom protocols are required.
|
||||
|
||||
A Ruby program uses EventMachine by registering the addresses and ports of
|
||||
network servers and clients, and then entering an event-handling loop.
|
||||
EventMachine contains glue code in Ruby which will execute callbacks to
|
||||
user-supplied code for all significant events occurring in the clients
|
||||
and servers. These events include connection acceptance, startup, data-receipt,
|
||||
shutdown, and timer events. Arbitrary processing can be performed by user code
|
||||
during event callbacks, including sending data to one or more remote network
|
||||
peers, startup and shutdown of network connections, and installation of new
|
||||
event handlers.
|
||||
|
||||
The EventMachine implements a very familiar model for network programming.
|
||||
It emphasizes: 1) the maximum possible isolation of user code from network
|
||||
objects like sockets; 2) maximum performance and scalability; and 3) extreme
|
||||
ease-of-use for user code. It attempts to provide a higher-level interface
|
||||
than similar projects which expose a variety of low-level event-handling
|
||||
and networking objects to Ruby programs.
|
||||
|
||||
The design and implementation of EventMachine grows out of nearly ten years
|
||||
of experience writing high-performance, high-scaling network server applications.
|
||||
We have taken particular account of the challenges and lessons described as
|
||||
the "C10K problem" by Dan Kegel and others.
|
||||
|
||||
EventMachine consists of an extension library written in C++ (which can be
|
||||
accessed from languages other than Ruby), and a Ruby module which can be dropped
|
||||
into user programs. On most platforms, EventMachine uses the
|
||||
<tt>select(2)</tt> system call,
|
||||
so it will run on a large range of Unix-like systems and on Microsoft
|
||||
Windows with good performance and scalability. On Linux 2.6 kernels, EventMachine
|
||||
automatically configures itself to use <tt>epoll(4)</tt> instead of
|
||||
<tt>select(2),</tt> so scalability on that platform can be significantly
|
||||
improved.
|
||||
|
||||
Here's a fully-functional echo server written with EventMachine:
|
||||
|
||||
require 'eventmachine'
|
||||
|
||||
module EchoServer
|
||||
def post_init
|
||||
puts "-- someone connected to the echo server!"
|
||||
end
|
||||
|
||||
def receive_data data
|
||||
send_data ">>>you sent: #{data}"
|
||||
close_connection if data =~ /quit/i
|
||||
end
|
||||
|
||||
def unbind
|
||||
puts "-- someone disconnected from the echo server!"
|
||||
end
|
||||
end
|
||||
|
||||
EventMachine::run {
|
||||
EventMachine::start_server "127.0.0.1", 8081, EchoServer
|
||||
}
|
374
vendor/gems/gems/eventmachine-0.12.10/Rakefile
vendored
|
@ -1,374 +0,0 @@
|
|||
#!/usr/bin/env rake
|
||||
#--
|
||||
# Ruby/EventMachine
|
||||
# http://rubyeventmachine.com
|
||||
# Copyright (C) 2006-07 by Francis Cianfrocca
|
||||
#
|
||||
# This program is copyrighted free software. You may use it under
|
||||
# the terms of either the GPL or Ruby's License. See the file
|
||||
# COPYING in the EventMachine distribution for full licensing
|
||||
# information.
|
||||
#
|
||||
# $Id$
|
||||
#++
|
||||
|
||||
### OLD RAKE: ###
|
||||
# # The tasks and external gemspecs we used to generate binary gems are now
|
||||
# # obsolete. Use Patrick Hurley's gembuilder to build binary gems for any
|
||||
# # desired platform.
|
||||
# # To build a binary gem on Win32, ensure that the include and lib paths
|
||||
# # both contain the proper references to OPENSSL. Use the static version
|
||||
# # of the libraries, not the dynamic, otherwise we expose the user to a
|
||||
# # runtime dependency.
|
||||
#
|
||||
# # To build a binary gem for win32, first build rubyeventmachine.so
|
||||
# # using VC6 outside of the build tree (the normal way: ruby extconf.rb,
|
||||
# # and then nmake). Then copy rubyeventmachine.so into the lib directory,
|
||||
# # and run rake gemwin32.
|
||||
#
|
||||
|
||||
require 'rubygems' unless defined?(Gem)
|
||||
require 'rake' unless defined?(Rake)
|
||||
|
||||
Package = false # Build zips and tarballs?
|
||||
Dir.glob('tasks/*.rake').each { |r| Rake.application.add_import r }
|
||||
|
||||
# e.g. rake EVENTMACHINE_LIBRARY=java for forcing java build tasks as defaults!
|
||||
$eventmachine_library = :java if RUBY_PLATFORM =~ /java/ || ENV['EVENTMACHINE_LIBRARY'] == 'java'
|
||||
$eventmachine_library = :pure_ruby if ENV['EVENTMACHINE_LIBRARY'] == 'pure_ruby'
|
||||
|
||||
MAKE = ENV['MAKE'] || if RUBY_PLATFORM =~ /mswin/ # mingw uses make.
|
||||
'nmake'
|
||||
else
|
||||
'make'
|
||||
end
|
||||
|
||||
desc "Build gemspec, then build eventmachine, then run tests."
|
||||
task :default => [:build, :test]
|
||||
|
||||
desc "Build extension (or EVENTMACHINE_LIBRARY) and place in lib"
|
||||
build_task = 'ext:build'
|
||||
build_task = 'java:build' if $eventmachine_library == :java
|
||||
build_task = :dummy_build if $eventmachine_library == :pure_ruby
|
||||
task :build => build_task do |t|
|
||||
Dir.glob('{ext,java/src,ext/fastfilereader}/*.{so,bundle,dll,jar}').each do |f|
|
||||
mv f, "lib"
|
||||
end
|
||||
end
|
||||
|
||||
task :dummy_build
|
||||
|
||||
require 'rake/testtask'
|
||||
Rake::TestTask.new(:test) do |t|
|
||||
t.pattern = 'tests/**/test_*.rb'
|
||||
t.warning = true
|
||||
end
|
||||
|
||||
# Basic clean definition, this is enhanced by imports aswell.
|
||||
task :clean do
|
||||
chdir 'ext' do
|
||||
sh "#{MAKE} clean" if test ?e, 'Makefile'
|
||||
end
|
||||
chdir 'ext/fastfilereader' do
|
||||
sh "#{MAKE} clean" if test ?e, 'Makefile'
|
||||
end
|
||||
Dir.glob('**/Makefile').each { |file| rm file }
|
||||
Dir.glob('**/*.{o,so,bundle,class,jar,dll,log}').each { |file| rm file }
|
||||
Dir.glob('ext/**/conftest.dSYM').each{ |file| rm_rf file }
|
||||
end
|
||||
|
||||
Spec = Gem::Specification.new do |s|
|
||||
s.name = "eventmachine"
|
||||
s.summary = "Ruby/EventMachine library"
|
||||
s.platform = Gem::Platform::RUBY
|
||||
|
||||
s.has_rdoc = true
|
||||
s.rdoc_options = %w(--title EventMachine --main README --line-numbers -x lib/em/version -x lib/emva -x lib/evma/ -x lib/pr_eventmachine -x lib/jeventmachine)
|
||||
s.extra_rdoc_files = Dir['README,docs/*']
|
||||
|
||||
s.files = `git ls-files`.split("\n")
|
||||
|
||||
s.require_path = 'lib'
|
||||
|
||||
# TODO / XXX - should we enable this? rubygems fails the install if anything
|
||||
# is broken. What we could do is CI submission, though, and always terminate
|
||||
# with a positive code...
|
||||
# s.test_file = "tests/testem.rb"
|
||||
|
||||
# XXX Using rake to compile extensions breaks when you have multiple ruby installations
|
||||
# and your path isn't set. We can switch back to this once the Gem.exec patch is merged.
|
||||
# s.extensions = "Rakefile"
|
||||
s.extensions = ["ext/extconf.rb", "ext/fastfilereader/extconf.rb"]
|
||||
|
||||
s.author = "Francis Cianfrocca"
|
||||
s.email = "garbagecat10@gmail.com"
|
||||
s.rubyforge_project = 'eventmachine'
|
||||
s.homepage = "http://rubyeventmachine.com"
|
||||
|
||||
# Pulled in from readme, as code to pull from readme was not working!
|
||||
# Might be worth removing as no one seems to use gem info anyway.
|
||||
s.description = <<-EOD
|
||||
EventMachine implements a fast, single-threaded engine for arbitrary network
|
||||
communications. It's extremely easy to use in Ruby. EventMachine wraps all
|
||||
interactions with IP sockets, allowing programs to concentrate on the
|
||||
implementation of network protocols. It can be used to create both network
|
||||
servers and clients. To create a server or client, a Ruby program only needs
|
||||
to specify the IP address and port, and provide a Module that implements the
|
||||
communications protocol. Implementations of several standard network protocols
|
||||
are provided with the package, primarily to serve as examples. The real goal
|
||||
of EventMachine is to enable programs to easily interface with other programs
|
||||
using TCP/IP, especially if custom protocols are required.
|
||||
EOD
|
||||
|
||||
require 'lib/em/version'
|
||||
s.version = EventMachine::VERSION
|
||||
end
|
||||
|
||||
if RUBY_PLATFORM =~ /mswin/
|
||||
Spec.platform = 'x86-mswin32-60'
|
||||
Spec.files += %w[ lib/rubyeventmachine.so lib/fastfilereaderext.so ]
|
||||
Spec.extensions = nil
|
||||
elsif RUBY_PLATFORM =~ /java/
|
||||
Spec.platform = 'java'
|
||||
Spec.files += %w[ lib/em_reactor.jar ]
|
||||
Spec.extensions = nil
|
||||
end
|
||||
|
||||
# this is a hack right now, it requires installing msysgit in the global path so it can use tar/curl/etc.
|
||||
namespace :win32 do
|
||||
task :check_git do
|
||||
unless `git` =~ /rebase/
|
||||
raise 'git not found, install msys git into the GLOBAL PATH: http://msysgit.googlecode.com/files/Git-1.6.2-preview20090308.exe'
|
||||
end
|
||||
end
|
||||
|
||||
task :check_vc6 do
|
||||
begin
|
||||
raise unless `nmake 2>&1` =~ /Microsoft/
|
||||
rescue
|
||||
raise 'VC6 not found, please run c:\vc\setvc.bat vc6'
|
||||
end
|
||||
end
|
||||
|
||||
task :check_perl do
|
||||
unless `perl --version` =~ /ActiveState/
|
||||
raise 'ActiveState perl required to build OpenSSL: http://downloads.activestate.com/ActivePerl/Windows/5.10/ActivePerl-5.10.0.1004-MSWin32-x86-287188.msi'
|
||||
end
|
||||
end
|
||||
|
||||
task :build_openssl => [:check_git, :check_perl, :check_vc6] do
|
||||
mkdir_p 'build'
|
||||
chdir 'build' do
|
||||
unless File.exists?('openssl-0.9.8j')
|
||||
sh 'curl http://www.openssl.org/source/openssl-0.9.8j.tar.gz > openssl.tar.gz'
|
||||
sh 'tar zxvf openssl.tar.gz' rescue nil # fails because of symlinks
|
||||
end
|
||||
|
||||
mkdir_p 'local'
|
||||
chdir 'openssl-0.9.8j' do
|
||||
sh "perl Configure VC-WIN32 --prefix=\"../local/\""
|
||||
sh 'ms\do_ms.bat'
|
||||
sh 'nmake -f ms\nt.mak install'
|
||||
end
|
||||
|
||||
chdir '../ext' do
|
||||
sh 'git clean -fd .'
|
||||
end
|
||||
|
||||
mv 'local/include/openssl', '../ext/'
|
||||
mv 'local/lib/ssleay32.lib', '../ext/'
|
||||
mv 'local/lib/libeay32.lib', '../ext/'
|
||||
end
|
||||
end
|
||||
|
||||
desc "build binary win32 gem"
|
||||
task :gem => :build_openssl do
|
||||
Rake::Task['build'].invoke
|
||||
Rake::Task['gem'].invoke
|
||||
end
|
||||
end
|
||||
|
||||
namespace :ext do
|
||||
ext_sources = FileList['ext/*.{h,cpp,rb,c}']
|
||||
ffr_sources = FileList['ext/fastfilereader/*.{h,cpp,rb}']
|
||||
file ext_extconf = 'ext/extconf.rb'
|
||||
file ffr_extconf = 'ext/fastfilereader/extconf.rb'
|
||||
ext_libname = "lib/rubyeventmachine.#{Config::CONFIG['DLEXT']}"
|
||||
ffr_libname = "lib/fastfilereaderext.#{Config::CONFIG['DLEXT']}"
|
||||
|
||||
file ext_libname => ext_sources + ['ext/Makefile'] do
|
||||
chdir('ext') { sh MAKE }
|
||||
end
|
||||
|
||||
file ffr_libname => ffr_sources + ['ext/fastfilereader/Makefile'] do
|
||||
chdir('ext/fastfilereader') { sh MAKE }
|
||||
end
|
||||
|
||||
desc "Build C++ extension"
|
||||
task :build => [:make]
|
||||
|
||||
task :make => ext_libname
|
||||
task :make => ffr_libname
|
||||
|
||||
file 'ext/Makefile' => ext_extconf do
|
||||
chdir 'ext' do
|
||||
ruby 'extconf.rb'
|
||||
end
|
||||
end
|
||||
|
||||
file 'ext/fastfilereader/Makefile' => ffr_extconf do
|
||||
chdir 'ext/fastfilereader' do
|
||||
ruby 'extconf.rb'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
namespace :java do
|
||||
# This task creates the JRuby JAR file and leaves it in the lib directory.
|
||||
# This step is required before executing the jgem task.
|
||||
desc "Build java extension"
|
||||
task :build => [:jar] do |t|
|
||||
mv 'java/em_reactor.jar', 'lib/'
|
||||
end
|
||||
|
||||
task :compile do
|
||||
chdir('java') do
|
||||
mkdir_p "build"
|
||||
sh 'javac src/com/rubyeventmachine/*.java -d build'
|
||||
end
|
||||
end
|
||||
|
||||
task :jar => [:compile] do
|
||||
chdir('java/build') do
|
||||
sh "jar -cf ../em_reactor.jar com/rubyeventmachine/*.class"
|
||||
end
|
||||
end
|
||||
|
||||
desc "build a java binary gem"
|
||||
task :gem => :build do
|
||||
Spec.platform = 'java'
|
||||
Spec.files += %w[ lib/em_reactor.jar ]
|
||||
Spec.extensions = nil
|
||||
|
||||
Rake::Task['gem'].invoke
|
||||
end
|
||||
end
|
||||
|
||||
namespace :osx do
|
||||
desc "Build OSX binary gem"
|
||||
task :gem do
|
||||
Spec.platform = RUBY_PLATFORM.sub(/darwin.+$/, 'darwin')
|
||||
Spec.files += %w[ lib/rubyeventmachine.bundle lib/fastfilereaderext.bundle ]
|
||||
Spec.extensions = nil
|
||||
|
||||
Rake::Task['build'].invoke
|
||||
Rake::Task['gem'].invoke
|
||||
end
|
||||
|
||||
# XXX gcc will still prefer the shared libssl on the system, so we need to hack the extconf
|
||||
# XXX to use the static library to make this actually work
|
||||
task :static_gem => [:build_openssl, :gem]
|
||||
|
||||
task :build_openssl do
|
||||
mkdir_p 'build'
|
||||
chdir 'build' do
|
||||
unless File.exists?('openssl-0.9.8j')
|
||||
sh 'curl http://www.openssl.org/source/openssl-0.9.8j.tar.gz > openssl-0.9.8j.tar.gz'
|
||||
sh 'tar zxvf openssl-0.9.8j.tar.gz'
|
||||
end
|
||||
|
||||
mkdir_p 'local'
|
||||
chdir 'openssl-0.9.8j' do
|
||||
local_dir = File.expand_path(File.join(File.dirname(__FILE__),'build','local'))
|
||||
sh "./config --prefix=#{local_dir}"
|
||||
sh 'make'
|
||||
sh 'make install'
|
||||
end
|
||||
|
||||
chdir '../ext' do
|
||||
sh 'git clean -fd .'
|
||||
end
|
||||
|
||||
mv 'local/include/openssl', '../ext/'
|
||||
mv 'local/lib/libssl.a', '../ext/'
|
||||
mv 'local/lib/libcrypto.a', '../ext/'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require 'rake/clean'
|
||||
|
||||
rdoc_task_type = begin
|
||||
require 'rdoc/task'
|
||||
RDoc::Task
|
||||
rescue LoadError
|
||||
require 'rake/rdoctask'
|
||||
Rake::RDocTask
|
||||
end
|
||||
df = begin; require 'rdoc/generator/darkfish'; true; rescue LoadError; end
|
||||
rdtask = rdoc_task_type.new do |rd|
|
||||
rd.title = Spec.name
|
||||
rd.rdoc_dir = 'rdoc'
|
||||
rd.main = "README"
|
||||
rd.rdoc_files.include("lib/**/*.rb", *Spec.extra_rdoc_files)
|
||||
rd.rdoc_files.exclude(*%w(lib/em/version lib/emva lib/evma/ lib/pr_eventmachine lib/jeventmachine))
|
||||
rd.template = 'darkfish' if df
|
||||
end
|
||||
Rake::Task[:clean].enhance [:clobber_rdoc]
|
||||
|
||||
desc 'Generate and open documentation'
|
||||
task :docs => :rdoc do
|
||||
case RUBY_PLATFORM
|
||||
when /darwin/ ; sh 'open rdoc/index.html'
|
||||
when /mswin|mingw/ ; sh 'start rdoc\index.html'
|
||||
else
|
||||
sh 'firefox rdoc/index.html'
|
||||
end
|
||||
end
|
||||
|
||||
def windows?; RUBY_PLATFORM =~ /mswin|mingw/; end
|
||||
def sudo(cmd)
|
||||
if windows? || (require 'etc'; Etc.getpwuid.uid == 0)
|
||||
sh cmd
|
||||
else
|
||||
sh "sudo #{cmd}"
|
||||
end
|
||||
end
|
||||
def gem_cmd(action, name, *args)
|
||||
rb = Gem.ruby rescue nil
|
||||
rb ||= (require 'rbconfig'; File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name']))
|
||||
sudo "#{rb} -r rubygems -e 'require %{rubygems/gem_runner}; Gem::GemRunner.new.run(%w{#{action} #{name} #{args.join(' ')}})'"
|
||||
end
|
||||
|
||||
begin
|
||||
require 'rubygems/package_task'
|
||||
Gem::PackageTask
|
||||
rescue LoadError
|
||||
require 'rake/gempackagetask'
|
||||
Rake::GemPackageTask
|
||||
end.new(Spec) do |pkg|
|
||||
pkg.need_tar, pkg.need_tar_gz, pkg.need_zip = true, true, true if Package
|
||||
pkg.gem_spec = Spec
|
||||
end
|
||||
|
||||
Rake::Task[:clean].enhance [:clobber_package]
|
||||
|
||||
namespace :gem do
|
||||
desc 'Install gem (and sudo if required)'
|
||||
task :install => :package do
|
||||
gem_cmd(:install, "pkg/#{Spec.name}-#{Spec.version}.gem")
|
||||
end
|
||||
|
||||
desc 'Uninstall gem (and sudo if required)'
|
||||
task :uninstall do
|
||||
gem_cmd(:uninstall, "#{Spec.name}", "-v=#{Spec.version}")
|
||||
end
|
||||
|
||||
desc "Generate new gemspec"
|
||||
task :spec => :clobber do
|
||||
open("eventmachine.gemspec", 'w') { |f| f.write Spec.to_ruby }
|
||||
end
|
||||
end
|
||||
|
||||
task :clobber => :clean
|
||||
task :test => :build
|
|
@ -1,60 +0,0 @@
|
|||
EventMachine is copyrighted free software owned by Francis Cianfrocca
|
||||
(blackhedd ... gmail.com). The Owner of this software permits you to
|
||||
redistribute and/or modify the software under either the terms of the GPL
|
||||
version 2 (see the file GPL), or the conditions below ("Ruby License"):
|
||||
|
||||
1. You may make and give away verbatim copies of the source form of this
|
||||
software without restriction, provided that you retain ALL of the
|
||||
original copyright notices and associated disclaimers.
|
||||
|
||||
2. You may modify your copy of the software in any way, provided that
|
||||
you do at least ONE of the following:
|
||||
|
||||
a) place your modifications in the Public Domain or otherwise
|
||||
make them Freely Available, such as by posting said
|
||||
modifications to Usenet or an equivalent medium, or by allowing
|
||||
the author to include your modifications in the software.
|
||||
|
||||
b) use the modified software only within your corporation or
|
||||
organization.
|
||||
|
||||
c) give non-standard binaries non-standard names, with
|
||||
instructions on where to get the original software distribution.
|
||||
|
||||
d) make other distribution arrangements with the Owner.
|
||||
|
||||
3. You may distribute the software in object code or binary form,
|
||||
provided that you do at least ONE of the following:
|
||||
|
||||
a) distribute the binaries and library files of the software,
|
||||
together with instructions (in a manual page or equivalent)
|
||||
on where to get the original distribution.
|
||||
|
||||
b) accompany the distribution with the machine-readable source of
|
||||
the software.
|
||||
|
||||
c) give non-standard binaries non-standard names, with
|
||||
instructions on where to get the original software distribution.
|
||||
|
||||
d) make other distribution arrangements with the Owner.
|
||||
|
||||
4. You may modify and include parts of the software into any other
|
||||
software (possibly commercial), provided you comply with the terms in
|
||||
Sections 1, 2, and 3 above. But some files in the distribution
|
||||
are not written by the Owner, so they may be made available to you
|
||||
under different terms.
|
||||
|
||||
For the list of those files and their copying conditions, see the
|
||||
file LEGAL.
|
||||
|
||||
5. The scripts and library files supplied as input to or produced as
|
||||
output from the software do not automatically fall under the
|
||||
copyright of the software, but belong to whoever generated them,
|
||||
and may be sold commercially, and may be aggregated with this
|
||||
software.
|
||||
|
||||
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE.
|
||||
|
211
vendor/gems/gems/eventmachine-0.12.10/docs/ChangeLog
vendored
|
@ -1,211 +0,0 @@
|
|||
01Oct06: Replaced EventMachine#open_datagram_server with a version that can
|
||||
take a Class or a Module, instead of just a Module. Thanks to Tobias
|
||||
Gustafsson for pointing out the missing case.
|
||||
04Oct06: Supported subsecond timer resolutions, per request by Jason Roelofs.
|
||||
05Oct06: Added EventMachine#set_quantum, which sets the timer resolution.
|
||||
15Nov06: Added Connection#set_comm_inactivity_timeout.
|
||||
15Nov06: Checked in a Line-and-Text Protocol Handler.
|
||||
18Nov06: Checked in a Header-and-Body Protocol Handler.
|
||||
22Nov06: Changed EventMachine#reconnect: no longer excepts when called on an
|
||||
already-connected handler.
|
||||
28Nov06: Supported a binary-unix gem.
|
||||
19Dec06: Added EventMachine#set_effective_user.
|
||||
05Jan07: Upped max outstanding timers to 1000.
|
||||
15May07: Applied Solaris patches from Brett Eisenberg
|
||||
22May07: Cleaned up the license text in all the source files.
|
||||
22May07: Released version 0.7.2
|
||||
|
||||
23May07: Per suggestion from Bill Kelly, fixed a bug with the initialization
|
||||
of the network libraries under Windows. The goal is to enable EM to
|
||||
be used without Ruby.
|
||||
28May07: Applied patch from Bill Kelly, refactors the declarations of
|
||||
event names to make EM easier to use from C programs without Ruby.
|
||||
31May07: Added a preliminary implementation of EventMachine#popen.
|
||||
01Jun07: Added EM, a "pseudo-alias" for EventMachine.
|
||||
01Jun07: Added EM#next_tick.
|
||||
01Jun07: Added EM::Connection#get_outbound_data_size
|
||||
05Jun07: Removed the code which loads a pure-Ruby EM library in case the
|
||||
compiled extension is unavailable. Suggested by Moshe Litvin.
|
||||
06Jun07: Preliminary epoll implementation.
|
||||
12Jun07: Added an evented popen implementation that, like Ruby's, is
|
||||
full-duplex and makes the subprocess PID available to the caller.
|
||||
06Jul07: Performance-tweaked the callback dispatcher in eventmachine.rb.
|
||||
10Jul07: Released version 0.8.0.
|
||||
12Jul07: Applied patches from Tim Pease to fix Solaris build problems.
|
||||
15Jul07: Created a new provisional source branch, experiments/jruby-1.
|
||||
This is a preliminary implementation of the EM reactor in Java,
|
||||
suitable for use with JRuby.
|
||||
17Jul07: Added EventMachine#stop_server, per request from Kirk Haines,
|
||||
and associated unit tests.
|
||||
22Jul07: Added EventMachine#stream_file_data. This is a very fast and scalable
|
||||
way of sending data from static files over network connections. It
|
||||
has separate implementations for small files and large file, and
|
||||
has tunings to minimize memory consumption.
|
||||
26Jul07: Added some patches by Kirk Haines to improve the behavior of
|
||||
EM::Connection#send_file_data_to_connection.
|
||||
26Jul07: Added a C++ module for directly integrating EM into C++ programs
|
||||
with no Ruby dependencies. Needs example code.
|
||||
29Jul07: Added EventMachine::Protocols::LineText2.
|
||||
29Jul07: Added EventMachine::Protocols::Stomp.
|
||||
30Jul07: Added sys/stat.h to project.h to fix compilation bug on Darwin.
|
||||
13Aug07: Added EventMachine#reactor_running?
|
||||
15Aug07: Added parameters for EventMachine::Connection:start_tls that can be
|
||||
used to specify client-side private keys and certificates.
|
||||
17Aug07: Added EventMachine#run_block, a sugaring for a common use case.
|
||||
24Aug07: Added a preliminary keyboard handler. Needs docs and testing on
|
||||
windows.
|
||||
26Aug07: Created EventMachine::Spawnable, an implementation of Erlang-like
|
||||
processes.
|
||||
27Aug07: Silenced some -w warnings, requested by James Edward Gray II.
|
||||
30Aug07: Added cookies to EM::HttpClient#request.
|
||||
04Sep07: Added an initial implementation of an evented SMTP client.
|
||||
04Sep07: Added an initial implementation of an evented SMTP server.
|
||||
10Sep07: Changed EM#spawn to run spawned blocks in the context of the
|
||||
SpawnedProcess object, not of whatever was the active object at the
|
||||
time of the spawn.
|
||||
14Sep07: Heartbeats weren't working with EPOLL. Noticed by Brian Candler.
|
||||
15Sep07: Added some features, tests and documents to Deferrable.
|
||||
16Sep07: Added [:content] parameter to EM::Protocols::SmtpClient#send.
|
||||
16Sep07: Bumped version to 0.9.0 in anticipation of a release.
|
||||
18Sep07: Released version 0.9.0.
|
||||
19Sep07: Added #receive_reset to EM::Protocols::SmtpServer.
|
||||
19Sep07: User overrides of EM::Protocols::SmtpServer#receive_recipient can now
|
||||
return a Deferrable. Also fixed bug: SmtpClient now raises a protocol
|
||||
error if none of its RCPT TO: commands are accepted by the server.
|
||||
26Sep07: Fixed missing keyboard support for Windows.
|
||||
03Oct07: Added a default handler for RuntimeErrors emitted from user-written
|
||||
code. Suggested by Brian Candler.
|
||||
19Oct07: Set the SO_BROADCAST option automatically on all UDP sockets.
|
||||
10Nov07: Forced integer conversion of send_datagram's port parameter.
|
||||
Suggested by Matthieu Riou.
|
||||
12Nov07: Added saslauth.rb, a protocol module to replace the Cyrus SASL
|
||||
daemons saslauthd and pwcheck.
|
||||
15Nov07: Fixed bug reported by Mark Zvillius. We were failing to dispatch
|
||||
zero-length datagrams under certain conditions.
|
||||
19Nov07: Added EventMachine#set_max_timers. Requested by Matthieu Riou and
|
||||
others.
|
||||
19Nov07: Fixed bug with EM::Connection#start_tls. Was not working with server
|
||||
connections. Reported by Michael S. Fischer.
|
||||
26Nov07: Supported a hack for EventMachine#popen so it can return an exit
|
||||
status from subprocesses. Requested by Michael S. Fischer.
|
||||
30Nov07: Changed Pipe descriptors so that the child-side of the socketpair is
|
||||
NOT set nonblocking. Suggested by Duane Johnson.
|
||||
05Dec07: Re-enabled the pure-Ruby implementation.
|
||||
06Dec07: Released Version 0.10.0.
|
||||
13Dec07: Added EM::DeferrableChildProcess
|
||||
24Dec07: Added a SASL client for simple password authentication.
|
||||
27Dec07: Removed the hookable error handler. No one was using it and it significantly
|
||||
degraded performance.
|
||||
30Dec07: Implemented Kqueue support for OSX and BSD.
|
||||
04Jan08: Fixed bug in epoll ("Bad file descriptor"), patch supplied by Chris
|
||||
Heath.
|
||||
04Jan08: Fixed bug reported by Michael S. Fischer. We were terminating
|
||||
SSL connections that sent data before the handshake was complete.
|
||||
08Jan08: Added an OpenBSD branch for extconf.rb, contributed by Guillaume
|
||||
Sellier.
|
||||
19Jan08: Added EM::Connection::get_sockname per request by Michael Fischer.
|
||||
19Jan08: Supported IPv6 addresses.
|
||||
30Apr08: Set the NODELAY option on sockets that we connect to other servers.
|
||||
Omission noted by Roger Pack.
|
||||
14May08: Generated a 0.12 release.
|
||||
15May08: Supported EM#get_sockname for acceptors (TCP server sockets).
|
||||
Requested by Roger Pack.
|
||||
15May08; Accepted a patch from Dan Aquino that allows the interval of a
|
||||
PeriodicTimer to be changed on the fly.
|
||||
15Jun08: Supported nested calls to EM#run. Many people contributed ideas to
|
||||
this, notably raggi and tmm1.
|
||||
20Jul08: Accepted patch from tmm1 for EM#fork_reactor.
|
||||
28Jul08: Added a Postgres3 implementation, written by FCianfrocca.
|
||||
14Aug08: Added a patch by Mike Murphy to support basic auth in the http
|
||||
client.
|
||||
28Aug08: Added a patch by tmm1 to fix a longstanding problem with Java
|
||||
data-sends.
|
||||
13Sep08: Added LineText2#set_binary_mode, a back-compatibility alias.
|
||||
13Sep08: Modified the load order of protocol libraries in eventmachine.rb
|
||||
to permit a modification of HeaderAndContentProtocol.
|
||||
13Sep08: Modified HeaderAndContent to use LineText2, which is less buggy
|
||||
than LineAndTextProtocol. This change may be reversed if we can fix
|
||||
the bugs in buftok.
|
||||
13Sep08: Improved the password handling in the Postgres protocol handler.
|
||||
15Sep08: Added attach/detach, contributed by Aman Gupta (tmm1) and Riham Aldakkak,
|
||||
to support working with file descriptors not created in the reactor.
|
||||
16Sep08: Added an optional version string to the HTTP client. This is a hack
|
||||
that allows a client to specify a version 1.0 request, which
|
||||
keeps the server from sending a chunked response. The right way to
|
||||
solve this, of course, is to support chunked responses.
|
||||
23Sep08: ChangeLog Summary for Merge of branches/raggi
|
||||
Most notable work and patches by Aman Gupta, Roger Pack, and James Tucker.
|
||||
Patches / Tickets also submitted by: Jeremy Evans, aanand, darix, mmmurf,
|
||||
danielaquino, macournoyer.
|
||||
- Moved docs into docs/ dir
|
||||
- Major refactor of rakefile, added generic rakefile helpers in tasks
|
||||
- Added example CPP build rakefile in tasks/cpp.rake
|
||||
- Moved rake tests out to tasks/tests.rake
|
||||
- Added svn ignores where appropriate
|
||||
- Fixed jruby build on older java platforms
|
||||
- Gem now builds from Rakefile rather than directly via extconf
|
||||
- Gem unified for jruby, C++ and pure ruby.
|
||||
- Correction for pure C++ build, removing ruby dependency
|
||||
- Fix for CYGWIN builds on ipv6
|
||||
- Major refactor for extconf.rb
|
||||
- Working mingw builds
|
||||
- extconf optionally uses pkg_config over manual configuration
|
||||
- extconf builds for 1.9 on any system that has 1.9
|
||||
- extconf no longer links pthread explicitly
|
||||
- looks for kqueue on all *nix systems
|
||||
- better error output on std::runtime_error, now says where it came from
|
||||
- Fixed some tests on jruby
|
||||
- Added test for general send_data flaw, required for a bugfix in jruby build
|
||||
- Added timeout to epoll tests
|
||||
- Added fixes for java reactor ruby api
|
||||
- Small addition of some docs in httpclient.rb and httpcli2.rb
|
||||
- Some refactor and fixes in smtpserver.rb
|
||||
- Added parenthesis where possible to avoid excess ruby warnings
|
||||
- Refactor of $eventmachine_library logic for accuracy and maintenance, jruby
|
||||
- EM::start_server now supports unix sockets
|
||||
- EM::connect now supports unix sockets
|
||||
- EM::defer @threadqueue now handled more gracefully
|
||||
- Added better messages on exceptions raised
|
||||
- Fix edge case in timer fires
|
||||
- Explicitly require buftok.rb
|
||||
- Add protocols to autoload, rather than require them all immediately
|
||||
- Fix a bug in pr_eventmachine for outbound_q
|
||||
- Refactors to take some of the use of defer out of tests.
|
||||
- Fixes in EM.defer under start/stop conditions. Reduced scope of threads.
|
||||
23Sep08: Added patch from tmm1 to avoid popen errors on exit.
|
||||
30Sep08: Added File.exists? checks in the args for start_tls, as suggested by
|
||||
Brian Lopez (brianmario).
|
||||
10Nov08: ruby 1.9 compatibility enhancements
|
||||
28Nov08: Allow for older ruby builds where RARRAY_LEN is not defined
|
||||
03Dec08: allow passing arguments to popen handlers
|
||||
13Jan09: SSL support for httpclient2 (David Smalley)
|
||||
22Jan09: Fixed errors on OSX with the kqueue reactor, fixed errors in the pure
|
||||
ruby reactor. Added EM.current_time. Added EM.epoll? and EM.kqueue?
|
||||
27Jan09: Reactor errors are now raised as ruby RuntimeErrors.
|
||||
28Jan09: Documentation patch from alloy
|
||||
29Jan09: (Late sign-off) Use a longer timeout for connect_server (Ilya
|
||||
Grigorik)
|
||||
07Feb09: Fix signal handling issues with threads+epoll
|
||||
07Feb09: Use rb_thread_schedule in the epoll reactor
|
||||
07Feb09: Use TRAP_BEG/END and rb_thread_schedule in kqueue reactor
|
||||
08Feb09: Added fastfilereader from swiftiply
|
||||
08Feb09: 1.9 fix for rb_trap_immediate
|
||||
08Feb09: Enable rb_thread_blocking_region for 1.9.0 and 1.9.1
|
||||
10Feb09: Support win32 builds for fastfilereader
|
||||
10Feb09: Added a new event to indicate completion of SSL handshake on TCP
|
||||
connections
|
||||
10Feb09: Working get_peer_cert method. Returns the certificate as a Ruby
|
||||
String in PEM format. (Jake Douglas)
|
||||
10Feb09: Added EM.get_max_timers
|
||||
11Feb09: Fix compile options for sun compiler (Alasdairrr)
|
||||
11Feb09: get_status returns a Process::Status object
|
||||
12Feb09: Add EM::Protocols::Memcache with simple get/set functionality
|
||||
19Feb09: Add catch-all EM.error_handler
|
||||
20Feb09: Support miniunit (1.9)
|
||||
20Feb09: Return success on content-length = 0 instead of start waiting forever
|
||||
(Ugo Riboni)
|
||||
25Feb09: Allow next_tick to be used to pre-schedule reactor operations before
|
||||
EM.run
|
||||
26Feb09: Added EM.get_connection_count
|
||||
01Mar09: Switch back to extconf for compiling gem extensions
|
||||
01Mar09: fixed a small bug with basic auth (mmmurf)
|
|
@ -1,133 +0,0 @@
|
|||
EventMachine (EM) adds two different formalisms for lightweight concurrency to the Ruby programmer's toolbox: spawned processes and deferrables. This note will show you how to use deferrables. For more information, see the separate document LIGHTWEIGHT_CONCURRENCY.
|
||||
|
||||
=== What are Deferrables?
|
||||
|
||||
EventMachine's Deferrable borrows heavily from the "deferred" object in Python's "Twisted" event-handling framework. Here's a minimal example that illustrates Deferrable:
|
||||
|
||||
require 'eventmachine'
|
||||
|
||||
class MyClass
|
||||
include EM::Deferrable
|
||||
|
||||
def print_value x
|
||||
puts "MyClass instance received #{x}"
|
||||
end
|
||||
end
|
||||
|
||||
EM.run {
|
||||
df = MyClass.new
|
||||
df.callback {|x|
|
||||
df.print_value(x)
|
||||
EM.stop
|
||||
}
|
||||
|
||||
EM::Timer.new(2) {
|
||||
df.set_deferred_status :succeeded, 100
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
This program will spin for two seconds, print out the string "MyClass instance received 100" and then exit. The Deferrable pattern relies on an unusual metaphor that may be unfamiliar to you, unless you've used Python's Twisted. You may need to read the following material through more than once before you get the idea.
|
||||
|
||||
EventMachine::Deferrable is simply a Ruby Module that you can include in your own classes. (There also is a class named EventMachine::DefaultDeferrable for when you want to create one without including it in code of your own.)
|
||||
|
||||
An object that includes EventMachine::Deferrable is like any other Ruby object: it can be created whenever you want, returned from your functions, or passed as an argument to other functions.
|
||||
|
||||
The Deferrable pattern allows you to specify any number of Ruby code blocks (callbacks or errbacks) that will be executed at some future time when the status of the Deferrable object changes.
|
||||
|
||||
How might that be useful? Well, imagine that you're implementing an HTTP server, but you need to make a call to some other server in order to fulfill a client request.
|
||||
|
||||
When you receive a request from one of your clients, you can create and return a Deferrable object. Some other section of your program can add a callback to the Deferrable that will cause the client's request to be fulfilled. Simultaneously, you initiate an event-driven or threaded client request to some different server. And then your EM program will continue to process other events and service other client requests.
|
||||
|
||||
When your client request to the other server completes some time later, you will call the #set_deferred_status method on the Deferrable object, passing either a success or failure status, and an arbitrary number of parameters (which might include the data you received from the other server).
|
||||
|
||||
At that point, the status of the Deferrable object becomes known, and its callback or errback methods are immediately executed. Callbacks and errbacks are code blocks that are attached to Deferrable objects at any time through the methods #callback and #errback.
|
||||
|
||||
The deep beauty of this pattern is that it decouples the disposition of one operation (such as a client request to an outboard server) from the subsequent operations that depend on that disposition (which may include responding to a different client or any other operation).
|
||||
|
||||
The code which invokes the deferred operation (that will eventually result in a success or failure status together with associated data) is completely separate from the code which depends on that status and data. This achieves one of the primary goals for which threading is typically used in sophisticated applications, with none of the nondeterminacy or debugging difficulties of threads.
|
||||
|
||||
As soon as the deferred status of a Deferrable becomes known by way of a call to #set_deferred_status, the Deferrable will IMMEDIATELY execute all of its callbacks or errbacks in the order in which they were added to the Deferrable.
|
||||
|
||||
Callbacks and errbacks can be added to a Deferrable object at any time, not just when the object is created. They can even be added after the status of the object has been determined! (In this case, they will be executed immediately when they are added.)
|
||||
|
||||
A call to Deferrable#set_deferred_status takes :succeeded or :failed as its first argument. (This determines whether the object will call its callbacks or its errbacks.) #set_deferred_status also takes zero or more additional parameters, that will in turn be passed as parameters to the callbacks or errbacks.
|
||||
|
||||
In general, you can only call #set_deferred_status ONCE on a Deferrable object. A call to #set_deferred_status will not return until all of the associated callbacks or errbacks have been called. If you add callbacks or errbacks AFTER making a call to #set_deferred_status, those additional callbacks or errbacks will execute IMMEDIATELY. Any given callback or errback will be executed AT MOST once.
|
||||
|
||||
It's possible to call #set_deferred_status AGAIN, during the execution a callback or errback. This makes it possible to change the parameters which will be sent to the callbacks or errbacks farther down the chain, enabling some extremely elegant use-cases. You can transform the data returned from a deferred operation in arbitrary ways as needed by subsequent users, without changing any of the code that generated the original data.
|
||||
|
||||
A call to #set_deferred_status will not return until all of the associated callbacks or errbacks have been called. If you add callbacks or errbacks AFTER making a call to #set_deferred_status, those additional callbacks or errbacks will execute IMMEDIATELY.
|
||||
|
||||
Let's look at some more sample code. It turns out that many of the internal protocol implementations in the EventMachine package rely on Deferrable. One of these is EM::Protocols::HttpClient.
|
||||
|
||||
To make an evented HTTP request, use the module function EM::Protocols::HttpClient#request, which returns a Deferrable object. Here's how:
|
||||
|
||||
require 'eventmachine'
|
||||
|
||||
EM.run {
|
||||
df = EM::Protocols::HttpClient.request( :host=>"www.example.com", :request=>"/index.html" )
|
||||
|
||||
df.callback {|response|
|
||||
puts "Succeeded: #{response[:content]}"
|
||||
EM.stop
|
||||
}
|
||||
|
||||
df.errback {|response|
|
||||
puts "ERROR: #{response[:status]}"
|
||||
EM.stop
|
||||
}
|
||||
}
|
||||
|
||||
(See the documentation of EventMachine::Protocols::HttpClient for information on the object returned by #request.)
|
||||
|
||||
In this code, we make a call to HttpClient#request, which immediately returns a Deferrable object. In the background, an HTTP client request is being made to www.example.com, although your code will continue to run concurrently.
|
||||
|
||||
At some future point, the HTTP client request will complete, and the code in EM::Protocols::HttpClient will process either a valid HTTP response (including returned content), or an error.
|
||||
|
||||
At that point, EM::Protocols::HttpClient will call EM::Deferrable#set_deferred_status on the Deferrable object that was returned to your program, as the return value from EM::Protocols::HttpClient.request. You don't have to do anything to make this happen. All you have to do is tell the Deferrable what to do in case of either success, failure, or both.
|
||||
|
||||
In our code sample, we set one callback and one errback. The former will be called if the HTTP call succeeds, and the latter if it fails. (For simplicity, we have both of them calling EM#stop to end the program, although real programs would be very unlikely to do this.)
|
||||
|
||||
Setting callbacks and errbacks is optional. They are handlers to defined events in the lifecycle of the Deferrable event. It's not an error if you fail to set either a callback, an errback, or both. But of course your program will then fail to receive those notifications.
|
||||
|
||||
If through some bug it turns out that #set_deferred_status is never called on a Deferrable object, then that object's callbacks or errbacks will NEVER be called. It's also possible to set a timeout on a Deferrable. If the timeout elapses before any other call to #set_deferred_status, the Deferrable object will behave as is you had called set_deferred_status(:failed) on it.
|
||||
|
||||
|
||||
Now let's modify the example to illustrate some additional points:
|
||||
|
||||
require 'eventmachine'
|
||||
|
||||
EM.run {
|
||||
df = EM::Protocols::HttpClient.request( :host=>"www.example.com", :request=>"/index.html" )
|
||||
|
||||
df.callback {|response|
|
||||
df.set_deferred_status :succeeded, response[:content]
|
||||
}
|
||||
|
||||
df.callback {|string|
|
||||
puts "Succeeded: #{string}"
|
||||
EM.stop
|
||||
}
|
||||
|
||||
df.errback {|response|
|
||||
puts "ERROR: #{response[:status]}"
|
||||
EM.stop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Just for the sake of illustration, we've now set two callbacks instead of one. If the deferrable operation (the HTTP client-request) succeeds, then both of the callbacks will be executed in order.
|
||||
|
||||
But notice that we've also made our own call to #set_deferred_status in the first callback. This isn't required, because the HttpClient implementation already made a call to #set_deferred_status. (Otherwise, of course, the callback would not be executing.)
|
||||
|
||||
But we used #set_deferred_status in the first callback in order to change the parameters that will be sent to subsequent callbacks in the chain. In this way, you can construct powerful sequences of layered functionality. If you want, you can even change the status of the Deferrable from :succeeded to :failed, which would abort the chain of callback calls, and invoke the chain of errbacks instead.
|
||||
|
||||
Now of course it's somewhat trivial to define two callbacks in the same method, even with the parameter-changing effect we just described. It would be much more interesting to pass the Deferrable to some other function (for example, a function defined in another module or a different gem), that would in turn add callbacks and/or errbacks of its own. That would illustrate the true power of the Deferrable pattern: to isolate the HTTP client-request from other functions that use the data that it returns without caring where those data came from.
|
||||
|
||||
Remember that you can add a callback or an errback to a Deferrable at any point in time, regardless of whether the status of the deferred operation is known (more precisely, regardless of when #set_deferred_status is called on the object). Even hours or days later.
|
||||
|
||||
When you add a callback or errback to a Deferrable object on which #set_deferred_status has not yet been called, the callback/errback is queued up for future execution, inside the Deferrable object. When you add a callback or errback to a Deferrable on which #set_deferred_status has already been called, the callback/errback will be executed immediately. Your code doesn't have to worry about the ordering, and there are no timing issues, as there would be with a threaded approach.
|
||||
|
||||
For more information on Deferrables and their typical usage patterns, look in the EM unit tests. There are also quite a few sugarings (including EM::Deferrable#future) that make typical Deferrable usages syntactically easier to work with.
|
||||
|
141
vendor/gems/gems/eventmachine-0.12.10/docs/EPOLL
vendored
|
@ -1,141 +0,0 @@
|
|||
EventMachine now supports epoll, bringing large increases in performance and scalability to Ruby programs.
|
||||
|
||||
Epoll(7) is a alternative mechanism for multiplexed I/O that is available in Linux 2.6 kernels.
|
||||
It features significantly greater performance than the standard select(2) mechanism, when used in
|
||||
applications that require very large numbers of open I/O descriptors.
|
||||
|
||||
EventMachine has always used select(2) because its behavior is well standardized and broadly supported.
|
||||
But select becomes unreasonably slow when a program has a
|
||||
very large number of file descriptors or sockets. Ruby's version of select hardcodes a limit
|
||||
of 1024 descriptors per process, but heavily loaded processes will start to show performance
|
||||
degradation even after only a few hundred descriptors are in use.
|
||||
|
||||
Epoll is an extended version of the poll(2) call, and it solves the problems with select. Programs
|
||||
based on epoll can easily scale past Ruby's 1024-descriptor limit, potentially to tens of thousands
|
||||
of connectors, with no significant impact on performance.
|
||||
|
||||
(Another alternative which is very similar to epoll in principle is kqueue, supplied on BSD and its
|
||||
variants.)
|
||||
|
||||
|
||||
|
||||
This note shows you how to use epoll in your programs.
|
||||
|
||||
=== Compiling EventMachine to use epoll.
|
||||
|
||||
You don't have to do anything to get epoll support in EventMachine.
|
||||
When you compile EventMachine on a platform that supports epoll, EM will
|
||||
automatically generate a Makefile that includes epoll. (At this writing, this will only work
|
||||
on Linux 2.6 kernels.) If you compile EM on a platform without epoll, then epoll support will
|
||||
be omitted from the Makefile, and EM will work just as it always has.
|
||||
|
||||
=== Using epoll in your programs.
|
||||
|
||||
First, you need to tell EventMachine to use epoll instead of select (but see below, as this requirement
|
||||
will be removed in a future EventMachine version). Second, you need to prepare your program to use
|
||||
more than 1024 descriptors, an operation that generally requires superuser privileges. Third, you will probably
|
||||
want your process to drop the superuser privileges after you increase your process's descriptor limit.
|
||||
|
||||
=== Using EventMachine#epoll
|
||||
|
||||
Call the method EventMachine#epoll anytime before you call EventMachine#run, and your program will
|
||||
automatically use epoll, if available. It's safe to call EventMachine#epoll on any platform because
|
||||
it compiles to a no-op on platforms that don't support epoll.
|
||||
|
||||
require 'rubygems'
|
||||
require 'eventmachine'
|
||||
|
||||
EM.epoll
|
||||
EM.run {
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
EventMachine#epoll was included in this initial release only to avoid changing the behavior of existing
|
||||
programs. However, it's expected that a future release of EM will convert EventMachine#epoll to a no-op,
|
||||
and run epoll by default on platforms that support it.
|
||||
|
||||
=== Using EventMachine#set_descriptor_table_size
|
||||
|
||||
In Linux (as in every Unix-like platform), every process has a internal table that determines the maximum
|
||||
number of file and socket descriptors you may have open at any given time. The size of this table is
|
||||
generally fixed at 1024, although it may be increased within certain system-defined hard and soft limits.
|
||||
|
||||
If you want your EventMachine program to support more than 1024 total descriptors, you must use
|
||||
EventMachine#set_descriptor_table_size, as follows:
|
||||
|
||||
require 'rubygems'
|
||||
require 'eventmachine'
|
||||
|
||||
new_size = EM.set_descriptor_table_size( 60000 )
|
||||
$>.puts "New descriptor-table size is #{new_size}"
|
||||
|
||||
EM.run {
|
||||
...
|
||||
}
|
||||
|
||||
If successful, this example will increase the maximum number of descriptors that epoll can use to 60,000.
|
||||
Call EventMachine#set_descriptor_table_size without an argument at any time to find out the current
|
||||
size of the descriptor table.
|
||||
|
||||
Using EventMachine#set_descriptor_table_size ONLY affects the number of descriptors that can be used
|
||||
by epoll. It has no useful effect on platforms that don't support epoll, and it does NOT increase the
|
||||
number of descriptors that Ruby's own I/O functions can use.
|
||||
|
||||
#set_descriptor_table_size can fail if your process is not running as superuser, or if you try to set a
|
||||
table size that exceeds the hard limits imposed by your system. In the latter case, try a smaller number.
|
||||
|
||||
|
||||
=== Using EventMachine#set_effective_user
|
||||
|
||||
In general, you must run your program with elevated or superuser privileges if you want to increase
|
||||
your descriptor-table size beyond 1024 descriptors. This is easy enough to verify. Try running the
|
||||
sample program given above, that increases the descriptor limit to 60,000. You will probably find that
|
||||
the table size will not be increased if you don't run your program as root or with elevated privileges.
|
||||
|
||||
But of course network servers, especially long-running ones, should not run with elevated privileges.
|
||||
You will want to drop superuser privileges as soon as possible after initialization. To do this,
|
||||
use EventMachine#set_effective_user:
|
||||
|
||||
require 'rubygems'
|
||||
require 'eventmachine'
|
||||
|
||||
# (Here, program is running as superuser)
|
||||
|
||||
EM.set_descriptor_table_size( 60000 )
|
||||
EM.set_effective_user( "nobody" )
|
||||
# (Here, program is running as nobody)
|
||||
|
||||
EM.run {
|
||||
...
|
||||
}
|
||||
|
||||
Of course, you will need to replace "nobody" in the example with the name of an unprivileged user
|
||||
that is valid on your system. What if you want to drop privileges after opening a server socket
|
||||
on a privileged (low-numbered) port? Easy, just call #set_effective_user after opening your sockets:
|
||||
|
||||
require 'rubygems'
|
||||
require 'eventmachine'
|
||||
|
||||
# (Here, program is running as superuser)
|
||||
|
||||
EM.set_descriptor_table_size( 60000 )
|
||||
|
||||
EM.run {
|
||||
EM.start_server( "0.0.0.0", 80, MyHttpServer )
|
||||
EM.start_server( "0.0.0.0", 443, MyEncryptedHttpServer )
|
||||
|
||||
EM.set_effective_user( "nobody" )
|
||||
# (Here, program is running as nobody)
|
||||
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
Because EventMachine#set_effective_user is used to enforce security
|
||||
requirements, it has no nonfatal errors. If you try to set a nonexistent or invalid effective user,
|
||||
#set_effective_user will abort your program, rather than continue to run with elevated privileges.
|
||||
|
||||
EventMachine#set_effective_user is a silent no-op on platforms that don't support it, such as Windows.
|
||||
|
||||
|
281
vendor/gems/gems/eventmachine-0.12.10/docs/GNU
vendored
|
@ -1,281 +0,0 @@
|
|||
.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
If you have obtained an EventMachine source-tarball (.tar.gz):
|
||||
unzip and untar the tarball, and enter the directory that is
|
||||
created. In that directory, say:
|
||||
ruby setup.rb
|
||||
(You may need to be root to execute this command.)
|
||||
|
||||
To create documentation for EventMachine, simply type:
|
||||
rake rdoc
|
||||
in the distro directory. Rdocs will be created in subdirectory rdoc.
|
||||
|
||||
If you have obtained a gem version of EventMachine, install it in the
|
||||
usual way (gem install eventmachine). You may need superuser privileges
|
||||
to execute this command.
|
|
@ -1,38 +0,0 @@
|
|||
EventMachine (EM) can respond to keyboard events. This gives your event-driven programs the ability to respond to input from local users.
|
||||
|
||||
Programming EM to handle keyboard input in Ruby is simplicity itself. Just use EventMachine#open_keyboard, and supply the name of a Ruby module or class that will receive the input:
|
||||
|
||||
require 'rubygems'
|
||||
require 'eventmachine'
|
||||
|
||||
module MyKeyboardHandler
|
||||
def receive_data keystrokes
|
||||
puts "I received the following data from the keyboard: #{keystrokes}"
|
||||
end
|
||||
end
|
||||
|
||||
EM.run {
|
||||
EM.open_keyboard(MyKeyboardHandler)
|
||||
}
|
||||
|
||||
|
||||
If you want EM to send line-buffered keyboard input to your program, just include the LineText2 protocol module in your handler class or module:
|
||||
|
||||
|
||||
|
||||
require 'rubygems'
|
||||
require 'eventmachine'
|
||||
|
||||
module MyKeyboardHandler
|
||||
include EM::Protocols::LineText2
|
||||
def receive_line data
|
||||
puts "I received the following line from the keyboard: #{data}"
|
||||
end
|
||||
end
|
||||
|
||||
EM.run {
|
||||
EM.open_keyboard(MyKeyboardHandler)
|
||||
}
|
||||
|
||||
As we said, simplicity itself. You can call EventMachine#open_keyboard at any time while the EM reactor loop is running. In other words, the method invocation may appear anywhere in an EventMachine#run block, or in any code invoked in the #run block.
|
||||
|
25
vendor/gems/gems/eventmachine-0.12.10/docs/LEGAL
vendored
|
@ -1,25 +0,0 @@
|
|||
LEGAL NOTICE INFORMATION
|
||||
------------------------
|
||||
|
||||
EventMachine is Copyright (C) 2006-07 by Francis Cianfrocca.
|
||||
|
||||
EventMachine is copyrighted software owned by Francis Cianfrocca
|
||||
(blackhedd ... gmail.com). You may redistribute and/or modify this
|
||||
software as long as you comply with either the terms of the GPL
|
||||
(see the file GPL), or Ruby's license (see the file COPYING).
|
||||
|
||||
Your use of all the files in this distribution is controlled by these
|
||||
license terms, except for those files specifically mentioned below:
|
||||
|
||||
|
||||
|
||||
setup.rb
|
||||
This file is Copyright (C) 2000-2005 by Minero Aoki
|
||||
You can distribute/modify this file under the terms of
|
||||
the GNU LGPL, Lesser General Public License version 2.1.
|
||||
|
||||
|
||||
lib/em/buftok.rb
|
||||
This file is Copyright (C) 2007 by Tony Arcieri. This file is
|
||||
covered by the terms of Ruby's License (see the file COPYING).
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
EventMachine (EM) adds two different formalisms for lightweight concurrency to the Ruby programmer's toolbox: spawned processes and deferrables. This note will show you how to use them.
|
||||
|
||||
|
||||
=== What is Lightweight Concurrency?
|
||||
|
||||
We use the term "Lightweight Concurrency" (LC) to refer to concurrency mechanisms that are lighter than Ruby threads. By "lighter," we mean: less resource-intensive in one or more dimensions, usually including memory and CPU usage. In general, you turn to LC in the hope of improving the performance and scalability of your programs.
|
||||
|
||||
In addition to the two EventMachine mechanisms we will discuss here, Ruby has at least one other LC construct: Fibers, which are currently under development in Ruby 1.9.
|
||||
|
||||
The technical feature that makes all of these LC mechanisms different from standard Ruby threads is that they are not scheduled automatically.
|
||||
|
||||
When you create and run Ruby threads, you can assume (within certain constraints) that your threads will all be scheduled fairly by Ruby's runtime. Ruby itself is responsible for giving each of your threads its own share of the total runtime.
|
||||
|
||||
But with LC, your program is responsible for causing different execution paths to run. In effect, your program has to act as a "thread scheduler." Scheduled entities in LC run to completion and are never preempted. The runtime system has far less work to do since it has no need to interrupt threads or to schedule them fairly. This is what makes LC lighter and faster.
|
||||
|
||||
You'll learn exactly how LC scheduling works in practice as we work through specific examples.
|
||||
|
||||
|
||||
=== EventMachine Lightweight Concurrency
|
||||
|
||||
Recall that EM provides a reactor loop that must be running in order for your programs to perform event-driven logic. An EM program typically has a structure like this:
|
||||
|
||||
require 'eventmachine'
|
||||
|
||||
# your initializations
|
||||
|
||||
EM.run {
|
||||
# perform event-driven I/O here, including network clients,
|
||||
# servers, timers, and thread-pool operations.
|
||||
}
|
||||
|
||||
# your cleanup
|
||||
# end of the program
|
||||
|
||||
|
||||
EventMachine#run executes the reactor loop, which causes your code to be called as events of interest to your program occur. The block you pass to EventMachine#run is executed right after the reactor loop starts, and is the right place to start socket acceptors, etc.
|
||||
|
||||
Because the reactor loop runs constantly in an EM program (until it is stopped by a call to EventMachine#stop), it has the ability to schedule blocks of code for asynchronous execution. Unlike a pre-emptive thread scheduler, it's NOT able to interrupt code blocks while they execute. But the scheduling capability it does have is enough to enable lightweight concurrency.
|
||||
|
||||
|
||||
For information on Spawned Processes, see the separate document SPAWNED_PROCESSES.
|
||||
|
||||
For information on Deferrables, see the separate document DEFERRABLES.
|
||||
|
||||
|
||||
=== [SIDEBAR]: I Heard That EventMachine Doesn't Work With Ruby Threads.
|
||||
|
||||
This is incorrect. EM is fully interoperable with all versions of Ruby threads, and has been since its earliest releases.
|
||||
|
||||
It's very true that EM encourages an "evented" (non-threaded) programming style. The specific benefits of event-driven programming are far better performance and scalabiity for well-written programs, and far easier debugging.
|
||||
|
||||
The benefit of using threads for similar applications is a possibly more intuitive programming model, as well as the fact that threads are already familiar to most programmers. Also, bugs in threaded programs often fail to show up until programs go into production. These factors create the illusion that threaded programs are easier to write.
|
||||
|
||||
However, some operations that occur frequently in professional-caliber applications simply can't be done without threads. (The classic example is making calls to database client-libraries that block on network I/O until they complete.)
|
||||
|
||||
EventMachine not only allows the use of Ruby threads in these cases, but it even provides a built-in thread-pool object to make them easier to work with.
|
||||
|
||||
You may have heard a persistent criticism that evented I/O is fundamentally incompatible with Ruby threads. It is true that some well-publicized attempts to incorporate event-handling libraries into Ruby were not successful. But EventMachine was designed from the ground up with Ruby compatibility in mind, so EM never suffered from the problems that defeated the earlier attempts.
|
||||
|
||||
|
||||
=== [SIDEBAR]: I Heard That EventMachine Doesn't Work Very Well On Windows.
|
||||
|
||||
This too is incorrect. EventMachine is an extension written in C++ and Java, and therefore it requires compilation. Many Windows computers (and some Unix computers, especially in production environments) don't have a build stack. Attempting to install EventMachine on a machine without a compiler usually produces a confusing error.
|
||||
|
||||
In addition, Ruby has a much-debated issue with Windows compiler versions. Ruby on Windows works best with Visual Studio 6, a compiler version that is long out-of-print, no longer supported by Microsoft, and difficult to obtain. (This problem is not specific to EventMachine.)
|
||||
|
||||
Shortly after EventMachine was first released, the compiler issues led to criticism that EM was incompatible with Windows. Since that time, every EventMachine release has been supplied in a precompiled binary form for Windows users, that does not require you to compile the code yourself. EM binary Gems for Windows are compiled using Visual Studio 6.
|
||||
|
||||
EventMachine does supply some advanced features (such as Linux EPOLL support, reduced-privilege operation, UNIX-domain sockets, etc.) that have no meaningful implementation on Windows. Apart from these special cases, all EM functionality (including lightweight concurrency) works perfectly well on Windows.
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
EventMachine is supplied in three alternative versions.
|
||||
|
||||
1) A version that includes a Ruby extension written in C++. This version requires compilation;
|
||||
2) A version for JRuby that contains a precompiled JAR file written in Java;
|
||||
3) A pure Ruby version that has no external dependencies and can run in any Ruby environment.
|
||||
|
||||
The Java version of EventMachine is packaged in a distinct manner and must be installed using a
|
||||
special procedure. This version is described fully in a different document, and not considered
|
||||
further here.
|
||||
|
||||
The C++ and pure-Ruby versions, however, are shipped in the same distribution. You use the same
|
||||
files (either tarball or Ruby gem) to install both of these versions.
|
||||
|
||||
If you intend to use the C++ version, you must successfully compile EventMachine after you install it.
|
||||
(The gem installation attempts to perform this step automatically.)
|
||||
|
||||
If you choose not to compile the EventMachine C++ extension, or if your compilation fails for any
|
||||
reason, you still have a fully-functional installation of the pure-Ruby version of EM.
|
||||
|
||||
However, for technical reasons, a default EM installation (whether or not the compilation succeeds)
|
||||
will always assume that the compiled ("extension") implementation should be used.
|
||||
|
||||
If you want your EM program to use the pure Ruby version, you must specifically request it. There
|
||||
are two ways to do this: by setting either a Ruby global variable, or an environment string.
|
||||
|
||||
The following code will invoke the pure-Ruby implementation of EM:
|
||||
|
||||
$eventmachine_library = :pure_ruby
|
||||
require 'eventmachine'
|
||||
|
||||
EM.library_type #=> "pure_ruby"
|
||||
|
||||
Notice that this requires a code change and is not the preferred way to select pure Ruby, unless
|
||||
for some reason you are absolutely sure you will never want the compiled implementation.
|
||||
|
||||
Setting the following environment string has the same effect:
|
||||
|
||||
export EVENTMACHINE_LIBRARY="pure_ruby"
|
||||
|
||||
This technique gives you the flexibility to select either version at runtime with no code changes.
|
||||
|
||||
Support
|
||||
|
||||
The EventMachine development team has committed to support precisely the same APIs for all the
|
||||
various implementations of EM.
|
||||
|
||||
This means that you can expect any EM program to behave identically, whether you use pure Ruby,
|
||||
the compiled C++ extension, or JRuby. Deviations from this behavior are to be considered bugs
|
||||
and should be reported as such.
|
||||
|
||||
There is a small number of exceptions to this rule, which arise from underlying platform
|
||||
distinctions. Notably, EM#epoll is a silent no-op in the pure Ruby implementation.
|
||||
|
||||
|
||||
When Should You Use the Pure-Ruby Implementation of EM?
|
||||
|
||||
|
||||
Use the pure Ruby implementation of EM when you must support a platform for which no C++ compiler
|
||||
is available, or on which the standard EM C++ code can't be compiled.
|
||||
|
||||
Keep in mind that you don't need a C++ compiler in order to deploy EM applications that rely on
|
||||
the compiled version, so long as appropriate C++ runtime libraries are available on the target platform.
|
||||
|
||||
In extreme cases, you may find that you can develop software with the compiled EM version, but are
|
||||
not allowed to install required runtime libraries on the deployment system(s). This would be another
|
||||
case in which the pure Ruby implementation can be useful.
|
||||
|
||||
In general you should avoid the pure Ruby version of EM when performance and scalability are important.
|
||||
EM in pure Ruby will necessarily run slower than the compiled version. Depending on your application
|
||||
this may or may not be a key issue.
|
||||
|
||||
Also, since EPOLL is not supported in pure Ruby, your applications will be affected by Ruby's built-in
|
||||
limit of 1024 file and socket descriptors that may be open in a single process. For maximum scalability
|
||||
and performance, always use EPOLL if possible.
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
RUBY/EventMachine RELEASE NOTES
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.9.0, released xxXXX07
|
||||
Added Erlang-like distributed-computing features
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.8.0, released 23Jun07
|
||||
Added an epoll implementation for Linux 2.6 kernels.
|
||||
Added evented #popen.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.7.3, released 22May07
|
||||
Added a large variety of small features. See the ChangeLog.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.7.1, released xxNov06
|
||||
Added protocol handlers for line-oriented protocols.
|
||||
Various bug fixes.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.7.0, released 20Nov06
|
||||
Added a fix in em.cpp/ConnectToServer to fix a fatal exception that
|
||||
occurred in FreeBSD when connecting successfully to a remote server.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.6.0, released xxJul06
|
||||
Added deferred operations, suggested by Don Stocks, amillionhitpoints@yahoo.com.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.5.4, released xxJun06
|
||||
Added get_peername support for streams and datagrams.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.5.3, released 17May06
|
||||
Fixed bugs in extconf.rb, thanks to Daniel Harple, dharple@generalconsumption.org.
|
||||
Added proper setup.rb and rake tasks, thanks to Austin Ziegler.
|
||||
Fixed a handful of reported problems with builds on various platforms.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.5.2, released 05May06
|
||||
Made several nonvisible improvements to the Windows
|
||||
implementation.
|
||||
Added an exception-handling patch contributed by Jeff Rose, jeff@rosejn.net.
|
||||
Added a dir-config patch contributed anonymously.
|
||||
Supported builds on Solaris.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.5.1, released 05May06
|
||||
Made it possible to pass a Class rather than a Module
|
||||
to a protocol handler.
|
||||
Added Windows port.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.5.0, released 30Apr06
|
||||
Added a preliminary SSL/TLS extension. This will probably
|
||||
change over the next few releases.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.4.5, released 29Apr06
|
||||
Changed ext files so the ruby.h is installed after unistd.h
|
||||
otherwise it doesn't compile on gcc 4.1
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.4.2, released 19Apr06
|
||||
Changed the Ruby-glue so the extension will play nicer
|
||||
in the sandbox with Ruby threads.
|
||||
Added an EventMachine::run_without_threads API to
|
||||
switch off the thread-awareness for better performance
|
||||
in programs that do not spin any Ruby threads.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.4.1, released 15Apr06
|
||||
Reworked the shared-object interface to make it easier to
|
||||
use EventMachine from languages other than Ruby.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.3.2, released 12Apr06
|
||||
Added support for a user-supplied block in EventMachine#connect.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.3.1, released 11Apr06
|
||||
Fixed bug that prevented EventMachine from being run multiple
|
||||
times in a single process.
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.3.0, released 10Apr06
|
||||
Added method EventHandler::Connection::post_init
|
||||
|
||||
--------------------------------------------------
|
||||
Version: 0.2.0, released 10Apr06
|
||||
Added method EventHandler::stop
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
This note details the usage of EventMachine's built-in support for SMTP. EM supports both client and server connections, which will be described in separate sections.
|
||||
|
|
@ -1,89 +0,0 @@
|
|||
EventMachine (EM) adds two different formalisms for lightweight concurrency to the Ruby programmer's toolbox: spawned processes and deferrables. This note will show you how to use spawned processes. For more information, see the separate document LIGHTWEIGHT_CONCURRENCY.
|
||||
|
||||
|
||||
=== What are Spawned Processes?
|
||||
|
||||
Spawned Processes in EventMachine are inspired directly by the "processes" found in the Erlang programming language. EM deliberately borrows much (but not all) of Erlang's terminology. However, EM's spawned processes differ from Erlang's in ways that reflect not only Ruby style, but also the fact that Ruby is not a functional language like Erlang.
|
||||
|
||||
Let's proceed with a complete, working code sample that we will analyze line by line. Here's an EM implementation of the "ping-pong" program that also appears in the Erlang tutorial:
|
||||
|
||||
|
||||
require 'eventmachine'
|
||||
|
||||
EM.run {
|
||||
pong = EM.spawn {|x, ping|
|
||||
puts "Pong received #{x}"
|
||||
ping.notify( x-1 )
|
||||
}
|
||||
|
||||
ping = EM.spawn {|x|
|
||||
if x > 0
|
||||
puts "Pinging #{x}"
|
||||
pong.notify x, self
|
||||
else
|
||||
EM.stop
|
||||
end
|
||||
}
|
||||
|
||||
ping.notify 3
|
||||
}
|
||||
|
||||
If you run this program, you'll see the following output:
|
||||
|
||||
Pinging 3
|
||||
Pong received 3
|
||||
Pinging 2
|
||||
Pong received 2
|
||||
Pinging 1
|
||||
Pong received 1
|
||||
|
||||
Let's take it step by step.
|
||||
|
||||
EventMachine#spawn works very much like the built-in function spawn in Erlang. It returns a reference to a Ruby object of class EventMachine::SpawnedProcess, which is actually a schedulable entity. In Erlang, the value returned from spawn is called a "process identifier" or "pid." But we'll refer to the Ruby object returned from EM#spawn simply as a "spawned process."
|
||||
|
||||
You pass a Ruby block with zero or more parameters to EventMachine#spawn. Like all Ruby blocks, this one is a closure, so it can refer to variables defined in the local context when you call EM#spawn.
|
||||
|
||||
However, the code block passed to EM#spawn does NOT execute immediately by default. Rather, it will execute only when the Spawned Object is "notified." In Erlang, this process is called "message passing," and is done with the operator !, but in Ruby it's done simply by calling the #notify method of a spawned-process object. The parameters you pass to #notify must match those defined in the block that was originally passed to EM#spawn.
|
||||
|
||||
When you call the #notify method of a spawned-process object, EM's reactor core will execute the code block originally passed to EM#spawn, at some point in the future. (#notify itself merely adds a notification to the object's message queue and ALWAYS returns immediately.)
|
||||
|
||||
When a SpawnedProcess object executes a notification, it does so in the context of the SpawnedProcess object itself. The notified code block can see local context from the point at which EM#spawn was called. However, the value of "self" inside the notified code block is a reference to the SpawnedProcesss object itself.
|
||||
|
||||
An EM spawned process is nothing more than a Ruby object with a message queue attached to it. You can have any number of spawned processes in your program without compromising scalability. You can notify a spawned process any number of times, and each notification will cause a "message" to be placed in the queue of the spawned process. Spawned processes with non-empty message queues are scheduled for execution automatically by the EM reactor. Spawned processes with no visible references are garbage-collected like any other Ruby object.
|
||||
|
||||
Back to our code sample:
|
||||
|
||||
pong = EM.spawn {|x, ping|
|
||||
puts "Pong received #{x}"
|
||||
ping.notify( x-1 )
|
||||
}
|
||||
|
||||
This simply creates a spawned process and assigns it to the local variable pong. You can see that the spawned code block takes a numeric parameter and a reference to another spawned process. When pong is notified, it expects to receive arguments corresponding to these two parameters. It simply prints out the number it receives as the first argument. Then it notifies the spawned process referenced by the second argument, passing it the first argument minus 1.
|
||||
|
||||
And then the block ends, which is crucial because otherwise nothing else can run. (Remember that in LC, scheduled entities run to completion and are never preempted.)
|
||||
|
||||
On to the next bit of the code sample:
|
||||
|
||||
ping = EM.spawn {|x|
|
||||
if x > 0
|
||||
puts "Pinging #{x}"
|
||||
pong.notify x, self
|
||||
else
|
||||
EM.stop
|
||||
end
|
||||
}
|
||||
|
||||
Here, we're spawning a process that takes a single (numeric) parameter. If the parameter is greater than zero, the block writes it to the console. It then notifies the spawned process referenced by the pong local variable, passing as arguments its number argument, and a reference to itself. The latter reference, as you saw above, is used by pong to send a return notification.
|
||||
|
||||
If the ping process receives a zero value, it will stop the reactor loop and end the program.
|
||||
|
||||
Now we've created a pair of spawned processes, but nothing else has happened. If we stop now, the program will spin in the EM reactor loop, doing nothing at all. Our spawned processes will never be scheduled for execution.
|
||||
|
||||
But look at the next line in the code sample:
|
||||
|
||||
ping.notify 3
|
||||
|
||||
This line gets the ping-pong ball rolling. We call ping's #notify method, passing the argument 3. This causes a message to be sent to the ping spawned process. The message contains the single argument, and it causes the EM reactor to schedule the ping process. And this in turn results in the execution of the Ruby code block passed to EM#spawn when ping was created. Everything else proceeds as a result of the messages that are subsequently passed to each other by the spawned processes.
|
||||
|
||||
[TODO, present the outbound network i/o use case, and clarify that spawned processes are interleaved with normal i/o operations and don't interfere with them at all. Also, blame Erlang for the confusing term "process"]
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
TODO List:
|
||||
|
||||
12Aug06: Noticed by Don Stocks. A TCP connect-request that results
|
||||
in a failed DNS resolution fires a fatal error back to user code.
|
||||
Uuuuuugly. We should probably cause an unbind event to get fired
|
||||
instead, and add some parameterization so the caller can detect
|
||||
the nature of the failure.
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
|
||||
Gem::Specification.new do |s|
|
||||
s.name = %q{eventmachine}
|
||||
s.version = "0.12.10"
|
||||
|
||||
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
||||
s.authors = ["Francis Cianfrocca"]
|
||||
s.date = %q{2009-10-24}
|
||||
s.description = %q{EventMachine implements a fast, single-threaded engine for arbitrary network
|
||||
communications. It's extremely easy to use in Ruby. EventMachine wraps all
|
||||
interactions with IP sockets, allowing programs to concentrate on the
|
||||
implementation of network protocols. It can be used to create both network
|
||||
servers and clients. To create a server or client, a Ruby program only needs
|
||||
to specify the IP address and port, and provide a Module that implements the
|
||||
communications protocol. Implementations of several standard network protocols
|
||||
are provided with the package, primarily to serve as examples. The real goal
|
||||
of EventMachine is to enable programs to easily interface with other programs
|
||||
using TCP/IP, especially if custom protocols are required.
|
||||
}
|
||||
s.email = %q{garbagecat10@gmail.com}
|
||||
s.extensions = ["ext/extconf.rb", "ext/fastfilereader/extconf.rb"]
|
||||
s.files = [".gitignore", "README", "Rakefile", "docs/COPYING", "docs/ChangeLog", "docs/DEFERRABLES", "docs/EPOLL", "docs/GNU", "docs/INSTALL", "docs/KEYBOARD", "docs/LEGAL", "docs/LIGHTWEIGHT_CONCURRENCY", "docs/PURE_RUBY", "docs/RELEASE_NOTES", "docs/SMTP", "docs/SPAWNED_PROCESSES", "docs/TODO", "eventmachine.gemspec", "examples/ex_channel.rb", "examples/ex_queue.rb", "examples/helper.rb", "ext/binder.cpp", "ext/binder.h", "ext/cmain.cpp", "ext/cplusplus.cpp", "ext/ed.cpp", "ext/ed.h", "ext/em.cpp", "ext/em.h", "ext/emwin.cpp", "ext/emwin.h", "ext/epoll.cpp", "ext/epoll.h", "ext/eventmachine.h", "ext/eventmachine_cpp.h", "ext/extconf.rb", "ext/fastfilereader/extconf.rb", "ext/fastfilereader/mapper.cpp", "ext/fastfilereader/mapper.h", "ext/fastfilereader/rubymain.cpp", "ext/files.cpp", "ext/files.h", "ext/kb.cpp", "ext/page.cpp", "ext/page.h", "ext/pipe.cpp", "ext/project.h", "ext/rubymain.cpp", "ext/sigs.cpp", "ext/sigs.h", "ext/ssl.cpp", "ext/ssl.h", "java/.classpath", "java/.project", "java/src/com/rubyeventmachine/EmReactor.java", "java/src/com/rubyeventmachine/EmReactorException.java", "java/src/com/rubyeventmachine/EventableChannel.java", "java/src/com/rubyeventmachine/EventableDatagramChannel.java", "java/src/com/rubyeventmachine/EventableSocketChannel.java", "java/src/com/rubyeventmachine/application/Application.java", "java/src/com/rubyeventmachine/application/Connection.java", "java/src/com/rubyeventmachine/application/ConnectionFactory.java", "java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java", "java/src/com/rubyeventmachine/application/PeriodicTimer.java", "java/src/com/rubyeventmachine/application/Timer.java", "java/src/com/rubyeventmachine/tests/ApplicationTest.java", "java/src/com/rubyeventmachine/tests/ConnectTest.java", "java/src/com/rubyeventmachine/tests/EMTest.java", "java/src/com/rubyeventmachine/tests/TestDatagrams.java", "java/src/com/rubyeventmachine/tests/TestServers.java", "java/src/com/rubyeventmachine/tests/TestTimers.java", "lib/em/buftok.rb", "lib/em/callback.rb", "lib/em/channel.rb", "lib/em/connection.rb", "lib/em/deferrable.rb", "lib/em/file_watch.rb", "lib/em/future.rb", "lib/em/messages.rb", "lib/em/process_watch.rb", "lib/em/processes.rb", "lib/em/protocols.rb", "lib/em/protocols/header_and_content.rb", "lib/em/protocols/httpclient.rb", "lib/em/protocols/httpclient2.rb", "lib/em/protocols/line_and_text.rb", "lib/em/protocols/linetext2.rb", "lib/em/protocols/memcache.rb", "lib/em/protocols/object_protocol.rb", "lib/em/protocols/postgres3.rb", "lib/em/protocols/saslauth.rb", "lib/em/protocols/smtpclient.rb", "lib/em/protocols/smtpserver.rb", "lib/em/protocols/socks4.rb", "lib/em/protocols/stomp.rb", "lib/em/protocols/tcptest.rb", "lib/em/queue.rb", "lib/em/spawnable.rb", "lib/em/streamer.rb", "lib/em/timers.rb", "lib/em/version.rb", "lib/eventmachine.rb", "lib/evma.rb", "lib/evma/callback.rb", "lib/evma/container.rb", "lib/evma/factory.rb", "lib/evma/protocol.rb", "lib/evma/reactor.rb", "lib/jeventmachine.rb", "lib/pr_eventmachine.rb", "setup.rb", "tasks/cpp.rake_example", "tests/client.crt", "tests/client.key", "tests/test_attach.rb", "tests/test_basic.rb", "tests/test_channel.rb", "tests/test_connection_count.rb", "tests/test_defer.rb", "tests/test_epoll.rb", "tests/test_error_handler.rb", "tests/test_errors.rb", "tests/test_exc.rb", "tests/test_file_watch.rb", "tests/test_futures.rb", "tests/test_get_sock_opt.rb", "tests/test_handler_check.rb", "tests/test_hc.rb", "tests/test_httpclient.rb", "tests/test_httpclient2.rb", "tests/test_inactivity_timeout.rb", "tests/test_kb.rb", "tests/test_ltp.rb", "tests/test_ltp2.rb", "tests/test_next_tick.rb", "tests/test_object_protocol.rb", "tests/test_pause.rb", "tests/test_pending_connect_timeout.rb", "tests/test_process_watch.rb", "tests/test_processes.rb", "tests/test_proxy_connection.rb", "tests/test_pure.rb", "tests/test_queue.rb", "tests/test_running.rb", "tests/test_sasl.rb", "tests/test_send_file.rb", "tests/test_servers.rb", "tests/test_smtpclient.rb", "tests/test_smtpserver.rb", "tests/test_spawn.rb", "tests/test_ssl_args.rb", "tests/test_ssl_methods.rb", "tests/test_ssl_verify.rb", "tests/test_timers.rb", "tests/test_ud.rb", "tests/testem.rb", "web/whatis"]
|
||||
s.homepage = %q{http://rubyeventmachine.com}
|
||||
s.rdoc_options = ["--title", "EventMachine", "--main", "README", "--line-numbers", "-x", "lib/em/version", "-x", "lib/emva", "-x", "lib/evma/", "-x", "lib/pr_eventmachine", "-x", "lib/jeventmachine"]
|
||||
s.require_paths = ["lib"]
|
||||
s.rubyforge_project = %q{eventmachine}
|
||||
s.rubygems_version = %q{1.3.5}
|
||||
s.summary = %q{Ruby/EventMachine library}
|
||||
|
||||
if s.respond_to? :specification_version then
|
||||
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
||||
s.specification_version = 3
|
||||
|
||||
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
||||
else
|
||||
end
|
||||
else
|
||||
end
|
||||
end
|
|
@ -1,43 +0,0 @@
|
|||
require File.dirname(__FILE__) + '/helper'
|
||||
|
||||
EM.run do
|
||||
|
||||
# Create a channel to push data to, this could be stocks...
|
||||
RandChannel = EM::Channel.new
|
||||
|
||||
# The server simply subscribes client connections to the channel on connect,
|
||||
# and unsubscribes them on disconnect.
|
||||
class Server < EM::Connection
|
||||
def self.start(host = '127.0.0.1', port = 8000)
|
||||
EM.start_server(host, port, self)
|
||||
end
|
||||
|
||||
def post_init
|
||||
@sid = RandChannel.subscribe { |m| send_data "#{m.inspect}\n" }
|
||||
end
|
||||
|
||||
def unbind
|
||||
RandChannel.unsubscribe @sid
|
||||
end
|
||||
end
|
||||
Server.start
|
||||
|
||||
# Two client connections, that just print what they receive.
|
||||
2.times do
|
||||
EM.connect('127.0.0.1', 8000) do |c|
|
||||
c.extend EM::P::LineText2
|
||||
def c.receive_line(line)
|
||||
puts "Subscriber: #{signature} got #{line}"
|
||||
end
|
||||
EM.add_timer(2) { c.close_connection }
|
||||
end
|
||||
end
|
||||
|
||||
# This part of the example is more fake, but imagine sleep was in fact a
|
||||
# long running calculation to achieve the value.
|
||||
40.times do
|
||||
EM.defer lambda { v = sleep(rand * 2); RandChannel << [Time.now, v] }
|
||||
end
|
||||
|
||||
EM.add_timer(5) { EM.stop }
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
require File.dirname(__FILE__) + '/helper'
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
||||
require 'eventmachine'
|
181
vendor/gems/gems/eventmachine-0.12.10/ext/Makefile
vendored
|
@ -1,181 +0,0 @@
|
|||
|
||||
SHELL = /bin/sh
|
||||
|
||||
#### Start of system configuration section. ####
|
||||
|
||||
srcdir = .
|
||||
topdir = /Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/include/ruby-1.9.1
|
||||
hdrdir = /Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/include/ruby-1.9.1
|
||||
arch_hdrdir = /Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/include/ruby-1.9.1/$(arch)
|
||||
VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
|
||||
prefix = $(DESTDIR)/Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243
|
||||
exec_prefix = $(prefix)
|
||||
vendorhdrdir = $(rubyhdrdir)/vendor_ruby
|
||||
sitehdrdir = $(rubyhdrdir)/site_ruby
|
||||
rubyhdrdir = $(includedir)/$(RUBY_INSTALL_NAME)-$(ruby_version)
|
||||
vendordir = $(libdir)/$(RUBY_INSTALL_NAME)/vendor_ruby
|
||||
sitedir = $(libdir)/$(RUBY_INSTALL_NAME)/site_ruby
|
||||
mandir = $(datarootdir)/man
|
||||
localedir = $(datarootdir)/locale
|
||||
libdir = $(exec_prefix)/lib
|
||||
psdir = $(docdir)
|
||||
pdfdir = $(docdir)
|
||||
dvidir = $(docdir)
|
||||
htmldir = $(docdir)
|
||||
infodir = $(datarootdir)/info
|
||||
docdir = $(datarootdir)/doc/$(PACKAGE)
|
||||
oldincludedir = $(DESTDIR)/usr/include
|
||||
includedir = $(prefix)/include
|
||||
localstatedir = $(prefix)/var
|
||||
sharedstatedir = $(prefix)/com
|
||||
sysconfdir = $(prefix)/etc
|
||||
datadir = $(datarootdir)
|
||||
datarootdir = $(prefix)/share
|
||||
libexecdir = $(exec_prefix)/libexec
|
||||
sbindir = $(exec_prefix)/sbin
|
||||
bindir = $(exec_prefix)/bin
|
||||
rubylibdir = $(libdir)/$(ruby_install_name)/$(ruby_version)
|
||||
archdir = $(rubylibdir)/$(arch)
|
||||
sitelibdir = $(sitedir)/$(ruby_version)
|
||||
sitearchdir = $(sitelibdir)/$(sitearch)
|
||||
vendorlibdir = $(vendordir)/$(ruby_version)
|
||||
vendorarchdir = $(vendorlibdir)/$(sitearch)
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
LIBRUBY = $(LIBRUBY_SO)
|
||||
LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
|
||||
LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
|
||||
LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
|
||||
OUTFLAG = -o
|
||||
COUTFLAG = -o
|
||||
|
||||
RUBY_EXTCONF_H =
|
||||
cflags = $(optflags) $(debugflags) $(warnflags)
|
||||
optflags = -O2
|
||||
debugflags = -g
|
||||
warnflags = -Wall -Wno-parentheses
|
||||
CFLAGS = -fno-common -O3 -march=core2 -m64 -mmmx -msse4.1 -w -pipe -fomit-frame-pointer -mmacosx-version-min=10.6 $(cflags) -fno-common -pipe -fno-common
|
||||
INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
|
||||
DEFS =
|
||||
CPPFLAGS = -DBUILD_FOR_RUBY -DHAVE_RB_THREAD_BLOCKING_REGION -DHAVE_TBR -DHAVE_WRITEV -DHAVE_WRITEV -DHAVE_RB_THREAD_CHECK_INTS -DHAVE_RB_TIME_NEW -DOS_UNIX -DHAVE_SYS_EVENT_H -DHAVE_SYS_QUEUE_H -DHAVE_KQUEUE -DHAVE_OPENSSL_SSL_H -DHAVE_OPENSSL_ERR_H -DWITH_SSL -DHAVE_MAKE_PAIR -I/Users/tdreyno/homebrew/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
|
||||
CXXFLAGS = $(CFLAGS) -O3 -march=core2 -m64 -mmmx -msse4.1 -w -pipe -fomit-frame-pointer -mmacosx-version-min=10.6 $(cxxflags)
|
||||
ldflags = -L. -L/Users/tdreyno/homebrew/lib -L/usr/local/lib
|
||||
dldflags =
|
||||
archflag =
|
||||
DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
|
||||
LDSHARED = $(CXX) -dynamic -bundle -undefined suppress -flat_namespace
|
||||
LDSHAREDXX = $(LDSHARED)
|
||||
AR = ar
|
||||
EXEEXT =
|
||||
|
||||
RUBY_INSTALL_NAME = ruby
|
||||
RUBY_SO_NAME = ruby
|
||||
arch = i386-darwin10.0.0
|
||||
sitearch = i386-darwin10.0.0
|
||||
ruby_version = 1.9.1
|
||||
ruby = /Users/tdreyno/homebrew/Cellar/ruby/1.9.1-p243/bin/ruby
|
||||
RUBY = $(ruby)
|
||||
RM = rm -f
|
||||
RM_RF = $(RUBY) -run -e rm -- -rf
|
||||
RMDIRS = $(RUBY) -run -e rmdir -- -p
|
||||
MAKEDIRS = mkdir -p
|
||||
INSTALL = /usr/bin/install -c
|
||||
INSTALL_PROG = $(INSTALL) -m 0755
|
||||
INSTALL_DATA = $(INSTALL) -m 644
|
||||
COPY = cp
|
||||
|
||||
#### End of system configuration section. ####
|
||||
|
||||
preload =
|
||||
|
||||
libpath = . $(libdir)
|
||||
LIBPATH = -L. -L$(libdir)
|
||||
DEFFILE =
|
||||
|
||||
CLEANFILES = mkmf.log
|
||||
DISTCLEANFILES =
|
||||
DISTCLEANDIRS =
|
||||
|
||||
extout =
|
||||
extout_prefix =
|
||||
target_prefix =
|
||||
LOCAL_LIBS =
|
||||
LIBS = $(LIBRUBYARG_SHARED) -lC -lcrypto -lssl -lpthread -ldl -lobjc
|
||||
SRCS = binder.cpp cmain.cpp cplusplus.cpp ed.cpp em.cpp emwin.cpp epoll.cpp files.cpp kb.cpp page.cpp pipe.cpp rubymain.cpp sigs.cpp ssl.cpp
|
||||
OBJS = binder.o cmain.o cplusplus.o ed.o em.o emwin.o epoll.o files.o kb.o page.o pipe.o rubymain.o sigs.o ssl.o
|
||||
TARGET = rubyeventmachine
|
||||
DLLIB = $(TARGET).bundle
|
||||
EXTSTATIC =
|
||||
STATIC_LIB =
|
||||
|
||||
BINDIR = $(bindir)
|
||||
RUBYCOMMONDIR = $(sitedir)$(target_prefix)
|
||||
RUBYLIBDIR = /Users/tdreyno/Dropbox/Sites/middleman/vendor/gems/gems/eventmachine-0.12.10/lib$(target_prefix)
|
||||
RUBYARCHDIR = /Users/tdreyno/Dropbox/Sites/middleman/vendor/gems/gems/eventmachine-0.12.10/lib$(target_prefix)
|
||||
HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
|
||||
ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
|
||||
|
||||
TARGET_SO = $(DLLIB)
|
||||
CLEANLIBS = $(TARGET).bundle
|
||||
CLEANOBJS = *.o *.bak
|
||||
|
||||
all: $(DLLIB)
|
||||
static: $(STATIC_LIB)
|
||||
|
||||
clean-rb-default::
|
||||
clean-rb::
|
||||
clean-so::
|
||||
clean: clean-so clean-rb-default clean-rb
|
||||
@-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
|
||||
|
||||
distclean-rb-default::
|
||||
distclean-rb::
|
||||
distclean-so::
|
||||
distclean: clean distclean-so distclean-rb-default distclean-rb
|
||||
@-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
|
||||
@-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
|
||||
@-$(RMDIRS) $(DISTCLEANDIRS)
|
||||
|
||||
realclean: distclean
|
||||
install: install-so install-rb
|
||||
|
||||
install-so: $(RUBYARCHDIR)
|
||||
install-so: $(RUBYARCHDIR)/$(DLLIB)
|
||||
$(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
|
||||
$(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
|
||||
install-rb: pre-install-rb install-rb-default
|
||||
install-rb-default: pre-install-rb-default
|
||||
pre-install-rb: Makefile
|
||||
pre-install-rb-default: Makefile
|
||||
$(RUBYARCHDIR):
|
||||
$(MAKEDIRS) $@
|
||||
|
||||
site-install: site-install-so site-install-rb
|
||||
site-install-so: install-so
|
||||
site-install-rb: install-rb
|
||||
|
||||
.SUFFIXES: .c .m .cc .cxx .cpp .C .o
|
||||
|
||||
.cc.o:
|
||||
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.cxx.o:
|
||||
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.cpp.o:
|
||||
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.C.o:
|
||||
$(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
.c.o:
|
||||
$(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
|
||||
|
||||
$(DLLIB): $(OBJS) Makefile
|
||||
@-$(RM) $(@)
|
||||
$(LDSHAREDXX) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
|
||||
|
||||
|
||||
|
||||
$(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
|
125
vendor/gems/gems/eventmachine-0.12.10/ext/binder.cpp
vendored
|
@ -1,125 +0,0 @@
|
|||
/*****************************************************************************
|
||||
|
||||
$Id$
|
||||
|
||||
File: binder.cpp
|
||||
Date: 07Apr06
|
||||
|
||||
Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
||||
Gmail: blackhedd
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of either: 1) the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version; or 2) Ruby's License.
|
||||
|
||||
See the file COPYING for complete licensing information.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#include "project.h"
|
||||
|
||||
#define DEV_URANDOM "/dev/urandom"
|
||||
|
||||
|
||||
map<unsigned long, Bindable_t*> Bindable_t::BindingBag;
|
||||
|
||||
|
||||
/********************************
|
||||
STATIC Bindable_t::CreateBinding
|
||||
********************************/
|
||||
|
||||
unsigned long Bindable_t::CreateBinding()
|
||||
{
|
||||
// XXX use atomic_t to prevent thread-safety issues
|
||||
static unsigned long num = 0;
|
||||
while(BindingBag[++num]);
|
||||
return num;
|
||||
}
|
||||
|
||||
#if 0
|
||||
string Bindable_t::CreateBinding()
|
||||
{
|
||||
static int index = 0;
|
||||
static string seed;
|
||||
|
||||
if ((index >= 1000000) || (seed.length() == 0)) {
|
||||
#ifdef OS_UNIX
|
||||
int fd = open (DEV_URANDOM, O_RDONLY);
|
||||
if (fd < 0)
|
||||
throw std::runtime_error ("No entropy device");
|
||||
|
||||
unsigned char u[16];
|
||||
size_t r = read (fd, u, sizeof(u));
|
||||
if (r < sizeof(u))
|
||||
throw std::runtime_error ("Unable to read entropy device");
|
||||
|
||||
unsigned char *u1 = (unsigned char*)u;
|
||||
char u2 [sizeof(u) * 2 + 1];
|
||||
|
||||
for (size_t i=0; i < sizeof(u); i++)
|
||||
sprintf (u2 + (i * 2), "%02x", u1[i]);
|
||||
|
||||
seed = string (u2);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef OS_WIN32
|
||||
UUID uuid;
|
||||
UuidCreate (&uuid);
|
||||
unsigned char *uuidstring = NULL;
|
||||
UuidToString (&uuid, &uuidstring);
|
||||
if (!uuidstring)
|
||||
throw std::runtime_error ("Unable to read uuid");
|
||||
seed = string ((const char*)uuidstring);
|
||||
|
||||
RpcStringFree (&uuidstring);
|
||||
#endif
|
||||
|
||||
index = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
stringstream ss;
|
||||
ss << seed << (++index);
|
||||
return ss.str();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************************
|
||||
STATIC: Bindable_t::GetObject
|
||||
*****************************/
|
||||
|
||||
Bindable_t *Bindable_t::GetObject (const unsigned long binding)
|
||||
{
|
||||
map<unsigned long, Bindable_t*>::const_iterator i = BindingBag.find (binding);
|
||||
if (i != BindingBag.end())
|
||||
return i->second;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
Bindable_t::Bindable_t
|
||||
**********************/
|
||||
|
||||
Bindable_t::Bindable_t()
|
||||
{
|
||||
Binding = Bindable_t::CreateBinding();
|
||||
BindingBag [Binding] = this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/***********************
|
||||
Bindable_t::~Bindable_t
|
||||
***********************/
|
||||
|
||||
Bindable_t::~Bindable_t()
|
||||
{
|
||||
BindingBag.erase (Binding);
|
||||
}
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*****************************************************************************
|
||||
|
||||
$Id$
|
||||
|
||||
File: binder.h
|
||||
Date: 07Apr06
|
||||
|
||||
Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
||||
Gmail: blackhedd
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of either: 1) the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version; or 2) Ruby's License.
|
||||
|
||||
See the file COPYING for complete licensing information.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef __ObjectBindings__H_
|
||||
#define __ObjectBindings__H_
|
||||
|
||||
|
||||
class Bindable_t
|
||||
{
|
||||
public:
|
||||
static unsigned long CreateBinding();
|
||||
static Bindable_t *GetObject (const unsigned long);
|
||||
static map<unsigned long, Bindable_t*> BindingBag;
|
||||
|
||||
public:
|
||||
Bindable_t();
|
||||
virtual ~Bindable_t();
|
||||
|
||||
const unsigned long GetBinding() {return Binding;}
|
||||
|
||||
private:
|
||||
unsigned long Binding;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // __ObjectBindings__H_
|
||||
|
BIN
vendor/gems/gems/eventmachine-0.12.10/ext/binder.o
vendored
827
vendor/gems/gems/eventmachine-0.12.10/ext/cmain.cpp
vendored
|
@ -1,827 +0,0 @@
|
|||
/*****************************************************************************
|
||||
|
||||
$Id$
|
||||
|
||||
File: cmain.cpp
|
||||
Date: 06Apr06
|
||||
|
||||
Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
||||
Gmail: blackhedd
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of either: 1) the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version; or 2) Ruby's License.
|
||||
|
||||
See the file COPYING for complete licensing information.
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#include "project.h"
|
||||
|
||||
/* 21Sep09: ruby 1.9 defines macros for common i/o functions that point to rb_w32_* implementations.
|
||||
We need to undef the stat to fix a build failure in evma_send_file_data_to_connection.
|
||||
See http://groups.google.com/group/eventmachine/browse_thread/thread/fc60d9bb738ffc71
|
||||
*/
|
||||
#if defined(BUILD_FOR_RUBY) && defined(OS_WIN32)
|
||||
#undef stat
|
||||
#endif
|
||||
|
||||
static EventMachine_t *EventMachine;
|
||||
static int bUseEpoll = 0;
|
||||
static int bUseKqueue = 0;
|
||||
|
||||
extern "C" void ensure_eventmachine (const char *caller = "unknown caller")
|
||||
{
|
||||
if (!EventMachine) {
|
||||
const int err_size = 128;
|
||||
char err_string[err_size];
|
||||
snprintf (err_string, err_size, "eventmachine not initialized: %s", caller);
|
||||
#ifdef BUILD_FOR_RUBY
|
||||
rb_raise(rb_eRuntimeError, "%s", err_string);
|
||||
#else
|
||||
throw std::runtime_error (err_string);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/***********************
|
||||
evma_initialize_library
|
||||
***********************/
|
||||
|
||||
extern "C" void evma_initialize_library (void(*cb)(const unsigned long, int, const char*, const unsigned long))
|
||||
{
|
||||
// Probably a bad idea to mess with the signal mask of a process
|
||||
// we're just being linked into.
|
||||
//InstallSignalHandlers();
|
||||
if (EventMachine)
|
||||
#ifdef BUILD_FOR_RUBY
|
||||
rb_raise(rb_eRuntimeError, "eventmachine already initialized: evma_initialize_library");
|
||||
#else
|
||||
throw std::runtime_error ("eventmachine already initialized: evma_initialize_library");
|
||||
#endif
|
||||
EventMachine = new EventMachine_t (cb);
|
||||
if (bUseEpoll)
|
||||
EventMachine->_UseEpoll();
|
||||
if (bUseKqueue)
|
||||
EventMachine->_UseKqueue();
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
evma_release_library
|
||||
********************/
|
||||
|
||||
extern "C" void evma_release_library()
|
||||
{
|
||||
ensure_eventmachine("evma_release_library");
|
||||
delete EventMachine;
|
||||
EventMachine = NULL;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
evma_run_machine
|
||||
****************/
|
||||
|
||||
extern "C" void evma_run_machine()
|
||||
{
|
||||
ensure_eventmachine("evma_run_machine");
|
||||
EventMachine->Run();
|
||||
}
|
||||
|
||||
|
||||
/**************************
|
||||
evma_install_oneshot_timer
|
||||
**************************/
|
||||
|
||||
extern "C" const unsigned long evma_install_oneshot_timer (int seconds)
|
||||
{
|
||||
ensure_eventmachine("evma_install_oneshot_timer");
|
||||
return EventMachine->InstallOneshotTimer (seconds);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
evma_connect_to_server
|
||||
**********************/
|
||||
|
||||
extern "C" const unsigned long evma_connect_to_server (const char *bind_addr, int bind_port, const char *server, int port)
|
||||
{
|
||||
ensure_eventmachine("evma_connect_to_server");
|
||||
return EventMachine->ConnectToServer (bind_addr, bind_port, server, port);
|
||||
}
|
||||
|
||||
/***************************
|
||||
evma_connect_to_unix_server
|
||||
***************************/
|
||||
|
||||
extern "C" const unsigned long evma_connect_to_unix_server (const char *server)
|
||||
{
|
||||
ensure_eventmachine("evma_connect_to_unix_server");
|
||||
return EventMachine->ConnectToUnixServer (server);
|
||||
}
|
||||
|
||||
/**************
|
||||
evma_attach_fd
|
||||
**************/
|
||||
|
||||
extern "C" const unsigned long evma_attach_fd (int file_descriptor, int watch_mode)
|
||||
{
|
||||
ensure_eventmachine("evma_attach_fd");
|
||||
return EventMachine->AttachFD (file_descriptor, watch_mode ? true : false);
|
||||
}
|
||||
|
||||
/**************
|
||||
evma_detach_fd
|
||||
**************/
|
||||
|
||||
extern "C" int evma_detach_fd (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_detach_fd");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed)
|
||||
return EventMachine->DetachFD (ed);
|
||||
else
|
||||
#ifdef BUILD_FOR_RUBY
|
||||
rb_raise(rb_eRuntimeError, "invalid binding to detach");
|
||||
#else
|
||||
throw std::runtime_error ("invalid binding to detach");
|
||||
#endif
|
||||
}
|
||||
|
||||
/************************
|
||||
evma_get_file_descriptor
|
||||
************************/
|
||||
|
||||
extern "C" int evma_get_file_descriptor (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_get_file_descriptor");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed)
|
||||
return ed->GetSocket();
|
||||
else
|
||||
#ifdef BUILD_FOR_RUBY
|
||||
rb_raise(rb_eRuntimeError, "invalid binding to get_fd");
|
||||
#else
|
||||
throw std::runtime_error ("invalid binding to get_fd");
|
||||
#endif
|
||||
}
|
||||
|
||||
/***********************
|
||||
evma_is_notify_readable
|
||||
***********************/
|
||||
|
||||
extern "C" int evma_is_notify_readable (const unsigned long binding)
|
||||
{
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
return cd->IsNotifyReadable() ? 1 : 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/************************
|
||||
evma_set_notify_readable
|
||||
************************/
|
||||
|
||||
extern "C" void evma_set_notify_readable (const unsigned long binding, int mode)
|
||||
{
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
cd->SetNotifyReadable (mode ? true : false);
|
||||
}
|
||||
|
||||
/***********************
|
||||
evma_is_notify_writable
|
||||
***********************/
|
||||
|
||||
extern "C" int evma_is_notify_writable (const unsigned long binding)
|
||||
{
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
return cd->IsNotifyWritable() ? 1 : 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/************************
|
||||
evma_set_notify_writable
|
||||
************************/
|
||||
|
||||
extern "C" void evma_set_notify_writable (const unsigned long binding, int mode)
|
||||
{
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
cd->SetNotifyWritable (mode ? true : false);
|
||||
}
|
||||
|
||||
/**********
|
||||
evma_pause
|
||||
**********/
|
||||
|
||||
extern "C" int evma_pause (const unsigned long binding)
|
||||
{
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
return cd->Pause() ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********
|
||||
evma_resume
|
||||
***********/
|
||||
|
||||
extern "C" int evma_resume (const unsigned long binding)
|
||||
{
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
return cd->Resume() ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************
|
||||
evma_is_paused
|
||||
**************/
|
||||
|
||||
extern "C" int evma_is_paused (const unsigned long binding)
|
||||
{
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
return cd->IsPaused() ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**********************
|
||||
evma_create_tcp_server
|
||||
**********************/
|
||||
|
||||
extern "C" const unsigned long evma_create_tcp_server (const char *address, int port)
|
||||
{
|
||||
ensure_eventmachine("evma_create_tcp_server");
|
||||
return EventMachine->CreateTcpServer (address, port);
|
||||
}
|
||||
|
||||
/******************************
|
||||
evma_create_unix_domain_server
|
||||
******************************/
|
||||
|
||||
extern "C" const unsigned long evma_create_unix_domain_server (const char *filename)
|
||||
{
|
||||
ensure_eventmachine("evma_create_unix_domain_server");
|
||||
return EventMachine->CreateUnixDomainServer (filename);
|
||||
}
|
||||
|
||||
/*************************
|
||||
evma_open_datagram_socket
|
||||
*************************/
|
||||
|
||||
extern "C" const unsigned long evma_open_datagram_socket (const char *address, int port)
|
||||
{
|
||||
ensure_eventmachine("evma_open_datagram_socket");
|
||||
return EventMachine->OpenDatagramSocket (address, port);
|
||||
}
|
||||
|
||||
/******************
|
||||
evma_open_keyboard
|
||||
******************/
|
||||
|
||||
extern "C" const unsigned long evma_open_keyboard()
|
||||
{
|
||||
ensure_eventmachine("evma_open_keyboard");
|
||||
return EventMachine->OpenKeyboard();
|
||||
}
|
||||
|
||||
/*******************
|
||||
evma_watch_filename
|
||||
*******************/
|
||||
|
||||
extern "C" const unsigned long evma_watch_filename (const char *fname)
|
||||
{
|
||||
ensure_eventmachine("evma_watch_filename");
|
||||
return EventMachine->WatchFile(fname);
|
||||
}
|
||||
|
||||
/*********************
|
||||
evma_unwatch_filename
|
||||
*********************/
|
||||
|
||||
extern "C" void evma_unwatch_filename (const unsigned long sig)
|
||||
{
|
||||
ensure_eventmachine("evma_unwatch_file");
|
||||
EventMachine->UnwatchFile(sig);
|
||||
}
|
||||
|
||||
/**************
|
||||
evma_watch_pid
|
||||
**************/
|
||||
|
||||
extern "C" const unsigned long evma_watch_pid (int pid)
|
||||
{
|
||||
ensure_eventmachine("evma_watch_pid");
|
||||
return EventMachine->WatchPid(pid);
|
||||
}
|
||||
|
||||
/****************
|
||||
evma_unwatch_pid
|
||||
****************/
|
||||
|
||||
extern "C" void evma_unwatch_pid (const unsigned long sig)
|
||||
{
|
||||
ensure_eventmachine("evma_unwatch_pid");
|
||||
EventMachine->UnwatchPid(sig);
|
||||
}
|
||||
|
||||
/****************************
|
||||
evma_send_data_to_connection
|
||||
****************************/
|
||||
|
||||
extern "C" int evma_send_data_to_connection (const unsigned long binding, const char *data, int data_length)
|
||||
{
|
||||
ensure_eventmachine("evma_send_data_to_connection");
|
||||
return ConnectionDescriptor::SendDataToConnection (binding, data, data_length);
|
||||
}
|
||||
|
||||
/******************
|
||||
evma_send_datagram
|
||||
******************/
|
||||
|
||||
extern "C" int evma_send_datagram (const unsigned long binding, const char *data, int data_length, const char *address, int port)
|
||||
{
|
||||
ensure_eventmachine("evma_send_datagram");
|
||||
return DatagramDescriptor::SendDatagram (binding, data, data_length, address, port);
|
||||
}
|
||||
|
||||
|
||||
/*********************
|
||||
evma_close_connection
|
||||
*********************/
|
||||
|
||||
extern "C" void evma_close_connection (const unsigned long binding, int after_writing)
|
||||
{
|
||||
ensure_eventmachine("evma_close_connection");
|
||||
ConnectionDescriptor::CloseConnection (binding, (after_writing ? true : false));
|
||||
}
|
||||
|
||||
/***********************************
|
||||
evma_report_connection_error_status
|
||||
***********************************/
|
||||
|
||||
extern "C" int evma_report_connection_error_status (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_report_connection_error_status");
|
||||
return ConnectionDescriptor::ReportErrorStatus (binding);
|
||||
}
|
||||
|
||||
/********************
|
||||
evma_stop_tcp_server
|
||||
********************/
|
||||
|
||||
extern "C" void evma_stop_tcp_server (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_stop_tcp_server");
|
||||
AcceptorDescriptor::StopAcceptor (binding);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
evma_stop_machine
|
||||
*****************/
|
||||
|
||||
extern "C" void evma_stop_machine()
|
||||
{
|
||||
ensure_eventmachine("evma_stop_machine");
|
||||
EventMachine->ScheduleHalt();
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
evma_start_tls
|
||||
**************/
|
||||
|
||||
extern "C" void evma_start_tls (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_start_tls");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed)
|
||||
ed->StartTls();
|
||||
}
|
||||
|
||||
/******************
|
||||
evma_set_tls_parms
|
||||
******************/
|
||||
|
||||
extern "C" void evma_set_tls_parms (const unsigned long binding, const char *privatekey_filename, const char *certchain_filename, int verify_peer)
|
||||
{
|
||||
ensure_eventmachine("evma_set_tls_parms");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed)
|
||||
ed->SetTlsParms (privatekey_filename, certchain_filename, (verify_peer == 1 ? true : false));
|
||||
}
|
||||
|
||||
/******************
|
||||
evma_get_peer_cert
|
||||
******************/
|
||||
|
||||
#ifdef WITH_SSL
|
||||
extern "C" X509 *evma_get_peer_cert (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_get_peer_cert");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed)
|
||||
return ed->GetPeerCert();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************
|
||||
evma_accept_ssl_peer
|
||||
********************/
|
||||
|
||||
#ifdef WITH_SSL
|
||||
extern "C" void evma_accept_ssl_peer (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_accept_ssl_peer");
|
||||
ConnectionDescriptor *cd = dynamic_cast <ConnectionDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (cd)
|
||||
cd->AcceptSslPeer();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*****************
|
||||
evma_get_peername
|
||||
*****************/
|
||||
|
||||
extern "C" int evma_get_peername (const unsigned long binding, struct sockaddr *sa)
|
||||
{
|
||||
ensure_eventmachine("evma_get_peername");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed) {
|
||||
return ed->GetPeername (sa) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************
|
||||
evma_get_sockname
|
||||
*****************/
|
||||
|
||||
extern "C" int evma_get_sockname (const unsigned long binding, struct sockaddr *sa)
|
||||
{
|
||||
ensure_eventmachine("evma_get_sockname");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed) {
|
||||
return ed->GetSockname (sa) ? 1 : 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************
|
||||
evma_get_subprocess_pid
|
||||
***********************/
|
||||
|
||||
extern "C" int evma_get_subprocess_pid (const unsigned long binding, pid_t *pid)
|
||||
{
|
||||
ensure_eventmachine("evma_get_subprocess_pid");
|
||||
#ifdef OS_UNIX
|
||||
PipeDescriptor *pd = dynamic_cast <PipeDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (pd) {
|
||||
return pd->GetSubprocessPid (pid) ? 1 : 0;
|
||||
}
|
||||
else if (pid && EventMachine->SubprocessPid) {
|
||||
*pid = EventMachine->SubprocessPid;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**************************
|
||||
evma_get_subprocess_status
|
||||
**************************/
|
||||
|
||||
extern "C" int evma_get_subprocess_status (const unsigned long binding, int *status)
|
||||
{
|
||||
ensure_eventmachine("evma_get_subprocess_status");
|
||||
if (status) {
|
||||
*status = EventMachine->SubprocessExitStatus;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************
|
||||
evma_get_connection_count
|
||||
*************************/
|
||||
|
||||
extern "C" int evma_get_connection_count()
|
||||
{
|
||||
ensure_eventmachine("evma_get_connection_count");
|
||||
return EventMachine->GetConnectionCount();
|
||||
}
|
||||
|
||||
/*********************
|
||||
evma_signal_loopbreak
|
||||
*********************/
|
||||
|
||||
extern "C" void evma_signal_loopbreak()
|
||||
{
|
||||
ensure_eventmachine("evma_signal_loopbreak");
|
||||
EventMachine->SignalLoopBreaker();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/****************
|
||||
evma__write_file
|
||||
****************/
|
||||
|
||||
extern "C" const unsigned long evma__write_file (const char *filename)
|
||||
{
|
||||
ensure_eventmachine("evma__write_file");
|
||||
return EventMachine->_OpenFileForWriting (filename);
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
evma_get_comm_inactivity_timeout
|
||||
********************************/
|
||||
|
||||
extern "C" float evma_get_comm_inactivity_timeout (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_get_comm_inactivity_timeout");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed) {
|
||||
return ed->GetCommInactivityTimeout();
|
||||
}
|
||||
else
|
||||
return 0.0; //Perhaps this should be an exception. Access to an unknown binding.
|
||||
}
|
||||
|
||||
/********************************
|
||||
evma_set_comm_inactivity_timeout
|
||||
********************************/
|
||||
|
||||
extern "C" int evma_set_comm_inactivity_timeout (const unsigned long binding, float value)
|
||||
{
|
||||
ensure_eventmachine("evma_set_comm_inactivity_timeout");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed) {
|
||||
return ed->SetCommInactivityTimeout (value);
|
||||
}
|
||||
else
|
||||
return 0; //Perhaps this should be an exception. Access to an unknown binding.
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
evma_get_pending_connect_timeout
|
||||
********************************/
|
||||
|
||||
extern "C" float evma_get_pending_connect_timeout (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_get_pending_connect_timeout");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed) {
|
||||
return ed->GetPendingConnectTimeout();
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
evma_set_pending_connect_timeout
|
||||
********************************/
|
||||
|
||||
extern "C" int evma_set_pending_connect_timeout (const unsigned long binding, float value)
|
||||
{
|
||||
ensure_eventmachine("evma_set_pending_connect_timeout");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
if (ed) {
|
||||
return ed->SetPendingConnectTimeout (value);
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
evma_set_timer_quantum
|
||||
**********************/
|
||||
|
||||
extern "C" void evma_set_timer_quantum (int interval)
|
||||
{
|
||||
ensure_eventmachine("evma_set_timer_quantum");
|
||||
EventMachine->SetTimerQuantum (interval);
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
evma_get_max_timer_count
|
||||
************************/
|
||||
|
||||
extern "C" int evma_get_max_timer_count()
|
||||
{
|
||||
return EventMachine_t::GetMaxTimerCount();
|
||||
}
|
||||
|
||||
|
||||
/************************
|
||||
evma_set_max_timer_count
|
||||
************************/
|
||||
|
||||
extern "C" void evma_set_max_timer_count (int ct)
|
||||
{
|
||||
// This may only be called if the reactor is not running.
|
||||
|
||||
if (EventMachine)
|
||||
#ifdef BUILD_FOR_RUBY
|
||||
rb_raise(rb_eRuntimeError, "eventmachine already initialized: evma_set_max_timer_count");
|
||||
#else
|
||||
throw std::runtime_error ("eventmachine already initialized: evma_set_max_timer_count");
|
||||
#endif
|
||||
EventMachine_t::SetMaxTimerCount (ct);
|
||||
}
|
||||
|
||||
/******************
|
||||
evma_setuid_string
|
||||
******************/
|
||||
|
||||
extern "C" void evma_setuid_string (const char *username)
|
||||
{
|
||||
// We do NOT need to be running an EM instance because this method is static.
|
||||
EventMachine_t::SetuidString (username);
|
||||
}
|
||||
|
||||
|
||||
/**********
|
||||
evma_popen
|
||||
**********/
|
||||
|
||||
extern "C" const unsigned long evma_popen (char * const*cmd_strings)
|
||||
{
|
||||
ensure_eventmachine("evma_popen");
|
||||
return EventMachine->Socketpair (cmd_strings);
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
evma_get_outbound_data_size
|
||||
***************************/
|
||||
|
||||
extern "C" int evma_get_outbound_data_size (const unsigned long binding)
|
||||
{
|
||||
ensure_eventmachine("evma_get_outbound_data_size");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding));
|
||||
return ed ? ed->GetOutboundDataSize() : 0;
|
||||
}
|
||||
|
||||
|
||||
/**************
|
||||
evma_set_epoll
|
||||
**************/
|
||||
|
||||
extern "C" void evma_set_epoll (int use)
|
||||
{
|
||||
bUseEpoll = !!use;
|
||||
}
|
||||
|
||||
/***************
|
||||
evma_set_kqueue
|
||||
***************/
|
||||
|
||||
extern "C" void evma_set_kqueue (int use)
|
||||
{
|
||||
bUseKqueue = !!use;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
evma_set_rlimit_nofile
|
||||
**********************/
|
||||
|
||||
extern "C" int evma_set_rlimit_nofile (int nofiles)
|
||||
{
|
||||
return EventMachine_t::SetRlimitNofile (nofiles);
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
evma_send_file_data_to_connection
|
||||
*********************************/
|
||||
|
||||
extern "C" int evma_send_file_data_to_connection (const unsigned long binding, const char *filename)
|
||||
{
|
||||
/* This is a sugaring over send_data_to_connection that reads a file into a
|
||||
* locally-allocated buffer, and sends the file data to the remote peer.
|
||||
* Return the number of bytes written to the caller.
|
||||
* TODO, needs to impose a limit on the file size. This is intended only for
|
||||
* small files. (I don't know, maybe 8K or less.) For larger files, use interleaved
|
||||
* I/O to avoid slowing the rest of the system down.
|
||||
* TODO: we should return a code rather than barf, in case of file-not-found.
|
||||
* TODO, does this compile on Windows?
|
||||
* TODO, given that we want this to work only with small files, how about allocating
|
||||
* the buffer on the stack rather than the heap?
|
||||
*
|
||||
* Modified 25Jul07. This now returns -1 on file-too-large; 0 for success, and a positive
|
||||
* errno in case of other errors.
|
||||
*
|
||||
* Contributed by Kirk Haines.
|
||||
*/
|
||||
|
||||
char data[32*1024];
|
||||
int r;
|
||||
|
||||
ensure_eventmachine("evma_send_file_data_to_connection");
|
||||
|
||||
int Fd = open (filename, O_RDONLY);
|
||||
|
||||
if (Fd < 0)
|
||||
return errno;
|
||||
// From here on, all early returns MUST close Fd.
|
||||
|
||||
struct stat st;
|
||||
if (fstat (Fd, &st)) {
|
||||
int e = errno;
|
||||
close (Fd);
|
||||
return e;
|
||||
}
|
||||
|
||||
off_t filesize = st.st_size;
|
||||
if (filesize <= 0) {
|
||||
close (Fd);
|
||||
return 0;
|
||||
}
|
||||
else if (filesize > (off_t) sizeof(data)) {
|
||||
close (Fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
r = read (Fd, data, filesize);
|
||||
if (r != filesize) {
|
||||
int e = errno;
|
||||
close (Fd);
|
||||
return e;
|
||||
}
|
||||
evma_send_data_to_connection (binding, data, r);
|
||||
close (Fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************
|
||||
evma_start_proxy
|
||||
*****************/
|
||||
|
||||
extern "C" void evma_start_proxy (const unsigned long from, const unsigned long to, const unsigned long bufsize)
|
||||
{
|
||||
ensure_eventmachine("evma_start_proxy");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (from));
|
||||
if (ed)
|
||||
ed->StartProxy(to, bufsize);
|
||||
}
|
||||
|
||||
|
||||
/***************
|
||||
evma_stop_proxy
|
||||
****************/
|
||||
|
||||
extern "C" void evma_stop_proxy (const unsigned long from)
|
||||
{
|
||||
ensure_eventmachine("evma_stop_proxy");
|
||||
EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (from));
|
||||
if (ed)
|
||||
ed->StopProxy();
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
evma_get_heartbeat_interval
|
||||
****************************/
|
||||
|
||||
extern "C" float evma_get_heartbeat_interval()
|
||||
{
|
||||
ensure_eventmachine("evma_get_heartbeat_interval");
|
||||
return EventMachine->GetHeartbeatInterval();
|
||||
}
|
||||
|
||||
|
||||
/***************************
|
||||
evma_set_heartbeat_interval
|
||||
****************************/
|
||||
|
||||
extern "C" int evma_set_heartbeat_interval(float interval)
|
||||
{
|
||||
ensure_eventmachine("evma_set_heartbeat_interval");
|
||||
return EventMachine->SetHeartbeatInterval(interval);
|
||||
}
|