asir 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/Gemfile +16 -0
- data/README.textile +50 -0
- data/Rakefile +83 -0
- data/VERSION +1 -0
- data/asir.gemspec +36 -0
- data/asir.riterate.yml +114 -0
- data/bin/asir +6 -0
- data/doc/Rakefile +8 -0
- data/doc/asir-sequence.pic +84 -0
- data/doc/asir-sequence.svg +1559 -0
- data/doc/sequence.pic +430 -0
- data/example/asir_control.sh +24 -0
- data/example/asir_control_client_http.rb +14 -0
- data/example/asir_control_client_zmq.rb +15 -0
- data/example/config/asir_config.rb +63 -0
- data/example/delayed_service.rb +15 -0
- data/example/ex01.rb +12 -0
- data/example/ex02.rb +12 -0
- data/example/ex03.rb +19 -0
- data/example/ex04.rb +33 -0
- data/example/ex05.rb +16 -0
- data/example/ex06.rb +26 -0
- data/example/ex07.rb +28 -0
- data/example/ex08.rb +30 -0
- data/example/ex09.rb +25 -0
- data/example/ex10.rb +24 -0
- data/example/ex11.rb +48 -0
- data/example/ex12.rb +34 -0
- data/example/ex13.rb +35 -0
- data/example/ex14.rb +30 -0
- data/example/ex15.rb +13 -0
- data/example/ex16.rb +33 -0
- data/example/ex17.rb +41 -0
- data/example/ex18.rb +62 -0
- data/example/ex19.rb +32 -0
- data/example/ex20.rb +28 -0
- data/example/ex21.rb +28 -0
- data/example/ex22.rb +15 -0
- data/example/ex23.rb +20 -0
- data/example/ex24.rb +35 -0
- data/example/example_helper.rb +51 -0
- data/example/sample_service.rb +162 -0
- data/example/unsafe_service.rb +12 -0
- data/hack_night/README.txt +18 -0
- data/hack_night/exercise/prob-1.rb +18 -0
- data/hack_night/exercise/prob-2.rb +21 -0
- data/hack_night/exercise/prob-3.rb +16 -0
- data/hack_night/exercise/prob-4.rb +36 -0
- data/hack_night/exercise/prob-5.rb +36 -0
- data/hack_night/exercise/prob-6.rb +95 -0
- data/hack_night/exercise/prob-7.rb +34 -0
- data/hack_night/solution/math_service.rb +11 -0
- data/hack_night/solution/prob-1.rb +12 -0
- data/hack_night/solution/prob-2.rb +15 -0
- data/hack_night/solution/prob-3.rb +17 -0
- data/hack_night/solution/prob-4.rb +37 -0
- data/hack_night/solution/prob-5.rb +21 -0
- data/hack_night/solution/prob-6.rb +33 -0
- data/hack_night/solution/prob-7.rb +36 -0
- data/lab/phony_proc.rb +31 -0
- data/lib/asir.rb +253 -0
- data/lib/asir/additional_data.rb +25 -0
- data/lib/asir/channel.rb +130 -0
- data/lib/asir/client.rb +111 -0
- data/lib/asir/code_block.rb +57 -0
- data/lib/asir/code_more.rb +50 -0
- data/lib/asir/coder.rb +26 -0
- data/lib/asir/coder/base64.rb +19 -0
- data/lib/asir/coder/chain.rb +30 -0
- data/lib/asir/coder/identity.rb +23 -0
- data/lib/asir/coder/json.rb +30 -0
- data/lib/asir/coder/marshal.rb +17 -0
- data/lib/asir/coder/null.rb +23 -0
- data/lib/asir/coder/proc.rb +22 -0
- data/lib/asir/coder/sign.rb +48 -0
- data/lib/asir/coder/xml.rb +213 -0
- data/lib/asir/coder/yaml.rb +33 -0
- data/lib/asir/coder/zlib.rb +21 -0
- data/lib/asir/configuration.rb +32 -0
- data/lib/asir/error.rb +34 -0
- data/lib/asir/identity.rb +36 -0
- data/lib/asir/initialization.rb +23 -0
- data/lib/asir/log.rb +82 -0
- data/lib/asir/main.rb +396 -0
- data/lib/asir/message.rb +31 -0
- data/lib/asir/message/delay.rb +35 -0
- data/lib/asir/object_resolving.rb +15 -0
- data/lib/asir/result.rb +39 -0
- data/lib/asir/retry_behavior.rb +54 -0
- data/lib/asir/transport.rb +241 -0
- data/lib/asir/transport/beanstalk.rb +217 -0
- data/lib/asir/transport/broadcast.rb +34 -0
- data/lib/asir/transport/buffer.rb +115 -0
- data/lib/asir/transport/composite.rb +19 -0
- data/lib/asir/transport/connection_oriented.rb +180 -0
- data/lib/asir/transport/delay.rb +38 -0
- data/lib/asir/transport/delegation.rb +53 -0
- data/lib/asir/transport/fallback.rb +36 -0
- data/lib/asir/transport/file.rb +88 -0
- data/lib/asir/transport/http.rb +54 -0
- data/lib/asir/transport/local.rb +21 -0
- data/lib/asir/transport/null.rb +14 -0
- data/lib/asir/transport/payload_io.rb +52 -0
- data/lib/asir/transport/rack.rb +73 -0
- data/lib/asir/transport/retry.rb +41 -0
- data/lib/asir/transport/stream.rb +35 -0
- data/lib/asir/transport/subprocess.rb +30 -0
- data/lib/asir/transport/tcp_socket.rb +34 -0
- data/lib/asir/transport/webrick.rb +50 -0
- data/lib/asir/transport/zmq.rb +110 -0
- data/lib/asir/uuid.rb +32 -0
- data/lib/asir/version.rb +3 -0
- data/spec/const_get_speed_spec.rb +33 -0
- data/spec/debug_helper.rb +20 -0
- data/spec/example_spec.rb +88 -0
- data/spec/json_spec.rb +128 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/xml_spec.rb +144 -0
- data/stylesheets/slides.css +105 -0
- metadata +173 -0
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'asir'
|
2
|
+
require 'asir/object_resolving'
|
3
|
+
gem 'libxml-ruby'
|
4
|
+
require 'xml'
|
5
|
+
|
6
|
+
module ASIR
|
7
|
+
class Coder
|
8
|
+
# !SLIDE
|
9
|
+
# XML
|
10
|
+
#
|
11
|
+
# Encode/Decode objects as XML.
|
12
|
+
class XML < self
|
13
|
+
class Error < ::ASIR::Error
|
14
|
+
class BadIdref < self; end
|
15
|
+
end
|
16
|
+
def _encode obj
|
17
|
+
@stream = ''
|
18
|
+
@dom_id_map = { }
|
19
|
+
@dom_id = 0
|
20
|
+
@cls_tag_map = { }
|
21
|
+
encode_dom obj
|
22
|
+
@stream
|
23
|
+
end
|
24
|
+
|
25
|
+
def _decode obj
|
26
|
+
@stream = obj
|
27
|
+
@decoder ||= DECODER; @decoder_object = nil
|
28
|
+
@dom_id_map = { }
|
29
|
+
@dom_id = 0
|
30
|
+
@cls_tag_map = { }
|
31
|
+
@parser = ::XML::Parser.string(@stream)
|
32
|
+
@dom = @parser.parse
|
33
|
+
decode_dom @dom.root
|
34
|
+
end
|
35
|
+
|
36
|
+
def encode_dom obj
|
37
|
+
if dom_id = @dom_id_map[obj.object_id]
|
38
|
+
tag_obj(obj, nil, :idref => dom_id.first)
|
39
|
+
else
|
40
|
+
_encode_dom obj
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def _encode_dom obj
|
45
|
+
case obj
|
46
|
+
when NilClass, TrueClass, FalseClass
|
47
|
+
tag_obj(obj)
|
48
|
+
when Numeric
|
49
|
+
tag_obj(obj, nil, :v => obj.to_s)
|
50
|
+
when Symbol
|
51
|
+
tag_obj(obj) do
|
52
|
+
@stream << obj.to_s
|
53
|
+
end
|
54
|
+
when String
|
55
|
+
tag_obj(obj, :id) do
|
56
|
+
@stream << obj.to_s
|
57
|
+
end
|
58
|
+
when Array
|
59
|
+
tag_obj(obj, :id) do
|
60
|
+
obj.each do | elem |
|
61
|
+
encode_dom elem
|
62
|
+
end
|
63
|
+
end
|
64
|
+
when Hash
|
65
|
+
tag_obj(obj, :id) do
|
66
|
+
obj.each do | key, val |
|
67
|
+
encode_dom key
|
68
|
+
encode_dom val
|
69
|
+
end
|
70
|
+
end
|
71
|
+
else
|
72
|
+
tag_obj(obj, :id) do
|
73
|
+
obj.instance_variables.each do | attr |
|
74
|
+
val = obj.instance_variable_get(attr)
|
75
|
+
key = attr.to_s.sub(/^@/, '')
|
76
|
+
tag(key) do
|
77
|
+
encode_dom val
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def tag_obj obj, with_id = false, attrs = nil
|
85
|
+
if block_given?
|
86
|
+
tag(cls_tag(obj), with_id ? { with_id => map_obj_to_dom_id!(obj) } : nil) do
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
else
|
90
|
+
tag(cls_tag(obj), attrs)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
CC = '::'.freeze; D = '.'.freeze
|
95
|
+
def cls_tag obj
|
96
|
+
obj = obj.class
|
97
|
+
@cls_tag_map[obj] ||= obj.name.gsub(CC, D).freeze
|
98
|
+
end
|
99
|
+
|
100
|
+
def map_obj_to_dom_id! obj
|
101
|
+
if dom_id = @dom_id_map[obj.object_id]
|
102
|
+
dom_id.first
|
103
|
+
else
|
104
|
+
@dom_id_map[obj.object_id] = [ @dom_id += 1, obj ]
|
105
|
+
@dom_id
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
B = '<'.freeze; S = ' '.freeze; E = '>'.freeze; SE = '/>'.freeze
|
110
|
+
BS = '</'.freeze; A = '='.freeze
|
111
|
+
def tag tag, attrs = nil
|
112
|
+
tag = tag.to_s
|
113
|
+
@stream << B << tag << S
|
114
|
+
if attrs
|
115
|
+
attrs.each do | key, val |
|
116
|
+
@stream << key.to_s << A << val.to_s.inspect << S
|
117
|
+
end
|
118
|
+
end
|
119
|
+
if block_given?
|
120
|
+
@stream << E; yield; @stream << BS << tag << E
|
121
|
+
else
|
122
|
+
@stream << SE
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
################################################################
|
127
|
+
|
128
|
+
def decode_dom dom
|
129
|
+
if dom_id = dom.attributes[:idref]
|
130
|
+
unless obj = @dom_id_map[dom_id]
|
131
|
+
raise Error::BadIdref, "in element #{dom}"
|
132
|
+
end
|
133
|
+
obj
|
134
|
+
else
|
135
|
+
obj = _decode_dom(dom)
|
136
|
+
map_dom_id_to_obj! dom, obj if dom.attributes[:id]
|
137
|
+
obj
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def _decode_dom dom
|
142
|
+
cls_name = dom.name
|
143
|
+
decoder = @decoder[cls_name] ||
|
144
|
+
(@decoder_object ||= @decoder['Object'])
|
145
|
+
raise Error, "BUG: " unless decoder
|
146
|
+
decoder.call(self, dom)
|
147
|
+
end
|
148
|
+
|
149
|
+
DECODER = {
|
150
|
+
'NilClass' => lambda { | _, dom | nil },
|
151
|
+
'TrueClass' => lambda { | _, dom | true },
|
152
|
+
'FalseClass' => lambda { | _, dom | false },
|
153
|
+
'String' => lambda { | _, dom | (dom.attributes[:v] || dom.content) },
|
154
|
+
'Symbol' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_sym },
|
155
|
+
'Integer' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_i },
|
156
|
+
'Float' => lambda { | _, dom | (dom.attributes[:v] || dom.content).to_f },
|
157
|
+
"Array" => lambda { | _, dom |
|
158
|
+
obj = [ ]
|
159
|
+
_.map_dom_id_to_obj! dom, obj
|
160
|
+
dom.each_element do | elem |
|
161
|
+
obj << _.decode_dom(elem)
|
162
|
+
end
|
163
|
+
obj
|
164
|
+
},
|
165
|
+
'Hash' => lambda { | _, dom |
|
166
|
+
obj = { }
|
167
|
+
_.map_dom_id_to_obj! dom, obj
|
168
|
+
key = nil
|
169
|
+
dom.each_element do | val |
|
170
|
+
if key
|
171
|
+
obj[_.decode_dom(key)] = _.decode_dom(val)
|
172
|
+
key = nil
|
173
|
+
else
|
174
|
+
key = val
|
175
|
+
end
|
176
|
+
end
|
177
|
+
obj
|
178
|
+
},
|
179
|
+
'Object' => lambda { | _, dom |
|
180
|
+
cls_name = dom.name
|
181
|
+
# $stderr.puts "cls_name = #{cls_name.inspect}"
|
182
|
+
cls = _.tag_cls(cls_name)
|
183
|
+
obj = cls.allocate
|
184
|
+
_.map_dom_id_to_obj! dom, obj
|
185
|
+
dom.each_element do | child |
|
186
|
+
key = child.name
|
187
|
+
val = _.decode_dom child.first
|
188
|
+
obj.instance_variable_set("@#{key}", val)
|
189
|
+
end
|
190
|
+
obj
|
191
|
+
},
|
192
|
+
}
|
193
|
+
DECODER['Fixnum'] = DECODER['Bignum'] = DECODER['Integer']
|
194
|
+
|
195
|
+
def map_dom_id_to_obj! dom, obj
|
196
|
+
dom_id = dom.attributes[:id]
|
197
|
+
debugger unless dom_id
|
198
|
+
raise Error, "no :id attribute in #{dom}" unless dom_id
|
199
|
+
if (other_obj = @dom_id_map[dom_id]) and other_obj.object_id != obj.object_id
|
200
|
+
raise Error, "BUG: :id #{dom_id} already used for #{other_obj.class.name} #{other_obj.inspect}"
|
201
|
+
end
|
202
|
+
@dom_id_map[dom_id] = obj
|
203
|
+
end
|
204
|
+
|
205
|
+
include ObjectResolving
|
206
|
+
def tag_cls cls_name
|
207
|
+
@cls_tag_map[cls_name.freeze] ||= resolve_object(cls_name.gsub('.', '::'))
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
# !SLIDE END
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module ASIR
|
4
|
+
class Coder
|
5
|
+
# !SLIDE
|
6
|
+
# YAML Coder
|
7
|
+
# Use YAML for encode/decode.
|
8
|
+
class Yaml < self
|
9
|
+
def _encode obj
|
10
|
+
case obj
|
11
|
+
when Message, Result
|
12
|
+
obj = obj.encode_more!
|
13
|
+
end
|
14
|
+
::YAML::dump(obj)
|
15
|
+
rescue ::Exception
|
16
|
+
require 'pp'
|
17
|
+
msg = "#{self}: failed to encode: #{$!.inspect}:\n #{PP.pp(obj, '')}"
|
18
|
+
$stderr.puts msg
|
19
|
+
raise Error, msg
|
20
|
+
end
|
21
|
+
|
22
|
+
def _decode obj
|
23
|
+
case obj = ::YAML::load(obj)
|
24
|
+
when Message, Result
|
25
|
+
obj.decode_more!
|
26
|
+
else
|
27
|
+
obj
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end # class
|
31
|
+
end # class
|
32
|
+
end # module
|
33
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'asir'
|
2
|
+
|
3
|
+
require 'zlib'
|
4
|
+
|
5
|
+
module ASIR
|
6
|
+
class Coder
|
7
|
+
class Zlib < self
|
8
|
+
attr_accessor :compression_level
|
9
|
+
|
10
|
+
def _encode obj
|
11
|
+
raise TypeError unless String === obj
|
12
|
+
::Zlib::Deflate.deflate(obj, @compression_level || ::Zlib::DEFAULT_COMPRESSION)
|
13
|
+
end
|
14
|
+
def _decode obj
|
15
|
+
raise TypeError unless String === obj
|
16
|
+
::Zlib::Inflate.inflate(obj)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ASIR
|
2
|
+
IDENTITY_PROC = lambda { | x | x }
|
3
|
+
module Configuration
|
4
|
+
def self.included target
|
5
|
+
super
|
6
|
+
target.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
# Global default config_proc
|
10
|
+
def self.config_proc_hash
|
11
|
+
@@config_proc_hash ||= { }
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def config_proc
|
16
|
+
ASIR::Configuration.config_proc_hash[self]
|
17
|
+
end
|
18
|
+
def config_proc= x
|
19
|
+
ASIR::Configuration.config_proc_hash[self] = x
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize *args
|
24
|
+
super
|
25
|
+
ch = ASIR::Configuration.config_proc_hash
|
26
|
+
(self.class.ancestors.map{|m| ch[m]}.compact.first ||
|
27
|
+
ch[nil] ||
|
28
|
+
IDENTITY_PROC
|
29
|
+
).call(self)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/asir/error.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module ASIR
|
2
|
+
# Generic API error.
|
3
|
+
class Error < ::Exception
|
4
|
+
# Subclass should override method.
|
5
|
+
class SubclassResponsibility < self; end
|
6
|
+
|
7
|
+
# Unsupported Feature.
|
8
|
+
class Unsupported < self; end
|
9
|
+
|
10
|
+
# Requested Stop.
|
11
|
+
class Terminate < self; end
|
12
|
+
|
13
|
+
# Unforwardable Exception.
|
14
|
+
#
|
15
|
+
# This encapsulates an Exception that should never be
|
16
|
+
# forwarded and re-thrown directly in the client.
|
17
|
+
# E.g.: SystemExit, Interrupt.
|
18
|
+
class Unforwardable < self
|
19
|
+
attr_accessor :original
|
20
|
+
def initialize msg, original = nil, *args
|
21
|
+
if ::Exception === msg
|
22
|
+
original ||= msg
|
23
|
+
msg = "#{original.class.name} #{msg.message}"
|
24
|
+
end
|
25
|
+
@original = original
|
26
|
+
super(msg)
|
27
|
+
self.set_backtrace original && original.backtrace
|
28
|
+
end
|
29
|
+
def self.unforwardable; @@unforwardable; end
|
30
|
+
def self.unforwardable= x; @@unforwardable = x; end
|
31
|
+
@@unforwardable ||= [ ::SystemExit, ::Interrupt ]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'asir/uuid'
|
2
|
+
require 'thread' # Mutex
|
3
|
+
|
4
|
+
module ASIR
|
5
|
+
# !SLIDE
|
6
|
+
# Message Identity
|
7
|
+
#
|
8
|
+
module Identity
|
9
|
+
attr_accessor :identifier, :timestamp
|
10
|
+
|
11
|
+
# Optional: Opaque data about the Client that created the Message.
|
12
|
+
attr_accessor :client
|
13
|
+
|
14
|
+
# Optional: Opaque data about the Service that handled the Result.
|
15
|
+
attr_accessor :server
|
16
|
+
|
17
|
+
# Creates a thread-safe unique identifier.
|
18
|
+
def create_identifier!
|
19
|
+
@identifier ||=
|
20
|
+
@@identifier_mutex.synchronize do
|
21
|
+
if @@uuid_pid != $$
|
22
|
+
@@uuid_pid = $$
|
23
|
+
@@uuid = nil
|
24
|
+
end
|
25
|
+
"#{@@counter += 1}-#{@@uuid ||= ::ASIR::UUID.generate}".freeze
|
26
|
+
end
|
27
|
+
end
|
28
|
+
@@counter ||= 0; @@uuid ||= nil; @@uuid_pid = nil; @@identifier_mutex ||= Mutex.new
|
29
|
+
|
30
|
+
# Creates a timestamp.
|
31
|
+
def create_timestamp!
|
32
|
+
@timestamp ||=
|
33
|
+
::Time.now.gmtime
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module ASIR
|
3
|
+
# !SLIDE
|
4
|
+
# Object Initialization
|
5
|
+
#
|
6
|
+
# Support initialization by Hash.
|
7
|
+
#
|
8
|
+
# E.g.:
|
9
|
+
# Foo.new(:bar => 1, :baz => 2)
|
10
|
+
# ->
|
11
|
+
# obj = Foo.new; obj.bar = 1; obj.baz = 2; obj
|
12
|
+
module Initialization
|
13
|
+
def initialize opts = nil
|
14
|
+
opts ||= EMPTY_HASH
|
15
|
+
initialize_before_opts if respond_to? :initialize_before_opts
|
16
|
+
opts.each do | k, v |
|
17
|
+
send(:"#{k}=", v)
|
18
|
+
end
|
19
|
+
initialize_after_opts if respond_to? :initialize_after_opts
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
data/lib/asir/log.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
module ASIR
|
2
|
+
# !SLIDE
|
3
|
+
# Diagnostic Logging
|
4
|
+
#
|
5
|
+
# Logging mixin.
|
6
|
+
module Log
|
7
|
+
attr_accessor :_logger
|
8
|
+
|
9
|
+
def self.included target
|
10
|
+
super
|
11
|
+
target.send(:extend, ClassMethods)
|
12
|
+
end
|
13
|
+
|
14
|
+
@@enabled = false
|
15
|
+
def self.enabled
|
16
|
+
@@enabled
|
17
|
+
end
|
18
|
+
def self.enabled= x
|
19
|
+
@@enabled = x
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
def _log_enabled= x
|
24
|
+
(Thread.current[:'ASIR::Log.enabled'] ||= { })[self] = x
|
25
|
+
end
|
26
|
+
def _log_enabled?
|
27
|
+
(Thread.current[:'ASIR::Log.enabled'] ||= { })[self]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def _log_enabled= x
|
32
|
+
@_log_enabled = x
|
33
|
+
end
|
34
|
+
|
35
|
+
def _log_enabled?
|
36
|
+
ASIR::Log.enabled ||
|
37
|
+
@_log_enabled ||
|
38
|
+
self.class._log_enabled?
|
39
|
+
end
|
40
|
+
|
41
|
+
def _log msg = nil
|
42
|
+
return unless _log_enabled?
|
43
|
+
msg ||= yield if block_given?
|
44
|
+
msg = String === msg ? msg : _log_format(msg)
|
45
|
+
msg = " #{$$} #{Module === self ? self : self.class} #{msg}"
|
46
|
+
case @_logger
|
47
|
+
when Proc
|
48
|
+
@_logger.call msg
|
49
|
+
when IO
|
50
|
+
@_logger.puts msg
|
51
|
+
else
|
52
|
+
$stderr.puts msg
|
53
|
+
end
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
def _log_result msg
|
58
|
+
_log {
|
59
|
+
msg = String === msg ? msg : _log_format(msg);
|
60
|
+
"#{msg} => ..." }
|
61
|
+
result = yield
|
62
|
+
_log { "#{msg} => \n #{result.inspect}" }
|
63
|
+
result
|
64
|
+
end
|
65
|
+
|
66
|
+
def _log_format obj
|
67
|
+
case obj
|
68
|
+
when Exception
|
69
|
+
msg = "#{obj.inspect}"
|
70
|
+
msg << "\n #{obj.backtrace * "\n "}" if false
|
71
|
+
msg
|
72
|
+
when Array
|
73
|
+
obj.map { | x | _log_format x } * ", "
|
74
|
+
else
|
75
|
+
obj.inspect
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end # module
|
79
|
+
end # module
|
80
|
+
|
81
|
+
|
82
|
+
|