sensu-em 2.4.0-x86-mingw32

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.
Files changed (178) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.travis.yml +12 -0
  4. data/.yardopts +7 -0
  5. data/CHANGELOG.md +33 -0
  6. data/GNU +281 -0
  7. data/Gemfile +2 -0
  8. data/LICENSE +60 -0
  9. data/README.md +109 -0
  10. data/Rakefile +20 -0
  11. data/docs/DocumentationGuidesIndex.md +27 -0
  12. data/docs/GettingStarted.md +521 -0
  13. data/docs/old/ChangeLog +211 -0
  14. data/docs/old/DEFERRABLES +246 -0
  15. data/docs/old/EPOLL +141 -0
  16. data/docs/old/INSTALL +13 -0
  17. data/docs/old/KEYBOARD +42 -0
  18. data/docs/old/LEGAL +25 -0
  19. data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
  20. data/docs/old/PURE_RUBY +75 -0
  21. data/docs/old/RELEASE_NOTES +94 -0
  22. data/docs/old/SMTP +4 -0
  23. data/docs/old/SPAWNED_PROCESSES +148 -0
  24. data/docs/old/TODO +8 -0
  25. data/eventmachine.gemspec +37 -0
  26. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  27. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  28. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  29. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  30. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  31. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  32. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  33. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  34. data/examples/old/ex_channel.rb +43 -0
  35. data/examples/old/ex_queue.rb +2 -0
  36. data/examples/old/ex_tick_loop_array.rb +15 -0
  37. data/examples/old/ex_tick_loop_counter.rb +32 -0
  38. data/examples/old/helper.rb +2 -0
  39. data/ext/binder.cpp +124 -0
  40. data/ext/binder.h +46 -0
  41. data/ext/cmain.cpp +887 -0
  42. data/ext/ed.cpp +1992 -0
  43. data/ext/ed.h +424 -0
  44. data/ext/em.cpp +2352 -0
  45. data/ext/em.h +253 -0
  46. data/ext/eventmachine.h +128 -0
  47. data/ext/extconf.rb +179 -0
  48. data/ext/fastfilereader/extconf.rb +103 -0
  49. data/ext/fastfilereader/mapper.cpp +214 -0
  50. data/ext/fastfilereader/mapper.h +59 -0
  51. data/ext/fastfilereader/rubymain.cpp +127 -0
  52. data/ext/kb.cpp +79 -0
  53. data/ext/page.cpp +107 -0
  54. data/ext/page.h +51 -0
  55. data/ext/pipe.cpp +347 -0
  56. data/ext/project.h +161 -0
  57. data/ext/rubymain.cpp +1318 -0
  58. data/ext/ssl.cpp +476 -0
  59. data/ext/ssl.h +95 -0
  60. data/java/.classpath +6 -0
  61. data/java/.gitignore +1 -0
  62. data/java/.project +17 -0
  63. data/java/src/com/rubyeventmachine/DatagramPacket.java +13 -0
  64. data/java/src/com/rubyeventmachine/EmReactor.java +531 -0
  65. data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
  66. data/java/src/com/rubyeventmachine/EventCallback.java +7 -0
  67. data/java/src/com/rubyeventmachine/EventCode.java +26 -0
  68. data/java/src/com/rubyeventmachine/EventableChannel.java +130 -0
  69. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +179 -0
  70. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +405 -0
  71. data/java/src/com/rubyeventmachine/SslBox.java +311 -0
  72. data/lib/em/buftok.rb +110 -0
  73. data/lib/em/callback.rb +58 -0
  74. data/lib/em/channel.rb +64 -0
  75. data/lib/em/completion.rb +304 -0
  76. data/lib/em/connection.rb +716 -0
  77. data/lib/em/deferrable.rb +210 -0
  78. data/lib/em/deferrable/pool.rb +2 -0
  79. data/lib/em/file_watch.rb +73 -0
  80. data/lib/em/future.rb +61 -0
  81. data/lib/em/iterator.rb +231 -0
  82. data/lib/em/messages.rb +66 -0
  83. data/lib/em/pool.rb +151 -0
  84. data/lib/em/process_watch.rb +45 -0
  85. data/lib/em/processes.rb +123 -0
  86. data/lib/em/protocols.rb +37 -0
  87. data/lib/em/protocols/header_and_content.rb +138 -0
  88. data/lib/em/protocols/httpclient.rb +279 -0
  89. data/lib/em/protocols/httpclient2.rb +600 -0
  90. data/lib/em/protocols/line_and_text.rb +125 -0
  91. data/lib/em/protocols/line_protocol.rb +29 -0
  92. data/lib/em/protocols/linetext2.rb +161 -0
  93. data/lib/em/protocols/memcache.rb +331 -0
  94. data/lib/em/protocols/object_protocol.rb +46 -0
  95. data/lib/em/protocols/postgres3.rb +246 -0
  96. data/lib/em/protocols/saslauth.rb +175 -0
  97. data/lib/em/protocols/smtpclient.rb +365 -0
  98. data/lib/em/protocols/smtpserver.rb +643 -0
  99. data/lib/em/protocols/socks4.rb +66 -0
  100. data/lib/em/protocols/stomp.rb +205 -0
  101. data/lib/em/protocols/tcptest.rb +54 -0
  102. data/lib/em/pure_ruby.rb +1017 -0
  103. data/lib/em/queue.rb +71 -0
  104. data/lib/em/resolver.rb +209 -0
  105. data/lib/em/spawnable.rb +84 -0
  106. data/lib/em/streamer.rb +118 -0
  107. data/lib/em/threaded_resource.rb +90 -0
  108. data/lib/em/tick_loop.rb +85 -0
  109. data/lib/em/timers.rb +61 -0
  110. data/lib/em/version.rb +3 -0
  111. data/lib/eventmachine.rb +1553 -0
  112. data/lib/fastfilereaderext.rb +2 -0
  113. data/lib/jeventmachine.rb +321 -0
  114. data/lib/rubyeventmachine.rb +2 -0
  115. data/rakelib/cpp.rake_example +77 -0
  116. data/rakelib/package.rake +98 -0
  117. data/rakelib/test.rake +8 -0
  118. data/tests/client.crt +31 -0
  119. data/tests/client.key +51 -0
  120. data/tests/em_test_helper.rb +64 -0
  121. data/tests/server.crt +36 -0
  122. data/tests/server.key +51 -0
  123. data/tests/test_attach.rb +150 -0
  124. data/tests/test_basic.rb +294 -0
  125. data/tests/test_channel.rb +62 -0
  126. data/tests/test_completion.rb +177 -0
  127. data/tests/test_connection_count.rb +53 -0
  128. data/tests/test_defer.rb +18 -0
  129. data/tests/test_deferrable.rb +35 -0
  130. data/tests/test_epoll.rb +145 -0
  131. data/tests/test_error_handler.rb +38 -0
  132. data/tests/test_exc.rb +28 -0
  133. data/tests/test_file_watch.rb +65 -0
  134. data/tests/test_futures.rb +170 -0
  135. data/tests/test_get_sock_opt.rb +37 -0
  136. data/tests/test_handler_check.rb +35 -0
  137. data/tests/test_hc.rb +155 -0
  138. data/tests/test_httpclient.rb +190 -0
  139. data/tests/test_httpclient2.rb +133 -0
  140. data/tests/test_idle_connection.rb +25 -0
  141. data/tests/test_inactivity_timeout.rb +54 -0
  142. data/tests/test_iterator.rb +97 -0
  143. data/tests/test_kb.rb +34 -0
  144. data/tests/test_line_protocol.rb +33 -0
  145. data/tests/test_ltp.rb +138 -0
  146. data/tests/test_ltp2.rb +288 -0
  147. data/tests/test_next_tick.rb +104 -0
  148. data/tests/test_object_protocol.rb +36 -0
  149. data/tests/test_pause.rb +102 -0
  150. data/tests/test_pending_connect_timeout.rb +52 -0
  151. data/tests/test_pool.rb +194 -0
  152. data/tests/test_process_watch.rb +48 -0
  153. data/tests/test_processes.rb +128 -0
  154. data/tests/test_proxy_connection.rb +180 -0
  155. data/tests/test_pure.rb +88 -0
  156. data/tests/test_queue.rb +50 -0
  157. data/tests/test_resolver.rb +55 -0
  158. data/tests/test_running.rb +14 -0
  159. data/tests/test_sasl.rb +47 -0
  160. data/tests/test_send_file.rb +217 -0
  161. data/tests/test_servers.rb +33 -0
  162. data/tests/test_set_sock_opt.rb +37 -0
  163. data/tests/test_shutdown_hooks.rb +23 -0
  164. data/tests/test_smtpclient.rb +55 -0
  165. data/tests/test_smtpserver.rb +57 -0
  166. data/tests/test_spawn.rb +293 -0
  167. data/tests/test_ssl_args.rb +78 -0
  168. data/tests/test_ssl_echo_data.rb +60 -0
  169. data/tests/test_ssl_methods.rb +56 -0
  170. data/tests/test_ssl_verify.rb +82 -0
  171. data/tests/test_stomp.rb +37 -0
  172. data/tests/test_system.rb +42 -0
  173. data/tests/test_threaded_resource.rb +53 -0
  174. data/tests/test_tick_loop.rb +59 -0
  175. data/tests/test_timers.rb +123 -0
  176. data/tests/test_ud.rb +8 -0
  177. data/tests/test_unbind_reason.rb +48 -0
  178. metadata +300 -0
data/lib/em/queue.rb ADDED
@@ -0,0 +1,71 @@
1
+ module EventMachine
2
+ # A cross thread, reactor scheduled, linear queue.
3
+ #
4
+ # This class provides a simple queue abstraction on top of the reactor
5
+ # scheduler. It services two primary purposes:
6
+ #
7
+ # * API sugar for stateful protocols
8
+ # * Pushing processing onto the reactor thread
9
+ #
10
+ # @example
11
+ #
12
+ # q = EM::Queue.new
13
+ # q.push('one', 'two', 'three')
14
+ # 3.times do
15
+ # q.pop { |msg| puts(msg) }
16
+ # end
17
+ #
18
+ class Queue
19
+ def initialize
20
+ @items = []
21
+ @popq = []
22
+ end
23
+
24
+ # Pop items off the queue, running the block on the reactor thread. The pop
25
+ # will not happen immediately, but at some point in the future, either in
26
+ # the next tick, if the queue has data, or when the queue is populated.
27
+ #
28
+ # @return [NilClass] nil
29
+ def pop(*a, &b)
30
+ cb = EM::Callback(*a, &b)
31
+ EM.schedule do
32
+ if @items.empty?
33
+ @popq << cb
34
+ else
35
+ cb.call @items.shift
36
+ end
37
+ end
38
+ nil # Always returns nil
39
+ end
40
+
41
+ # Push items onto the queue in the reactor thread. The items will not appear
42
+ # in the queue immediately, but will be scheduled for addition during the
43
+ # next reactor tick.
44
+ def push(*items)
45
+ EM.schedule do
46
+ @items.push(*items)
47
+ @popq.shift.call @items.shift until @items.empty? || @popq.empty?
48
+ end
49
+ end
50
+ alias :<< :push
51
+
52
+ # @return [Boolean]
53
+ # @note This is a peek, it's not thread safe, and may only tend toward accuracy.
54
+ def empty?
55
+ @items.empty?
56
+ end
57
+
58
+ # @return [Integer] Queue size
59
+ # @note This is a peek, it's not thread safe, and may only tend toward accuracy.
60
+ def size
61
+ @items.size
62
+ end
63
+
64
+ # @return [Integer] Waiting size
65
+ # @note This is a peek at the number of jobs that are currently waiting on the Queue
66
+ def num_waiting
67
+ @popq.size
68
+ end
69
+
70
+ end # Queue
71
+ end # EventMachine
@@ -0,0 +1,209 @@
1
+ module EventMachine
2
+ module DNS
3
+ class Resolver
4
+
5
+ def self.resolve(hostname)
6
+ Request.new(socket, hostname)
7
+ end
8
+
9
+ @socket = @nameservers = nil
10
+
11
+ def self.socket
12
+ if !@socket || (@socket && @socket.error?)
13
+ @socket = Socket.open
14
+
15
+ @hosts = {}
16
+ IO.readlines('/etc/hosts').each do |line|
17
+ next if line =~ /^#/
18
+ addr, host = line.split(/\s+/)
19
+
20
+ if @hosts[host]
21
+ @hosts[host] << addr
22
+ else
23
+ @hosts[host] = [addr]
24
+ end
25
+ end
26
+ end
27
+
28
+ @socket
29
+ end
30
+
31
+ def self.nameservers=(ns)
32
+ @nameservers = ns
33
+ end
34
+
35
+ def self.nameservers
36
+ if !@nameservers
37
+ @nameservers = []
38
+ IO.readlines('/etc/resolv.conf').each do |line|
39
+ if line =~ /^nameserver (.+)$/
40
+ @nameservers << $1.split(/\s+/).first
41
+ end
42
+ end
43
+ end
44
+ @nameservers
45
+ end
46
+
47
+ def self.nameserver
48
+ nameservers.shuffle.first
49
+ end
50
+
51
+ def self.hosts
52
+ @hosts
53
+ end
54
+ end
55
+
56
+ class RequestIdAlreadyUsed < RuntimeError; end
57
+
58
+ class Socket < EventMachine::Connection
59
+ def self.open
60
+ EventMachine::open_datagram_socket('0.0.0.0', 0, self)
61
+ end
62
+
63
+ def initialize
64
+ @nameserver = nil
65
+ end
66
+
67
+ def post_init
68
+ @requests = {}
69
+ end
70
+
71
+ def start_timer
72
+ @timer ||= EM.add_periodic_timer(0.1, &method(:tick))
73
+ end
74
+
75
+ def stop_timer
76
+ EM.cancel_timer(@timer)
77
+ @timer = nil
78
+ end
79
+
80
+ def unbind
81
+ end
82
+
83
+ def tick
84
+ @requests.each do |id,req|
85
+ req.tick
86
+ end
87
+ end
88
+
89
+ def register_request(id, req)
90
+ if @requests.has_key?(id)
91
+ raise RequestIdAlreadyUsed
92
+ else
93
+ @requests[id] = req
94
+ end
95
+
96
+ start_timer
97
+ end
98
+
99
+ def deregister_request(id, req)
100
+ @requests.delete(id)
101
+ stop_timer if @requests.length == 0
102
+ end
103
+
104
+ def send_packet(pkt)
105
+ send_datagram(pkt, nameserver, 53)
106
+ end
107
+
108
+ def nameserver=(ns)
109
+ @nameserver = ns
110
+ end
111
+
112
+ def nameserver
113
+ @nameserver || Resolver.nameserver
114
+ end
115
+
116
+ # Decodes the packet, looks for the request and passes the
117
+ # response over to the requester
118
+ def receive_data(data)
119
+ msg = nil
120
+ begin
121
+ msg = Resolv::DNS::Message.decode data
122
+ rescue
123
+ else
124
+ req = @requests[msg.id]
125
+ if req
126
+ @requests.delete(msg.id)
127
+ stop_timer if @requests.length == 0
128
+ req.receive_answer(msg)
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ class Request
135
+ include Deferrable
136
+ attr_accessor :retry_interval, :max_tries
137
+
138
+ def initialize(socket, hostname)
139
+ @socket = socket
140
+ @hostname = hostname
141
+ @tries = 0
142
+ @last_send = Time.at(0)
143
+ @retry_interval = 3
144
+ @max_tries = 5
145
+
146
+ if addrs = Resolver.hosts[hostname]
147
+ succeed addrs
148
+ else
149
+ EM.next_tick { tick }
150
+ end
151
+ end
152
+
153
+ def tick
154
+ # Break early if nothing to do
155
+ return if @last_send + @retry_interval > Time.now
156
+ if @tries < @max_tries
157
+ send
158
+ else
159
+ @socket.deregister_request(@id, self)
160
+ fail 'retries exceeded'
161
+ end
162
+ end
163
+
164
+ def receive_answer(msg)
165
+ addrs = []
166
+ msg.each_answer do |name,ttl,data|
167
+ if data.kind_of?(Resolv::DNS::Resource::IN::A) ||
168
+ data.kind_of?(Resolv::DNS::Resource::IN::AAAA)
169
+ addrs << data.address.to_s
170
+ end
171
+ end
172
+
173
+ if addrs.empty?
174
+ fail "rcode=#{msg.rcode}"
175
+ else
176
+ succeed addrs
177
+ end
178
+ end
179
+
180
+ private
181
+
182
+ def send
183
+ @tries += 1
184
+ @last_send = Time.now
185
+ @socket.send_packet(packet.encode)
186
+ end
187
+
188
+ def id
189
+ begin
190
+ @id = rand(65535)
191
+ @socket.register_request(@id, self)
192
+ rescue RequestIdAlreadyUsed
193
+ retry
194
+ end unless defined?(@id)
195
+
196
+ @id
197
+ end
198
+
199
+ def packet
200
+ msg = Resolv::DNS::Message.new
201
+ msg.id = id
202
+ msg.rd = 1
203
+ msg.add_question @hostname, Resolv::DNS::Resource::IN::A
204
+ msg
205
+ end
206
+
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,84 @@
1
+ #--
2
+ #
3
+ # Author:: Francis Cianfrocca (gmail: blackhedd)
4
+ # Homepage:: http://rubyeventmachine.com
5
+ # Date:: 25 Aug 2007
6
+ #
7
+ # See EventMachine and EventMachine::Connection for documentation and
8
+ # usage examples.
9
+ #
10
+ #----------------------------------------------------------------------------
11
+ #
12
+ # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
+ # Gmail: blackhedd
14
+ #
15
+ # This program is free software; you can redistribute it and/or modify
16
+ # it under the terms of either: 1) the GNU General Public License
17
+ # as published by the Free Software Foundation; either version 2 of the
18
+ # License, or (at your option) any later version; or 2) Ruby's License.
19
+ #
20
+ # See the file COPYING for complete licensing information.
21
+ #
22
+ #---------------------------------------------------------------------------
23
+ #
24
+ #
25
+
26
+ module EventMachine
27
+ # Support for Erlang-style processes.
28
+ #
29
+ class SpawnedProcess
30
+ # Send a message to the spawned process
31
+ def notify *x
32
+ me = self
33
+ EM.next_tick {
34
+ # A notification executes in the context of this
35
+ # SpawnedProcess object. That makes self and notify
36
+ # work as one would expect.
37
+ #
38
+ y = me.call(*x)
39
+ if y and y.respond_to?(:pull_out_yield_block)
40
+ a,b = y.pull_out_yield_block
41
+ set_receiver a
42
+ self.notify if b
43
+ end
44
+ }
45
+ end
46
+ alias_method :resume, :notify
47
+ alias_method :run, :notify # for formulations like (EM.spawn {xxx}).run
48
+
49
+ def set_receiver blk
50
+ (class << self ; self ; end).class_eval do
51
+ remove_method :call if method_defined? :call
52
+ define_method :call, blk
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ # @private
59
+ class YieldBlockFromSpawnedProcess
60
+ def initialize block, notify
61
+ @block = [block,notify]
62
+ end
63
+ def pull_out_yield_block
64
+ @block
65
+ end
66
+ end
67
+
68
+ # Spawn an erlang-style process
69
+ def self.spawn &block
70
+ s = SpawnedProcess.new
71
+ s.set_receiver block
72
+ s
73
+ end
74
+
75
+ # @private
76
+ def self.yield &block
77
+ return YieldBlockFromSpawnedProcess.new( block, false )
78
+ end
79
+
80
+ # @private
81
+ def self.yield_and_notify &block
82
+ return YieldBlockFromSpawnedProcess.new( block, true )
83
+ end
84
+ end
@@ -0,0 +1,118 @@
1
+ module EventMachine
2
+ # Streams a file over a given connection. Streaming begins once the object is
3
+ # instantiated. Typically FileStreamer instances are not reused.
4
+ #
5
+ # Streaming uses buffering for files larger than 16K and uses so-called fast file reader (a C++ extension)
6
+ # if available (it is part of eventmachine gem itself).
7
+ #
8
+ # @example
9
+ #
10
+ # module FileSender
11
+ # def post_init
12
+ # streamer = EventMachine::FileStreamer.new(self, '/tmp/bigfile.tar')
13
+ # streamer.callback{
14
+ # # file was sent successfully
15
+ # close_connection_after_writing
16
+ # }
17
+ # end
18
+ # end
19
+ #
20
+ #
21
+ # @author Francis Cianfrocca
22
+ class FileStreamer
23
+ include Deferrable
24
+
25
+ # Use mapped streamer for files bigger than 16k
26
+ MappingThreshold = 16384
27
+ # Wait until next tick to send more data when 50k is still in the outgoing buffer
28
+ BackpressureLevel = 50000
29
+ # Send 16k chunks at a time
30
+ ChunkSize = 16384
31
+
32
+ # @param [EventMachine::Connection] connection
33
+ # @param [String] filename File path
34
+ #
35
+ # @option args [Boolean] :http_chunks (false) Use HTTP 1.1 style chunked-encoding semantics.
36
+ def initialize connection, filename, args = {}
37
+ @connection = connection
38
+ @http_chunks = args[:http_chunks]
39
+
40
+ if File.exist?(filename)
41
+ @size = File.size(filename)
42
+ if @size <= MappingThreshold
43
+ stream_without_mapping filename
44
+ else
45
+ stream_with_mapping filename
46
+ end
47
+ else
48
+ fail "file not found"
49
+ end
50
+ end
51
+
52
+ # @private
53
+ def stream_without_mapping filename
54
+ if @http_chunks
55
+ @connection.send_data "#{@size.to_s(16)}\r\n"
56
+ @connection.send_file_data filename
57
+ @connection.send_data "\r\n0\r\n\r\n"
58
+ else
59
+ @connection.send_file_data filename
60
+ end
61
+ succeed
62
+ end
63
+ private :stream_without_mapping
64
+
65
+ # @private
66
+ def stream_with_mapping filename
67
+ ensure_mapping_extension_is_present
68
+
69
+ @position = 0
70
+ @mapping = EventMachine::FastFileReader::Mapper.new filename
71
+ stream_one_chunk
72
+ end
73
+ private :stream_with_mapping
74
+
75
+ # Used internally to stream one chunk at a time over multiple reactor ticks
76
+ # @private
77
+ def stream_one_chunk
78
+ loop {
79
+ if @position < @size
80
+ if @connection.get_outbound_data_size > BackpressureLevel
81
+ EventMachine::next_tick {stream_one_chunk}
82
+ break
83
+ else
84
+ len = @size - @position
85
+ len = ChunkSize if (len > ChunkSize)
86
+
87
+ @connection.send_data( "#{len.to_s(16)}\r\n" ) if @http_chunks
88
+ @connection.send_data( @mapping.get_chunk( @position, len ))
89
+ @connection.send_data("\r\n") if @http_chunks
90
+
91
+ @position += len
92
+ end
93
+ else
94
+ @connection.send_data "0\r\n\r\n" if @http_chunks
95
+ @mapping.close
96
+ succeed
97
+ break
98
+ end
99
+ }
100
+ end
101
+
102
+ #
103
+ # We use an outboard extension class to get memory-mapped files.
104
+ # It's outboard to avoid polluting the core distro, but that means
105
+ # there's a "hidden" dependency on it. The first time we get here in
106
+ # any run, try to load up the dependency extension. User code will see
107
+ # a LoadError if it's not available, but code that doesn't require
108
+ # mapped files will work fine without it. This is a somewhat difficult
109
+ # compromise between usability and proper modularization.
110
+ #
111
+ # @private
112
+ def ensure_mapping_extension_is_present
113
+ @@fastfilereader ||= (require 'fastfilereaderext')
114
+ end
115
+ private :ensure_mapping_extension_is_present
116
+
117
+ end # FileStreamer
118
+ end # EventMachine