dango 0.3.9 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE CHANGED
@@ -1,16 +1,21 @@
1
- Copyright (C) 2007 Keisuke Minami
1
+ Copyright (C) 2007-2008 Keisuke Minami
2
2
 
3
- This library is free software; you can redistribute it and/or
4
- modify it under the terms of the GNU Lesser General Public
5
- License as published by the Free Software Foundation; either
6
- version 2.1 of the License, or (at your option) any later version.
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
- This library is distributed in the hope that it will be useful,
9
- but WITHOUT ANY WARRANTY; without even the implied warranty of
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
- You should have received a copy of the GNU Lesser General Public
14
- License along with this library; if not, write to the Free Software
15
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
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.info "is_flash_policy_file"
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="#{@network_port}" />|
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
@@ -1,8 +1,8 @@
1
1
  module Dango #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 3
5
- TINY = 9
4
+ MINOR = 4
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
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.3.9
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-03 00:00:00 +09:00
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