rsence 2.0.0.6.pre → 2.0.0.7.pre

Sign up to get free protection for your applications and to get access to all the features.
data/INSTALL.rdoc CHANGED
@@ -7,6 +7,7 @@ If you already have a working ruby environment and know what to do, the easiest
7
7
 
8
8
  gem install rsence --pre
9
9
 
10
+
10
11
  Otherwise, follow these instructions:
11
12
 
12
13
 
@@ -30,7 +31,6 @@ This step applies only to Mac OS X 10.4 Tiger and 10.5 Leopard
30
31
 
31
32
  sudo port install ruby +thread_hooks
32
33
  sudo port install rb-rubygems
33
- sudo port install sqlite3-ruby
34
34
 
35
35
  ==== 1.1.2 Mac OS X 10.6
36
36
 
@@ -47,35 +47,49 @@ This step applies only to Debian, Ubuntu and similar Linux distributions.
47
47
 
48
48
  * Install these packages:
49
49
 
50
- sudo apt-get install build-essential ruby-full sqlite3-ruby rubygems rake
50
+ sudo apt-get install build-essential ruby-full rubygems rake
51
51
 
52
52
 
53
53
  === 1.3. Microsoft Windows
54
54
 
55
- Minimal Windows compatibility (Windows has no support for background processes and other UNIX-like features. It works fine for development, but it's not a suggested environment for production.
56
- Windows compatibility is tested on Windows XP SP3.
57
-
58
- Install ruby 1.8.7:
59
- * Download *ruby 1.8.7* (or newer) from http://rubyinstaller.org/download.html
60
- * Follow included instructions
61
- * Install the *Development Kit* (same page)
62
-
63
- Install rmagick first from:
64
- * Download *rmagick-win32* from http://rubyforge.org/projects/rmagick/
65
- * Follow included instructions
66
-
67
- Install the *sqlite3.dll* from:
68
- * Download *sqlitedll* from http://www.sqlite.org/download.html
69
- * Extract *sqlite3.dll* into C:\\ruby\\bin or other directory in PATH
70
-
71
- In the command prompt run:
72
- gem install rsence-deps
55
+ RSence works just fine on Windows too, with a few limitations.
56
+ Windows compatibility has been officially tested on Windows XP SP3 and Windows 7 (64 bit).
57
+
58
+ ==== 1.3.1. Install ruby 1.8.7:
59
+ * Download Ruby 1.8.7-p249 (RC2) from http://rubyinstaller.org/download.html
60
+ * Run the downloaded exe to install ruby
61
+ * In the installation and destination prompt, check these options:
62
+ * [x] Add Ruby executables to your PATH
63
+ * [x] Associate .rb and .rbw files with this Ruby installation
64
+ * Download and Install the Development Kit from http://rubyinstaller.org/download.html
65
+ * Extract the included directories into the directory where you installed ruby.
66
+ * It's C:\ruby by default.
67
+
68
+ ==== 1.3.2. Install RSence
69
+ * In the command prompt, run:
70
+ gem update --system
71
+ gem install rsence --pre
72
+ rsence help
73
+
74
+ ==== 1.3.3. Create RSence environment
75
+
76
+ This assumes you have \my_projects directory.
77
+ Also, the 'my_project' project directory is just for illustration purposes.
78
+ Use something else instead of those.
79
+
80
+ * In the command prompt, run:
81
+ cd \my_projects
82
+ rsence initenv my_project
83
+ * Answer the quetions
84
+ * In the command prompt, run:
85
+ rsence run my_project
86
+ * Open your web browser in the address as configured.
87
+ * If the address is 0.0.0.0, ether 127.0.0.1 instead.
88
+
89
+ ==== 1.3.4. Windows limitations
90
+ If you install the sqlite dll and the sqlite3-ruby gem, you'll gain persistent sessions and the "Warning: Session database is not available. Can't use persistent sessions" message will disappear when starting up rsence. It's not, however depended on in the default install, because it's not strictly required and makes the first installation much easier.
91
+ Backgrounding is not yet implemented, because POSIX signals are not fully implemented in windows and backgrounding requires some windows service hooks.
73
92
 
74
- NOTICE:
75
- * Configure http with either *mongrel* or *webrick*
76
- * Ensure the session database string doesn't include the "C:" -part (when using sqlite)
77
- * Only the *run* (foreground) mode is supported; no start, stop, restart etc commands because backgrounding isn't possible on Windows unless configured as a Service
78
- * Prefix all commands with ruby
79
93
 
80
94
  === 1.99. Other UNIX / Linux systems:
81
95
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.0.6.pre
1
+ 2.0.0.7.pre
@@ -59,9 +59,6 @@
59
59
  #
60
60
  # Rack handler to use, defaults to thin
61
61
  :rack_require: mongrel
62
- #
63
- # The rack handler; entered automatically.
64
- :rack_handler: null
65
62
  #
66
63
  # When enabled, sets http cache headers
67
64
  # to cache content as long as possible.
data/lib/conf/default.rb CHANGED
@@ -13,8 +13,16 @@ require 'rack'
13
13
  require 'yaml'
14
14
 
15
15
  if RUBY_VERSION.to_f >= 1.9
16
- # Encoding.default_external = Encoding::BINARY
17
- # Encoding.default_internal = Encoding::BINARY
16
+ # --
17
+ # Ruby 1.9 encoding defaults.
18
+ # This is clearly not enough but a good start for fixing the encoding madness.
19
+ # ++
20
+ Encoding.default_external = Encoding::BINARY
21
+ Encoding.default_internal = Encoding::BINARY
22
+ # --
23
+ # Ruby 1.9 doesn't have String#each anymore.
24
+ # This is a backwards-compatible work-around.
25
+ # ++
18
26
  class String
19
27
  def each
20
28
  self.split($/).each { |e| yield e }
@@ -22,15 +30,10 @@ if RUBY_VERSION.to_f >= 1.9
22
30
  end
23
31
  end
24
32
 
25
- # Legacy:
26
- LIB_PATHS = []
27
- PIDPATH = File.join(SERVER_PATH,'var','run')
28
- LOGPATH = File.join(SERVER_PATH,'var','log')
29
- def load_legacy( local_config_file_path )
30
- require local_config_file_path[0..-4]
31
- end
32
-
33
+ # Configuration handles config files and such.
33
34
  class Configuration
35
+
36
+ # Method for combining two arrays
34
37
  def array_merge( target, source )
35
38
  source.each do |item|
36
39
  unless target.include?(item)
@@ -48,6 +51,8 @@ class Configuration
48
51
  end
49
52
  end
50
53
  end
54
+
55
+ # Method for combining two hashes.
51
56
  def hash_merge( target, source )
52
57
  source.each do |key,item|
53
58
  if not target.has_key?key or target[key] != item
@@ -63,60 +68,57 @@ class Configuration
63
68
  end
64
69
  end
65
70
  end
66
- def wizard
67
- puts "Please answer the following questions, blank lines equal to the default in brackets:"
68
- require 'conf/wizard'
69
- if File.directory?( File.join( Dir.pwd, 'conf' ) )
70
- wizard_conf_file = File.join( Dir.pwd, 'conf', 'local_conf.yaml' )
71
- else
72
- wizard_conf_file = File.join( SERVER_PATH, 'conf', 'local_conf.yaml' )
73
- end
74
- wizard_config_data = ConfigWizard.new(config).run( wizard_conf_file )
75
- config.merge!( wizard_config_data )
76
- end
71
+
72
+ # The args structure comes from RSence::ARGVParser
73
+ # The dont_expand_path is for special cases, when
74
+ # Configuration is used without running RSence.
77
75
  def initialize( args, dont_expand_path=false )
76
+
78
77
  ## Paths for log and pid files
79
78
  pidpath = File.join( args[:env_path], 'run' )
80
79
  logpath = File.join( args[:env_path], 'log' )
81
80
 
81
+ # The default configuration path, this one is distributed with the system.
82
82
  yaml_conf_path = File.join( SERVER_PATH, 'conf', 'default_conf.yaml' )
83
83
 
84
+ # Parses the default configuration from yaml first.
85
+ # This is used as the basis for overriding the defaults in various other config files.
86
+ config = YAML.load( File.read( yaml_conf_path ) )
87
+
88
+ # The default strings for various messages, this one is distributed with the system.
84
89
  yaml_strings_path = File.join( SERVER_PATH, 'conf', 'default_strings.yaml' )
85
90
  strings = YAML.load( File.read( yaml_strings_path ) )
86
91
 
87
- ## Global configuration hash
88
- config = YAML.load( File.read( yaml_conf_path ) )
92
+ # Transporter-specific strings are set.
89
93
  config[:transporter_conf][:messages] = strings[:messages][:transporter]
90
94
 
95
+ # Makes the distribution 'js' directory containing the client core the
96
+ # first client package source directory.
91
97
  config[:client_pkg][:src_dirs].unshift( File.join( SERVER_PATH, 'js' ) )
92
98
 
99
+ # The distributed standard plugins are in this directory.
93
100
  default_plugins_path = File.join( SERVER_PATH, 'plugins' )
94
101
  unless config[:plugin_paths].include? default_plugins_path
95
102
  config[:plugin_paths].push( default_plugins_path )
96
103
  end
97
104
 
98
- ## Paths of server libraries
99
- lib_paths = [
100
- ## already included in launch.rb; override this one in local config, if needed
101
- #File.join( SERVER_PATH, 'lib' )
102
- ]
105
+ # Paths to add to $LOAD_PATH after all configuration files are read.
106
+ lib_paths = []
103
107
 
104
- ## Create default local configuratation override file, if it does not exist:
108
+ # List of configuration files to look for.
105
109
  local_config_file_paths = [
106
110
  File.join(SERVER_PATH,'conf','local_conf.yaml'),
107
111
  '/etc/rsence/config.yaml',
108
112
  File.expand_path('~/.rsence/config.yaml'),
109
- File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.yaml' ),
110
- # File.join( Dir.pwd, 'conf', 'local_conf.yaml' ),
111
- File.join(SERVER_PATH,'conf','local_conf.rb'),
112
- # File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.rb' ),
113
- # File.join( Dir.pwd, 'conf', 'local_conf.rb' )
113
+ File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.yaml' )
114
114
  ]
115
115
 
116
+ # Add the additional config files optionally specified in ARGVParser
116
117
  args[:conf_files].each do |conf_file|
117
118
  local_config_file_paths.push( conf_file )
118
119
  end
119
120
 
121
+ # Loads the configuration files
120
122
  local_config_file_paths.each do |local_config_file_path|
121
123
  if File.exists? local_config_file_path and File.file? local_config_file_path
122
124
  if local_config_file_path.end_with? '.yaml'
@@ -127,29 +129,24 @@ class Configuration
127
129
  next
128
130
  end
129
131
  hash_merge( config, local_conf )
130
- elsif local_config_file_path.end_with? '.rb'
131
- warn "WARNING: '.rb' configuration files are deprecated!"
132
- # Legacy work-arounds
133
- prev_pidpath = PIDPATH
134
- prev_logpath = LOGPATH
135
- # /Legacy work-arounds
136
- load_legacy( local_config_file_path )
137
- # Legacy work-arounds
138
- pidpath = PIDPATH if PIDPATH != prev_pidpath
139
- logpath = LOGPATH if LOGPATH != prev_logpath
140
- # /Legacy work-arounds
141
132
  else
142
- warn "Only Yaml and Ruby configuration files are allowed at this time."
133
+ warn "Only Yaml configuration files are supported."
143
134
  end
144
135
  end
145
136
  end
146
137
 
138
+ # Adds the plugins directory of the environment
139
+ # to the configuration automatically
147
140
  env_plugins_path = File.expand_path( 'plugins', args[:env_path] )
148
141
  unless config[:plugin_paths].include? env_plugins_path
149
142
  config[:plugin_paths].push( env_plugins_path )
150
143
  end
144
+
145
+ # At this point, configuration files are read and ready.
146
+
151
147
  puts "plugin paths: #{config[:plugin_paths].inspect}" if args[:debug]
152
148
 
149
+ # Override configuration options with command-line-options.
153
150
  config[:trace] = true if args[:trace_js]
154
151
  config[:debug_mode] = true if args[:debug]
155
152
  config[:http_server][:latency] = args[:latency]
@@ -158,23 +155,26 @@ class Configuration
158
155
  config[:http_server][:rack_require] = args[:server] if args[:server]
159
156
  config[:session_conf][:reset_sessions] = true if args[:reset_ses]
160
157
 
158
+ config[:client_pkg][:no_obfuscation] = true if args[:client_pkg_no_obfuscation]
159
+ config[:client_pkg][:no_whitespace_removal] = true if args[:client_pkg_no_whitespace_removal]
160
+
161
+ # Sets the default pid and log paths used by the HTTPDaemon
161
162
  config[:daemon][:pid_fn] = File.join(pidpath, "rsence.pid") unless config[:daemon].has_key?(:pid_fn)
162
163
  config[:daemon][:log_fn] = File.join(logpath, "rsence") unless config[:daemon].has_key?(:log_fn)
163
164
 
165
+ # Check database path for sqlite databases.
164
166
  if config[:database][:ses_db].start_with?('sqlite://') and not dont_expand_path
165
167
  db_url = File.expand_path( config[:database][:ses_db].split('sqlite://')[1], args[:env_path] )
166
168
  config[:database][:ses_db] = "sqlite://#{db_url}"
167
169
  end
168
170
 
169
- ## Broker configuration
171
+ # Sets the various standard url prefixes:
170
172
  [ ## POST-requests
171
173
  # broker_key # default_uri
172
174
  # The default responder for transporter requests.
173
175
  [ :x, File.join(config[:base_url],'x') ],
174
176
  # The default responder for cookie-enabled "handshake" transporter requests
175
177
  [ :hello, File.join(config[:base_url],'hello') ],
176
- # The default responder for SOAP -requests
177
- [ :soap, File.join(config[:base_url],'SOAP') ],
178
178
  # The default responder for file uploads
179
179
  [ :u, File.join(config[:base_url],'U') ],
180
180
 
@@ -199,30 +199,29 @@ class Configuration
199
199
  config[:broker_urls][broker_key] = default_uri
200
200
  end
201
201
  end
202
- # if RUBY_VERSION.to_f >= 1.9
203
- # config[:no_gzip] = true
204
- # end
202
+
203
+ if RUBY_VERSION.to_f >= 1.9
204
+ # The encodings mess up compression when using ruby1.9
205
+ warn "Disabling gzip support for ruby 1.9" if args[:debug]
206
+ config[:no_gzip] = true
207
+ end
208
+
205
209
  # The default address of the index_html plugin
206
210
  unless config[:index_html].has_key?(:respond_address)
207
211
  config[:index_html][:respond_address] = File.join(config[:base_url])
208
212
  end
209
213
 
210
- config[:client_pkg][:no_obfuscation] = true if args[:client_pkg_no_obfuscation]
211
- config[:client_pkg][:no_whitespace_removal] = true if args[:client_pkg_no_whitespace_removal]
212
-
213
214
  ## Uses the lib paths as search paths
215
+ lib_paths.merge( config[:lib_paths] ) if config.has_key?(:lib_paths)
214
216
  lib_paths.each do |lib_path|
215
217
  $LOAD_PATH << lib_path
216
218
  end
217
219
 
218
- ## Legacy:
219
- LIB_PATHS.each do |lib_path|
220
- $LOAD_PATH << lib_path
221
- end
222
-
223
220
  @config = config
224
221
  end
222
+
225
223
  attr_reader :config
224
+
226
225
  end
227
226
 
228
227
 
data/lib/daemon/daemon.rb CHANGED
@@ -10,29 +10,6 @@
10
10
 
11
11
  # Use rubygems to load rack
12
12
  require 'rubygems'
13
- require 'rack'
14
-
15
- # Loads the selected web-server (default is 'thin')
16
- require RSence.config[:http_server][:rack_require]
17
-
18
- # Methods that return rack the selected handler
19
- def rack_webrick_handler; Rack::Handler::WEBrick; end
20
- def rack_ebb_handler; Rack::Handler::Ebb; end
21
- def rack_thin_handler; Rack::Handler::Thin; end
22
- def rack_mongrel_handler; Rack::Handler::Mongrel; end
23
- def rack_unicorn_handler; Rack::Handler::Unicorn; end
24
- def rack_rainbows_handler; Rack::Handler::Rainbows; end
25
-
26
- # Selects the handler for Rack
27
- RSence.config[:http_server][:rack_handler] = self.method({
28
- 'fuzed' => :rack_fuzed_handler,
29
- 'webrick' => :rack_webrick_handler,
30
- 'ebb' => :rack_ebb_handler,
31
- 'thin' => :rack_thin_handler,
32
- 'mongrel' => :rack_mongrel_handler,
33
- 'unicorn' => :rack_unicorn_handler,
34
- 'rainbows' => :rack_rainbows_handler
35
- }[RSence.config[:http_server][:rack_require]]).call
36
13
 
37
14
  # Transporter is the top-level handler for calls coming from the javascript COMM.Transporter.
38
15
  require 'transporter/transporter'
@@ -42,327 +19,339 @@ require 'http/broker'
42
19
 
43
20
 
44
21
  module ::RSence
22
+
23
+ @@launch_pid = Process.pid
24
+
25
+ # Returns the pid of the process when starting up.
26
+ # PID is different for the forked child process(es)
27
+ def self.launch_pid
28
+ return @@launch_pid
29
+ end
45
30
 
46
- @@launch_pid = Process.pid
47
- def self.launch_pid
48
- return @@launch_pid
49
- end
50
-
51
- # The Controller module handles the damonizing
52
- # operations of the process referred to as +daemon+
53
- module Daemon
54
-
55
- # Writes the process id to disk, the pid_fn method of the daemon contains
56
- # the name of the pid file.
57
- def self.write_pid( daemon, pid )
58
- File.open( daemon.pid_fn, 'w' ) do |pidfile|
59
- pidfile.write( pid )
31
+ # The Controller module handles the damonizing
32
+ # operations of the process referred to as +daemon+
33
+ module Daemon
34
+
35
+ # Writes the process id to disk, the pid_fn method of the daemon contains
36
+ # the name of the pid file.
37
+ def self.write_pid( daemon, pid )
38
+ File.open( daemon.pid_fn, 'w' ) do |pidfile|
39
+ pidfile.write( pid )
40
+ end
60
41
  end
61
- end
62
42
 
63
- # Reads the process id from disk, the pid_fn method of the daemon contains
64
- # the name of the pid file. Returns nil on errors.
65
- def self.read_pid( daemon )
66
- File.read( daemon.pid_fn ).to_i rescue nil
67
- end
43
+ # Reads the process id from disk, the pid_fn method of the daemon contains
44
+ # the name of the pid file. Returns nil on errors.
45
+ def self.read_pid( daemon )
46
+ File.read( daemon.pid_fn ).to_i rescue nil
47
+ end
68
48
 
69
- def self.responds?( daemon )
70
- wait_signal_response( daemon, 'USR2' )
71
- end
49
+ def self.responds?( daemon )
50
+ wait_signal_response( daemon, 'USR2' )
51
+ end
72
52
 
73
- # Reads the pid file and calls the process.
74
- # Returns true if the process responds, false otherwise (no process)
75
- def self.status( daemon )
76
- pid = read_pid( daemon )
77
- return nil if not pid
78
- return responds?( daemon )
79
- end
53
+ # Reads the pid file and calls the process.
54
+ # Returns true if the process responds, false otherwise (no process)
55
+ def self.status( daemon )
56
+ pid = read_pid( daemon )
57
+ return nil if not pid
58
+ return responds?( daemon )
59
+ end
80
60
 
81
- # Redirects standard input and errors to the log files
82
- def self.start_logging( daemon )
83
- outpath = "#{daemon.log_fn}.stdout"
84
- errpath = "#{daemon.log_fn}.stderr"
85
- STDOUT.reopen( outpath, (File.exist?( outpath ) ? 'a' : 'w') )
86
- STDOUT.sync = true
87
- STDERR.reopen( errpath, (File.exist?( errpath ) ? 'a' : 'w') )
88
- STDERR.sync = true
89
- end
61
+ # Redirects standard input and errors to the log files
62
+ def self.start_logging( daemon )
63
+ outpath = "#{daemon.log_fn}.stdout"
64
+ errpath = "#{daemon.log_fn}.stderr"
65
+ STDOUT.reopen( outpath, (File.exist?( outpath ) ? 'a' : 'w') )
66
+ STDOUT.sync = true
67
+ STDERR.reopen( errpath, (File.exist?( errpath ) ? 'a' : 'w') )
68
+ STDERR.sync = true
69
+ end
90
70
 
91
- def self.write_signal_response( daemon, signal )
92
- pid = Process.pid.to_s
93
- pid_fn = daemon.pid_fn
94
- RSence::SIGComm.write_signal_response( pid, pid_fn, signal )
95
- end
71
+ # Writes a signal response file containing the pid.
72
+ def self.write_signal_response( daemon, signal )
73
+ pid = Process.pid.to_s
74
+ pid_fn = daemon.pid_fn
75
+ RSence::SIGComm.write_signal_response( pid, pid_fn, signal )
76
+ end
96
77
 
97
- def self.delete_signal_response( daemon, signal )
98
- pid_fn = daemon.pid_fn
99
- RSence::SIGComm.delete_signal_response( pid_fn )
100
- end
78
+ # Removes a signal response file.
79
+ def self.delete_signal_response( daemon, signal )
80
+ pid_fn = daemon.pid_fn
81
+ RSence::SIGComm.delete_signal_response( pid_fn )
82
+ end
101
83
 
102
- def self.wait_signal_response( daemon, signal, timeout = 10,
103
- debug_pre = false, debug_suf = false, sleep_secs = 0.2 )
104
- pid = read_pid( daemon )
105
- pid_fn = daemon.pid_fn
106
- return RSence::SIGComm.wait_signal_response( pid, pid_fn, signal, timeout, debug_pre, debug_suf, sleep_secs )
107
- end
84
+ # Waits for a signal response.
85
+ def self.wait_signal_response( daemon, signal, timeout = 10,
86
+ debug_pre = false, debug_suf = false, sleep_secs = 0.2 )
87
+ pid = read_pid( daemon )
88
+ pid_fn = daemon.pid_fn
89
+ return RSence::SIGComm.wait_signal_response( pid, pid_fn, signal, timeout, debug_pre, debug_suf, sleep_secs )
90
+ end
108
91
 
109
- def self.trap_windows_signals( daemon )
110
- ['INT'].each do | signal |
111
- Signal.trap( signal ) do
112
- puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
113
- daemon.usr1
114
- daemon.stop
115
- puts "Shutdown complete."
116
- exit
92
+ # Signal trapping for windows.
93
+ # The only supported POSIX signal trappable seems to be INT (CTRL-C).
94
+ def self.trap_windows_signals( daemon )
95
+ ['INT'].each do | signal |
96
+ Signal.trap( signal ) do
97
+ puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
98
+ daemon.usr1
99
+ daemon.stop
100
+ puts "Shutdown complete."
101
+ exit
102
+ end
117
103
  end
118
104
  end
119
- end
120
105
 
121
- # Traps common kill signals
122
- def self.trap_signals( daemon )
106
+ # Traps common POSIX signals
107
+ def self.trap_signals( daemon )
123
108
 
124
- # Triggered with 'kill -USR1 `cat rsence.pid`'
125
- Signal.trap( 'USR1' ) do
126
- daemon.usr1
127
- write_signal_response( daemon, 'USR1' )
128
- end
129
- Signal.trap('USR2') do
130
- daemon.usr2
131
- write_signal_response( daemon, 'USR2' )
132
- end
133
- ['INT', 'TERM', 'KILL'].each do | signal |
134
- Signal.trap( signal ) do
135
- puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
109
+ # Triggered with 'kill -USR1 `cat rsence.pid`'
110
+ Signal.trap( 'USR1' ) do
136
111
  daemon.usr1
112
+ write_signal_response( daemon, 'USR1' )
113
+ end
114
+ Signal.trap('USR2') do
115
+ daemon.usr2
116
+ write_signal_response( daemon, 'USR2' )
117
+ end
118
+ ['INT', 'TERM', 'KILL'].each do | signal |
119
+ Signal.trap( signal ) do
120
+ puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
121
+ daemon.usr1
122
+ daemon.stop
123
+ delete_stale_pids( daemon )
124
+ write_signal_response( daemon, signal )
125
+ puts "Shutdown complete."
126
+ exit
127
+ end
128
+ end
129
+ Signal.trap('HUP') do
137
130
  daemon.stop
138
- delete_stale_pids( daemon )
139
- write_signal_response( daemon, signal )
140
- puts "Shutdown complete."
141
- exit
131
+ daemon.start
142
132
  end
143
133
  end
144
- Signal.trap('HUP') do
145
- daemon.stop
146
- daemon.start
147
- end
148
- end
149
134
 
150
- def self.delete_stale_pids( daemon )
151
- ( pid_fn_path, pid_fn_name ) = File.split( daemon.pid_fn )
152
- Dir.entries( pid_fn_path ).each do | item_fn |
153
- item_path = File.join( pid_fn_path, item_fn )
154
- if item_fn.start_with?( pid_fn_name ) and File.file?( item_path )
155
- puts "Stale pid file (#{item_fn}), removing.." if RSence.args[:verbose]
156
- File.delete( item_path )
135
+ # Removes all pid files that were left around if a process died unexpectedly.
136
+ def self.delete_stale_pids( daemon )
137
+ ( pid_fn_path, pid_fn_name ) = File.split( daemon.pid_fn )
138
+ Dir.entries( pid_fn_path ).each do | item_fn |
139
+ item_path = File.join( pid_fn_path, item_fn )
140
+ if item_fn.start_with?( pid_fn_name ) and File.file?( item_path )
141
+ puts "Stale pid file (#{item_fn}), removing.." if RSence.args[:verbose]
142
+ File.delete( item_path )
143
+ end
157
144
  end
158
145
  end
159
- end
160
146
 
161
- def self.init_pid( daemon )
162
- if RSence.pid_support?
163
- is_running = status( daemon )
164
- if is_running
165
- puts "RSence is already running."
166
- puts "Stop the existing process first: see 'rsence help stop'"
167
- if RSence.launch_pid != Process.pid
168
- Process.kill( 'INT', RSence.launch_pid )
147
+ # Creates pid file and traps signal.
148
+ def self.init_pid( daemon )
149
+ if RSence.pid_support?
150
+ is_running = status( daemon )
151
+ if is_running
152
+ puts "RSence is already running."
153
+ puts "Stop the existing process first: see 'rsence help stop'"
154
+ if RSence.launch_pid != Process.pid
155
+ Process.kill( 'INT', RSence.launch_pid )
156
+ end
157
+ exit
158
+ elsif not is_running
159
+ delete_stale_pids( daemon )
169
160
  end
170
- exit
171
- elsif not is_running
172
- delete_stale_pids( daemon )
161
+ trap_signals( daemon )
162
+ pid = Process.pid
163
+ write_pid( daemon, pid )
164
+ return pid
165
+ else
166
+ trap_windows_signals( daemon )
167
+ return false
173
168
  end
174
- trap_signals( daemon )
175
- pid = Process.pid
176
- write_pid( daemon, pid )
177
- return pid
178
- else
179
- trap_windows_signals( daemon )
180
- return false
181
169
  end
182
- end
183
170
 
184
- def self.run( daemon )
185
- init_pid( daemon )
186
- daemon.run
187
- exit
188
- end
189
-
190
- def self.start( daemon )
191
- fork do
192
- exit if fork
171
+ # Inits the pid, signals and then starts the server in the foreground
172
+ def self.run( daemon )
193
173
  init_pid( daemon )
194
- daemon.start
195
- end
196
- Signal.trap('INT') do
197
- puts "RSence startup failed. Please inspect the log and/or run in debug mode."
174
+ daemon.run
198
175
  exit
199
176
  end
200
- Signal.trap('TERM') do
201
- puts "RSence is online at http://#{daemon.addr}:#{daemon.port}/"
202
- exit
177
+
178
+ # Inits the pid, signals and then starts the daemon in
179
+ # the background and waits until the daemon sends the TERM signal.
180
+ def self.start( daemon )
181
+ fork do
182
+ exit if fork
183
+ init_pid( daemon )
184
+ daemon.start
185
+ end
186
+ Signal.trap('INT') do
187
+ puts "RSence startup failed. Please inspect the log and/or run in debug mode."
188
+ exit
189
+ end
190
+ Signal.trap('TERM') do
191
+ puts "RSence is online at http://#{daemon.addr}:#{daemon.port}/"
192
+ exit
193
+ end
194
+ sleep 1 while true
203
195
  end
204
- sleep 1 while true
205
- end
206
196
 
207
- # Sends the USR1 signal to the process, which in turn
208
- # calls the save method of the daemon.
209
- def self.save( daemon )
210
- status_ = status( daemon )
211
- if status_
212
- if wait_signal_response( daemon, 'USR1', 10, 'saving.', 'saved', 0.3 )
213
- puts "Session data saved."
197
+ # Sends the USR1 signal to the process, which in turn
198
+ # calls the save method of the daemon.
199
+ def self.save( daemon )
200
+ status_ = status( daemon )
201
+ if status_
202
+ if wait_signal_response( daemon, 'USR1', 10, 'saving.', 'saved', 0.3 )
203
+ puts "Session data saved."
204
+ else
205
+ puts "Warning: saving timed out! Session data not saved."
206
+ end
207
+ elsif status_ == false
208
+ puts "Warning, no such process (#{pid}) running: unable to save."
209
+ elsif status_ == nil
210
+ puts "No pid file: unable to save."
214
211
  else
215
- puts "Warning: saving timed out! Session data not saved."
212
+ throw "Unexpected process status: #{status_.inspect}"
216
213
  end
217
- elsif status_ == false
218
- puts "Warning, no such process (#{pid}) running: unable to save."
219
- elsif status_ == nil
220
- puts "No pid file: unable to save."
221
- else
222
- throw "Unexpected process status: #{status_.inspect}"
223
214
  end
224
- end
225
215
 
226
- # Sends the TERM signal to the process, which in turn
227
- # calls the stop method of the daemon
228
- def self.stop( daemon )#,is_restart=false)
229
- status_ = status( daemon )
230
- if status_
231
- if wait_signal_response( daemon, 'TERM', 10, 'killing.', 'killed', 0.3 )
232
- puts "RSence is terminated now."
216
+ # Sends the TERM signal to the process, which in turn
217
+ # calls the stop method of the daemon
218
+ def self.stop( daemon )#,is_restart=false)
219
+ status_ = status( daemon )
220
+ if status_
221
+ if wait_signal_response( daemon, 'TERM', 10, 'killing.', 'killed', 0.3 )
222
+ puts "RSence is terminated now."
223
+ else
224
+ puts "Warning: termination timed out!"
225
+ puts "RSence might still be running, please ensure manually."
226
+ end
227
+ elsif status_ == false
228
+ puts "Warning, no such process (#{read_pid(daemon)}) running."
229
+ elsif status_ == nil
230
+ puts "Warning, no pid file (process not running)."
233
231
  else
234
- puts "Warning: termination timed out!"
235
- puts "RSence might still be running, please ensure manually."
232
+ throw "Unexpected process status: #{status_.inspect}"
236
233
  end
237
- elsif status_ == false
238
- puts "Warning, no such process (#{read_pid(daemon)}) running."
239
- elsif status_ == nil
240
- puts "Warning, no pid file (process not running)."
241
- else
242
- throw "Unexpected process status: #{status_.inspect}"
243
234
  end
244
- end
245
235
 
246
- # Main entry point called from the daemon process passing +self+ as +daemon+.
247
- def self.daemonize( daemon )
236
+ # Main entry point called from the daemon process passing +self+ as +daemon+.
237
+ def self.daemonize( daemon )
248
238
 
249
- # Uses the command-line tool command to decide what to do.
250
- case RSence.cmd
251
- when :run
252
- run( daemon )
253
- when :start
254
- start( daemon )
255
- when :stop
256
- stop( daemon )
257
- when :restart
258
- stop( daemon )
259
- start( daemon )
260
- when :save
261
- save( daemon )
239
+ # Uses the command-line tool command to decide what to do.
240
+ case RSence.cmd
241
+ when :run
242
+ run( daemon )
243
+ when :start
244
+ start( daemon )
245
+ when :stop
246
+ stop( daemon )
247
+ when :restart
248
+ stop( daemon )
249
+ start( daemon )
250
+ when :save
251
+ save( daemon )
252
+ end
262
253
  end
263
- end
264
254
 
265
- end
255
+ end
266
256
 
267
- # Simple process control, constructed here and called from Daemon::Controller
268
- class HTTPDaemon
257
+ # Simple process control, constructed here and called from Daemon::Controller
258
+ class HTTPDaemon
269
259
 
270
- def run
271
- puts "Starting as a foreground process." if RSence.args[:verbose]
272
- puts "Press CTRL-C to terminate."
260
+ # RSence top-level run handler. Almost identical to start.
261
+ def run
273
262
 
274
- @transporter = Transporter.new
263
+ puts "Starting as a foreground process." if RSence.args[:verbose]
264
+ puts "Press CTRL-C to terminate."
275
265
 
276
- conf = RSence.config[:http_server]
266
+ @transporter = Transporter.new
277
267
 
278
- unless RSence.args[:log_fg]
279
- Daemon.start_logging( self )
280
- end
268
+ conf = RSence.config[:http_server]
281
269
 
282
- # This is the main http handler instance:
283
- @broker = Broker.start(
284
- @transporter,
285
- conf[:rack_handler],
286
- conf[:bind_address],
287
- conf[:port]
288
- )
270
+ unless RSence.args[:log_fg]
271
+ Daemon.start_logging( self )
272
+ end
289
273
 
290
- end
274
+ # This is the main http handler instance:
275
+ @broker = Broker.start(
276
+ @transporter,
277
+ conf
278
+ )
279
+
280
+ end
291
281
 
292
- # Returns the pid file path.
293
- def pid_fn
294
- RSence.config[:daemon][:pid_fn]
295
- end
282
+ # Returns the pid file path.
283
+ def pid_fn
284
+ RSence.config[:daemon][:pid_fn]
285
+ end
296
286
 
297
- # Returns the log path.
298
- def log_fn
299
- RSence.config[:daemon][:log_fn]
300
- end
287
+ # Returns the log path.
288
+ def log_fn
289
+ RSence.config[:daemon][:log_fn]
290
+ end
301
291
 
302
- def addr
303
- RSence.config[:http_server][:bind_address]
304
- end
292
+ # Returns the configured bind address
293
+ def addr
294
+ RSence.config[:http_server][:bind_address]
295
+ end
305
296
 
306
- def port
307
- RSence.config[:http_server][:port]
308
- end
297
+ # Returns the configured port.
298
+ def port
299
+ RSence.config[:http_server][:port]
300
+ end
309
301
 
310
- # Called by Controller#start, contains RSence-specific operations
311
- def start
302
+ # Called by Controller#start, contains RSence-specific operations
303
+ def start
312
304
 
313
- @transporter = Transporter.new
305
+ @transporter = Transporter.new
314
306
 
315
- conf = RSence.config[:http_server]
307
+ conf = RSence.config[:http_server]
316
308
 
317
- unless RSence.args[:log_fg]
318
- Daemon.start_logging( self )
319
- STDIN.reopen( "/dev/null" )
320
- end
309
+ unless RSence.args[:log_fg]
310
+ Daemon.start_logging( self )
311
+ STDIN.reopen( "/dev/null" )
312
+ end
321
313
 
322
- Process.setsid
314
+ Process.setsid
323
315
 
324
- # This is the main http handler instance:
325
- @broker = Broker.start(
326
- @transporter,
327
- conf[:rack_handler],
328
- conf[:bind_address],
329
- conf[:port]
330
- )
331
- yield @broker
316
+ # This is the main http handler instance:
317
+ @broker = Broker.start(
318
+ @transporter,
319
+ conf
320
+ )
321
+ yield @broker
332
322
 
333
- end
323
+ end
334
324
 
335
- # Called by Controller#stop, contains RSence-specific operations
336
- def stop
337
- @transporter.shutdown
338
- end
325
+ # Called by Controller#stop, contains RSence-specific operations
326
+ def stop
327
+ @transporter.shutdown
328
+ end
339
329
 
340
- # Called on USR1 signals (save data)
341
- def usr1
342
- save
343
- end
330
+ # Called on USR1 signals (save data)
331
+ def usr1
332
+ save
333
+ end
344
334
 
345
- # Save state
346
- def save
347
- puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- Saving state..."
348
- transporter_state = @transporter.online?
349
- @transporter.online = false
350
- @transporter.plugins.delegate(:flush)
351
- @transporter.sessions.store_sessions
352
- @transporter.online = transporter_state
353
- puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- State saved."
354
- end
335
+ # Save state
336
+ def save
337
+ puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- Saving state..."
338
+ transporter_state = @transporter.online?
339
+ @transporter.online = false
340
+ @transporter.plugins.delegate(:flush)
341
+ @transporter.sessions.store_sessions
342
+ @transporter.online = transporter_state
343
+ puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- State saved."
344
+ end
355
345
 
356
- # Called on USR2 signals ("Alive?")
357
- def usr2
358
- puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- RSence version #{RSence.version} is running."
359
- end
346
+ # Called on USR2 signals ("Alive?")
347
+ def usr2
348
+ puts "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} -- RSence version #{RSence.version} is running."
349
+ end
360
350
 
361
- # Main entry point, daemonizes itself using Controller.
362
- def daemonize!
363
- Daemon.daemonize( self )
364
- end
351
+ # Main entry point, daemonizes itself using Controller.
352
+ def daemonize!
353
+ Daemon.daemonize( self )
354
+ end
365
355
 
366
- end
367
-
356
+ end
368
357
  end