dango 0.3.9 → 0.4.0
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/LICENSE +17 -12
- data/lib/dango/dango_g_server.rb +293 -0
- data/lib/dango/server_framework.rb +22 -41
- data/lib/dango/version.rb +2 -2
- metadata +3 -2
data/LICENSE
CHANGED
@@ -1,16 +1,21 @@
|
|
1
|
-
Copyright (C) 2007 Keisuke Minami
|
1
|
+
Copyright (C) 2007-2008 Keisuke Minami
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
11
|
-
Lesser General Public License for more details.
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
16
21
|
|
@@ -0,0 +1,293 @@
|
|
1
|
+
#!ruby -Ku
|
2
|
+
|
3
|
+
=begin
|
4
|
+
= GServerを使うために継承
|
5
|
+
=end
|
6
|
+
|
7
|
+
|
8
|
+
#
|
9
|
+
# Copyright (C) 2001 John W. Small All Rights Reserved
|
10
|
+
#
|
11
|
+
# Author:: John W. Small
|
12
|
+
# Documentation:: Gavin Sinclair
|
13
|
+
# Licence:: Freeware.
|
14
|
+
#
|
15
|
+
# See the class GServer for documentation.
|
16
|
+
#
|
17
|
+
|
18
|
+
require "socket"
|
19
|
+
require "thread"
|
20
|
+
|
21
|
+
#
|
22
|
+
# GServer implements a generic server, featuring thread pool management,
|
23
|
+
# simple logging, and multi-server management. See HttpServer in
|
24
|
+
# <tt>xmlrpc/httpserver.rb</tt> in the Ruby standard library for an example of
|
25
|
+
# GServer in action.
|
26
|
+
#
|
27
|
+
# Any kind of application-level server can be implemented using this class.
|
28
|
+
# It accepts multiple simultaneous connections from clients, up to an optional
|
29
|
+
# maximum number. Several _services_ (i.e. one service per TCP port) can be
|
30
|
+
# run simultaneously, and stopped at any time through the class method
|
31
|
+
# <tt>GServer.stop(port)</tt>. All the threading issues are handled, saving
|
32
|
+
# you the effort. All events are optionally logged, but you can provide your
|
33
|
+
# own event handlers if you wish.
|
34
|
+
#
|
35
|
+
# === Example
|
36
|
+
#
|
37
|
+
# Using GServer is simple. Below we implement a simple time server, run it,
|
38
|
+
# query it, and shut it down. Try this code in +irb+:
|
39
|
+
#
|
40
|
+
# require 'gserver'
|
41
|
+
#
|
42
|
+
# #
|
43
|
+
# # A server that returns the time in seconds since 1970.
|
44
|
+
# #
|
45
|
+
# class TimeServer < GServer
|
46
|
+
# def initialize(port=10001, *args)
|
47
|
+
# super(port, *args)
|
48
|
+
# end
|
49
|
+
# def serve(io)
|
50
|
+
# io.puts(Time.now.to_i)
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# # Run the server with logging enabled (it's a separate thread).
|
55
|
+
# server = TimeServer.new
|
56
|
+
# server.audit = true # Turn logging on.
|
57
|
+
# server.start
|
58
|
+
#
|
59
|
+
# # *** Now point your browser to http://localhost:10001 to see it working ***
|
60
|
+
#
|
61
|
+
# # See if it's still running.
|
62
|
+
# GServer.in_service?(10001) # -> true
|
63
|
+
# server.stopped? # -> false
|
64
|
+
#
|
65
|
+
# # Shut the server down gracefully.
|
66
|
+
# server.shutdown
|
67
|
+
#
|
68
|
+
# # Alternatively, stop it immediately.
|
69
|
+
# GServer.stop(10001)
|
70
|
+
# # or, of course, "server.stop".
|
71
|
+
#
|
72
|
+
# All the business of accepting connections and exception handling is taken
|
73
|
+
# care of. All we have to do is implement the method that actually serves the
|
74
|
+
# client.
|
75
|
+
#
|
76
|
+
# === Advanced
|
77
|
+
#
|
78
|
+
# As the example above shows, the way to use GServer is to subclass it to
|
79
|
+
# create a specific server, overriding the +serve+ method. You can override
|
80
|
+
# other methods as well if you wish, perhaps to collect statistics, or emit
|
81
|
+
# more detailed logging.
|
82
|
+
#
|
83
|
+
# connecting
|
84
|
+
# disconnecting
|
85
|
+
# starting
|
86
|
+
# stopping
|
87
|
+
#
|
88
|
+
# The above methods are only called if auditing is enabled.
|
89
|
+
#
|
90
|
+
# You can also override +log+ and +error+ if, for example, you wish to use a
|
91
|
+
# more sophisticated logging system.
|
92
|
+
#
|
93
|
+
class GServer
|
94
|
+
|
95
|
+
DEFAULT_HOST = "127.0.0.1"
|
96
|
+
|
97
|
+
def serve(io)
|
98
|
+
end
|
99
|
+
|
100
|
+
@@services = {} # Hash of opened ports, i.e. services
|
101
|
+
@@servicesMutex = Mutex.new
|
102
|
+
|
103
|
+
def GServer.stop(port, host = DEFAULT_HOST)
|
104
|
+
@@servicesMutex.synchronize {
|
105
|
+
@@services[host][port].stop
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def GServer.in_service?(port, host = DEFAULT_HOST)
|
110
|
+
@@services.has_key?(host) and
|
111
|
+
@@services[host].has_key?(port)
|
112
|
+
end
|
113
|
+
|
114
|
+
def stop
|
115
|
+
@connectionsMutex.synchronize {
|
116
|
+
if @tcpServerThread
|
117
|
+
@tcpServerThread.raise "stop"
|
118
|
+
end
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def stopped?
|
123
|
+
@tcpServerThread == nil
|
124
|
+
end
|
125
|
+
|
126
|
+
def shutdown
|
127
|
+
@shutdown = true
|
128
|
+
end
|
129
|
+
|
130
|
+
def connections
|
131
|
+
@connections.size
|
132
|
+
end
|
133
|
+
|
134
|
+
def join
|
135
|
+
@tcpServerThread.join if @tcpServerThread
|
136
|
+
end
|
137
|
+
|
138
|
+
attr_reader :port, :host, :maxConnections
|
139
|
+
attr_accessor :stdlog, :audit, :debug
|
140
|
+
|
141
|
+
def connecting(client)
|
142
|
+
addr = client.peeraddr
|
143
|
+
log("#{self.class.to_s} #{@host}:#{@port} client:#{addr[1]} " +
|
144
|
+
"#{addr[2]}<#{addr[3]}> connect")
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
def disconnecting(clientPort)
|
149
|
+
log("#{self.class.to_s} #{@host}:#{@port} " +
|
150
|
+
"client:#{clientPort} disconnect")
|
151
|
+
end
|
152
|
+
|
153
|
+
protected :connecting, :disconnecting
|
154
|
+
|
155
|
+
def starting()
|
156
|
+
log("#{self.class.to_s} #{@host}:#{@port} start")
|
157
|
+
end
|
158
|
+
|
159
|
+
def stopping()
|
160
|
+
log("#{self.class.to_s} #{@host}:#{@port} stop")
|
161
|
+
end
|
162
|
+
|
163
|
+
protected :starting, :stopping
|
164
|
+
|
165
|
+
def error(detail)
|
166
|
+
log(detail.backtrace.join("\n"))
|
167
|
+
end
|
168
|
+
|
169
|
+
def log(msg)
|
170
|
+
if @stdlog
|
171
|
+
@stdlog.puts("[#{Time.new.ctime}] %s" % msg)
|
172
|
+
@stdlog.flush
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
protected :error, :log
|
177
|
+
|
178
|
+
def initialize(port, host = DEFAULT_HOST, maxConnections = 4,
|
179
|
+
stdlog = $stderr, audit = false, debug = false)
|
180
|
+
@tcpServerThread = nil
|
181
|
+
@port = port
|
182
|
+
@host = host
|
183
|
+
@maxConnections = maxConnections
|
184
|
+
@connections = []
|
185
|
+
@connectionsMutex = Mutex.new
|
186
|
+
@connectionsCV = ConditionVariable.new
|
187
|
+
@stdlog = stdlog
|
188
|
+
@audit = audit
|
189
|
+
@debug = debug
|
190
|
+
end
|
191
|
+
|
192
|
+
def start(maxConnections = -1, backlog = nil) # この部分を改造
|
193
|
+
raise "running" if !stopped?
|
194
|
+
@shutdown = false
|
195
|
+
@maxConnections = maxConnections if maxConnections > 0
|
196
|
+
@@servicesMutex.synchronize {
|
197
|
+
if GServer.in_service?(@port,@host)
|
198
|
+
raise "Port already in use: #{host}:#{@port}!"
|
199
|
+
end
|
200
|
+
@tcpServer = TCPServer.new(@host,@port)
|
201
|
+
@tcpServer.listen(backlog) if backlog # この部分を改造
|
202
|
+
@port = @tcpServer.addr[1]
|
203
|
+
@@services[@host] = {} unless @@services.has_key?(@host)
|
204
|
+
@@services[@host][@port] = self;
|
205
|
+
}
|
206
|
+
@tcpServerThread = Thread.new {
|
207
|
+
begin
|
208
|
+
starting if @audit
|
209
|
+
while !@shutdown
|
210
|
+
@connectionsMutex.synchronize {
|
211
|
+
while @connections.size >= @maxConnections
|
212
|
+
@connectionsCV.wait(@connectionsMutex)
|
213
|
+
end
|
214
|
+
}
|
215
|
+
client = @tcpServer.accept
|
216
|
+
@connections << Thread.new(client) { |myClient|
|
217
|
+
begin
|
218
|
+
myPort = myClient.peeraddr[1]
|
219
|
+
serve(myClient) if !@audit or connecting(myClient)
|
220
|
+
rescue => detail
|
221
|
+
error(detail) if @debug
|
222
|
+
ensure
|
223
|
+
begin
|
224
|
+
myClient.close
|
225
|
+
rescue
|
226
|
+
end
|
227
|
+
@connectionsMutex.synchronize {
|
228
|
+
@connections.delete(Thread.current)
|
229
|
+
@connectionsCV.signal
|
230
|
+
}
|
231
|
+
disconnecting(myPort) if @audit
|
232
|
+
end
|
233
|
+
}
|
234
|
+
end
|
235
|
+
rescue => detail
|
236
|
+
error(detail) if @debug
|
237
|
+
ensure
|
238
|
+
begin
|
239
|
+
@tcpServer.close
|
240
|
+
rescue
|
241
|
+
end
|
242
|
+
if @shutdown
|
243
|
+
@connectionsMutex.synchronize {
|
244
|
+
while @connections.size > 0
|
245
|
+
@connectionsCV.wait(@connectionsMutex)
|
246
|
+
end
|
247
|
+
}
|
248
|
+
else
|
249
|
+
@connections.each { |c| c.raise "stop" }
|
250
|
+
end
|
251
|
+
@tcpServerThread = nil
|
252
|
+
@@servicesMutex.synchronize {
|
253
|
+
@@services[@host].delete(@port)
|
254
|
+
}
|
255
|
+
stopping if @audit
|
256
|
+
end
|
257
|
+
}
|
258
|
+
self
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
262
|
+
|
263
|
+
|
264
|
+
#require "gserver"
|
265
|
+
class DangoGServer < GServer
|
266
|
+
def initialize(parent, *args)
|
267
|
+
@parent = parent
|
268
|
+
super(*args)
|
269
|
+
end
|
270
|
+
|
271
|
+
def serve(sock)
|
272
|
+
@parent.thread_main(sock)
|
273
|
+
end
|
274
|
+
|
275
|
+
def connecting(sock)
|
276
|
+
@parent.connecting(sock)
|
277
|
+
end
|
278
|
+
|
279
|
+
def disconnecting(sock)
|
280
|
+
@parent.disconnecting(sock)
|
281
|
+
end
|
282
|
+
|
283
|
+
def starting()
|
284
|
+
log("#{self.class.to_s} #{@host}:#{@port} start")
|
285
|
+
@parent.starting()
|
286
|
+
end
|
287
|
+
|
288
|
+
def stopping()
|
289
|
+
log("#{self.class.to_s} #{@host}:#{@port} stop")
|
290
|
+
@parent.stopping()
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
@@ -4,7 +4,6 @@
|
|
4
4
|
= コネクション型サーバーフレームワーク
|
5
5
|
=end
|
6
6
|
|
7
|
-
require 'gserver'
|
8
7
|
require 'digest/md5'
|
9
8
|
|
10
9
|
require "dango/framework_base"
|
@@ -16,6 +15,8 @@ require "dango/monitor/server_monitor_action"
|
|
16
15
|
|
17
16
|
# フレームワーククラス
|
18
17
|
class DangoServerFramework
|
18
|
+
require "dango/dango_g_server"
|
19
|
+
|
19
20
|
include DangoFrameworkModule
|
20
21
|
|
21
22
|
RAILS_ENV = ENV['RAILS_ENV'] || 'development'
|
@@ -47,35 +48,6 @@ class DangoServerFramework
|
|
47
48
|
|
48
49
|
MainLoopWaitSec = 3.0 # メインループの待ち時間(サーバー内ファイルのチェック時間)
|
49
50
|
|
50
|
-
class DangoGServer < GServer
|
51
|
-
def initialize(parent, *args)
|
52
|
-
@parent = parent
|
53
|
-
super(*args)
|
54
|
-
end
|
55
|
-
|
56
|
-
def serve(sock)
|
57
|
-
@parent.thread_main(sock)
|
58
|
-
end
|
59
|
-
|
60
|
-
def connecting(sock)
|
61
|
-
@parent.connecting(sock)
|
62
|
-
end
|
63
|
-
|
64
|
-
def disconnecting(sock)
|
65
|
-
@parent.disconnecting(sock)
|
66
|
-
end
|
67
|
-
|
68
|
-
def starting()
|
69
|
-
log("#{self.class.to_s} #{@host}:#{@port} start")
|
70
|
-
@parent.starting()
|
71
|
-
end
|
72
|
-
|
73
|
-
def stopping()
|
74
|
-
log("#{self.class.to_s} #{@host}:#{@port} stop")
|
75
|
-
@parent.stopping()
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
51
|
def stop_gserver() # gserverの停止
|
80
52
|
if @gserver && !@gserver.stopped?
|
81
53
|
# 強制的に接続しているsocketをクローズ
|
@@ -90,10 +62,6 @@ class DangoServerFramework
|
|
90
62
|
# サーバーを停止
|
91
63
|
@gserver.shutdown
|
92
64
|
@gserver.stop
|
93
|
-
# while(!@gserver.stopped?) do
|
94
|
-
# sleep ServerStopWait
|
95
|
-
# debug_print("waiting... #{@gserver.stopped?} #{@gserver.connections}")
|
96
|
-
# end
|
97
65
|
10.times do
|
98
66
|
break if @gserver.stopped?
|
99
67
|
sleep ServerStopWait
|
@@ -209,7 +177,8 @@ class DangoServerFramework
|
|
209
177
|
GC.disable
|
210
178
|
open(@pid_file, "wb"){|fh| fh.write Process.pid.to_s } # pidをファイルに保存
|
211
179
|
|
212
|
-
@gserver.start
|
180
|
+
# @gserver.start(@server_max_connections)
|
181
|
+
@gserver.start(@server_max_connections, 20) # backlogを20に設定
|
213
182
|
|
214
183
|
rescue Exception
|
215
184
|
error_print("#{error_message($!, 'u')}")
|
@@ -341,14 +310,15 @@ class DangoServerFramework
|
|
341
310
|
end
|
342
311
|
|
343
312
|
if is_flash_policy_file # Flashのポリシーファイルが来たら
|
344
|
-
logger.
|
313
|
+
logger.debug "is_flash_policy_file"
|
345
314
|
|
346
315
|
if @policy_file_request # ポリシーファイルを返す設定なら
|
347
316
|
logger.info "is_flash_policy_file #{sid} #{@policy_file_request}"
|
348
317
|
|
349
318
|
allow_str = ""
|
319
|
+
|
350
320
|
@policy_file_allow_domain.each do |one_host|
|
351
|
-
allow_str += %Q|<allow-access-from domain="#{one_host}" to-ports="#{@
|
321
|
+
allow_str += %Q|<allow-access-from domain="#{one_host}" to-ports="#{@policy_file_allow_port.join(',')}" />|
|
352
322
|
allow_str += "\n"
|
353
323
|
end
|
354
324
|
|
@@ -504,11 +474,9 @@ EOF
|
|
504
474
|
|
505
475
|
# 各種サーバー仕様の変数設定
|
506
476
|
def set_server_variables()
|
507
|
-
# debug
|
508
|
-
@server_debug = @config['server']['debug'] || false
|
509
|
-
Thread.abort_on_exception = true if @server_debug
|
510
|
-
|
511
477
|
# 変数の初期設定
|
478
|
+
@server_debug = @config['server']['debug'] || true
|
479
|
+
|
512
480
|
@network_port = @config['network']['port'] || DefaultNetworkPort
|
513
481
|
@network_host = @config['network']['host'] || DefaultNetworkHost
|
514
482
|
@server_host = @config['server']['host'] || DefaultServerHost
|
@@ -533,6 +501,9 @@ EOF
|
|
533
501
|
@policy_file_allow_domain = @config['server']['policy_file_allow_domain']
|
534
502
|
@policy_file_allow_domain = [@network_host] if @policy_file_allow_domain.class != Array
|
535
503
|
|
504
|
+
@policy_file_allow_port = @config['server']['policy_file_allow_port']
|
505
|
+
@policy_file_allow_port = [@network_port] if !@policy_file_allow_port
|
506
|
+
|
536
507
|
@safe_resolver = @config['server']['safe_resolver'] || false # require 'resolv-replace'するかどうか
|
537
508
|
|
538
509
|
@statistics_process_memory = @config['server']['statistics_process_memory'] || false # プロセスのメモリ使用量統計を取る
|
@@ -558,6 +529,9 @@ EOF
|
|
558
529
|
@log_level_str = str if const == @log_level
|
559
530
|
end
|
560
531
|
|
532
|
+
# スレッド終了時に全体停止する
|
533
|
+
Thread.abort_on_exception = true if @server_debug
|
534
|
+
|
561
535
|
# 統計用情報の初期化
|
562
536
|
@start_time = Time.now # サーバー起動時間
|
563
537
|
@recv_count = 0 # 受信回数
|
@@ -790,6 +764,8 @@ EOF
|
|
790
764
|
def thread_send_notice_queue()
|
791
765
|
loop do
|
792
766
|
begin
|
767
|
+
before_time = Time.now
|
768
|
+
|
793
769
|
send_data_list = []
|
794
770
|
|
795
771
|
pop_data = @queue_send_notice.pop
|
@@ -839,6 +815,11 @@ EOF
|
|
839
815
|
end
|
840
816
|
end
|
841
817
|
|
818
|
+
send_sec = Time.now - before_time
|
819
|
+
if send_sec > @send_receive_sleep_interval_sec
|
820
|
+
logger.debug "thread_send_notice_queue:send_sec=#{send_sec}sec"
|
821
|
+
end
|
822
|
+
|
842
823
|
sleep @send_receive_sleep_interval_sec # スリープ
|
843
824
|
|
844
825
|
rescue Exception
|
data/lib/dango/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dango
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keisuke Minami
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-09-
|
12
|
+
date: 2008-09-11 00:00:00 +09:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -60,6 +60,7 @@ files:
|
|
60
60
|
- lib/dango/mutex_socket_list.rb
|
61
61
|
- lib/dango/socket_list.rb
|
62
62
|
- lib/dango/session_manager.rb
|
63
|
+
- lib/dango/dango_g_server.rb
|
63
64
|
- lib/dango/controller_plugin/dango_controller_plugin.rb
|
64
65
|
- lib/dango/monitor/dango_monitor_client.rb
|
65
66
|
- lib/dango/monitor/server_monitor_action.rb
|