DeepConnect 0.4.06

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.
@@ -0,0 +1,127 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # serialize.rb -
4
+ # Copyright (C) 1996-2010 Keiju ISHITSUKA
5
+ # (Penta Advanced Labrabries, Co.,Ltd)
6
+ #
7
+ # --
8
+ #
9
+ #
10
+ #
11
+
12
+ require "deep-connect/reference"
13
+
14
+ module DeepConnect
15
+ UNSERIALIZABLE_CLASSES = [
16
+ Binding,
17
+ UnboundMethod,
18
+ Method,
19
+ Proc,
20
+ Dir,
21
+ File,
22
+ IO,
23
+ ThreadGroup,
24
+ Thread,
25
+ Data,
26
+ # Class,
27
+ # Module,
28
+ ]
29
+ if defined?(Continuation)
30
+ UNSERIALIZABLE_CLASSES.push Continuation
31
+ end
32
+ if defined?(StopIteration)
33
+ UNSERIALIZABLE_CLASSES.push StopIteration
34
+ end
35
+ if defined?(Enumerable::Enumerator)
36
+ UNSERIALIZABLE_CLASSES.push Enumerable::Enumerator
37
+ end
38
+
39
+ UNSERIALIZABLE_CLASS_SET = {}
40
+ UNSERIALIZABLE_CLASSES.each do|k|
41
+ UNSERIALIZABLE_CLASS_SET[k] = k
42
+ end
43
+ end
44
+
45
+ class Object
46
+ def self.deep_connect_materialize_val(deep_space, value)
47
+ obj = allocate
48
+ value.each do |v, o|
49
+ obj.instance_variable_set(v, DeepConnect::Reference.materialize(deep_space, *o))
50
+ end
51
+ obj
52
+ end
53
+
54
+ def deep_connect_serialize_val(deep_space)
55
+ if DeepConnect::UNSERIALIZABLE_CLASS_SET.include?(self.class)
56
+ DeepConnect.Raise CantSerializable, self.class.name
57
+ end
58
+ vnames = instance_variables
59
+ vnames.collect{|v|
60
+ [v,
61
+ DeepConnect::Reference.serialize(deep_space, instance_variable_get(v))]}
62
+ end
63
+
64
+ def deep_connect_dup
65
+ if DeepConnect::UNSERIALIZABLE_CLASS_SET.include?(self.class)
66
+ DeepConnect.Raise CantDup, self.class.name
67
+ end
68
+ self
69
+ end
70
+ alias dc_dup deep_connect_dup
71
+ DeepConnect.def_method_spec(self, :rets=>"VAL", :method=>:deep_connect_dup)
72
+ DeepConnect.def_method_spec(self, :rets=>"VAL", :method=>:dc_dup)
73
+
74
+ def deep_connect_deep_copy
75
+ if DeepConnect::UNSERIALIZABLE_CLASS_SET.include?(self.class)
76
+ DeepConnect.Raise CantDeepCopy, self.class.name
77
+ end
78
+ self
79
+ end
80
+ alias dc_deep_copy deep_connect_deep_copy
81
+ DeepConnect.def_method_spec(self, :rets=>"DVAL", :method=>:deep_connect_deep_copy)
82
+ DeepConnect.def_method_spec(self, :rets=>"DVAL", :method=>:dc_deep_copy)
83
+ end
84
+
85
+ class Array
86
+ def self.deep_connect_materialize_val(deep_space, value)
87
+ ary = new
88
+ value.each{|e| ary.push DeepConnect::Reference.materialize(deep_space, *e)}
89
+ ary
90
+ end
91
+
92
+ def deep_connect_serialize_val(deep_space)
93
+ collect{|e| DeepConnect::Reference.serialize(deep_space, e)}
94
+ end
95
+
96
+ end
97
+
98
+ class Hash
99
+ def self.deep_connect_materialize_val(deep_space, value)
100
+ hash = new
101
+ value.each do |k, v|
102
+ key = DeepConnect::Reference.materialize(deep_space, *k)
103
+ value = DeepConnect::Reference.materialize(deep_space, *v)
104
+ hash[key] = value
105
+ end
106
+ hash
107
+ end
108
+
109
+ def deep_connect_serialize_val(deep_space)
110
+ collect{|k, v|
111
+ [DeepConnect::Reference.serialize(deep_space, k),
112
+ DeepConnect::Reference.serialize(deep_space, v)]}
113
+ end
114
+
115
+ end
116
+
117
+ class Struct
118
+ def self.deep_connect_materialize_val(deep_space, value)
119
+ new(*value.collect{|e| DeepConnect::Reference.materialize(deep_space, *e)})
120
+ end
121
+
122
+ def deep_connect_serialize_val(deep_space)
123
+ to_a.collect{|e| DeepConnect::Reference.serialize(deep_space, e)}
124
+ end
125
+ end
126
+
127
+
@@ -0,0 +1,348 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # session.rb -
4
+ # Copyright (C) 1996-2010 Keiju ISHITSUKA
5
+ # (Penta Advanced Labrabries, Co.,Ltd)
6
+ #
7
+ # --
8
+ #
9
+ #
10
+ #
11
+
12
+ require "thread"
13
+ #require "mutex_m"
14
+ require "weakref"
15
+
16
+ require "ipaddr"
17
+
18
+ require "deep-connect/exceptions"
19
+
20
+ module DeepConnect
21
+ class Session
22
+
23
+ def initialize(deep_space, port, local_id = nil)
24
+ @status = :INITIALIZE
25
+
26
+ @organizer = deep_space.organizer
27
+ @deep_space = deep_space
28
+ @port = port
29
+
30
+ @export_queue = Queue.new
31
+
32
+ @waiting = Hash.new
33
+ @waiting_mutex = Mutex.new
34
+ @next_request_event_id = 0
35
+ @next_request_event_id_mutex = Mutex.new
36
+
37
+ @last_keep_alive = nil
38
+ end
39
+
40
+ attr_reader :organizer
41
+ attr_reader :deep_space
42
+
43
+ def peer_uuid
44
+ @deep_space.peer_uuid
45
+ end
46
+ alias peer_id peer_uuid
47
+
48
+ def start
49
+ @last_keep_alive = @organizer.tick
50
+
51
+ @status = :SERVICING
52
+ send_class_specs
53
+
54
+ @import_thread = Thread.start {
55
+ loop do
56
+ begin
57
+ ev = @port.import
58
+ @last_keep_alive = @organizer.tick
59
+ rescue EOFError, DC::DisconnectClient
60
+ # EOFError: クライアントが閉じていた場合
61
+ # DisconnectClient: 通信中にクライアント接続が切れた
62
+ Thread.start do
63
+ @organizer.disconnect_deep_space(@deep_space, :SESSION_CLOSED)
64
+ end
65
+ Thread.stop
66
+ rescue DC::ProtocolError
67
+ # 何らかの障害のためにプロトコルが正常じゃなくなった
68
+ end
69
+ if @status == :SERVICING
70
+ receive(ev)
71
+ else
72
+ puts "INFO: service is stoped, imported event abandoned(#{ev.inspect})"
73
+ end
74
+ end
75
+ }
76
+
77
+ @export_thread = Thread.start {
78
+ loop do
79
+ ev = @export_queue.pop
80
+ if @status == :SERVICING
81
+ begin
82
+ # export中にexportが発生するとデッドロックになる
83
+ # threadが欲しいか?
84
+ # Thread.start do
85
+ @port.export(ev)
86
+ # end
87
+ rescue Errno::EPIPE, DC::DisconnectClient
88
+ # EPIPE: クライアントが終了している
89
+ # DisconnectClient: 通信中にクライアント接続が切れた
90
+ Thread.start do
91
+ @organizer.disconnect_deep_space(@deep_space, :SESSION_CLOSED)
92
+ end
93
+ Thread.stop
94
+ end
95
+ else
96
+ puts "INFO: service is stoped, export event abandoned(#{ev.inspect})"
97
+ end
98
+ end
99
+ }
100
+ self
101
+ end
102
+
103
+ def stop_service(*opts)
104
+ unless Conf.DISABLE_INFO
105
+ puts "INFO: STOP_SERVICE: Session: #{self.peer_uuid} #{opts.join(' ')} "
106
+ end
107
+ org_status = @status
108
+ @status = :SERVICE_STOP
109
+
110
+ if !opts.include?(:SESSION_CLOSED)
111
+ @port.shutdown_reading
112
+ end
113
+
114
+ if org_status == :SERVICING
115
+ @import_thread.exit
116
+ @export_thread.exit
117
+
118
+ @waiting_mutex.synchronize do
119
+ waiting_events = @waiting.sort{|s1, s2| s1[0] <=> s2[0]}
120
+ for seq, ev in waiting_events
121
+ begin
122
+ p ev
123
+ DC.Raise SessionServiceStopped
124
+ rescue
125
+ ev.result = ev.reply(nil, $!)
126
+ end
127
+ end
128
+ @waiting.clear
129
+ end
130
+ end
131
+
132
+ end
133
+
134
+ def stop(*opts)
135
+ begin
136
+ @port.close
137
+ rescue IOError
138
+ puts "WARN: #{$!}"
139
+ end
140
+ end
141
+
142
+ # peerからの受取り
143
+ def receive(ev)
144
+ case ev
145
+ when Event::MQRequest
146
+ # Thread.start{ev.receiver.enq(self, ev)}
147
+ ev.receiver.enq(self, ev)
148
+ when Event::IteratorCallBackRequest
149
+ Thread.start{@organizer.evaluator.evaluate_block_yield(self, ev)}
150
+ when Event::IteratorRequest
151
+ Thread.start{@organizer.evaluator.evaluate_iterator_request(self, ev)}
152
+ when Event::Request
153
+ Thread.start{@organizer.evaluator.evaluate_request(self, ev)}
154
+ else
155
+ req = nil
156
+ @waiting_mutex.synchronize do
157
+ req = @waiting.delete(ev.seq)
158
+ end
159
+ unless req
160
+ DC.InternalError "対応する request eventがありません(#{ev.inspect})"
161
+ end
162
+ req.result = ev
163
+ end
164
+ end
165
+
166
+ # イベントの受け取り
167
+ def accept(ev)
168
+ @export_queue.push ev
169
+ end
170
+
171
+ # イベントの生成/送信
172
+ def send_to(ref, method, args=[], &block)
173
+ unless @status == :SERVICING
174
+ DC.Raise SessionServiceStopped
175
+ end
176
+ if iterator?
177
+ ev = Event::IteratorRequest.request(self, ref, method, args, block)
178
+ else
179
+ ev = Event::Request.request(self, ref, method, args)
180
+ end
181
+ @waiting_mutex.synchronize do
182
+ @waiting[ev.seq] = ev
183
+ end
184
+ @export_queue.push ev
185
+ ev.result
186
+ end
187
+
188
+ def block_yield(event, args)
189
+ ev = Event::IteratorCallBackRequest.call_back_event(event, args)
190
+ @waiting_mutex.synchronize do
191
+ @waiting[ev.seq] = ev
192
+ end
193
+ @export_queue.push ev
194
+ ev
195
+ end
196
+
197
+ def asynchronus_send_to(ref, method, args=[], callback=nil)
198
+ unless @status == :SERVICING
199
+ DC.Raise SessionServiceStopped
200
+ end
201
+ ev = Event::AsyncronusRequest.request(self, ref, method, args, callback)
202
+ @waiting_mutex.synchronize do
203
+ @waiting[ev.seq] = ev
204
+ end
205
+ @export_queue.push ev
206
+ nil
207
+ end
208
+ alias asyncronus_send_to asynchronus_send_to
209
+
210
+ def mq_send_to(ref, method, args=[], callback=nil)
211
+ unless @status == :SERVICING
212
+ DC.Raise SessionServiceStopped
213
+ end
214
+ ev = Event::MQRequest.request(self, ref, method, args, callback)
215
+ @waiting_mutex.synchronize do
216
+ @waiting[ev.seq] = ev
217
+ end
218
+ @export_queue.push ev
219
+ ev.result
220
+ end
221
+
222
+ # イベントID取得
223
+ def next_request_event_id
224
+ @next_request_event_id_mutex.synchronize do
225
+ @next_request_event_id += 1
226
+ end
227
+ end
228
+
229
+ def send_peer_session(req, *args)
230
+ ev = Event::SessionRequest.request(self, (req.id2name+"_impl").intern, args)
231
+ @waiting_mutex.synchronize do
232
+ @waiting[ev.seq] = ev
233
+ end
234
+ @export_queue.push ev
235
+ ev.result
236
+ end
237
+
238
+ def send_peer_session_no_recv(req, *args)
239
+ ev = Event::SessionRequestNoReply.request(self, (req.id2name+"_impl").intern, args)
240
+ @export_queue.push ev
241
+ end
242
+
243
+ def send_disconnect
244
+ return unless @status == :SERVICING
245
+
246
+ ev = Event::SessionRequestNoReply.request(self, :recv_disconnect)
247
+ @port.export(ev)
248
+ end
249
+
250
+ def recv_disconnect
251
+ @organizer.disconnect_deep_space(@deep_space, :REQUEST_FROM_PEER)
252
+ end
253
+ Organizer.def_interface(self, :recv_disconnect)
254
+
255
+
256
+ def get_service(name, waitp = false)
257
+ if (sv = send_peer_session(:get_service, name, waitp)) == :DEEPCONNECT_NO_SUCH_SERVICE
258
+ DC.Raise NoServiceError, name
259
+ end
260
+ sv
261
+ end
262
+
263
+ def get_service_impl(name, waitp = false)
264
+ @organizer.service(name, waitp)
265
+ end
266
+ Organizer.def_interface(self, :get_service_impl)
267
+
268
+ def import_mq(name, waitp = false)
269
+ unless sv = send_peer_session(:import_mq, name, waitp)
270
+ DC.Raise NoServiceError, name
271
+ end
272
+ sv
273
+ end
274
+
275
+ def import_mq_impl(name, waitp = false)
276
+ @organizer.get_mq(name, waitp)
277
+ end
278
+ Organizer.def_interface(self, :import_mq_impl)
279
+
280
+
281
+ def register_root_to_peer(id)
282
+ # 同期を取るためにno_recvはNG
283
+ send_peer_session(:register_root, id)
284
+ end
285
+
286
+ def register_root_impl(id)
287
+ @deep_space.register_root_from_other_session(id)
288
+ end
289
+ Organizer.def_interface(self, :register_root_impl)
290
+
291
+ def deregister_root_to_peer(ids)
292
+ idsdump = Marshal.dump(ids)
293
+ send_peer_session_no_recv(:deregister_root, idsdump)
294
+ end
295
+
296
+ def deregister_root_impl(idsdump)
297
+ ids = Marshal.load(idsdump)
298
+ @deep_space.delete_roots(ids)
299
+ nil
300
+ end
301
+ Organizer.def_interface(self, :deregister_root_impl)
302
+
303
+ def send_class_specs
304
+ specs_dump = Marshal.dump(Organizer::class_specs)
305
+ send_peer_session_no_recv(:recv_class_specs, specs_dump)
306
+ end
307
+
308
+ def recv_class_specs_impl(specs_dump)
309
+ specs = Marshal.load(specs_dump)
310
+ @deep_space.class_specs = specs
311
+ #p specs
312
+ end
313
+ Organizer.def_interface(self, :recv_class_specs_impl)
314
+
315
+
316
+ # def send_class_specs(cspecs)
317
+ # specs_dump = Marshal.dump(cspecs)
318
+ # ret = send_peer_session(:send_class_specs_impl, cspecs)
319
+ # end
320
+
321
+ # def send_class_specs_impl(spec_dump)
322
+ # specs = Marshal.load(spec_dump)
323
+ # @object_space.recv_class_specs(specs)
324
+ # end
325
+
326
+ def keep_alive
327
+ now = @organizer.tick
328
+ if now > @last_keep_alive + Conf.KEEP_ALIVE_INTERVAL*10
329
+ puts "KEEP ALIVE: session #{self} is dead." if Conf.DISPLAY_KEEP_ALIVE
330
+ false
331
+ else
332
+ if Conf.DISPLAY_KEEP_ALIVE
333
+ puts "KEEP ALIVE: session #{self} is alive(INT: #{now - @last_keep_alive})."
334
+ puts "KEEP ALIVE: send #{self} to keep alive."
335
+ end
336
+ send_peer_session_no_recv(:recv_keep_alive)
337
+ true
338
+ end
339
+ end
340
+
341
+ def recv_keep_alive_impl
342
+ puts "RECV_KEEP_ALIVE" if Conf.DISPLAY_KEEP_ALIVE
343
+ @last_keep_alive = @organizer.tick
344
+ end
345
+ Organizer.def_interface(self, :recv_keep_alive_impl)
346
+ end
347
+ end
348
+