rsence 2.0.0.pre → 2.0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
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
-