eventmachine 0.12.10-x86-mswin32-60 → 1.0.0.beta.2-x86-mswin32-60

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 (150) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +1 -0
  3. data/README +80 -81
  4. data/Rakefile +7 -370
  5. data/docs/COPYING +60 -60
  6. data/docs/ChangeLog +211 -211
  7. data/docs/DEFERRABLES +246 -133
  8. data/docs/EPOLL +141 -141
  9. data/docs/GNU +281 -281
  10. data/docs/INSTALL +13 -13
  11. data/docs/KEYBOARD +42 -38
  12. data/docs/LEGAL +25 -25
  13. data/docs/LIGHTWEIGHT_CONCURRENCY +130 -70
  14. data/docs/PURE_RUBY +75 -75
  15. data/docs/RELEASE_NOTES +94 -94
  16. data/docs/SMTP +4 -2
  17. data/docs/SPAWNED_PROCESSES +148 -89
  18. data/docs/TODO +8 -8
  19. data/eventmachine.gemspec +19 -26
  20. data/examples/ex_channel.rb +42 -42
  21. data/examples/ex_queue.rb +2 -2
  22. data/examples/ex_tick_loop_array.rb +15 -0
  23. data/examples/ex_tick_loop_counter.rb +32 -0
  24. data/examples/helper.rb +1 -1
  25. data/ext/binder.cpp +0 -1
  26. data/ext/cmain.cpp +36 -25
  27. data/ext/ed.cpp +104 -113
  28. data/ext/ed.h +24 -30
  29. data/ext/em.cpp +349 -283
  30. data/ext/em.h +25 -29
  31. data/ext/eventmachine.h +5 -4
  32. data/ext/extconf.rb +58 -49
  33. data/ext/fastfilereader/extconf.rb +5 -3
  34. data/ext/fastfilereader/mapper.cpp +214 -214
  35. data/ext/fastfilereader/mapper.h +59 -59
  36. data/ext/fastfilereader/rubymain.cpp +127 -127
  37. data/ext/kb.cpp +1 -3
  38. data/ext/page.cpp +107 -107
  39. data/ext/page.h +51 -51
  40. data/ext/pipe.cpp +9 -11
  41. data/ext/project.h +12 -8
  42. data/ext/rubymain.cpp +138 -104
  43. data/java/.classpath +8 -8
  44. data/java/.project +17 -17
  45. data/java/src/com/rubyeventmachine/EmReactor.java +1 -0
  46. data/java/src/com/rubyeventmachine/EmReactorException.java +40 -40
  47. data/lib/em/buftok.rb +138 -138
  48. data/lib/em/callback.rb +25 -25
  49. data/lib/em/channel.rb +1 -1
  50. data/lib/em/connection.rb +6 -1
  51. data/lib/em/deferrable.rb +16 -2
  52. data/lib/em/file_watch.rb +53 -53
  53. data/lib/em/future.rb +61 -61
  54. data/lib/em/iterator.rb +270 -0
  55. data/lib/em/messages.rb +66 -66
  56. data/lib/em/process_watch.rb +43 -43
  57. data/lib/em/protocols.rb +1 -1
  58. data/lib/em/protocols/header_and_content.rb +138 -138
  59. data/lib/em/protocols/httpclient.rb +267 -262
  60. data/lib/em/protocols/line_protocol.rb +28 -0
  61. data/lib/em/protocols/memcache.rb +322 -322
  62. data/lib/em/protocols/postgres3.rb +247 -247
  63. data/lib/em/protocols/saslauth.rb +175 -175
  64. data/lib/em/protocols/smtpserver.rb +640 -547
  65. data/lib/em/protocols/stomp.rb +200 -200
  66. data/lib/em/protocols/tcptest.rb +52 -52
  67. data/lib/{pr_eventmachine.rb → em/pure_ruby.rb} +1013 -1022
  68. data/lib/em/queue.rb +1 -0
  69. data/lib/em/spawnable.rb +85 -85
  70. data/lib/em/streamer.rb +130 -130
  71. data/lib/em/tick_loop.rb +85 -0
  72. data/lib/em/timers.rb +2 -1
  73. data/lib/em/version.rb +1 -1
  74. data/lib/eventmachine.rb +40 -84
  75. data/lib/jeventmachine.rb +2 -1
  76. data/lib/rubyeventmachine.rb +2 -0
  77. data/setup.rb +1585 -1585
  78. data/tasks/doc.rake +30 -0
  79. data/tasks/package.rake +85 -0
  80. data/tasks/test.rake +6 -0
  81. data/tests/client.crt +31 -31
  82. data/tests/client.key +51 -51
  83. data/tests/test_attach.rb +13 -3
  84. data/tests/test_basic.rb +60 -95
  85. data/tests/test_channel.rb +3 -2
  86. data/tests/test_defer.rb +49 -47
  87. data/tests/test_deferrable.rb +35 -0
  88. data/tests/test_error_handler.rb +35 -35
  89. data/tests/test_errors.rb +82 -82
  90. data/tests/test_exc.rb +55 -55
  91. data/tests/test_file_watch.rb +49 -49
  92. data/tests/test_futures.rb +198 -198
  93. data/tests/test_handler_check.rb +36 -36
  94. data/tests/test_hc.rb +190 -218
  95. data/tests/test_httpclient.rb +227 -218
  96. data/tests/test_httpclient2.rb +3 -2
  97. data/tests/test_inactivity_timeout.rb +3 -3
  98. data/tests/test_kb.rb +60 -60
  99. data/tests/test_ltp.rb +13 -5
  100. data/tests/test_ltp2.rb +317 -317
  101. data/tests/test_next_tick.rb +1 -1
  102. data/tests/test_object_protocol.rb +36 -36
  103. data/tests/test_pending_connect_timeout.rb +2 -2
  104. data/tests/test_process_watch.rb +50 -48
  105. data/tests/test_proxy_connection.rb +52 -0
  106. data/tests/test_pure.rb +134 -125
  107. data/tests/test_queue.rb +44 -44
  108. data/tests/test_running.rb +42 -42
  109. data/tests/test_sasl.rb +72 -72
  110. data/tests/test_send_file.rb +251 -242
  111. data/tests/test_servers.rb +76 -76
  112. data/tests/test_smtpclient.rb +83 -83
  113. data/tests/test_smtpserver.rb +85 -85
  114. data/tests/test_spawn.rb +322 -322
  115. data/tests/test_ssl_methods.rb +49 -49
  116. data/tests/test_ssl_verify.rb +82 -82
  117. data/tests/test_tick_loop.rb +59 -0
  118. data/tests/test_timers.rb +13 -15
  119. data/tests/test_ud.rb +36 -36
  120. data/tests/testem.rb +31 -31
  121. metadata +66 -51
  122. data/ext/cplusplus.cpp +0 -202
  123. data/ext/emwin.cpp +0 -300
  124. data/ext/emwin.h +0 -94
  125. data/ext/epoll.cpp +0 -26
  126. data/ext/epoll.h +0 -25
  127. data/ext/eventmachine_cpp.h +0 -96
  128. data/ext/files.cpp +0 -94
  129. data/ext/files.h +0 -65
  130. data/ext/sigs.cpp +0 -89
  131. data/ext/sigs.h +0 -32
  132. data/java/src/com/rubyeventmachine/application/Application.java +0 -194
  133. data/java/src/com/rubyeventmachine/application/Connection.java +0 -74
  134. data/java/src/com/rubyeventmachine/application/ConnectionFactory.java +0 -37
  135. data/java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java +0 -46
  136. data/java/src/com/rubyeventmachine/application/PeriodicTimer.java +0 -38
  137. data/java/src/com/rubyeventmachine/application/Timer.java +0 -54
  138. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +0 -109
  139. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +0 -148
  140. data/java/src/com/rubyeventmachine/tests/EMTest.java +0 -80
  141. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +0 -53
  142. data/java/src/com/rubyeventmachine/tests/TestServers.java +0 -75
  143. data/java/src/com/rubyeventmachine/tests/TestTimers.java +0 -90
  144. data/lib/evma.rb +0 -32
  145. data/lib/evma/callback.rb +0 -32
  146. data/lib/evma/container.rb +0 -75
  147. data/lib/evma/factory.rb +0 -77
  148. data/lib/evma/protocol.rb +0 -87
  149. data/lib/evma/reactor.rb +0 -48
  150. data/web/whatis +0 -7
@@ -0,0 +1,28 @@
1
+ module EventMachine
2
+ module Protocols
3
+ # LineProtocol will parse out newline terminated strings from a receive_data stream
4
+ #
5
+ # module Server
6
+ # include EM::P::LineProtocol
7
+ #
8
+ # def receive_line(line)
9
+ # send_data("you said: #{line}")
10
+ # end
11
+ # end
12
+ #
13
+ module LineProtocol
14
+ def receive_data data # :nodoc:
15
+ (@buf ||= '') << data
16
+
17
+ while line = @buf.slice!(/(.*)\r?\n/)
18
+ receive_line(line)
19
+ end
20
+ end
21
+
22
+ # Invoked with lines received over the network
23
+ def receive_line(line)
24
+ # stub
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,323 +1,323 @@
1
- module EventMachine
2
- module Protocols
3
- # Implements the Memcache protocol (http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt).
4
- # Requires memcached >= 1.2.4 w/ noreply support
5
- #
6
- # == Usage example
7
- #
8
- # EM.run{
9
- # cache = EM::P::Memcache.connect 'localhost', 11211
10
- #
11
- # cache.set :a, 'hello'
12
- # cache.set :b, 'hi'
13
- # cache.set :c, 'how are you?'
14
- # cache.set :d, ''
15
- #
16
- # cache.get(:a){ |v| p v }
17
- # cache.get_hash(:a, :b, :c, :d){ |v| p v }
18
- # cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
19
- #
20
- # cache.get(:a,:z,:b,:y,:d){ |a,z,b,y,d| p [a,z,b,y,d] }
21
- #
22
- # cache.get(:missing){ |m| p [:missing=, m] }
23
- # cache.set(:missing, 'abc'){ p :stored }
24
- # cache.get(:missing){ |m| p [:missing=, m] }
25
- # cache.del(:missing){ p :deleted }
26
- # cache.get(:missing){ |m| p [:missing=, m] }
27
- # }
28
- #
29
- module Memcache
30
- include EM::Deferrable
31
-
32
- ##
33
- # constants
34
-
35
- # :stopdoc:
36
- unless defined? Cempty
37
- Cstored = 'STORED'.freeze
38
- Cend = 'END'.freeze
39
- Cdeleted = 'DELETED'.freeze
40
- Cunknown = 'NOT_FOUND'.freeze
41
- Cerror = 'ERROR'.freeze
42
-
43
- Cempty = ''.freeze
44
- Cdelimiter = "\r\n".freeze
45
- end
46
- # :startdoc:
47
-
48
- ##
49
- # commands
50
-
51
- # Get the value associated with one or multiple keys
52
- #
53
- # cache.get(:a){ |v| p v }
54
- # cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
55
- #
56
- def get *keys
57
- raise ArgumentError unless block_given?
58
-
59
- callback{
60
- keys = keys.map{|k| k.to_s.gsub(/\s/,'_') }
61
- send_data "get #{keys.join(' ')}\r\n"
62
- @get_cbs << [keys, proc{ |values|
63
- yield *keys.map{ |k| values[k] }
64
- }]
65
- }
66
- end
67
-
68
- # Set the value for a given key
69
- #
70
- # cache.set :a, 'hello'
71
- # cache.set(:missing, 'abc'){ puts "stored the value!" }
72
- #
73
- def set key, val, exptime = 0, &cb
74
- callback{
75
- val = val.to_s
76
- send_cmd :set, key, 0, exptime, val.respond_to?(:bytesize) ? val.bytesize : val.size, !block_given?
77
- send_data val
78
- send_data Cdelimiter
79
- @set_cbs << cb if cb
80
- }
81
- end
82
-
83
- # Gets multiple values as a hash
84
- #
85
- # cache.get_hash(:a, :b, :c, :d){ |h| puts h[:a] }
86
- #
87
- def get_hash *keys
88
- raise ArgumentError unless block_given?
89
-
90
- get *keys do |*values|
91
- yield keys.inject({}){ |hash, k| hash.update k => values[keys.index(k)] }
92
- end
93
- end
94
-
95
- # Delete the value associated with a key
96
- #
97
- # cache.del :a
98
- # cache.del(:b){ puts "deleted the value!" }
99
- #
100
- def delete key, expires = 0, &cb
101
- callback{
102
- send_data "delete #{key} #{expires}#{cb ? '' : ' noreply'}\r\n"
103
- @del_cbs << cb if cb
104
- }
105
- end
106
- alias del delete
107
-
108
- # Connect to a memcached server (must support NOREPLY, memcached >= 1.2.4)
109
- def self.connect host = 'localhost', port = 11211
110
- EM.connect host, port, self, host, port
111
- end
112
-
113
- # :stopdoc:
114
-
115
- def send_cmd cmd, key, flags = 0, exptime = 0, bytes = 0, noreply = false # :nodoc:
116
- send_data "#{cmd} #{key} #{flags} #{exptime} #{bytes}#{noreply ? ' noreply' : ''}\r\n"
117
- end
118
- private :send_cmd
119
-
120
- ##
121
- # errors
122
-
123
- class ParserError < StandardError
124
- end
125
-
126
- ##
127
- # em hooks
128
-
129
- def initialize host, port = 11211
130
- @host, @port = host, port
131
- end
132
-
133
- def connection_completed
134
- @get_cbs = []
135
- @set_cbs = []
136
- @del_cbs = []
137
-
138
- @values = {}
139
-
140
- @reconnecting = false
141
- @connected = true
142
- succeed
143
- # set_delimiter "\r\n"
144
- # set_line_mode
145
- end
146
-
147
- #--
148
- # 19Feb09 Switched to a custom parser, LineText2 is recursive and can cause
149
- # stack overflows when there is too much data.
150
- # include EM::P::LineText2
151
- def receive_data data
152
- (@buffer||='') << data
153
-
154
- while index = @buffer.index(Cdelimiter)
155
- begin
156
- line = @buffer.slice!(0,index+2)
157
- process_cmd line
158
- rescue ParserError
159
- @buffer[0...0] = line
160
- break
161
- end
162
- end
163
- end
164
-
165
- #--
166
- # def receive_line line
167
- def process_cmd line
168
- case line.strip
169
- when /^VALUE\s+(.+?)\s+(\d+)\s+(\d+)/ # VALUE <key> <flags> <bytes>
170
- bytes = Integer($3)
171
- # set_binary_mode bytes+2
172
- # @cur_key = $1
173
- if @buffer.size >= bytes + 2
174
- @values[$1] = @buffer.slice!(0,bytes)
175
- @buffer.slice!(0,2) # \r\n
176
- else
177
- raise ParserError
178
- end
179
-
180
- when Cend # END
181
- if entry = @get_cbs.shift
182
- keys, cb = entry
183
- cb.call(@values)
184
- end
185
- @values = {}
186
-
187
- when Cstored # STORED
188
- if cb = @set_cbs.shift
189
- cb.call(true)
190
- end
191
-
192
- when Cdeleted # DELETED
193
- if cb = @del_cbs.shift
194
- cb.call(true)
195
- end
196
-
197
- when Cunknown # NOT_FOUND
198
- if cb = @del_cbs.shift
199
- cb.call(false)
200
- end
201
-
202
- else
203
- p [:MEMCACHE_UNKNOWN, line]
204
- end
205
- end
206
-
207
- #--
208
- # def receive_binary_data data
209
- # @values[@cur_key] = data[0..-3]
210
- # end
211
-
212
- def unbind
213
- if @connected or @reconnecting
214
- EM.add_timer(1){ reconnect @host, @port }
215
- @connected = false
216
- @reconnecting = true
217
- @deferred_status = nil
218
- else
219
- raise 'Unable to connect to memcached server'
220
- end
221
- end
222
-
223
- # :startdoc:
224
- end
225
- end
226
- end
227
-
228
- if __FILE__ == $0
229
- # ruby -I ext:lib -r eventmachine -rubygems lib/protocols/memcache.rb
230
- require 'em/spec'
231
-
232
- class TestConnection # :nodoc:
233
- include EM::P::Memcache
234
- def send_data data
235
- sent_data << data
236
- end
237
- def sent_data
238
- @sent_data ||= ''
239
- end
240
-
241
- def initialize
242
- connection_completed
243
- end
244
- end
245
-
246
- EM.describe EM::Protocols::Memcache do
247
-
248
- before{
249
- @c = TestConnection.new
250
- }
251
-
252
- should 'send get requests' do
253
- @c.get('a'){}
254
- @c.sent_data.should == "get a\r\n"
255
- done
256
- end
257
-
258
- should 'send set requests' do
259
- @c.set('a', 1){}
260
- @c.sent_data.should == "set a 0 0 1\r\n1\r\n"
261
- done
262
- end
263
-
264
- should 'use noreply on set without block' do
265
- @c.set('a', 1)
266
- @c.sent_data.should == "set a 0 0 1 noreply\r\n1\r\n"
267
- done
268
- end
269
-
270
- should 'send delete requests' do
271
- @c.del('a')
272
- @c.sent_data.should == "delete a 0 noreply\r\n"
273
- done
274
- end
275
-
276
- should 'work when get returns no values' do
277
- @c.get('a'){ |a|
278
- a.should.be.nil
279
- done
280
- }
281
-
282
- @c.receive_data "END\r\n"
283
- end
284
-
285
- should 'invoke block on set' do
286
- @c.set('a', 1){
287
- done
288
- }
289
-
290
- @c.receive_data "STORED\r\n"
291
- end
292
-
293
- should 'invoke block on delete' do
294
- @c.delete('a'){ |found|
295
- found.should.be.false
296
- }
297
- @c.delete('b'){ |found|
298
- found.should.be.true
299
- done
300
- }
301
-
302
- @c.receive_data "NOT_FOUND\r\n"
303
- @c.receive_data "DELETED\r\n"
304
- end
305
-
306
- should 'parse split responses' do
307
- @c.get('a'){ |a|
308
- a.should == 'abc'
309
- done
310
- }
311
-
312
- @c.receive_data "VAL"
313
- @c.receive_data "UE a 0 "
314
- @c.receive_data "3\r\n"
315
- @c.receive_data "ab"
316
- @c.receive_data "c"
317
- @c.receive_data "\r\n"
318
- @c.receive_data "EN"
319
- @c.receive_data "D\r\n"
320
- end
321
-
322
- end
1
+ module EventMachine
2
+ module Protocols
3
+ # Implements the Memcache protocol (http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt).
4
+ # Requires memcached >= 1.2.4 w/ noreply support
5
+ #
6
+ # == Usage example
7
+ #
8
+ # EM.run{
9
+ # cache = EM::P::Memcache.connect 'localhost', 11211
10
+ #
11
+ # cache.set :a, 'hello'
12
+ # cache.set :b, 'hi'
13
+ # cache.set :c, 'how are you?'
14
+ # cache.set :d, ''
15
+ #
16
+ # cache.get(:a){ |v| p v }
17
+ # cache.get_hash(:a, :b, :c, :d){ |v| p v }
18
+ # cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
19
+ #
20
+ # cache.get(:a,:z,:b,:y,:d){ |a,z,b,y,d| p [a,z,b,y,d] }
21
+ #
22
+ # cache.get(:missing){ |m| p [:missing=, m] }
23
+ # cache.set(:missing, 'abc'){ p :stored }
24
+ # cache.get(:missing){ |m| p [:missing=, m] }
25
+ # cache.del(:missing){ p :deleted }
26
+ # cache.get(:missing){ |m| p [:missing=, m] }
27
+ # }
28
+ #
29
+ module Memcache
30
+ include EM::Deferrable
31
+
32
+ ##
33
+ # constants
34
+
35
+ # :stopdoc:
36
+ unless defined? Cempty
37
+ Cstored = 'STORED'.freeze
38
+ Cend = 'END'.freeze
39
+ Cdeleted = 'DELETED'.freeze
40
+ Cunknown = 'NOT_FOUND'.freeze
41
+ Cerror = 'ERROR'.freeze
42
+
43
+ Cempty = ''.freeze
44
+ Cdelimiter = "\r\n".freeze
45
+ end
46
+ # :startdoc:
47
+
48
+ ##
49
+ # commands
50
+
51
+ # Get the value associated with one or multiple keys
52
+ #
53
+ # cache.get(:a){ |v| p v }
54
+ # cache.get(:a,:b,:c,:d){ |a,b,c,d| p [a,b,c,d] }
55
+ #
56
+ def get *keys
57
+ raise ArgumentError unless block_given?
58
+
59
+ callback{
60
+ keys = keys.map{|k| k.to_s.gsub(/\s/,'_') }
61
+ send_data "get #{keys.join(' ')}\r\n"
62
+ @get_cbs << [keys, proc{ |values|
63
+ yield *keys.map{ |k| values[k] }
64
+ }]
65
+ }
66
+ end
67
+
68
+ # Set the value for a given key
69
+ #
70
+ # cache.set :a, 'hello'
71
+ # cache.set(:missing, 'abc'){ puts "stored the value!" }
72
+ #
73
+ def set key, val, exptime = 0, &cb
74
+ callback{
75
+ val = val.to_s
76
+ send_cmd :set, key, 0, exptime, val.respond_to?(:bytesize) ? val.bytesize : val.size, !block_given?
77
+ send_data val
78
+ send_data Cdelimiter
79
+ @set_cbs << cb if cb
80
+ }
81
+ end
82
+
83
+ # Gets multiple values as a hash
84
+ #
85
+ # cache.get_hash(:a, :b, :c, :d){ |h| puts h[:a] }
86
+ #
87
+ def get_hash *keys
88
+ raise ArgumentError unless block_given?
89
+
90
+ get *keys do |*values|
91
+ yield keys.inject({}){ |hash, k| hash.update k => values[keys.index(k)] }
92
+ end
93
+ end
94
+
95
+ # Delete the value associated with a key
96
+ #
97
+ # cache.del :a
98
+ # cache.del(:b){ puts "deleted the value!" }
99
+ #
100
+ def delete key, expires = 0, &cb
101
+ callback{
102
+ send_data "delete #{key} #{expires}#{cb ? '' : ' noreply'}\r\n"
103
+ @del_cbs << cb if cb
104
+ }
105
+ end
106
+ alias del delete
107
+
108
+ # Connect to a memcached server (must support NOREPLY, memcached >= 1.2.4)
109
+ def self.connect host = 'localhost', port = 11211
110
+ EM.connect host, port, self, host, port
111
+ end
112
+
113
+ # :stopdoc:
114
+
115
+ def send_cmd cmd, key, flags = 0, exptime = 0, bytes = 0, noreply = false # :nodoc:
116
+ send_data "#{cmd} #{key} #{flags} #{exptime} #{bytes}#{noreply ? ' noreply' : ''}\r\n"
117
+ end
118
+ private :send_cmd
119
+
120
+ ##
121
+ # errors
122
+
123
+ class ParserError < StandardError
124
+ end
125
+
126
+ ##
127
+ # em hooks
128
+
129
+ def initialize host, port = 11211
130
+ @host, @port = host, port
131
+ end
132
+
133
+ def connection_completed
134
+ @get_cbs = []
135
+ @set_cbs = []
136
+ @del_cbs = []
137
+
138
+ @values = {}
139
+
140
+ @reconnecting = false
141
+ @connected = true
142
+ succeed
143
+ # set_delimiter "\r\n"
144
+ # set_line_mode
145
+ end
146
+
147
+ #--
148
+ # 19Feb09 Switched to a custom parser, LineText2 is recursive and can cause
149
+ # stack overflows when there is too much data.
150
+ # include EM::P::LineText2
151
+ def receive_data data
152
+ (@buffer||='') << data
153
+
154
+ while index = @buffer.index(Cdelimiter)
155
+ begin
156
+ line = @buffer.slice!(0,index+2)
157
+ process_cmd line
158
+ rescue ParserError
159
+ @buffer[0...0] = line
160
+ break
161
+ end
162
+ end
163
+ end
164
+
165
+ #--
166
+ # def receive_line line
167
+ def process_cmd line
168
+ case line.strip
169
+ when /^VALUE\s+(.+?)\s+(\d+)\s+(\d+)/ # VALUE <key> <flags> <bytes>
170
+ bytes = Integer($3)
171
+ # set_binary_mode bytes+2
172
+ # @cur_key = $1
173
+ if @buffer.size >= bytes + 2
174
+ @values[$1] = @buffer.slice!(0,bytes)
175
+ @buffer.slice!(0,2) # \r\n
176
+ else
177
+ raise ParserError
178
+ end
179
+
180
+ when Cend # END
181
+ if entry = @get_cbs.shift
182
+ keys, cb = entry
183
+ cb.call(@values)
184
+ end
185
+ @values = {}
186
+
187
+ when Cstored # STORED
188
+ if cb = @set_cbs.shift
189
+ cb.call(true)
190
+ end
191
+
192
+ when Cdeleted # DELETED
193
+ if cb = @del_cbs.shift
194
+ cb.call(true)
195
+ end
196
+
197
+ when Cunknown # NOT_FOUND
198
+ if cb = @del_cbs.shift
199
+ cb.call(false)
200
+ end
201
+
202
+ else
203
+ p [:MEMCACHE_UNKNOWN, line]
204
+ end
205
+ end
206
+
207
+ #--
208
+ # def receive_binary_data data
209
+ # @values[@cur_key] = data[0..-3]
210
+ # end
211
+
212
+ def unbind
213
+ if @connected or @reconnecting
214
+ EM.add_timer(1){ reconnect @host, @port }
215
+ @connected = false
216
+ @reconnecting = true
217
+ @deferred_status = nil
218
+ else
219
+ raise 'Unable to connect to memcached server'
220
+ end
221
+ end
222
+
223
+ # :startdoc:
224
+ end
225
+ end
226
+ end
227
+
228
+ if __FILE__ == $0
229
+ # ruby -I ext:lib -r eventmachine -rubygems lib/protocols/memcache.rb
230
+ require 'em/spec'
231
+
232
+ class TestConnection # :nodoc:
233
+ include EM::P::Memcache
234
+ def send_data data
235
+ sent_data << data
236
+ end
237
+ def sent_data
238
+ @sent_data ||= ''
239
+ end
240
+
241
+ def initialize
242
+ connection_completed
243
+ end
244
+ end
245
+
246
+ EM.describe EM::Protocols::Memcache do
247
+
248
+ before{
249
+ @c = TestConnection.new
250
+ }
251
+
252
+ should 'send get requests' do
253
+ @c.get('a'){}
254
+ @c.sent_data.should == "get a\r\n"
255
+ done
256
+ end
257
+
258
+ should 'send set requests' do
259
+ @c.set('a', 1){}
260
+ @c.sent_data.should == "set a 0 0 1\r\n1\r\n"
261
+ done
262
+ end
263
+
264
+ should 'use noreply on set without block' do
265
+ @c.set('a', 1)
266
+ @c.sent_data.should == "set a 0 0 1 noreply\r\n1\r\n"
267
+ done
268
+ end
269
+
270
+ should 'send delete requests' do
271
+ @c.del('a')
272
+ @c.sent_data.should == "delete a 0 noreply\r\n"
273
+ done
274
+ end
275
+
276
+ should 'work when get returns no values' do
277
+ @c.get('a'){ |a|
278
+ a.should.be.nil
279
+ done
280
+ }
281
+
282
+ @c.receive_data "END\r\n"
283
+ end
284
+
285
+ should 'invoke block on set' do
286
+ @c.set('a', 1){
287
+ done
288
+ }
289
+
290
+ @c.receive_data "STORED\r\n"
291
+ end
292
+
293
+ should 'invoke block on delete' do
294
+ @c.delete('a'){ |found|
295
+ found.should.be.false
296
+ }
297
+ @c.delete('b'){ |found|
298
+ found.should.be.true
299
+ done
300
+ }
301
+
302
+ @c.receive_data "NOT_FOUND\r\n"
303
+ @c.receive_data "DELETED\r\n"
304
+ end
305
+
306
+ should 'parse split responses' do
307
+ @c.get('a'){ |a|
308
+ a.should == 'abc'
309
+ done
310
+ }
311
+
312
+ @c.receive_data "VAL"
313
+ @c.receive_data "UE a 0 "
314
+ @c.receive_data "3\r\n"
315
+ @c.receive_data "ab"
316
+ @c.receive_data "c"
317
+ @c.receive_data "\r\n"
318
+ @c.receive_data "EN"
319
+ @c.receive_data "D\r\n"
320
+ end
321
+
322
+ end
323
323
  end