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.
- data/History.txt +159 -0
- data/Manifest.txt +71 -0
- data/README.txt +172 -0
- data/Rakefile +38 -0
- data/STATUS +5 -0
- data/bin/stompserver_ng +63 -0
- data/client/README.txt +1 -0
- data/client/both.rb +25 -0
- data/client/consume.rb +14 -0
- data/client/send.rb +17 -0
- data/config/stompserver_ng.conf +11 -0
- data/etc/19xcompat/notes.txt +223 -0
- data/etc/arutils/README-activerecord.txt +78 -0
- data/etc/arutils/cre_mysql.rb +34 -0
- data/etc/arutils/cre_postgres.rb +33 -0
- data/etc/arutils/cre_sqlite3.rb +28 -0
- data/etc/arutils/mysql_boot.sql +12 -0
- data/etc/arutils/postgres_boot.sql +14 -0
- data/etc/database.mysql.yml +9 -0
- data/etc/database.postgres.yml +9 -0
- data/etc/passwd.example +3 -0
- data/etc/ppqinfo.rb +15 -0
- data/etc/runserver.sh +17 -0
- data/etc/stompserver_ng +50 -0
- data/etc/stompserver_ng.conf +13 -0
- data/lib/stomp_server_ng.rb +471 -0
- data/lib/stomp_server_ng/protocols/http.rb +128 -0
- data/lib/stomp_server_ng/protocols/stomp.rb +407 -0
- data/lib/stomp_server_ng/qmonitor.rb +58 -0
- data/lib/stomp_server_ng/queue.rb +248 -0
- data/lib/stomp_server_ng/queue/activerecord_queue.rb +118 -0
- data/lib/stomp_server_ng/queue/ar_message.rb +21 -0
- data/lib/stomp_server_ng/queue/ar_reconnect.rb +18 -0
- data/lib/stomp_server_ng/queue/dbm_queue.rb +72 -0
- data/lib/stomp_server_ng/queue/file_queue.rb +56 -0
- data/lib/stomp_server_ng/queue/memory_queue.rb +64 -0
- data/lib/stomp_server_ng/queue_manager.rb +302 -0
- data/lib/stomp_server_ng/stomp_auth.rb +26 -0
- data/lib/stomp_server_ng/stomp_frame.rb +32 -0
- data/lib/stomp_server_ng/stomp_frame_recognizer.rb +77 -0
- data/lib/stomp_server_ng/stomp_id.rb +32 -0
- data/lib/stomp_server_ng/stomp_user.rb +17 -0
- data/lib/stomp_server_ng/test_server.rb +21 -0
- data/lib/stomp_server_ng/topic_manager.rb +46 -0
- data/setup.rb +1585 -0
- data/stompserver_ng.gemspec +136 -0
- data/test/devserver/props.yaml +5 -0
- data/test/devserver/runserver.sh +16 -0
- data/test/devserver/stompserver_ng.dbm.conf +12 -0
- data/test/devserver/stompserver_ng.file.conf +12 -0
- data/test/devserver/stompserver_ng.memory.conf +12 -0
- data/test/noserver/mocklogger.rb +12 -0
- data/test/noserver/test_queue_manager.rb +134 -0
- data/test/noserver/test_stomp_frame.rb +138 -0
- data/test/noserver/test_topic_manager.rb +79 -0
- data/test/noserver/ts_all_no_server.rb +12 -0
- data/test/props.yaml +5 -0
- data/test/runalltests.sh +14 -0
- data/test/runtest.sh +4 -0
- data/test/test_0000_base.rb +107 -0
- data/test/test_0001_conn.rb +47 -0
- data/test/test_0002_conn_sr.rb +94 -0
- data/test/test_0006_client.rb +41 -0
- data/test/test_0011_send_recv.rb +74 -0
- data/test/test_0015_ack_conn.rb +78 -0
- data/test/test_0017_ack_client.rb +78 -0
- data/test/test_0019_ack_no_ack.rb +145 -0
- data/test/test_0022_ack_noack_conn.rb +123 -0
- data/test/test_0030_subscr_id.rb +44 -0
- data/test/test_0040_receipt_conn.rb +87 -0
- data/test/ts_all_server.rb +10 -0
- 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
|
+
|
data/etc/passwd.example
ADDED
data/etc/ppqinfo.rb
ADDED
@@ -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
|
+
|
data/etc/runserver.sh
ADDED
@@ -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
|
data/etc/stompserver_ng
ADDED
@@ -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,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
|
+
|