rsence 2.0.0.pre → 2.0.0.1.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. data/INSTALL.rdoc +295 -0
  2. data/LICENSE +622 -0
  3. data/README.rdoc +87 -0
  4. data/VERSION +1 -0
  5. data/bin/rsence +5 -101
  6. data/conf/config.yaml +4 -0
  7. data/conf/default_conf.yaml +6 -4
  8. data/conf/{local_conf.yaml → local_conf.yaml.devel} +2 -1
  9. data/js/comm/comm/autosync/autosync.js +0 -1
  10. data/js/comm/comm/queue/queue.js +1 -1
  11. data/js/comm/comm/urlresponder/urlresponder.js +58 -35
  12. data/js/comm/comm/values/values.js +13 -3
  13. data/js/comm/jsloader/jsloader.js +29 -12
  14. data/js/controls/button/themes/default/button_parts1-ie6.gif +0 -0
  15. data/js/controls/checkbox/themes/default/checkbox_parts1-ie6.gif +0 -0
  16. data/js/controls/datetime/timesheet/timesheet.js +2 -2
  17. data/js/controls/dialogs/sheet/themes/default/sheet_bg-ie6.gif +0 -0
  18. data/js/controls/dialogs/sheet/themes/default/sheet_parts1-ie6.gif +0 -0
  19. data/js/controls/dialogs/sheet/themes/default/sheet_parts2-ie6.gif +0 -0
  20. data/js/controls/dialogs/sheet/themes/default/sheet_warning-ie6.gif +0 -0
  21. data/js/controls/passwordcontrol/themes/default/passwordcontrol.html +1 -1
  22. data/js/controls/radiobutton/themes/default/radiobutton_parts1-ie6.gif +0 -0
  23. data/js/controls/sliders/slider/themes/default/hslider_tracks-ie6.gif +0 -0
  24. data/js/controls/sliders/slider/themes/default/slider.css +2 -0
  25. data/js/controls/sliders/slider/themes/default/slider_thumbs-ie6.gif +0 -0
  26. data/js/controls/sliders/vslider/themes/default/vslider.css +2 -0
  27. data/js/controls/sliders/vslider/themes/default/vslider_tracks-ie6.gif +0 -0
  28. data/js/controls/stepper/themes/default/stepper-ie6.gif +0 -0
  29. data/js/controls/tab/tab.js +2 -6
  30. data/js/controls/tab/themes/default/tab.css +1 -0
  31. data/js/controls/tab/themes/default/tab.html +1 -1
  32. data/js/controls/tab/themes/default/tab_border_pattern-ie6.gif +0 -0
  33. data/js/controls/tab/themes/default/tab_parts1-ie6.gif +0 -0
  34. data/js/controls/textarea/themes/default/textarea.css +21 -0
  35. data/js/controls/textarea/themes/default/textarea.html +2 -2
  36. data/js/controls/textcontrol/textcontrol.js +56 -69
  37. data/js/controls/textcontrol/themes/default/textcontrol.css +23 -20
  38. data/js/controls/textcontrol/themes/default/textcontrol.html +1 -1
  39. data/js/controls/window/themes/default/window.css +1 -0
  40. data/js/controls/window/themes/default/window_bg_active-ie6.gif +0 -0
  41. data/js/controls/window/themes/default/window_bg_inactive-ie6.gif +0 -0
  42. data/js/controls/window/themes/default/window_buttons-ie6.gif +0 -0
  43. data/js/controls/window/themes/default/window_parts1-ie6.gif +0 -0
  44. data/js/controls/window/themes/default/window_parts2-ie6.gif +0 -0
  45. data/js/controls/window/window.js +28 -7
  46. data/js/core/class/class.js +31 -30
  47. data/js/core/elem/elem.js +94 -71
  48. data/js/core/event/event.js +34 -26
  49. data/js/core/iefix/iefix.js +46 -31
  50. data/js/debugg/debugg.js +43 -0
  51. data/js/debugg/js.inc +0 -0
  52. data/js/foundation/application/application.js +3 -1
  53. data/js/foundation/control/dyncontrol/dyncontrol.js +1 -0
  54. data/js/foundation/control/eventresponder/eventresponder.js +1 -1
  55. data/js/foundation/json_renderer/json_renderer.js +1 -3
  56. data/js/foundation/system/system.js +4 -4
  57. data/js/foundation/thememanager/thememanager.js +3 -3
  58. data/js/foundation/view/view.js +71 -1
  59. data/lib/conf/argv.rb +664 -0
  60. data/lib/conf/default.rb +51 -52
  61. data/lib/daemon/daemon.rb +281 -195
  62. data/lib/plugins/plugin_plugins.rb +47 -0
  63. data/lib/plugins/pluginmanager.rb +17 -12
  64. data/lib/transporter/transporter.rb +6 -9
  65. data/plugins/client_pkg/client_pkg.rb +12 -9
  66. data/plugins/client_pkg/lib/client_pkg_build.rb +1 -1
  67. data/plugins/index_html/tmpl/index.html +3 -3
  68. data/plugins/main/main.rb +1 -0
  69. metadata +16 -14
  70. data/bin/build_client.rb +0 -254
  71. data/bin/help +0 -6
  72. data/bin/launch.rb +0 -120
  73. data/bin/rdoc.sh +0 -2
  74. data/bin/restart +0 -6
  75. data/bin/run +0 -6
  76. data/bin/run.rb +0 -6
  77. data/bin/save +0 -6
  78. data/bin/start +0 -6
  79. data/bin/status +0 -6
  80. data/bin/stop +0 -6
data/lib/conf/default.rb CHANGED
@@ -12,6 +12,10 @@ require 'rubygems'
12
12
  require 'rack'
13
13
  require 'yaml'
14
14
 
15
+ if RUBY_VERSION.to_f >= 1.9
16
+ Encoding.default_external = Encoding::ASCII_8BIT
17
+ end
18
+
15
19
  # Legacy:
16
20
  LIB_PATHS = []
17
21
  PIDPATH = File.join(SERVER_PATH,'var','run')
@@ -20,8 +24,6 @@ def load_legacy( local_config_file_path )
20
24
  require local_config_file_path[0..-4]
21
25
  end
22
26
 
23
- module RSence
24
-
25
27
  class Configuration
26
28
  def array_merge( target, source )
27
29
  source.each do |item|
@@ -55,10 +57,21 @@ class Configuration
55
57
  end
56
58
  end
57
59
  end
58
- def initialize
60
+ def wizard
61
+ puts "Please answer the following questions, blank lines equal to the default in brackets:"
62
+ require 'conf/wizard'
63
+ if File.directory?( File.join( Dir.pwd, 'conf' ) )
64
+ wizard_conf_file = File.join( Dir.pwd, 'conf', 'local_conf.yaml' )
65
+ else
66
+ wizard_conf_file = File.join( SERVER_PATH, 'conf', 'local_conf.yaml' )
67
+ end
68
+ wizard_config_data = ConfigWizard.new(config).run( wizard_conf_file )
69
+ config.merge!( wizard_config_data )
70
+ end
71
+ def initialize(args)
59
72
  ## Paths for log and pid files
60
- pidpath = File.join(SERVER_PATH,'var','run')
61
- logpath = File.join(SERVER_PATH,'var','log')
73
+ pidpath = File.join( args[:env_path], 'run' )
74
+ logpath = File.join( args[:env_path], 'log' )
62
75
 
63
76
  yaml_conf_path = File.join( SERVER_PATH, 'conf', 'default_conf.yaml' )
64
77
 
@@ -69,8 +82,9 @@ class Configuration
69
82
  config = YAML.load( File.read( yaml_conf_path ) )
70
83
  config[:transporter_conf][:messages] = strings[:messages][:transporter]
71
84
 
72
- default_plugins_path = File.join( SERVER_PATH, 'plugins' )
85
+ config[:client_pkg][:src_dirs].unshift( File.join( SERVER_PATH, 'js' ) )
73
86
 
87
+ default_plugins_path = File.join( SERVER_PATH, 'plugins' )
74
88
  unless config[:plugin_paths].include? default_plugins_path
75
89
  config[:plugin_paths].push( default_plugins_path )
76
90
  end
@@ -84,28 +98,31 @@ class Configuration
84
98
  ## Create default local configuratation override file, if it does not exist:
85
99
  local_config_file_paths = [
86
100
  File.join(SERVER_PATH,'conf','local_conf.yaml'),
101
+ '/etc/rsence/config.yaml',
102
+ File.expand_path('~/.rsence/config.yaml'),
87
103
  File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.yaml' ),
88
- File.join( Dir.pwd, 'conf', 'local_conf.yaml' ),
104
+ # File.join( Dir.pwd, 'conf', 'local_conf.yaml' ),
89
105
  File.join(SERVER_PATH,'conf','local_conf.rb'),
90
- File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.rb' ),
91
- File.join( Dir.pwd, 'conf', 'local_conf.rb' )
106
+ # File.join( File.split( SERVER_PATH )[0], 'conf', 'local_conf.rb' ),
107
+ # File.join( Dir.pwd, 'conf', 'local_conf.rb' )
92
108
  ]
93
- if ARGV.include?('--config')
94
- argv_conf_file = ARGV[ARGV.index('--config')+1]
95
- if not argv_conf_file.begin_with? '/'
96
- argv_conf_file = File.join( Dir.pwd, conf_file )
97
- end
98
- local_config_file_paths.push( argv_conf_file )
109
+
110
+ args[:conf_files].each do |conf_file|
111
+ local_config_file_paths.push( conf_file )
99
112
  end
100
113
 
101
- local_config_file_path_found = false
102
114
  local_config_file_paths.each do |local_config_file_path|
103
115
  if File.exists? local_config_file_path and File.file? local_config_file_path
104
116
  if local_config_file_path.end_with? '.yaml'
117
+ puts "loading config file: #{local_config_file_path}" if args[:verbose]
105
118
  local_conf = YAML.load( File.read( local_config_file_path ) )
119
+ unless local_conf.class == Hash
120
+ warn "invalid configuration file: #{local_config_file_path.inspect}"
121
+ next
122
+ end
106
123
  hash_merge( config, local_conf )
107
- local_config_file_path_found = true
108
124
  elsif local_config_file_path.end_with? '.rb'
125
+ warn "WARNING: '.rb' configuration files are deprecated!"
109
126
  # Legacy work-arounds
110
127
  prev_pidpath = PIDPATH
111
128
  prev_logpath = LOGPATH
@@ -115,47 +132,35 @@ class Configuration
115
132
  pidpath = PIDPATH if PIDPATH != prev_pidpath
116
133
  logpath = LOGPATH if LOGPATH != prev_logpath
117
134
  # /Legacy work-arounds
118
- local_config_file_path_found = true
119
135
  else
120
136
  warn "Only Yaml and Ruby configuration files are allowed at this time."
121
137
  end
122
138
  end
123
139
  end
124
140
 
125
- if not local_config_file_path_found or ARGV.include? '--run-wizard'
126
- puts "NOTE: No local configuration file found, running the, configuration wizard." unless ARGV.include? '--run-wizard'
127
- puts "Please answer the following questions, blank lines equal to the default in brackets:"
128
- require 'conf/wizard'
129
- if File.directory?( File.join( Dir.pwd, 'conf' ) )
130
- wizard_conf_file = File.join( Dir.pwd, 'conf', 'local_conf.yaml' )
131
- else
132
- wizard_conf_file = File.join( SERVER_PATH, 'conf', 'local_conf.yaml' )
133
- end
134
- wizard_config_data = ConfigWizard.new(config).run( wizard_conf_file )
135
- config.merge!( wizard_config_data )
136
- end
137
-
138
- if not config[:database].has_key?( :ses_db ) and config[:database].has_key?( :auth_setup )
139
- warn "WARNING: The database is not configured with a :ses_db url."
140
- warn " You are advised to convert the :root_setup and :auth_setup keys of"
141
- warn " config[:database] to the new url format."
142
- db_auth = config[:database][:auth_setup]
143
- config[:database][:ses_db] = "mysql://#{db_auth[:user]}:#{db_auth[:pass]}@#{db_auth[:host]}:#{db_auth[:port]}/#{db_auth[:db]}"
144
- warn " -> Performed automatic conversion of :auth_setup as"
145
- warn " config[:database][:ses_db] = #{config[:database][:ses_db].inspect}"
141
+ env_plugins_path = File.join( args[:env_path], 'plugins' )
142
+ unless config[:plugin_paths].include? env_plugins_path
143
+ config[:plugin_paths].push( env_plugins_path )
146
144
  end
147
145
 
146
+ config[:trace] = true if args[:trace_js]
147
+ config[:debug_mode] = true if args[:debug]
148
+ config[:http_server][:latency] = args[:latency]
149
+ config[:http_server][:port] = args[:port] if args[:port]
150
+ config[:http_server][:bind_address] = args[:addr] if args[:addr]
151
+ config[:http_server][:rack_require] = args[:server] if args[:server]
152
+ config[:session_conf][:reset_sessions] = true if args[:reset_ses]
148
153
 
149
- config[:trace] = true if ARGV.include?('--trace-js')
150
- config[:debug_mode] = true if ARGV.include?('-d') or ARGV.include?('--debug')
151
- config[:http_server][:latency] = ARGV[ARGV.index('--latency')+1].to_i if ARGV.include?('--latency')
152
- config[:http_server][:port] = ARGV[ARGV.index('--port')+1].to_i if ARGV.include?('--port')
153
- config[:http_server][:bind_address] = ARGV[ARGV.index('--addr')+1] if ARGV.include?('--addr')
154
- config[:http_server][:rack_require] = ARGV[ARGV.index('--server')+1] if ARGV.include?('--server')
155
- config[:session_conf][:reset_sessions] = true if ARGV.include?('--reset-sessions=true') or ARGV.include?('--reset-sessions')
156
154
  config[:daemon][:pid_fn] = File.join(pidpath, "rsence.pid") unless config[:daemon].has_key?(:pid_fn)
157
155
  config[:daemon][:log_fn] = File.join(logpath, "rsence") unless config[:daemon].has_key?(:log_fn)
158
156
 
157
+ if config[:database][:ses_db].start_with?('sqlite://')
158
+ db_url = config[:database][:ses_db].split('sqlite://')[1]
159
+ unless db_url.start_with?('/')
160
+ db_url = File.join( args[:env_path], db_url )
161
+ config[:database][:ses_db] = "sqlite://#{db_url}"
162
+ end
163
+ end
159
164
 
160
165
  ## Broker configuration
161
166
  [ ## POST-requests
@@ -210,11 +215,5 @@ class Configuration
210
215
  end
211
216
  attr_reader :config
212
217
  end
213
- @@config = Configuration.new.config
214
- def self.config
215
- @@config
216
- end
217
-
218
- end
219
218
 
220
219
 
data/lib/daemon/daemon.rb CHANGED
@@ -8,9 +8,6 @@
8
8
  ##
9
9
  #++
10
10
 
11
- # Use the default configuration:
12
- require 'conf/default'
13
-
14
11
  # Use rubygems to load rack
15
12
  require 'rubygems'
16
13
  require 'rack'
@@ -47,247 +44,336 @@ require 'transporter/transporter'
47
44
  require 'http/broker'
48
45
 
49
46
 
50
- module RSence
51
-
52
- # adapted from:
53
- # http://snippets.dzone.com/posts/show/2265
47
+ module ::RSence
54
48
 
55
- require 'fileutils'
49
+ @@launch_pid = Process.pid
50
+ def self.launch_pid
51
+ return @@launch_pid
52
+ end
56
53
 
54
+ # The Controller module handles the damonizing
55
+ # operations of the process referred to as +daemon+
57
56
  module Daemon
58
57
 
59
- class Base
60
- def self.pid_fn
61
- RSence.config[:daemon][:pid_fn]
62
- end
63
- def self.log_fn
64
- RSence.config[:daemon][:log_fn]
65
- end
66
- def self.daemonize
67
- Controller.daemonize(self)
58
+ # Writes the process id to disk, the pid_fn method of the daemon contains
59
+ # the name of the pid file.
60
+ def self.write_pid( daemon, pid )
61
+ File.open( daemon.pid_fn, 'w' ) do |pidfile|
62
+ pidfile.write( pid )
68
63
  end
69
64
  end
70
65
 
71
- module PidFile
72
- def self.store(daemon, pid)
73
- dir_path_pid = File.split( daemon.pid_fn )[0]
74
- FileUtils.mkdir_p( dir_path_pid ) unless File.exists? dir_path_pid
75
- File.open(daemon.pid_fn, 'w') {|f| f << pid}
76
- end
77
- def self.recall(daemon)
78
- IO.read(daemon.pid_fn).to_i rescue nil
79
- end
66
+ # Reads the process id from disk, the pid_fn method of the daemon contains
67
+ # the name of the pid file. Returns nil on errors.
68
+ def self.read_pid( daemon )
69
+ File.read( daemon.pid_fn ).to_i rescue nil
80
70
  end
81
71
 
82
- module Controller
83
-
84
- def self.print_status(daemon)
85
- is_running = self.status(daemon)
86
- puts "Riassence Framework is #{'not ' unless is_running}running"
72
+ def self.responds?( daemon )
73
+ wait_signal_response( daemon, 'USR2' )
74
+ end
75
+
76
+ # Reads the pid file and calls the process.
77
+ # Returns true if the process responds, false otherwise (no process)
78
+ def self.status( daemon )
79
+ pid = read_pid( daemon )
80
+ return nil if not pid
81
+ return responds?( daemon )
82
+ end
83
+
84
+ # Redirects standard input and errors to the log files
85
+ def self.start_logging( daemon )
86
+ outpath = "#{daemon.log_fn}.stdout"
87
+ errpath = "#{daemon.log_fn}.stderr"
88
+ STDOUT.reopen( outpath, (File.exist?( outpath ) ? 'a' : 'w') )
89
+ STDOUT.sync = true
90
+ STDERR.reopen( errpath, (File.exist?( errpath ) ? 'a' : 'w') )
91
+ STDERR.sync = true
92
+ end
93
+
94
+ def self.write_signal_response( daemon, signal )
95
+ sig_fn = daemon.pid_fn+'.response.'+signal
96
+ File.open(sig_fn,'w') do |file|
97
+ file.write(Process.pid.to_s)
87
98
  end
88
-
89
- ## Status is not entirely reliable
90
- def self.status(daemon)
91
- if File.file?(daemon.pid_fn)
92
- begin
93
- pid = File.read(daemon.pid_fn).to_i
94
- pid && Process.kill('USR2',pid)
95
- return true
96
- rescue Errno::ESRCH => e
97
- return false
98
- end
99
- end
100
- return false
99
+ end
100
+
101
+ def self.delete_signal_response( daemon, signal )
102
+ sig_fn = daemon.pid_fn+'.response.'+signal
103
+ if File.file?( sig_fn )
104
+ File.delete( sig_fn )
101
105
  end
102
-
103
- def self.open_log( outpath, errpath )
104
- dir_path_out = File.split( outpath )[0]
105
- FileUtils.mkdir_p( dir_path_out ) unless File.exists? dir_path_out
106
- dir_path_err = File.split( outpath )[0]
107
- FileUtils.mkdir_p( dir_path_err ) unless File.exists? dir_path_err
108
- if File.exist?( outpath )
109
- STDOUT.reopen( outpath, "a" )
110
- else
111
- STDOUT.reopen( outpath, "w" )
106
+ end
107
+
108
+ def self.wait_signal_response( daemon, signal, timeout = 10,
109
+ debug_pre = '<', debug_suf = '>', sleep_secs = 0.2 )
110
+ begin
111
+ if RSence.args[:verbose]
112
+ print debug_pre
113
+ STDOUT.flush
112
114
  end
113
- if File.exist?( errpath )
114
- STDERR.reopen( errpath, "a" )
115
- else
116
- STDERR.reopen( errpath, "w" )
115
+ pid = read_pid( daemon )
116
+ sig_fn = daemon.pid_fn+'.response.'+signal
117
+ File.delete( sig_fn ) if File.file?( sig_fn )
118
+ status = Process.kill( signal, pid )
119
+ time_out = Time.now + timeout
120
+ until time_out > Time.now or File.file?( sig_fn )
121
+ if RSence.args[:verbose]
122
+ print "."
123
+ STDOUT.flush
124
+ end
125
+ sleep sleep_secs
117
126
  end
118
- STDOUT.sync = true
119
- STDERR.sync = true
120
- end
121
-
122
- def self.log_io(daemon)
123
- outpath = "#{daemon.log_fn}.stdout"
124
- errpath = "#{daemon.log_fn}.stderr"
125
- if $DEBUG_MODE
126
- Thread.new do
127
- puts "Waiting 2 seconds before switching output to log file #{outpath} and .../#{File.split(errpath)[1]}"
128
- sleep 2
129
- puts "Switching to stdin and stdout to log mode. Follow the log file to see further server output."
130
- self.open_log( outpath, errpath )
127
+ sleep sleep_secs
128
+ if File.file?( sig_fn )
129
+ sig_pid = File.read( sig_fn ).to_i
130
+ if sig_pid != pid
131
+ puts "Warning, signal PID mismatch. Expected #{pid}, got #{sig_pid}"
131
132
  end
133
+ File.delete( sig_fn )
132
134
  else
133
- self.open_log( outpath, errpath )
135
+ puts "Warning, signal response file disappeared! Expected #{sig_fn}"
134
136
  end
137
+ puts debug_suf if RSence.args[:verbose]
138
+ return true
139
+ rescue Errno::ESRCH
140
+ return false
135
141
  end
142
+ end
143
+
144
+ # Traps common kill signals
145
+ def self.trap_signals( daemon )
136
146
 
137
- def self.daemonize(daemon)
138
- cmd = ARGV[0]
139
- if ['i386-mingw32','x86-mingw32'].include? RUBY_PLATFORM
140
- if cmd == 'start'
141
- warn "Running on Microsoft Windows: unable to background. Using the run command instead of start"
142
- cmd = 'run'
143
- elsif cmd != 'run'
144
- puts "Invalid command: #{cmd.inspect}. Windows supports only run and help."
145
- exit
146
- end
147
- elsif not cmd or not %w[status start stop restart save run].include?( cmd )
148
- puts "Invalid command. Please specify one of the following: run, start, stop, restart, status, save or help."
147
+ # Triggered with 'kill -USR1 `cat rsence.pid`'
148
+ Signal.trap( 'USR1' ) do
149
+ daemon.usr1
150
+ write_signal_response( daemon, 'USR1' )
151
+ end
152
+ Signal.trap('USR2') do
153
+ daemon.usr2
154
+ write_signal_response( daemon, 'USR2' )
155
+ end
156
+ ['INT', 'TERM', 'KILL'].each do | signal |
157
+ Signal.trap( signal ) do
158
+ puts "RSence killed with signal #{signal.inspect}" if RSence.args[:verbose]
159
+ daemon.usr1
160
+ daemon.stop
161
+ # delete_signal_response( daemon, 'USR1' )
162
+ # delete_signal_response( daemon, 'USR2' )
163
+ File.delete( daemon.pid_fn ) if File.file?( daemon.pid_fn )
164
+ write_signal_response( daemon, signal )
165
+ puts "Shutdown complete."
149
166
  exit
150
167
  end
151
- case cmd
152
- when 'run'
153
- puts "Starting as a foreground process."
154
- puts "Enter CTRL-C to stop."
155
- self.start_fg(daemon)
156
- when 'status'
157
- self.print_status(daemon)
158
- when 'start'
159
- self.start(daemon)
160
- when 'stop'
161
- self.stop(daemon)
162
- when 'restart'
163
- self.stop(daemon,true)
164
- self.start(daemon)
165
- when 'save'
166
- self.save(daemon)
167
- end
168
168
  end
169
- def self.start_fg(daemon)
170
- ['INT', 'TERM', 'KILL'].each do |signal|
171
- Signal.trap(signal) do
172
- puts "Got signal #{signal.inspect}"
173
- daemon.stop
174
- exit
169
+ # Signal.trap('HUP') do
170
+ # daemon.restart
171
+ # end
172
+ end
173
+
174
+ def self.handle_pid( daemon )
175
+ if RSence.pid_support?
176
+ is_running = status( daemon )
177
+ if is_running
178
+ puts "RSence is already running."
179
+ puts "Stop the existing process first: see 'rsence help stop'"
180
+ if RSence.launch_pid != Process.pid
181
+ Process.kill( 'INT', RSence.launch_pid )
175
182
  end
183
+ exit
184
+ elsif not is_running and File.file?( daemon.pid_fn )
185
+ puts "Stale pid file, removing.."
186
+ File.delete( daemon.pid_fn )
176
187
  end
188
+ trap_signals( daemon )
189
+ pid = Process.pid
190
+ write_pid( daemon, pid )
191
+ return pid
192
+ else
193
+ return false
194
+ end
195
+ end
196
+
197
+ def self.run( daemon )
198
+ handle_pid( daemon )
199
+ daemon.run
200
+ exit
201
+ end
202
+
203
+ def self.start( daemon )
204
+ fork do
205
+ exit if fork
206
+ handle_pid( daemon )
177
207
  daemon.start
208
+ end
209
+ Signal.trap('INT') do
210
+ puts "RSence startup failed. Please inspect the log and/or run in debug mode."
178
211
  exit
179
212
  end
180
- def self.start(daemon)
181
- is_running = self.status(daemon)
182
- if is_running
183
- puts "Riassence Framework is already running. Try restart."
184
- exit
185
- elsif not is_running and File.file?(daemon.pid_fn)
186
- puts "Stale pid file, removing.."
187
- FileUtils.rm(daemon.pid_fn)
188
- end
189
- fork do
190
- Process.setsid
191
- exit if fork
192
- PidFile.store(daemon, Process.pid)
193
- Signal.trap('USR1') do
194
- if @transporter != nil
195
- @transporter.plugins.shutdown if @transporter.plugins
196
- @transporter.sessions.shutdown if @transporter.session
197
- end
198
- end
199
- Signal.trap('USR2') do
200
- puts "Alive."
201
- end
202
- ['INT', 'TERM', 'KILL'].each do |signal|
203
- Signal.trap(signal) do
204
- puts "Got signal #{signal.inspect}"
205
- daemon.stop
206
- exit
207
- end
208
- end
209
- Signal.trap('HUP') {
210
- daemon.restart
211
- }
212
- STDIN.reopen( "/dev/null" )
213
- daemon.start
214
- end
215
-
216
- timeout = Time.now + 10
217
- sleep 0.1 until self.status(daemon) or timeout < Time.now
218
-
219
- if timeout < Time.now
220
- puts "Riassence Framework did not start, please check the logfile."
221
- else
222
- puts "Riassence Framework is running now."
223
- end
224
-
225
- sleep 2.5 if $DEBUG_MODE
226
-
227
- #Process.kill("USR2", File.read(daemon.pid_fn).to_i)
213
+ Signal.trap('TERM') do
214
+ puts "RSence is online at http://#{daemon.addr}:#{daemon.port}/"
215
+ exit
228
216
  end
229
- def self.save(daemon,is_restart=false)
230
- if !File.file?(daemon.pid_fn)
231
- puts "Pid file not found. Is Riassence Framework started?"
232
- return if is_restart
233
- exit
234
- end
235
- pid = File.read(daemon.pid_fn).to_i
236
- begin
237
- pid && Process.kill("USR1", pid)
217
+ sleep 1 while true
218
+ end
219
+
220
+ # Sends the USR1 signal to the process, which in turn
221
+ # calls the save method of the daemon.
222
+ def self.save( daemon )
223
+ status_ = status( daemon )
224
+ if status_
225
+ if wait_signal_response( daemon, 'USR1', 10, 'saving.', 'saved', 0.3 )
238
226
  puts "Session data saved."
239
- rescue
240
- puts "Error, no such pid (#{pid}) running"
227
+ else
228
+ puts "Warning: saving timed out! Session data not saved."
241
229
  end
230
+ elsif status_ == false
231
+ puts "Warning, no such process (#{pid}) running: unable to save."
232
+ elsif status_ == nil
233
+ puts "No pid file: unable to save."
234
+ else
235
+ throw "Unexpected process status: #{status_.inspect}"
242
236
  end
243
- def self.stop(daemon,is_restart=false)
244
- self.save(daemon,is_restart)
245
- if !File.file?(daemon.pid_fn)
246
- puts "Pid file not found. Is Riassence Framework started?"
247
- return if is_restart
248
- exit
249
- end
250
- pid = PidFile.recall(daemon)
251
- begin
252
- pid && Process.kill("TERM", pid)
253
- puts "Riassence Framework is stopped now."
254
- rescue
255
- puts "Error, no such pid (#{pid}) running"
237
+ end
238
+
239
+ # Sends the TERM signal to the process, which in turn
240
+ # calls the stop method of the daemon
241
+ def self.stop( daemon )#,is_restart=false)
242
+ status_ = status( daemon )
243
+ if status_
244
+ if wait_signal_response( daemon, 'TERM', 10, 'killing.', 'killed', 0.3 )
245
+ puts "RSence is terminated now."
246
+ else
247
+ puts "Warning: termination timed out!"
248
+ puts "RSence might still be running, please ensure manually."
256
249
  end
257
- FileUtils.rm(daemon.pid_fn)
250
+ elsif status_ == false
251
+ puts "Warning, no such process (#{pid}) running."
252
+ elsif status_ == nil
253
+ puts "Warning, no pid file (process not running)."
254
+ else
255
+ throw "Unexpected process status: #{status_.inspect}"
258
256
  end
259
257
  end
258
+
259
+ # Main entry point called from the daemon process passing +self+ as +daemon+.
260
+ def self.daemonize( daemon )
261
+
262
+ # Uses the command-line tool command to decide what to do.
263
+ case RSence.cmd
264
+ when :run
265
+ run( daemon )
266
+ when :start
267
+ start( daemon )
268
+ when :stop
269
+ stop( daemon )
270
+ when :restart
271
+ stop( daemon )
272
+ start( daemon )
273
+ when :save
274
+ save( daemon )
275
+ end
276
+ end
277
+
260
278
  end
261
279
 
262
- class HTTPDaemon < Daemon::Base
263
- def self.start
280
+ # Simple process control, constructed here and called from Daemon::Controller
281
+ class HTTPDaemon
282
+
283
+ def run
284
+ puts "Starting as a foreground process." if RSence.args[:verbose]
285
+ puts "Press CTRL-C to terminate."
286
+
264
287
  @transporter = Transporter.new
265
288
 
266
- unless ARGV.include?('--log-fg')
267
- Daemon::Controller.log_io(self)
289
+ conf = RSence.config[:http_server]
290
+
291
+ unless RSence.args[:log_fg]
292
+ Daemon.start_logging( self )
268
293
  end
269
294
 
270
295
  # This is the main http handler instance:
271
296
  @broker = Broker.start(
272
297
  @transporter,
273
- RSence.config[:http_server][:rack_handler],
274
- RSence.config[:http_server][:bind_address],
275
- RSence.config[:http_server][:port]
298
+ conf[:rack_handler],
299
+ conf[:bind_address],
300
+ conf[:port]
276
301
  )
277
302
 
278
- yield @broker if block_given?
279
-
280
303
  end
281
- def self.restart
282
- self.stop
283
- @broker = nil
284
- self.start
304
+
305
+ # Returns the pid file path.
306
+ def pid_fn
307
+ RSence.config[:daemon][:pid_fn]
308
+ end
309
+
310
+ # Returns the log path.
311
+ def log_fn
312
+ RSence.config[:daemon][:log_fn]
313
+ end
314
+
315
+ def addr
316
+ RSence.config[:http_server][:bind_address]
317
+ end
318
+
319
+ def port
320
+ RSence.config[:http_server][:port]
285
321
  end
286
- def self.stop
322
+
323
+ # Called by Controller#start, contains RSence-specific operations
324
+ def start
325
+
326
+ @transporter = Transporter.new
327
+
328
+ conf = RSence.config[:http_server]
329
+
330
+ unless RSence.args[:log_fg]
331
+ Daemon.start_logging( self )
332
+ STDIN.reopen( "/dev/null" )
333
+ end
334
+
335
+ Process.setsid
336
+
337
+ # This is the main http handler instance:
338
+ @broker = Broker.start(
339
+ @transporter,
340
+ conf[:rack_handler],
341
+ conf[:bind_address],
342
+ conf[:port]
343
+ )
344
+ yield @broker
345
+
346
+ end
347
+
348
+ # Called by Controller#stop, contains RSence-specific operations
349
+ def stop
287
350
  @transporter.plugins.shutdown
288
351
  @transporter.sessions.shutdown
289
352
  end
353
+
354
+ # Called on USR1 signals (save data)
355
+ def usr1
356
+ save
357
+ end
358
+
359
+ # Save state
360
+ def save
361
+ puts "Saving."
362
+ @transporter.plugins.delegate(:flush)
363
+ @transporter.sessions.store_sessions
364
+ puts "Saved."
365
+ end
366
+
367
+ # Called on USR2 signals ("Alive?")
368
+ def usr2
369
+ puts "Alive."
370
+ end
371
+
372
+ # Main entry point, daemonizes itself using Controller.
373
+ def daemonize!
374
+ Daemon.daemonize( self )
375
+ end
376
+
290
377
  end
291
378
 
292
379
  end
293
-