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 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