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,38 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # exceptions.rb -
4
+ # Copyright (C) 1996-2010 Keiju ISHITSUKA
5
+ # (Penta Advanced Labrabries, Co.,Ltd)
6
+ #
7
+
8
+ @RCS_ID='-$Id: $-'
9
+
10
+
11
+ require "e2mmap"
12
+
13
+ module DeepConnect
14
+ extend Exception2MessageMapper
15
+
16
+ def_exception :IllegalReference, "不正なリファレンス参照です(id=%x, method=%s)"
17
+
18
+ def_exception :NoInterfaceMethod, "No interface method(%s.%s)"
19
+
20
+ def_exception :NoServiceError, "No such service(%s)"
21
+ def_exception :CantSerializable, "%sはシリアライズできません"
22
+ def_exception :CantDup, "%sはdupできません"
23
+ def_exception :CantDeepCopy, "%sはdeep copyできません"
24
+
25
+ def_exception :SessionServiceStopped, "Session service stopped"
26
+ def_exception :DisconnectClient, "%sの接続が切れました"
27
+ def_exception :ConnectCancel, "%sの接続を拒否しました"
28
+ def_exception :ConnectionRefused, "%sへの接続が拒否されました"
29
+
30
+ def_exception :InternalError, "DeepConnect internal error(%s)"
31
+ def_exception :ProtocolError, "Protocol error!!"
32
+
33
+
34
+ def self.InternalError(message)
35
+ DC.Raise InternalError, message
36
+ end
37
+ end
38
+
@@ -0,0 +1,67 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # future.rb -
4
+ # Copyright (C) 1996-2010 Keiju ISHITSUKA
5
+ # (Penta Advanced Labrabries, Co.,Ltd)
6
+ #
7
+ # --
8
+ #
9
+ # v = DeepConnect::future{exp}
10
+ # v = DeepConnect::Future.future{exp}
11
+ #
12
+ #
13
+
14
+ require "thread"
15
+ require "delegate"
16
+
17
+ module DeepConnect
18
+ def future(&block)
19
+ Future.new(&block)
20
+ end
21
+ module_function :future
22
+
23
+ class Future < Delegator
24
+
25
+ NULLVALUE = :__DEEPCONNECT_FUTURE_NULLVALUE__
26
+
27
+ def self.future(&block)
28
+ Futre.new(&block)
29
+ end
30
+
31
+ def initialize(&block)
32
+ super(@value = NULLVALUE)
33
+ @value_mutex = Mutex.new
34
+ @value_cv = ConditionVariable.new
35
+ Thread.start do
36
+ @value = yield
37
+ @value_cv.broadcast
38
+ end
39
+ end
40
+
41
+ def __setobj__(dummy); end
42
+
43
+ def value
44
+ @value_mutex.synchronize do
45
+ while @value == NULLVALUE
46
+ @value_cv.wait(@value_mutex)
47
+ end
48
+ end
49
+ @value
50
+ end
51
+ alias __getobj__ value
52
+
53
+ def value?
54
+ @value != NULLVALUE
55
+ end
56
+
57
+ def inspect
58
+ if @value == NULLVALUE
59
+ "#<DeepConnect::Future: (NOT ARRIVED)>"
60
+ else
61
+ "#<DeepConnect::Future: #{@value.inspect}>"
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+
@@ -0,0 +1,378 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # organizer.rb -
4
+ # Copyright (C) 1996-2010 Keiju ISHITSUKA
5
+ # (Penta Advanced Labrabries, Co.,Ltd)
6
+ #
7
+
8
+ require "forwardable"
9
+ require "monitor"
10
+ require "resolv"
11
+ require "ipaddr"
12
+
13
+ require "deep-connect/class-spec-space"
14
+
15
+ require "matrix"
16
+
17
+ module DeepConnect
18
+ class Organizer
19
+ @CLASS_SPEC_SPACE = ClassSpecSpace.new(:local)
20
+
21
+ extend SingleForwardable
22
+
23
+ def_delegator :@CLASS_SPEC_SPACE, :class_specs
24
+ def_delegator :@CLASS_SPEC_SPACE, :def_method_spec
25
+ def_delegator :@CLASS_SPEC_SPACE, :def_single_method_spec
26
+ def_delegator :@CLASS_SPEC_SPACE, :def_interface
27
+ def_delegator :@CLASS_SPEC_SPACE, :def_single_interface
28
+ def_delegator :@CLASS_SPEC_SPACE, :method_spec
29
+ def_delegator :@CLASS_SPEC_SPACE, :class_spec_id_of
30
+ end
31
+ end
32
+
33
+ require "deep-connect/accepter"
34
+ require "deep-connect/evaluator"
35
+ require "deep-connect/deep-space"
36
+ require "deep-connect/port"
37
+ require "deep-connect/event"
38
+ require "deep-connect/cron"
39
+ require "deep-connect/exceptions"
40
+
41
+ trap("SIGPIPE", "IGNORE")
42
+
43
+ module DeepConnect
44
+
45
+ class Organizer
46
+ def initialize
47
+ @shallow_connect = false
48
+
49
+ @accepter = Accepter.new(self)
50
+ @evaluator = Evaluator.new(self)
51
+
52
+ @services = {}
53
+ @services_mx = Mutex.new
54
+ @services_cv = ConditionVariable.new
55
+
56
+ @messageqs = {}
57
+ @messageqs_mx = Mutex.new
58
+ @messageqs_cv = ConditionVariable.new
59
+
60
+ @deep_spaces = {}
61
+ @deep_spaces_mon = Monitor.new
62
+ @deep_spaces_cv = @deep_spaces_mon.new_cond
63
+
64
+ @cron = Cron.new(self)
65
+
66
+ @when_connect_proc = proc{true}
67
+ @when_disconnect_proc = proc{}
68
+
69
+ @local_id_mutex = Mutex.new
70
+ @local_id_cv = ConditionVariable.new
71
+ @local_id = nil
72
+ end
73
+
74
+ attr_accessor :shallow_connect
75
+ alias shallow_connect? shallow_connect
76
+
77
+ attr_reader :accepter
78
+ attr_reader :evaluator
79
+
80
+ def tick
81
+ @cron.tick
82
+ end
83
+
84
+ def deep_spaces
85
+ @deep_spaces
86
+ end
87
+
88
+ def local_id
89
+ @local_id_mutex.synchronize do
90
+ while !@local_id
91
+ @local_id_cv.wait(@local_id_mutex)
92
+ end
93
+ end
94
+ @local_id
95
+ end
96
+
97
+ def start(service)
98
+ @accepter.open(service)
99
+ @local_id = @accepter.port_number
100
+ @local_id_cv.broadcast
101
+
102
+ @accepter.start
103
+ @cron.start
104
+ end
105
+
106
+ def stop
107
+ @accepter.stop
108
+ end
109
+
110
+ IPADDR_REGEXP = /(::ffff:)?([0-9]+\.){3}[0-9]+|[0-9a-f]+:([0-9a-f]*:)[0-9a-f]*/
111
+ # client sesssion開始
112
+ def open_deep_space(host, port)
113
+
114
+ @deep_spaces_mon.synchronize do
115
+ ipaddr = nil
116
+ if IPADDR_REGEXP !~ host
117
+ Resolv.each_address(host) do |addr|
118
+ ipaddr = IPAddr.new(addr)
119
+ ipaddr = ipaddr.native.to_s
120
+
121
+ peer_id = [ipaddr, port]
122
+ if deep_space = @deep_spaces[peer_id]
123
+ return deep_space
124
+ end
125
+ end
126
+ else
127
+ ipaddr = IPAddr.new(host)
128
+ ipaddr = ipaddr.native.to_s
129
+
130
+ peer_id = [ipaddr, port]
131
+ if deep_space = @deep_spaces[peer_id]
132
+ return deep_space
133
+ end
134
+ end
135
+
136
+ sock = TCPSocket.new(ipaddr, port)
137
+ port = Port.new(sock)
138
+ init_session_ev = Event::InitSessionEvent.new(local_id)
139
+ port.export init_session_ev
140
+ connect_deep_space_with_port(port)
141
+ end
142
+ end
143
+ alias open_deepspace open_deep_space
144
+
145
+ def close_deep_space(deep_space)
146
+ disconnect_deep_space(deep_space)
147
+ end
148
+ alias close_deepspace close_deep_space
149
+
150
+ def deep_space(peer_id, &block)
151
+ @deep_spaces_mon.synchronize do
152
+ if deep_space = @deep_spaces[peer_id]
153
+ return deep_space
154
+ end
155
+
156
+ # セッションを自動的に開く
157
+ begin
158
+ deep_space = open_deep_space(*peer_id)
159
+ block.call deep_space if block_given?
160
+ deep_space
161
+ rescue ConnectionRefused, Errno::ECONNREFUSED
162
+ puts "WARN: クライアント(#{peer_id}への接続が拒否されました"
163
+ return DeepSpaceNoConnection.new(peer_id)
164
+ end
165
+ end
166
+ end
167
+ alias deepspace deep_space
168
+
169
+ # sessionサービス開始
170
+ def connect_deep_space_with_port(port, local_id = nil)
171
+ @deep_spaces_mon.synchronize do
172
+ deep_space = DeepSpace.new(self, port, local_id)
173
+ port.attach(deep_space.session)
174
+ # uuid = session.peer_id unless uuid
175
+ if @deep_spaces[deep_space.peer_uuid]
176
+ # ポート番号が再利用されているときは, 既存の方はすでにおなくな
177
+ # りになっている
178
+ old = @deep_spaces[deep_space.peer_uuid]
179
+ puts "INFO: port no recyicled"
180
+ puts "INFO: disconnect recycled deep_space: #{old}"
181
+
182
+ disconnect_deep_space(old, :SESSION_CLOSED)
183
+ end
184
+ unless @when_connect_proc.call deep_space, port
185
+ puts "CONNECT Canceld DeepSpace: #{deep_space.peer_uuid}" if Conf.DEBUG
186
+ connect_ev = Event::ConnectResult.new(false)
187
+ port.export connect_ev
188
+
189
+ disconnect_deep_space(deep_space)
190
+ DC::Raise ConnectCancel, deep_space
191
+ end
192
+
193
+ connect_ev = Event::ConnectResult.new(true)
194
+ port.export connect_ev
195
+
196
+ ev = port.import
197
+ if ev.kind_of?(Event::ConnectResult)
198
+ unless ev.result
199
+ DC::Raise ConnectionRefused, deep_space
200
+ end
201
+ else
202
+ DC::Raise ProtocolError, deep_space
203
+ end
204
+
205
+ @deep_spaces[deep_space.peer_uuid] = deep_space
206
+
207
+ puts "CONNECT DeepSpace: #{deep_space.peer_uuid}" if Conf.DEBUG
208
+ deep_space.connect
209
+ deep_space
210
+ end
211
+ end
212
+ alias connect_deepspace_with_port connect_deep_space_with_port
213
+
214
+ def disconnect_deep_space(deep_space, *opts)
215
+ @deep_spaces_mon.synchronize do
216
+ @deep_spaces.delete(deep_space.peer_uuid)
217
+ end
218
+ deep_space.disconnect(*opts)
219
+ @when_disconnect_proc.call(deep_space, opts)
220
+ end
221
+
222
+ def when_connected(&block)
223
+ @when_connect_proc = block
224
+ end
225
+
226
+ def when_disconnected(&block)
227
+ @when_disconnect_proc = block
228
+ end
229
+
230
+ #
231
+ def keep_alive
232
+ puts "KEEP ALIVE: Start" if Conf.DISPLAY_KEEP_ALIVE
233
+ for uuid, deep_space in @deep_spaces.dup
234
+ unless deep_space.session.keep_alive
235
+ disconnect_deep_space(deep_space, :SESSION_CLOSED)
236
+ end
237
+ end
238
+ end
239
+
240
+
241
+ # services
242
+ def register_service(name, obj)
243
+ @services_mx.synchronize do
244
+ @services[name] = obj
245
+ @services_cv.broadcast
246
+ end
247
+ end
248
+ alias export register_service
249
+
250
+ def service(name, waitp = false)
251
+ @services_mx.synchronize do
252
+ until @services.key?(name)
253
+ if waitp
254
+ @services_cv.wait(@services_mx)
255
+ else
256
+ return :DEEPCONNECT_NO_SUCH_SERVICE
257
+ end
258
+ end
259
+ @services[name]
260
+ end
261
+ end
262
+ alias import service
263
+
264
+ # MQ
265
+ def export_mq(name)
266
+ @messageqs_mx.synchronize do
267
+ @messageqs[name] = DeepMQ::SV.new(self)
268
+ end
269
+ end
270
+ alias register_mq export_mq
271
+
272
+ def get_mq(name, waitp = false)
273
+ @messageqs_mx.synchronize do
274
+ until @messageqs.key?(name)
275
+ if waitp
276
+ @messageqs_cv.wait(@messageqs_mx)
277
+ else
278
+ return nil
279
+ end
280
+ end
281
+ @messageqs[name]
282
+ end
283
+ end
284
+
285
+ def release_object(obj)
286
+ for id, dspace in @deep_spaces.dup
287
+ dspace.release_object(obj)
288
+ end
289
+ end
290
+
291
+ def id2obj(id)
292
+ @deep_spaces_mon.synchronize do
293
+ for peer_id, s in @deep_spaces
294
+ if o = s.root(id) and !o.kind_of?(IllegalObject)
295
+ # if o = s.root(id) and o != :__DEEPCONNECT_NO_VALUE__
296
+ return o
297
+ end
298
+ end
299
+ # begin
300
+ # ObjectSpace._id2ref(id)
301
+ # rescue
302
+ # end
303
+ # sleep 5
304
+ IllegalObject.new(id)
305
+ end
306
+ # DC::InternalError "deep_spaceにid(=#{id})をobject_idとするオブジェクトが登録されていません.)"
307
+ end
308
+
309
+ @@ABSOLUTE_IMMUTABLE_CLASSES = [
310
+ NilClass,
311
+ TrueClass,
312
+ FalseClass,
313
+ Symbol,
314
+ Fixnum,
315
+ Bignum,
316
+ Range,
317
+ Rational
318
+ ]
319
+
320
+ @@DEFAULT_IMMUTABLE_CLASSES = [
321
+ Numeric,
322
+ String,
323
+ Regexp,
324
+ MatchData,
325
+ Range,
326
+ Time,
327
+ File::Stat,
328
+ Matrix,
329
+ Vector,
330
+ Matrix::Scalar
331
+ ]
332
+
333
+ @@IMMUTABLE_CLASSES = @@ABSOLUTE_IMMUTABLE_CLASSES +
334
+ @@DEFAULT_IMMUTABLE_CLASSES
335
+
336
+ def self.absolute_immutable_classes
337
+ @@ABSOLUTE_IMMUTABLE_CLASSES
338
+ end
339
+ def self.default_immutable_classes
340
+ @@DEFAULT_IMMUTABLE_CLASSES
341
+ end
342
+ def self.immutable_classes
343
+ @@IMMUTABLE_CLASSES
344
+ end
345
+
346
+ def_interface(Exception, :message)
347
+
348
+ def_method_spec(Exception, "VAL backtrace()")
349
+ def_interface(Exception, :backtrace)
350
+
351
+ def_method_spec(Exception, "REF set_backtrace(VAL)")
352
+
353
+ def_method_spec(Object, "VAL to_a()")
354
+ #def_method_spec(Object, "VAL to_s()")
355
+ def_method_spec(Object, "VAL to_ary()")
356
+ def_method_spec(Object, "VAL to_str()")
357
+ def_method_spec(Object, "VAL to_int()")
358
+ def_method_spec(Object, "VAL to_regexp()")
359
+ def_method_spec(Object, "VAL to_splat()")
360
+
361
+ def_method_spec(Array, :method=> :-, :args=> "VAL")
362
+ def_method_spec(Array, :method=> :&, :args=> "VAL")
363
+ def_method_spec(Array, :method=> :|, :args=> "VAL")
364
+ def_method_spec(Array, :method=> :<=>, :args=> "VAL")
365
+ def_method_spec(Array, :method=> :==, :args=> "VAL")
366
+
367
+ #def_single_method_spec(Regexp, :method=> :union, :args=> "*DVAL")
368
+
369
+ def_method_spec(Hash, "merge(VAL)")
370
+ def_method_spec(Hash, :method=> :merge!, :args=> "VAL")
371
+ def_method_spec(Hash, "replace(VAL)")
372
+ def_method_spec(Hash, "update(VAL)")
373
+
374
+ end
375
+ end
376
+
377
+ require "deep-connect/deep-mq"
378
+