riser 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +926 -0
- data/Rakefile +31 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example/halo.html +18 -0
- data/example/halo.rb +171 -0
- data/example/halo.yml +21 -0
- data/example/local_services.rb +60 -0
- data/example/multiproc_server.rb +21 -0
- data/example/simple_count.rb +52 -0
- data/example/simple_daemon.rb +22 -0
- data/example/simple_key_count.rb +65 -0
- data/example/simple_server.rb +20 -0
- data/example/simple_services.rb +60 -0
- data/example/simple_tls.rb +32 -0
- data/lib/riser/daemon.rb +579 -0
- data/lib/riser/poll.rb +35 -0
- data/lib/riser/resource.rb +386 -0
- data/lib/riser/server.rb +869 -0
- data/lib/riser/services.rb +631 -0
- data/lib/riser/stream.rb +115 -0
- data/lib/riser/temppath.rb +25 -0
- data/lib/riser/test.rb +42 -0
- data/lib/riser/version.rb +10 -0
- data/lib/riser.rb +28 -0
- data/riser.gemspec +35 -0
- metadata +129 -0
@@ -0,0 +1,386 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'delegate'
|
4
|
+
require 'drb'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'riser'
|
7
|
+
require 'set'
|
8
|
+
|
9
|
+
module Riser
|
10
|
+
class Resource
|
11
|
+
class Manager
|
12
|
+
def initialize(create, destroy)
|
13
|
+
@mutex = Thread::Mutex.new
|
14
|
+
@create = create
|
15
|
+
@destroy = destroy
|
16
|
+
@ref_count = 0
|
17
|
+
@ref_object = nil
|
18
|
+
@ref_proxy = {} # to keep proxy objects living in dRuby process
|
19
|
+
end
|
20
|
+
|
21
|
+
def ref_count
|
22
|
+
@mutex.synchronize{ @ref_count }
|
23
|
+
end
|
24
|
+
|
25
|
+
def proxy_count
|
26
|
+
@mutex.synchronize{ @ref_proxy.length }
|
27
|
+
end
|
28
|
+
|
29
|
+
def ref_object?
|
30
|
+
@mutex.synchronize{ ! @ref_object.nil? }
|
31
|
+
end
|
32
|
+
|
33
|
+
def ref_object
|
34
|
+
@mutex.synchronize{
|
35
|
+
if (@ref_count < 0) then
|
36
|
+
raise "internal error: negative reference count <#{@ref_count}>"
|
37
|
+
end
|
38
|
+
|
39
|
+
if (@ref_count == 0) then
|
40
|
+
# if an exception occurs at `@create.call', the object should not be referenced.
|
41
|
+
@ref_object = @create.call
|
42
|
+
end
|
43
|
+
@ref_count += 1
|
44
|
+
@ref_object
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def unref_object
|
49
|
+
@mutex.synchronize{
|
50
|
+
unless (@ref_count > 0) then
|
51
|
+
raise "internal error: unreferenced resource object <#{@ref_count}>"
|
52
|
+
end
|
53
|
+
|
54
|
+
@ref_count -= 1
|
55
|
+
if (@ref_count == 0) then
|
56
|
+
tmp_object = @ref_object
|
57
|
+
@ref_object = nil
|
58
|
+
# even if an exception occurs at `@destroy.call', the object should be unreferenced.
|
59
|
+
@destroy.call(tmp_object)
|
60
|
+
end
|
61
|
+
}
|
62
|
+
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
def ref_proxy(proxy)
|
67
|
+
@mutex.synchronize{
|
68
|
+
if (@ref_proxy.key? proxy.__id__) then
|
69
|
+
raise "internal error: duplicated proxy object <#{proxy.__id__}>"
|
70
|
+
end
|
71
|
+
@ref_proxy[proxy.__id__] = proxy
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def unref_proxy(proxy)
|
76
|
+
@mutex.synchronize{
|
77
|
+
@ref_proxy.delete(proxy.__id__) or raise "internal error: unreferenced proxy object <#{proxy.__id__}>"
|
78
|
+
}
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
module Delegatable
|
83
|
+
def __getobj__
|
84
|
+
if (@delegate_proxy_obj.nil?) then
|
85
|
+
return yield if block_given?
|
86
|
+
__raise__ ::ArgumentError, "not delegated"
|
87
|
+
end
|
88
|
+
@delegate_proxy_obj
|
89
|
+
end
|
90
|
+
|
91
|
+
def __setobj__(obj)
|
92
|
+
__raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
|
93
|
+
@delegate_proxy_obj = obj
|
94
|
+
end
|
95
|
+
protected :__setobj__
|
96
|
+
end
|
97
|
+
|
98
|
+
module DelegateUnrefAlias
|
99
|
+
def method_missing(name, *args, &block)
|
100
|
+
if (@unref_alias_set.include? name.to_sym) then
|
101
|
+
__unref__
|
102
|
+
else
|
103
|
+
super
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def respond_to_missing?(name, include_private)
|
108
|
+
if (@unref_alias_set.include? name.to_sym) then
|
109
|
+
true
|
110
|
+
else
|
111
|
+
super
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class Proxy < Delegator
|
117
|
+
include DRb::DRbUndumped
|
118
|
+
include Delegatable
|
119
|
+
include DelegateUnrefAlias
|
120
|
+
|
121
|
+
def initialize(manager, unref_alias_set)
|
122
|
+
@manager = manager
|
123
|
+
@unref_alias_set = unref_alias_set
|
124
|
+
# if an exception occurs at `@create.call', the proxy should not be referenced.
|
125
|
+
super(@manager.ref_object)
|
126
|
+
@manager.ref_proxy(self)
|
127
|
+
end
|
128
|
+
|
129
|
+
def __unref__
|
130
|
+
delegated = true
|
131
|
+
__getobj__{ delegated = false }
|
132
|
+
|
133
|
+
if (delegated) then
|
134
|
+
__setobj__(nil)
|
135
|
+
@manager.unref_proxy(self)
|
136
|
+
# even if an exception occurs at `@destroy.call', the proxy should be unreferenced.
|
137
|
+
@manager.unref_object
|
138
|
+
end
|
139
|
+
|
140
|
+
nil
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
class Builder
|
145
|
+
def initialize
|
146
|
+
@create = nil
|
147
|
+
@destroy = nil
|
148
|
+
@unref_alias_set = Set.new
|
149
|
+
end
|
150
|
+
|
151
|
+
def at_create(&block) # :yields:
|
152
|
+
@create = block
|
153
|
+
nil
|
154
|
+
end
|
155
|
+
|
156
|
+
def at_destroy(&block) # :yields: resource_object
|
157
|
+
@destroy = block
|
158
|
+
nil
|
159
|
+
end
|
160
|
+
|
161
|
+
def alias_unref(name)
|
162
|
+
@unref_alias_set << name.to_sym
|
163
|
+
nil
|
164
|
+
end
|
165
|
+
|
166
|
+
def call
|
167
|
+
@create or raise 'not defined create block'
|
168
|
+
@destroy or raise 'not defined destroy block'
|
169
|
+
Resource.new(Manager.new(@create, @destroy), @unref_alias_set)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.build
|
174
|
+
builder = Builder.new
|
175
|
+
yield(builder)
|
176
|
+
builder.call
|
177
|
+
end
|
178
|
+
|
179
|
+
extend Forwardable
|
180
|
+
include DRb::DRbUndumped
|
181
|
+
|
182
|
+
def initialize(manager, unref_alias_set)
|
183
|
+
@manager = manager
|
184
|
+
@unref_alias_set = unref_alias_set
|
185
|
+
end
|
186
|
+
|
187
|
+
def_delegators :@manager, :ref_count, :proxy_count, :ref_object?
|
188
|
+
|
189
|
+
def call
|
190
|
+
proxy = Proxy.new(@manager, @unref_alias_set)
|
191
|
+
if (block_given?) then
|
192
|
+
begin
|
193
|
+
yield(proxy)
|
194
|
+
ensure
|
195
|
+
proxy.__unref__
|
196
|
+
end
|
197
|
+
else
|
198
|
+
proxy
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
class ResourceSet
|
204
|
+
class Manager
|
205
|
+
Reference = Struct.new(:count, :object) # :nodoc:
|
206
|
+
|
207
|
+
def initialize(create, destroy)
|
208
|
+
@mutex = Thread::Mutex.new
|
209
|
+
@create = create
|
210
|
+
@destroy = destroy
|
211
|
+
@ref_table = {}
|
212
|
+
@ref_proxy = {} # to keep proxy objects living in dRuby process
|
213
|
+
end
|
214
|
+
|
215
|
+
def key_count
|
216
|
+
@mutex.synchronize{ @ref_table.size }
|
217
|
+
end
|
218
|
+
|
219
|
+
def ref_count(access_key)
|
220
|
+
@mutex.synchronize{
|
221
|
+
if (ref = @ref_table[access_key]) then
|
222
|
+
ref.count
|
223
|
+
else
|
224
|
+
0
|
225
|
+
end
|
226
|
+
}
|
227
|
+
end
|
228
|
+
|
229
|
+
def proxy_count
|
230
|
+
@mutex.synchronize{ @ref_proxy.length }
|
231
|
+
end
|
232
|
+
|
233
|
+
def ref_object?(access_key)
|
234
|
+
@mutex.synchronize{
|
235
|
+
if (ref = @ref_table[access_key]) then
|
236
|
+
! ref.object.nil?
|
237
|
+
else
|
238
|
+
false
|
239
|
+
end
|
240
|
+
}
|
241
|
+
end
|
242
|
+
|
243
|
+
def ref_object(access_key)
|
244
|
+
@mutex.synchronize{
|
245
|
+
if (ref = @ref_table[access_key]) then
|
246
|
+
unless (ref.count > 0) then
|
247
|
+
raise "internal error: unreferenced resource object <#{ref.count}>"
|
248
|
+
end
|
249
|
+
ref.count += 1
|
250
|
+
ref.object
|
251
|
+
else
|
252
|
+
# if an exception occurs at `@create.call', the object should not be referenced.
|
253
|
+
tmp_object = @create.call(access_key)
|
254
|
+
@ref_table[access_key] = Reference.new(1, tmp_object)
|
255
|
+
tmp_object
|
256
|
+
end
|
257
|
+
}
|
258
|
+
end
|
259
|
+
|
260
|
+
def unref_object(access_key)
|
261
|
+
@mutex.synchronize{
|
262
|
+
ref = @ref_table[access_key] or raise "internal error: not defined resource object <#{access_key}>"
|
263
|
+
unless (ref.count > 0) then
|
264
|
+
raise "internal error: unreferenced resource object <#{ref.count}>"
|
265
|
+
end
|
266
|
+
|
267
|
+
ref.count -= 1
|
268
|
+
if (ref.count == 0) then
|
269
|
+
@ref_table.delete(access_key)
|
270
|
+
# even if an exception occurs at `@destroy.call', the object should be unreferenced.
|
271
|
+
@destroy.call(ref.object)
|
272
|
+
end
|
273
|
+
}
|
274
|
+
|
275
|
+
nil
|
276
|
+
end
|
277
|
+
|
278
|
+
def ref_proxy(proxy)
|
279
|
+
@mutex.synchronize{
|
280
|
+
if (@ref_proxy.key? proxy.__id__) then
|
281
|
+
raise "internal error: duplicated proxy object <#{proxy.__id__}>"
|
282
|
+
end
|
283
|
+
@ref_proxy[proxy.__id__] = proxy
|
284
|
+
}
|
285
|
+
end
|
286
|
+
|
287
|
+
def unref_proxy(proxy)
|
288
|
+
@mutex.synchronize{
|
289
|
+
@ref_proxy.delete(proxy.__id__) or raise "internal error: unreferenced proxy object <#{proxy.__id__}>"
|
290
|
+
}
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class Proxy < Delegator
|
295
|
+
include DRb::DRbUndumped
|
296
|
+
include Resource::Delegatable
|
297
|
+
include Resource::DelegateUnrefAlias
|
298
|
+
|
299
|
+
def initialize(manager, unref_alias_set, access_key)
|
300
|
+
@manager = manager
|
301
|
+
@unref_alias_set = unref_alias_set
|
302
|
+
@access_key = access_key
|
303
|
+
# if an exception occurs at `@create.call', the proxy should not be referenced.
|
304
|
+
__setobj__(@manager.ref_object(@access_key))
|
305
|
+
@manager.ref_proxy(self)
|
306
|
+
end
|
307
|
+
|
308
|
+
def __unref__
|
309
|
+
delegated = true
|
310
|
+
__getobj__{ delegated = false }
|
311
|
+
|
312
|
+
if (delegated) then
|
313
|
+
__setobj__(nil)
|
314
|
+
@manager.unref_proxy(self)
|
315
|
+
# even if an exception occurs at `@destroy.call', the proxy should be unreferenced.
|
316
|
+
@manager.unref_object(@access_key)
|
317
|
+
end
|
318
|
+
|
319
|
+
nil
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
class Builder
|
324
|
+
def initialize
|
325
|
+
@create = nil
|
326
|
+
@destroy = nil
|
327
|
+
@unref_alias_set = Set.new
|
328
|
+
end
|
329
|
+
|
330
|
+
def at_create(&block) # :yields: access_key
|
331
|
+
@create = block
|
332
|
+
nil
|
333
|
+
end
|
334
|
+
|
335
|
+
def at_destroy(&block) # :yields: resource_object
|
336
|
+
@destroy = block
|
337
|
+
nil
|
338
|
+
end
|
339
|
+
|
340
|
+
def alias_unref(name)
|
341
|
+
@unref_alias_set << name.to_sym
|
342
|
+
nil
|
343
|
+
end
|
344
|
+
|
345
|
+
def call
|
346
|
+
@create or raise 'not defined create block'
|
347
|
+
@destroy or raise 'not defined destroy block'
|
348
|
+
ResourceSet.new(Manager.new(@create, @destroy), @unref_alias_set)
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def self.build
|
353
|
+
builder = Builder.new
|
354
|
+
yield(builder)
|
355
|
+
builder.call
|
356
|
+
end
|
357
|
+
|
358
|
+
extend Forwardable
|
359
|
+
include DRb::DRbUndumped
|
360
|
+
|
361
|
+
def initialize(manager, unref_alias_set)
|
362
|
+
@manager = manager
|
363
|
+
@unref_alias_set = unref_alias_set
|
364
|
+
end
|
365
|
+
|
366
|
+
def_delegators :@manager, :key_count, :ref_count, :proxy_count, :ref_object?
|
367
|
+
|
368
|
+
def call(access_key)
|
369
|
+
proxy = Proxy.new(@manager, @unref_alias_set, access_key)
|
370
|
+
if (block_given?) then
|
371
|
+
begin
|
372
|
+
yield(proxy)
|
373
|
+
ensure
|
374
|
+
proxy.__unref__
|
375
|
+
end
|
376
|
+
else
|
377
|
+
proxy
|
378
|
+
end
|
379
|
+
end
|
380
|
+
end
|
381
|
+
end
|
382
|
+
|
383
|
+
# Local Variables:
|
384
|
+
# mode: Ruby
|
385
|
+
# indent-tabs-mode: nil
|
386
|
+
# End:
|