dango 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -58,6 +58,7 @@ class DangoFrameworkDisconnectException < DangoFrameworkException; end
58
58
  class DangoFrameworkReadNoDataException < DangoFrameworkException; end
59
59
  class DangoFrameworkFlashPolicyException < DangoFrameworkException; end
60
60
  class DangoFrameworkMonitorSecurityException < DangoFrameworkException; end
61
+ class DangoFrameworkTransactionException < DangoFrameworkException; end
61
62
 
62
63
  # エラー出力用モジュール
63
64
  module ErrorMessage
@@ -9,7 +9,6 @@ require 'digest/md5'
9
9
  require "dango/framework_base"
10
10
  require "dango/socket_list"
11
11
  require "dango/version"
12
- require "dango/mutex_socket_list"
13
12
  require "dango/session_manager"
14
13
  require "dango/monitor/server_monitor_action"
15
14
 
@@ -51,12 +50,12 @@ class DangoServerFramework
51
50
  def stop_gserver() # gserverの停止
52
51
  if @gserver && !@gserver.stopped?
53
52
  # 強制的に接続しているsocketをクローズ
54
- logger.info "socket_list.keys:#{socket_list.keys.inspect}"
55
- socket_list.keys.each do |sk|
56
- logger.debug "sk:#{socket_list[sk].inspect}"
57
- next if ! socket_list[sk]
58
- socket_list[sk].close if ! socket_list[sk].closed?
59
- socket_list[sk]
53
+ logger.info "socket_list.all_sid:#{socket_list.all_sid.inspect}"
54
+ socket_list.all_sid.each do |sid|
55
+ logger.debug "sk:#{socket_list[sid].inspect}"
56
+ next if ! socket_list[sid]
57
+ socket_list[sid].close if ! socket_list[sid].closed?
58
+ socket_list[sid]
60
59
  end
61
60
 
62
61
  # サーバーを停止
@@ -144,24 +143,24 @@ class DangoServerFramework
144
143
  logger.warn("Process.pid=#{Process.pid}")
145
144
  logger.warn("Dango Version=#{Dango::VERSION::STRING}")
146
145
  # logger.debug("$LOADED_FEATURES=#{$LOADED_FEATURES.pretty_inspect}")
147
-
148
- @session_manager = SessionManager.new # セッション情報の初期化
149
- shared_init() # 共有メモリを初期化
150
- socket_list_init() # ソケット一覧を初期化
151
- mutex_socket_list_init() # ソケット毎用のmutexを初期化
152
- @mutex_proc_thread = Mutex.new # スレッドが同時起動しないようにするためのMutex
153
- heart_beat_thread_start() # ハートビートスレッドの開始
154
- gc_thread_start() # GCスレッドの開始
155
-
156
- dango_server_init() # 初期設定読み込み
157
-
158
- @mutex_send_response = Mutex.new # 送信レスポンス用のMutex
159
- @arr_send_response = [] # 送信レスポンス用のキャッシュ
146
+
147
+ shared_init() # 共有メモリを初期化
148
+ socket_list_init() # ソケット一覧を初期化
149
+ @session_manager = SessionManager.new(shared) # セッション情報の初期化
150
+ @mutex_proc_thread = Mutex.new # スレッドが同時起動しないようにするためのMutex
151
+ heart_beat_thread_start() # ハートビートスレッドの開始
152
+ gc_thread_start() # GCスレッドの開始
153
+
154
+ dango_server_init() # 初期設定読み込み
155
+
156
+ @mutex_send_response = Mutex.new # 送信レスポンス用のMutex
157
+ @arr_send_response = [] # 送信レスポンス用のキャッシュ
158
+
160
159
 
161
160
  TCPSocket.do_not_reverse_lookup = true # 逆引きを行わない
162
161
  # TCPSocket.do_not_reverse_lookup = false # 逆引きを行う
163
162
 
164
- if @backdoor_run_drb_server # backdoor用のdrbを起動
163
+ if @backdoor_run_drb_server # backdoor用のdrbを起動
165
164
  uri = "druby://#{@network_host}:#{@backdoor_run_drb_port}"
166
165
  DRb.start_service(uri, self)
167
166
  logger.warn("start drb server: uri=#{DRb.uri}")
@@ -283,7 +282,6 @@ class DangoServerFramework
283
282
  logger.debug "thread_main:start_session. sid=#{sid} sock=#{sock} thread.current=#{Thread.current.object_id}"
284
283
 
285
284
  socket_list.add(sid, sock)
286
- mutex_socket_list.add(sid)
287
285
 
288
286
  session[:connected] = nil # まだdango_connectを呼び出していない
289
287
 
@@ -574,12 +572,6 @@ EOF
574
572
  end
575
573
  attr_accessor(:socket_list)
576
574
 
577
- # ソケット毎用のmutex
578
- def mutex_socket_list_init()
579
- @mutex_socket_list = MutexSocketList.new() # ソケット毎用のmutex
580
- end
581
- attr_accessor(:mutex_socket_list)
582
-
583
575
 
584
576
  # 接続時に呼び出されるメソッド
585
577
  def dango_connect
@@ -667,7 +659,7 @@ EOF
667
659
  heart_beat_time_hash = shared[:_heart_beat_time_hash]
668
660
 
669
661
  # 全員分のチェック
670
- socket_list.keys.each do |sid|
662
+ socket_list.all_sid.each do |sid|
671
663
  sock = socket_list[sid]
672
664
 
673
665
  if ! sock # すでにsocketが無い場合は、スキップ
@@ -694,7 +686,7 @@ EOF
694
686
  if logger.debug?
695
687
  count += 1
696
688
  if count % 100 == 0
697
- sids = socket_list.keys
689
+ sids = socket_list.all_sid
698
690
  thr_list = @thr_gr_gserver_serve.list.collect{|th| th.object_id }
699
691
 
700
692
  logger.debug "heart_beat_thread_start:sids=#{sids.inspect}"
@@ -719,6 +711,7 @@ EOF
719
711
  shared.transaction(:_heart_beat_time_hash) do |heart_beat_time_hash|
720
712
  heart_beat_time_hash[session[:sid]] = Time.now
721
713
  heart_beat_time_hash
714
+ shared.commit(heart_beat_time_hash)
722
715
  end
723
716
  end
724
717
 
@@ -4,12 +4,13 @@
4
4
  class SessionManager
5
5
  MaxSidCounter = 999999
6
6
 
7
- def initialize
7
+ def initialize(shared)
8
+ @shared = shared
8
9
  @session_list = {}
9
10
  @session_mutex = Mutex.new
10
11
 
11
- @sid_counter = 0
12
- @sid_list = {}
12
+ @shared[:_session_manager] = {}
13
+
13
14
  end
14
15
 
15
16
 
@@ -22,7 +23,7 @@ class SessionManager
22
23
  end
23
24
 
24
25
  # session終了
25
- def close_session()
26
+ def close_session(sid)
26
27
  @session_mutex.synchronize do
27
28
  drop_sid()
28
29
  @session_list[Thread.current.object_id] = nil
@@ -42,19 +43,37 @@ class SessionManager
42
43
  # sid情報作成
43
44
  def generate_sid()
44
45
  sid = nil
45
- while(sid == nil) do
46
- @sid_counter += 1
47
- @sid_counter = 1 if @sid_counter > MaxSidCounter
48
- sid = @sid_counter if ! @sid_list.has_key?(@sid_counter)
46
+ @shared.transaction(:_session_manager) do |ses_man|
47
+
48
+ ses_man[:sid_counter] = 0 if ! ses_man[:sid_counter]
49
+ ses_man[:sid_list] = {} if ! ses_man[:sid_list]
50
+
51
+ while(sid == nil) do
52
+ ses_man[:sid_counter] += 1
53
+ ses_man[:sid_counter] = 1 if ses_man[:sid_counter] > MaxSidCounter
54
+ sid = ses_man[:sid_counter] if ! ses_man[:sid_list].has_key?(ses_man[:sid_counter])
55
+ end
56
+
57
+ ses_man[:sid_list][ses_man[:sid_counter]] = "#{Process.pid}:#{Thread.current.object_id}"
58
+
59
+ ses_man
60
+ @shared.commit(ses_man)
49
61
  end
50
62
 
51
- @sid_list[sid] = Thread.current.object_id
52
63
  sid
53
64
  end
54
65
 
55
66
  # sid削除
56
67
  def drop_sid()
57
- @sid_list.delete_if{|sid, oid| oid == Thread.current.object_id }
68
+ @shared.transaction(:_session_manager) do |ses_man|
69
+
70
+ # ses_man[:sid_list].delete(sid)
71
+ ses_man[:sid_list].delete_if{|sid, oid| oid == "#{Process.pid}:#{Thread.current.object_id}" }
72
+
73
+ ses_man
74
+ @shared.commit(ses_man)
75
+ end
76
+
58
77
  self
59
78
  end
60
79
 
@@ -13,12 +13,19 @@ module DangoFrameworkModule
13
13
  @data = {}
14
14
  @mutex = {}
15
15
  @size = 0
16
+
17
+ @transact_key = {}
18
+ @transact_thread = {}
19
+ @transact_commit = {}
20
+ @transact_rollback = {}
21
+ @transact_data = {}
16
22
  end
17
23
 
18
24
  def keys
19
25
  @data.keys
20
26
  end
21
27
 
28
+ # ハッシュ形式で取得
22
29
  def to_hash
23
30
  hash = {}
24
31
  @data.each do |k, v|
@@ -27,18 +34,106 @@ module DangoFrameworkModule
27
34
  hash
28
35
  end
29
36
 
30
- def transaction(key) # トランザクション処理ブロックを作る
37
+ =begin
38
+ # 昔のトランザクション処理ロジック
39
+ def transaction(key)
31
40
  key = key.to_s
32
41
  if !@mutex.has_key?(key) # 未定義キーならエラー
33
42
  raise(DangoFrameworkException, "Shared key is not exist.")
34
43
  end
44
+
35
45
  @mutex[key].synchronize do
36
46
  # data = yield(@data[key].deep_dup)
37
47
  data = yield(@data[key])
38
48
  @data[key] = data.deep_dup
39
49
  end
50
+
51
+ self
52
+ end
53
+ def commit(key, value) # トランザクションのコミット処理
54
+ value
55
+ end
56
+ def rollback(key) # トランザクションのロールバック処理
57
+ end
58
+ =end
59
+
60
+ # トランザクション処理ブロックを作る(key単位のロック)
61
+ # このブロックの中でcommitかrollbackか例外発生を行わなければならない
62
+ def transaction(key)
63
+ key = key.to_s
64
+ if !@mutex.has_key?(key) # 未定義キーならエラー
65
+ raise(DangoFrameworkException, "Shared key is not exist.")
66
+ end
67
+
68
+ @mutex[key].synchronize do
69
+ @transact_key[Thread.current] = key # 違うスレッドからcommitできないように
70
+
71
+ raise("nested transaction #{key}") if @transact_thread.has_key?(key)
72
+ @transact_thread[key] = Thread.current
73
+ @transact_commit[key] = false
74
+ @transact_rollback[key] = false
75
+ @transact_data[key] = nil
76
+
77
+ begin
78
+ catch(:memory_store_finish_transaction) do
79
+ yield(@data[key].deep_dup)
80
+ end
81
+ rescue Exception # 例外発生の場合はrollbackとみなして、直前のエラーを再発生
82
+ @transact_rollback[key] = true
83
+ raise
84
+ ensure
85
+ @transact_thread.delete(key)
86
+
87
+ if @transact_commit[key] # commitされた場合 データ書き込み
88
+ @data[key] = @transact_data[key].deep_dup
89
+
90
+ elsif @transact_rollback[key] # rollbackがあった場合 何もしない
91
+
92
+ else # commitもrollbackもしていなければ
93
+ raise(DangoFrameworkTransactionException, "not found commit and rollback in transaction")
94
+ end
95
+
96
+ @transact_commit.delete(key)
97
+ @transact_rollback.delete(key)
98
+ @transact_data.delete(key)
99
+
100
+ @transact_key.delete(Thread.current)
101
+ end
102
+ end
103
+
104
+ self
105
+ end
106
+
107
+ def commit(value) # トランザクションのコミット処理
108
+ if ! @transact_key.has_key?(Thread.current)
109
+ raise(DangoFrameworkTransactionException, "this thread has not transaction #{Thread.current}")
110
+ end
111
+ key = @transact_key[Thread.current]
112
+
113
+ if @transact_thread[key] != Thread.current
114
+ raise(DangoFrameworkTransactionException, "not in transaction #{key}")
115
+ end
116
+
117
+ @transact_commit[key] = true
118
+ @transact_data[key] = value
119
+ throw(:memory_store_finish_transaction)
40
120
  end
41
121
 
122
+ def rollback() # トランザクションのロールバック処理
123
+ if ! @transact_key.has_key?(Thread.current)
124
+ raise(DangoFrameworkTransactionException, "this thread has not transaction #{Thread.current}")
125
+ end
126
+ key = @transact_key[Thread.current]
127
+
128
+ if @transact_thread[key] != Thread.current
129
+ raise(DangoFrameworkTransactionException, "not in transaction #{key}")
130
+ end
131
+
132
+ @transact_rollback[key] = true
133
+ throw(:memory_store_finish_transaction)
134
+ end
135
+
136
+
42
137
  def has_key?(key) # キーがあるかどうかを返す
43
138
  key = key.to_s
44
139
  @data.has_key?(key)
@@ -51,10 +146,13 @@ module DangoFrameworkModule
51
146
  # raise(DangoFrameworkException, "Shared key is not exist.")
52
147
  end
53
148
 
54
- @data[key].deep_dup
149
+ # @mutex[key].synchronize do
150
+ @data[key].deep_dup
151
+ # end
55
152
  end
56
153
 
57
154
  def []=(key, value)
155
+ key = key.to_s
58
156
  # キーはString Symbolのみ
59
157
  if key.class != String && key.class != Symbol
60
158
  raise(DangoFrameworkException, "Shared key is not String or Symbol.")
@@ -72,7 +170,7 @@ module DangoFrameworkModule
72
170
  @data[key] = value.deep_dup
73
171
  end
74
172
 
75
- nil
173
+ value
76
174
  end
77
175
  end
78
176
 
@@ -7,39 +7,31 @@ class SocketList
7
7
  @sl_mutex = Mutex.new
8
8
  end
9
9
 
10
- def keys()
10
+ def all_sid()
11
11
  @sl_mutex.synchronize do
12
12
  @sl_hash.keys
13
13
  end
14
14
  end
15
15
 
16
- def delete(key)
16
+ def delete(sid)
17
17
  @sl_mutex.synchronize do
18
- @sl_hash.delete(key)
18
+ @sl_hash.delete(sid)
19
19
  end
20
20
  end
21
21
 
22
- def add(key, sock)
22
+ def add(sid, sock)
23
23
  @sl_mutex.synchronize do
24
- raise("already exist key(#{key.inspect})") if @sl_hash.has_key?(key)
24
+ raise("already exist sid(#{sid.inspect})") if @sl_hash.has_key?(sid)
25
25
  raise("sock(#{sock.inspect}) is not Socket") if sock.kind_of?(Socket)
26
- @sl_hash[key] = sock
26
+ @sl_hash[sid] = sock
27
27
  end
28
28
  end
29
29
 
30
- def [](key)
30
+ def [](sid)
31
31
  @sl_mutex.synchronize do
32
- # raise("not exist key(#{key.inspect})") if ! @sl_hash.has_key?(key)
33
- return(nil) if ! @sl_hash.has_key?(key)
34
- @sl_hash[key]
35
- end
36
- end
37
-
38
- def []=(key, sock)
39
- @sl_mutex.synchronize do
40
- # raise("not exist key(#{key.inspect})") if ! @sl_hash.has_key?(key)
41
- raise("sock(#{sock.inspect}) is not Socket") if sock.kind_of?(Socket)
42
- @sl_hash[key] = sock
32
+ # raise("not exist sid(#{sid.inspect})") if ! @sl_hash.has_key?(sid)
33
+ return(nil) if ! @sl_hash.has_key?(sid)
34
+ @sl_hash[sid]
43
35
  end
44
36
  end
45
37
  end
@@ -218,6 +218,7 @@ class TestClient < DangoClientFramework
218
218
  send_receive_shared.transaction(:receive_cache) do |receive_cache|
219
219
  receive_cache.push([name, ret_obj, Time.now])
220
220
  receive_cache
221
+ send_receive_shared.commit(receive_cache)
221
222
  end
222
223
 
223
224
  else
@@ -269,14 +270,18 @@ class TestClient < DangoClientFramework
269
270
  send_receive_shared.transaction(:receive_cache) do |receive_cache|
270
271
  receive_cache.delete_at(receive_idx)
271
272
  receive_cache
273
+ send_receive_shared.commit(receive_cache)
272
274
  end
273
275
 
274
276
  # 古いreceive_cacheを削除しておく
275
277
  send_receive_shared.transaction(:receive_cache) do |receive_cache|
276
- receive_cache.select do |one_receive_cache|
278
+ receive_cache = receive_cache.select do |one_receive_cache|
277
279
  # true
278
280
  one_receive_cache[2] > Time.now - @receive_cache_auto_delete_sec
279
281
  end
282
+
283
+ receive_cache
284
+ send_receive_shared.commit(receive_cache)
280
285
  end
281
286
 
282
287
  receive_data[1]
@@ -292,6 +297,7 @@ class TestClient < DangoClientFramework
292
297
  true if (! notice_name) || (notice_name && one_rec_data[0] == notice_name)
293
298
  end
294
299
  receive_cache
300
+ send_receive_shared.commit(receive_cache)
295
301
  end
296
302
  end
297
303
 
data/lib/dango/version.rb CHANGED
@@ -2,7 +2,7 @@ module Dango #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 4
5
- TINY = 0
5
+ TINY = 1
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.4.0
4
+ version: 0.4.1
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-11 00:00:00 +09:00
12
+ date: 2008-09-17 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -57,7 +57,6 @@ files:
57
57
  - lib/dango/client_framework.rb
58
58
  - lib/dango/framework_base.rb
59
59
  - lib/dango/server_framework.rb
60
- - lib/dango/mutex_socket_list.rb
61
60
  - lib/dango/socket_list.rb
62
61
  - lib/dango/session_manager.rb
63
62
  - lib/dango/dango_g_server.rb
@@ -1,35 +0,0 @@
1
- #!ruby -Ku
2
-
3
- # ソケット毎用のmutex
4
- class MutexSocketList
5
- def initialize()
6
- @msl_hash = Hash.new
7
- end
8
-
9
- def keys()
10
- @msl_hash.keys
11
- end
12
-
13
- def delete(key)
14
- @msl_hash.delete(key)
15
- end
16
-
17
- def add(key)
18
- @msl_hash[key] = Mutex.new
19
- end
20
-
21
- # def [](key)
22
- # raise("not exist key(#{key})") if ! @msl_hash.has_key?(key)
23
- # add(key) if @msl_hash.has_key?(key)
24
- # @msl_hash[key]
25
- # end
26
-
27
- def synchronize(key)
28
- raise("not exist key(#{key})") if ! @msl_hash.has_key?(key)
29
- ret = nil
30
- @msl_hash[key].synchronize do
31
- ret = yield
32
- end
33
- ret
34
- end
35
- end