stompserver_ng 1.0.6

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 (72) hide show
  1. data/History.txt +159 -0
  2. data/Manifest.txt +71 -0
  3. data/README.txt +172 -0
  4. data/Rakefile +38 -0
  5. data/STATUS +5 -0
  6. data/bin/stompserver_ng +63 -0
  7. data/client/README.txt +1 -0
  8. data/client/both.rb +25 -0
  9. data/client/consume.rb +14 -0
  10. data/client/send.rb +17 -0
  11. data/config/stompserver_ng.conf +11 -0
  12. data/etc/19xcompat/notes.txt +223 -0
  13. data/etc/arutils/README-activerecord.txt +78 -0
  14. data/etc/arutils/cre_mysql.rb +34 -0
  15. data/etc/arutils/cre_postgres.rb +33 -0
  16. data/etc/arutils/cre_sqlite3.rb +28 -0
  17. data/etc/arutils/mysql_boot.sql +12 -0
  18. data/etc/arutils/postgres_boot.sql +14 -0
  19. data/etc/database.mysql.yml +9 -0
  20. data/etc/database.postgres.yml +9 -0
  21. data/etc/passwd.example +3 -0
  22. data/etc/ppqinfo.rb +15 -0
  23. data/etc/runserver.sh +17 -0
  24. data/etc/stompserver_ng +50 -0
  25. data/etc/stompserver_ng.conf +13 -0
  26. data/lib/stomp_server_ng.rb +471 -0
  27. data/lib/stomp_server_ng/protocols/http.rb +128 -0
  28. data/lib/stomp_server_ng/protocols/stomp.rb +407 -0
  29. data/lib/stomp_server_ng/qmonitor.rb +58 -0
  30. data/lib/stomp_server_ng/queue.rb +248 -0
  31. data/lib/stomp_server_ng/queue/activerecord_queue.rb +118 -0
  32. data/lib/stomp_server_ng/queue/ar_message.rb +21 -0
  33. data/lib/stomp_server_ng/queue/ar_reconnect.rb +18 -0
  34. data/lib/stomp_server_ng/queue/dbm_queue.rb +72 -0
  35. data/lib/stomp_server_ng/queue/file_queue.rb +56 -0
  36. data/lib/stomp_server_ng/queue/memory_queue.rb +64 -0
  37. data/lib/stomp_server_ng/queue_manager.rb +302 -0
  38. data/lib/stomp_server_ng/stomp_auth.rb +26 -0
  39. data/lib/stomp_server_ng/stomp_frame.rb +32 -0
  40. data/lib/stomp_server_ng/stomp_frame_recognizer.rb +77 -0
  41. data/lib/stomp_server_ng/stomp_id.rb +32 -0
  42. data/lib/stomp_server_ng/stomp_user.rb +17 -0
  43. data/lib/stomp_server_ng/test_server.rb +21 -0
  44. data/lib/stomp_server_ng/topic_manager.rb +46 -0
  45. data/setup.rb +1585 -0
  46. data/stompserver_ng.gemspec +136 -0
  47. data/test/devserver/props.yaml +5 -0
  48. data/test/devserver/runserver.sh +16 -0
  49. data/test/devserver/stompserver_ng.dbm.conf +12 -0
  50. data/test/devserver/stompserver_ng.file.conf +12 -0
  51. data/test/devserver/stompserver_ng.memory.conf +12 -0
  52. data/test/noserver/mocklogger.rb +12 -0
  53. data/test/noserver/test_queue_manager.rb +134 -0
  54. data/test/noserver/test_stomp_frame.rb +138 -0
  55. data/test/noserver/test_topic_manager.rb +79 -0
  56. data/test/noserver/ts_all_no_server.rb +12 -0
  57. data/test/props.yaml +5 -0
  58. data/test/runalltests.sh +14 -0
  59. data/test/runtest.sh +4 -0
  60. data/test/test_0000_base.rb +107 -0
  61. data/test/test_0001_conn.rb +47 -0
  62. data/test/test_0002_conn_sr.rb +94 -0
  63. data/test/test_0006_client.rb +41 -0
  64. data/test/test_0011_send_recv.rb +74 -0
  65. data/test/test_0015_ack_conn.rb +78 -0
  66. data/test/test_0017_ack_client.rb +78 -0
  67. data/test/test_0019_ack_no_ack.rb +145 -0
  68. data/test/test_0022_ack_noack_conn.rb +123 -0
  69. data/test/test_0030_subscr_id.rb +44 -0
  70. data/test/test_0040_receipt_conn.rb +87 -0
  71. data/test/ts_all_server.rb +10 -0
  72. metadata +196 -0
@@ -0,0 +1,33 @@
1
+ require 'rubygems' if RUBY_VERSION =~ /1.8/
2
+ require 'active_record'
3
+ #
4
+ # = cre_postgres - create a postgres data base for use by stompserver_ng
5
+ #
6
+ # For now, the db parameters are hard coded. Change as required.
7
+ #
8
+ db_params = {
9
+ 'adapter' => 'postgresql',
10
+ 'encoding' => 'utf8',
11
+ 'database' => 'ssng_dev',
12
+ 'pool' => 5,
13
+ 'username' => 'ssng',
14
+ 'password' => 'xxxxxxxx',
15
+ 'host' => 'localhost',
16
+ 'port' => 5432
17
+ }
18
+ #
19
+ # Connect.
20
+ #
21
+ ActiveRecord::Base.establish_connection(db_params)
22
+ puts "postgres Connection complete."
23
+ #
24
+ # Define the ar_messages table.
25
+ #
26
+ ActiveRecord::Schema.define do
27
+ create_table 'ar_messages' do |t|
28
+ t.column 'stomp_id', :string, :null => false
29
+ t.column 'frame', :text, :null => false
30
+ end
31
+ end
32
+ puts "postgres table create complete."
33
+
@@ -0,0 +1,28 @@
1
+ require 'rubygems' if RUBY_VERSION =~ /1.8/
2
+ require 'active_record'
3
+ #
4
+ # = cre_sqlite3 - create an sqlite3 data base for use by stompserver_ng
5
+ #
6
+ # For now, the db parameters are hard coded. Change as required.
7
+ # Note: directory structure should already exist.
8
+ #
9
+ db_params = {
10
+ 'adapter' => 'sqlite3',
11
+ 'database' => "/tmp/stompserver/etc/stompserver_development"
12
+ }
13
+ #
14
+ # Connect.
15
+ #
16
+ ActiveRecord::Base.establish_connection(db_params)
17
+ puts "sqlite3 Connection complete."
18
+ #
19
+ # Define the ar_messages table.
20
+ #
21
+ ActiveRecord::Schema.define do
22
+ create_table 'ar_messages' do |t|
23
+ t.column 'stomp_id', :string, :null => false
24
+ t.column 'frame', :text, :null => false
25
+ end
26
+ end
27
+ puts "sqlite3 table create complete."
28
+
@@ -0,0 +1,12 @@
1
+ --
2
+ --
3
+ -- This might depend on your mysql set up:
4
+ --
5
+ -- * mysql -u root -p mysql < mysql_boot.sql
6
+ --
7
+ CREATE USER 'ssng'@'localhost' IDENTIFIED BY 'xxxxxxxx';
8
+ GRANT ALL PRIVILEGES ON ssng_dev.* TO 'ssng'@'localhost' WITH GRANT OPTION;
9
+ GRANT ALL PRIVILEGES ON ssng_dev.* TO 'ssng'@'%' WITH GRANT OPTION;
10
+ --
11
+ CREATE DATABASE ssng_dev;
12
+
@@ -0,0 +1,14 @@
1
+ --
2
+ -- This probably depends on your postgres setup:
3
+ -- * su - postgres
4
+ -- * (enter password if necessary)
5
+ -- * psql < postgres_boot.sql
6
+ --
7
+ -- Create the user/role.
8
+ --
9
+ CREATE ROLE ssng LOGIN PASSWORD 'xxxxxxxx';
10
+ --
11
+ -- And the data base.
12
+ --
13
+ CREATE DATABASE ssng_dev OWNER ssng;
14
+
@@ -0,0 +1,9 @@
1
+ adapter: mysql
2
+ encoding: utf8
3
+ database: ssng_dev
4
+ pool: 5
5
+ username: ssng
6
+ password: xxxxxxxx
7
+ host: localhost
8
+ port: 3306
9
+
@@ -0,0 +1,9 @@
1
+ adapter: postgresql
2
+ encoding: utf8
3
+ database: ssng_dev
4
+ pool: 5
5
+ username: ssng
6
+ password: xxxxxxxx
7
+ host: localhost
8
+ port: 5432
9
+
@@ -0,0 +1,3 @@
1
+ # Stompserver will look for a .passwd file in the directory you are running it from. One login/passcode per line, separated by a colon.
2
+ # Comment lines are ignored
3
+ testuser:testpass
@@ -0,0 +1,15 @@
1
+ require 'pp'
2
+ #
3
+ # Pretty print the queue information file.
4
+ #
5
+ # Sample Use:
6
+ #
7
+ # ruby etc/ppqinfo.rb /ad3/tmp/stompserver/.queue/qinfo
8
+ #
9
+ qfile = ARGV[0]
10
+ qinfo = nil
11
+ File.open(qfile) do |f|
12
+ qinfo = Marshal.load(f)
13
+ end
14
+ pp qinfo
15
+
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+ cd /home/stompserver_ng
3
+ >stompserver.log
4
+ echo Start >>stompserver.log
5
+ x=$(ruby -v)
6
+ echo $x >>stompserver.log
7
+ #
8
+ # Set command line options.
9
+ #
10
+ sopts="$*"
11
+ #
12
+ # Start the server.
13
+ #
14
+ echo Start server >>stompserver.log
15
+ stompserver_ng $sopts
16
+ set +x
17
+ exit 0
@@ -0,0 +1,50 @@
1
+ #!/bin/sh
2
+ ### BEGIN INIT INFO
3
+ # Provides: stompserver_ng
4
+ # Required-Start: $syslog
5
+ # Required-Stop: $syslog
6
+ # Default-Start: 2 3 4 5
7
+ # Default-Stop: 0 1 6
8
+ # Short-Description: Start/stop the stompserver_ng gem
9
+ ### END INIT INFO
10
+ #
11
+ NAME=stompserver_ng
12
+ DESC="stompserver_ng ruby gem"
13
+ #
14
+ NAMEHOME=/home/$NAME
15
+ #
16
+ CONFIGFILE="$NAMEHOME/$NAME.conf"
17
+ STOMPCMD="$NAMEHOME/bin/runserver.sh"
18
+ #
19
+ WORKDIR=$(grep "working_dir" $CONFIGFILE | cut -d" " -f2)
20
+ PIDFILE="$WORKDIR/$NAME.pid"
21
+ #
22
+ EXTRA_OPTS="--daemon --session_cache=25 -C $CONFIGFILE"
23
+ EXTRA_OPTS="${EXTRA_OPTS} ${STOMP_OPTS}"
24
+ #
25
+ set -e
26
+ # set -x
27
+ #
28
+ case "$1" in
29
+ start)
30
+ echo -n "Starting $DESC: "
31
+ test -f /var/tmp/ruby-uuid && rm /var/tmp/ruby-uuid
32
+ test -d $WORKDIR && rm -rf $WORKDIR
33
+ su -l $NAME -c "$STOMPCMD $EXTRA_OPTS"
34
+ echo "$NAME."
35
+ ;;
36
+ stop)
37
+ echo -n "Stopping $DESC: "
38
+ pid=$(ps -ef | grep -i stompserver | grep -i ruby |awk '{print $2}')
39
+ kill $pid
40
+ echo "$NAME."
41
+ ;;
42
+ *)
43
+ echo "Usage: $0 { start | stop }" >&2
44
+ exit 1
45
+ ;;
46
+ esac
47
+ #
48
+ # set +x
49
+ exit 0
50
+
@@ -0,0 +1,13 @@
1
+ ---
2
+ :daemon: true
3
+ :working_dir: /tmp/stompserver
4
+ :storage: .queue
5
+ :queue: file
6
+ :auth: false
7
+ :debug: false
8
+ :group:
9
+ :user:
10
+ :host: localhost
11
+ :port: 61613
12
+ :log_level: debug
13
+
@@ -0,0 +1,471 @@
1
+ require 'rubygems'
2
+ require 'eventmachine'
3
+ require 'uuid'
4
+ require 'stomp_server_ng/stomp_frame'
5
+ require 'stomp_server_ng/stomp_frame_recognizer'
6
+ require 'stomp_server_ng/stomp_id'
7
+ require 'stomp_server_ng/stomp_auth'
8
+ require 'stomp_server_ng/topic_manager'
9
+ require 'stomp_server_ng/queue_manager'
10
+ require 'stomp_server_ng/qmonitor'
11
+ require 'stomp_server_ng/queue'
12
+ require 'stomp_server_ng/queue/memory_queue'
13
+ require 'stomp_server_ng/queue/file_queue'
14
+ require 'stomp_server_ng/queue/dbm_queue'
15
+ require 'stomp_server_ng/protocols/stomp'
16
+ require 'logger'
17
+
18
+ module StompServer
19
+ VERSION = '1.0.6'
20
+ #
21
+ # session ID cache manager
22
+ #
23
+ class SessionIDManager
24
+ #
25
+ @@session_cache = nil
26
+ #
27
+ @@generator = nil
28
+ #
29
+ def self.initialize_cache(requested_size)
30
+ #
31
+ return [] if requested_size <= 0
32
+ #
33
+ @@session_cache = @@session_cache || []
34
+ #
35
+ if not @@generator
36
+ UUID::state_file = "./.temp_uuid_state"
37
+ @@generator = UUID::new()
38
+ end
39
+ #
40
+ return @@session_cache if @@session_cache.size > requested_size
41
+ #
42
+ (requested_size - @@session_cache.size).times do
43
+ @@session_cache << @@generator.generate
44
+ end
45
+ end
46
+ #
47
+ def self.get_cache_id(requested_size)
48
+ session_id = @@session_cache.pop
49
+ initialize_cache(requested_size) if @@session_cache.size == 0
50
+ session_id
51
+ end
52
+ #
53
+ def self.dump_cache(logger)
54
+ logger.debug("Session ID Dump:")
55
+ @@session_cache.each do |sessid|
56
+ logger.debug("#{sessid}")
57
+ end
58
+ end
59
+ end
60
+ #
61
+ # Ruby Logger Level Handler.
62
+ #
63
+ class LogHelper
64
+ #
65
+ # Set the desired logger level.
66
+ #
67
+ def self.set_loglevel(opts)
68
+ @@loglevel = nil
69
+ case opts[:log_level].downcase
70
+ when 'debug' then @@loglevel = Logger::DEBUG
71
+ when 'info' then @@loglevel = Logger::INFO
72
+ when 'warn' then @@loglevel = Logger::WARN
73
+ when 'error' then @@loglevel = Logger::ERROR
74
+ else
75
+ @@loglevel = Logger::ERROR
76
+ end
77
+ end
78
+ #
79
+ # Return the desired logging level.
80
+ #
81
+ def self.get_loglevel
82
+ @@loglevel
83
+ end
84
+ #
85
+ # Display ruby version information on a defined logger output
86
+ # destination.
87
+ #
88
+ def self.showversion(logger)
89
+ # stompserver version
90
+ logger.debug "stomp_server version: #{StompServer::VERSION}"
91
+ # ruby version for all versions
92
+ logger.debug "ruby: ver=#{RUBY_VERSION}p#{RUBY_PATCHLEVEL} (reldate=#{RUBY_RELEASE_DATE})"
93
+ # more ruby version information for 1.9+
94
+ if RUBY_VERSION =~ /1.9/
95
+ logger.debug "ruby: rev=#{RUBY_REVISION} engine=#{RUBY_ENGINE}"
96
+ end
97
+ end
98
+ #
99
+ # Clean logging of all options values.
100
+ #
101
+ def self.showoptions(logger, opts)
102
+ logger.debug("Options Display Starts")
103
+ # This is ugly, but it should only happen once at startup ......
104
+ if RUBY_VERSION =~ /1.8/
105
+ opts.keys.map {|key| key.to_s}.sort.each do |str_opt|
106
+ optname = str_opt.to_sym
107
+ logger.debug("Option: #{optname}=#{opts[optname]}")
108
+ end
109
+ else # 1.9 version
110
+ opts.keys.sort.each do |optname|
111
+ logger.debug("Option: #{optname}=#{opts[optname]}")
112
+ end
113
+ end
114
+ logger.debug("Options Display Ends")
115
+ end
116
+ #
117
+ # Show load path
118
+ #
119
+ def self.showloadpath(logger)
120
+ return unless @@loglevel == Logger::DEBUG
121
+ pos = 1
122
+ $:.each do |lp|
123
+ logger.debug("#{pos} #{lp}")
124
+ pos += 1
125
+ end
126
+ end
127
+ end # of class LogHelper
128
+ #
129
+ # Module level configuration
130
+ #
131
+ class Configurator
132
+
133
+ # The final options, merged from the defaults, the config file, and the
134
+ # command line.
135
+ #--
136
+ # Should this be 'read' only after construction ????
137
+ attr_accessor :opts
138
+
139
+ def initialize
140
+
141
+ @opts = nil
142
+ @defaults = {
143
+ #
144
+ # For clarity maintain the same order here as below in the 'getopts'
145
+ # method!!!!
146
+ #
147
+ :auth => false, # -a
148
+ :host => "127.0.0.1", # -b
149
+ :checkpoint => 0, # -c
150
+ :config => 'stompserver.conf', # -C
151
+ :debug => false, # -d
152
+ :logdir => 'log', # -D
153
+ :log_level => 'error', # -l
154
+ :logfile => 'stompserver.log', # -L
155
+ :port => 61613, # -p
156
+ :pidfile => 'stompserver.pid', # -P
157
+ :queue => 'memory', # -q
158
+ :storage => ".stompserver", # -s
159
+ :session_cache => 0, # -S
160
+ :working_dir => Dir.getwd, # -w
161
+ :dbyml => 'database.yml', # -y
162
+ :daemon => false # -z
163
+ }
164
+ # Get a crude logger
165
+ @@log = Logger.new(STDOUT)
166
+
167
+ # Show version numbers regardless
168
+ StompServer::LogHelper.showversion(@@log)
169
+
170
+ # Options handling
171
+ @opts = getopts() # get and merge the options
172
+
173
+ # Finalize logger level handling
174
+ @@log.debug "Logger Level Requested: #{@opts[:log_level].upcase}"
175
+ StompServer::LogHelper.set_loglevel(@opts)
176
+
177
+ # Show Load Path
178
+ StompServer::LogHelper.showloadpath(@@log)
179
+
180
+ @@log.level = StompServer::LogHelper.get_loglevel()
181
+
182
+ # Turn on $DEBUG for extra debugging info if requested
183
+ if opts[:debug]
184
+ $DEBUG=true
185
+ @@log.debug "-d / --debug set, $DEBUG is true"
186
+ end
187
+
188
+ # Configuration is complete!
189
+ @@log.debug("#{self.class} Configuration complete")
190
+ end
191
+
192
+ def getopts()
193
+
194
+ # New Options Parser
195
+ opts_parser = OptionParser.new
196
+
197
+ # Empty Hash for parser values
198
+ hopts = {}
199
+
200
+ # :auth
201
+ opts_parser.on("-a", "--auth", String,
202
+ "Require client authorization") {|a|
203
+ hopts[:auth] = true}
204
+
205
+ # :host
206
+ opts_parser.on("-b", "--host=ADDR", String,
207
+ "Change the host (default: localhost)") {|a|
208
+ hopts[:host] = a}
209
+
210
+ # :checkpoint
211
+ opts_parser.on("-c", "--checkpoint=SECONDS", Integer,
212
+ "Time between checkpointing the queues in seconds (default: 0)") {|c|
213
+ hopts[:checkpoint] = c}
214
+
215
+ # :config
216
+ opts_parser.on("-C", "--config=CONFIGFILE", String,
217
+ "Configuration File (default: stompserver.conf)") {|c|
218
+ hopts[:config] = c}
219
+
220
+ # :debug
221
+ opts_parser.on("-d", "--debug", String,
222
+ "Turn on debug messages") {|d|
223
+ hopts[:debug] = true}
224
+
225
+ # :logdir
226
+ opts_parser.on("-D", "--logdir=LOGDIR", String,
227
+ "Log file directory (default: log)") {|d|
228
+ hopts[:logdir] = d} # new
229
+
230
+ # :log_level
231
+ opts_parser.on("-l", "--log_level=LEVEL", String,
232
+ "Logger Level (default: ERROR)") {|l|
233
+ hopts[:log_level] = l}
234
+
235
+ # :logfile
236
+ opts_parser.on("-L", "--logfile=LOGFILE", String,
237
+ "Log file name (default: stompserver.log") {|l|
238
+ hopts[:logfile] = l} # new
239
+
240
+ # :port
241
+ opts_parser.on("-p", "--port=PORT", Integer,
242
+ "Change the port (default: 61613)") {|p|
243
+ hopts[:port] = p}
244
+
245
+ # :pidfile
246
+ opts_parser.on("-P", "--pidfile=PIDFILE", Integer,
247
+ "PID file name (default: stompserver.pid)") {|p|
248
+ hopts[:pidfile] = p} # new
249
+
250
+ # :queue
251
+ opts_parser.on("-q", "--queuetype=QUEUETYPE", String,
252
+ "Queue type (memory|dbm|activerecord|file) (default: memory)") {|q|
253
+ hopts[:queue] = q}
254
+
255
+ # :storage
256
+ opts_parser.on("-s", "--storage=DIR", String,
257
+ "Change the storage directory (default: .stompserver, relative to working_dir)") {|s|
258
+ hopts[:storage] = s}
259
+
260
+ # :session_cache
261
+ opts_parser.on("-S", "--session_cache=SIZE", Integer,
262
+ "session ID cache size (default: 0, disable session ID cache)") {|s|
263
+ hopts[:session_cache] = s}
264
+
265
+ # :working_dir
266
+ opts_parser.on("-w", "--working_dir=DIR", String,
267
+ "Change the working directory (default: current directory)") {|s|
268
+ hopts[:working_dir] = s}
269
+
270
+ # :dbyml
271
+ opts_parser.on("-y", "--dbyml=YMLFILE", String,
272
+ "Database .yml file name (default: database.yml)") {|y|
273
+ hopts[:dbyml] = y}
274
+
275
+ # :daemon
276
+ opts_parser.on("-z", "--daemon", String,
277
+ "Daemonize server process") {|d|
278
+ hopts[:daemon] = true}
279
+
280
+ # Handle help if required
281
+ opts_parser.on("-h", "--help", "Show this message") do
282
+ puts opts_parser
283
+ exit
284
+ end
285
+
286
+ opts_parser.parse(ARGV)
287
+
288
+ # Handle the config file
289
+ config_found = false
290
+ # Load a default config file first if it exists.
291
+ loaded_opts = {}
292
+ full_path_default = File.expand_path(@defaults[:config])
293
+ if File.exists?(full_path_default)
294
+ @@log.debug("Loading config file defaults from: #{full_path_default}")
295
+ loaded_opts.merge!(YAML.load_file(full_path_default))
296
+ @defaults[:config] = full_path_default
297
+ config_found = true
298
+ end
299
+ # If a command line specified config file exists, overlay any new
300
+ # parameters in that file.
301
+ if hopts[:config]
302
+ full_path_cl = File.expand_path(hopts[:config])
303
+ if File.exists?(full_path_cl)
304
+ @@log.debug("Loading config file overrides from: #{full_path_cl}")
305
+ loaded_opts.merge!(YAML.load_file(full_path_cl))
306
+ hopts[:config] = full_path_cl
307
+ config_found = true
308
+ end
309
+ end
310
+ @@log.warn("No configuration file found.") unless config_found
311
+
312
+ # Run basic required merges on all the options
313
+ opts = {} # set to empty
314
+ opts = opts.merge(@defaults) # 01 = merge in defaults
315
+ opts = opts.merge(loaded_opts) # 02 = merge in loaded from config file
316
+ opts = opts.merge(hopts) # 03 = merge in command line options
317
+
318
+ # Last but not least: Miscellaneous file definitions
319
+ opts[:etcdir] = File.join(opts[:working_dir],'etc') # Define ':etcdir'
320
+ opts[:storage] = File.join(opts[:working_dir],opts[:storage]) # Override! ':storage'
321
+ opts[:logdir] = File.join(opts[:working_dir],opts[:logdir]) # Override! ':logdir'
322
+ opts[:logfile] = File.join(opts[:logdir],opts[:logfile]) # Override! ':logfile'
323
+ opts[:pidfile] = File.join(opts[:logdir],opts[:pidfile]) # Override! ':pidfile'
324
+ # :dbyml will be a full path and file name
325
+ unless File.exists?(File.expand_path(opts[:dbyml]))
326
+ opts[:dbyml] = File.join(opts[:etcdir],opts[:dbyml]) # Override! ':dbyml'
327
+ else
328
+ opts[:dbyml] = File.expand_path(opts[:dbyml])
329
+ end
330
+
331
+ # Authorization - working file
332
+ if opts[:auth]
333
+ opts[:passwd] = File.join(opts[:etcdir],'.passwd')
334
+ end
335
+
336
+ # Return merged values (in Hash)
337
+ return opts
338
+ end
339
+ end
340
+
341
+ #
342
+ # Run server start up.
343
+ #
344
+ class Run
345
+ #
346
+ attr_accessor :queue_manager, :auth_required, :stompauth, :topic_manager
347
+
348
+ #
349
+ attr_accessor :session_cache
350
+
351
+ # Intiialize
352
+ def initialize(opts)
353
+ @@log = Logger.new(STDOUT)
354
+ @@log.level = StompServer::LogHelper.get_loglevel()
355
+
356
+ @opts = opts
357
+ @queue_manager = nil
358
+ @auth_required = nil
359
+ @stompauth = nil
360
+ @topic_manager = nil
361
+ @session_cache = nil
362
+ @@log.debug("#{self.class} Run class initialize method complete")
363
+ end
364
+
365
+ # Server stop on SIGINT or SIGTERM
366
+ def stop(pidfile)
367
+ @queue_manager.stop("KILL_ISSUED")
368
+ @@log.debug "Stompserver #{StompServer::VERSION} shutting down"
369
+ STDOUT.flush
370
+ EventMachine::stop_event_loop
371
+ File.delete(pidfile)
372
+ end
373
+
374
+ # Startup
375
+ def start
376
+ @@log.debug("#{self.class}.start begins")
377
+
378
+ # Handle group priviliges!
379
+ # N.B.: Handle these options from the command line ?????????
380
+ begin
381
+ if @opts[:group]
382
+ @@log.debug "Changing group to #{@opts[:group]}."
383
+ Process::GID.change_privilege(Etc.getgrnam(@opts[:group]).gid)
384
+ end
385
+
386
+ if @opts[:user]
387
+ @@log.debug "Changing user to #{@opts[:user]}."
388
+ Process::UID.change_privilege(Etc.getpwnam(@opts[:user]).uid)
389
+ end
390
+ rescue Errno::EPERM
391
+ @@log.error "FAILED to change user:group #{@opts[:user]}:#{@opts[:group]}: #$!"
392
+ exit 1
393
+ end
394
+
395
+ # Make required directories unless they already exist
396
+ Dir.mkdir(@opts[:working_dir]) unless File.directory?(@opts[:working_dir])
397
+ Dir.mkdir(@opts[:logdir]) unless File.directory?(@opts[:logdir])
398
+ Dir.mkdir(@opts[:etcdir]) unless File.directory?(@opts[:etcdir])
399
+
400
+ # Determine qstore type
401
+ if @opts[:queue] == 'dbm'
402
+ qstore=StompServer::DBMQueue.new(@opts[:storage])
403
+ @@log.debug "Queue storage is DBM"
404
+ elsif @opts[:queue] == 'file'
405
+ qstore=StompServer::FileQueue.new(@opts[:storage])
406
+ @@log.debug "Queue storage is FILE"
407
+ elsif @opts[:queue] == 'activerecord'
408
+ require 'stomp_server_ng/queue/activerecord_queue'
409
+ qstore=StompServer::ActiveRecordQueue.new(@opts[:etcdir], @opts[:storage], @opts[:dbyml])
410
+ @@log.debug "Queue storage is ActiveRecord"
411
+ else
412
+ qstore=StompServer::MemoryQueue.new
413
+ @@log.debug "Queue storage is MEMORY"
414
+ end
415
+
416
+ # Set checkpoint interval
417
+ qstore.checkpoint_interval = @opts[:checkpoint]
418
+ @@log.debug "Checkpoint interval is #{qstore.checkpoint_interval}" if $DEBUG
419
+
420
+ #
421
+ @topic_manager = StompServer::TopicManager.new
422
+ @queue_manager = StompServer::QueueManager.new(qstore)
423
+ @@log.debug("Managers are initialized.")
424
+ @@log.debug("Topic Manager: #{@topic_manager}")
425
+ @@log.debug("Queue Manager: #{@queue_manager}")
426
+
427
+ # Authorization: requirement
428
+ @auth_required = @opts[:auth]
429
+ if @auth_required
430
+ @stompauth = StompServer::StompAuth.new(@opts[:passwd])
431
+ end
432
+
433
+ # Initialize session ID cache
434
+ if @opts[:session_cache] > 0
435
+ StompServer::SessionIDManager.initialize_cache(@opts[:session_cache])
436
+ StompServer::SessionIDManager.dump_cache(@@log);
437
+ end
438
+
439
+ # If we are going to daemonize, it should be almost the last
440
+ # thing we do here.
441
+ @@log.debug("#{self.class}.start Daemonize: #{@opts[:daemon]}")
442
+ if @opts[:daemon]
443
+ @@log.debug("#{self.class}.start going to background")
444
+ @@log.debug("#{self.class}.start check #{@opts[:logfile]}")
445
+
446
+ StompServer::LogHelper.showversion(@@log)
447
+
448
+ STDOUT.flush # clear the decks
449
+ Daemonize.daemonize(log_file=@opts[:logfile])
450
+ # change back to the original starting directory
451
+ Dir.chdir(@opts[:working_dir])
452
+ end
453
+
454
+ # But write pidfile only after possible daemonization
455
+ curr_pid = Process.pid
456
+ open(@opts[:pidfile],"w") {|f| f.write(curr_pid) }
457
+ @@log.debug("Pid File Contents: #{curr_pid}")
458
+
459
+ # OK, log and set the SIGINT signal handler.
460
+ @@log.debug("#{self.class}.start setting trap at completion")
461
+ StompServer::LogHelper.showversion(@@log) # one more time at startup
462
+ # Show Load Path
463
+ StompServer::LogHelper.showloadpath(@@log)
464
+ StompServer::LogHelper.showoptions(@@log, @opts) # Dump runtime options
465
+ trap("INT") { @@log.debug "INT signal received.";stop(@opts[:pidfile]) }
466
+ trap("TERM") { @@log.debug "TERM signal received.";stop(@opts[:pidfile]) }
467
+ end
468
+ end # of class Run
469
+ #
470
+ end # of module StompServer
471
+