internethakai 0.2.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.
Files changed (36) hide show
  1. data/CHANGES +53 -0
  2. data/README +177 -0
  3. data/bin/hakaigen +10 -0
  4. data/bin/internethakai +9 -0
  5. data/internethakai.gemspec +27 -0
  6. data/lib/internethakai.rb +26 -0
  7. data/lib/internethakai.rb.~1~ +25 -0
  8. data/lib/internethakai/action.rb +403 -0
  9. data/lib/internethakai/client_handler.rb +175 -0
  10. data/lib/internethakai/client_queue.rb +27 -0
  11. data/lib/internethakai/concurrency_manager.rb +333 -0
  12. data/lib/internethakai/concurrency_manager.rb.~1~ +331 -0
  13. data/lib/internethakai/core.rb +146 -0
  14. data/lib/internethakai/executor.rb +129 -0
  15. data/lib/internethakai/generator.rb +32 -0
  16. data/lib/internethakai/hakairev.rb +119 -0
  17. data/lib/internethakai/hakairev/executor.rb +43 -0
  18. data/lib/internethakai/hakairev/http_client.rb +362 -0
  19. data/lib/internethakai/hakairev/http_client.rb.~1~ +371 -0
  20. data/lib/internethakai/hakairev/monkey.rb +70 -0
  21. data/lib/internethakai/hakairev/revpipe.rb +39 -0
  22. data/lib/internethakai/hakairev/task.rb +39 -0
  23. data/lib/internethakai/hakairev/time_register.rb +116 -0
  24. data/lib/internethakai/hakairev/timer_factory.rb +38 -0
  25. data/lib/internethakai/http_client.rb +120 -0
  26. data/lib/internethakai/logger.rb +52 -0
  27. data/lib/internethakai/main.rb +90 -0
  28. data/lib/internethakai/reporter.rb +143 -0
  29. data/lib/internethakai/response.rb +65 -0
  30. data/lib/internethakai/scenario.rb +98 -0
  31. data/lib/internethakai/scenario.tmpl +58 -0
  32. data/lib/internethakai/scenario_builder.rb +183 -0
  33. data/lib/internethakai/scenario_handler.rb +91 -0
  34. data/lib/internethakai/time_register.rb +53 -0
  35. data/lib/internethakai/util.rb +130 -0
  36. metadata +134 -0
@@ -0,0 +1,371 @@
1
+ module InternetHakai
2
+ class RevHttpConnection < Rev::HttpClient
3
+ def initialize args
4
+ @remote_addr, @remote_port = args
5
+ soc = TCPConnectSocket::new(::Socket::AF_INET, @remote_addr, @remote_port)
6
+ super(soc)
7
+ end
8
+ def init
9
+ @content = ''
10
+ @writable_flag = false
11
+ @send_flag = false
12
+ @busy = false
13
+ @on_request_complete = nil
14
+ @requested = false
15
+ @response_object = InternetHakai::ResponseObject::new
16
+ self
17
+ end
18
+ attr_reader :connected, :busy
19
+ def on_read s
20
+ super
21
+ end
22
+ def on_readable
23
+ begin
24
+ on_read @_io.read_nonblock(INPUT_SIZE)
25
+ rescue Errno::EAGAIN
26
+ rescue Errno::ECONNRESET, EOFError
27
+ rescue IOError => e
28
+ @exception = e
29
+ on_error('io error')
30
+ rescue Exception => e
31
+ @exception = e
32
+ on_error('io error')
33
+ end
34
+ end
35
+ def reconnect
36
+ @requested = false
37
+ @busy = false
38
+ free
39
+ socket = TCPConnectSocket::new(::Socket::AF_INET, @remote_addr, @remote_port)
40
+
41
+ @_io = socket
42
+ #@_write_buffer ||= ::IO::Buffer.new
43
+ @_read_watcher = Watcher.new(socket, self, :r)
44
+ @_write_watcher = Watcher.new(socket, self, :w)
45
+ @address_family, @remote_port, @remote_host, @remote_addr = socket.peeraddr
46
+
47
+
48
+ @state = :response_header
49
+ #@data = ::IO::Buffer.new
50
+
51
+ @response_header = Rev::HttpResponseHeader.new
52
+ @chunk_header = Rev::HttpChunkHeader.new
53
+ #initialize(socket)
54
+
55
+ @_connector = Connector::new(self, socket)
56
+ @_connector.attach(@loop)
57
+ end
58
+ def close
59
+ super
60
+ end
61
+ def on_writable
62
+ @writable_flag = true unless @writable_flag
63
+ # writable + send 両方そろったら開始時間
64
+ if @send_flag && !@starttime
65
+ @starttime = Time::now
66
+ end
67
+ begin
68
+ @_write_buffer.write_to(@_io)
69
+
70
+ rescue Errno::EPIPE, Errno::ECONNRESET => e
71
+ rescue IOError => e
72
+ rescue Exception => e
73
+ @exception = e
74
+ on_error('io error')
75
+ end
76
+ if @_write_buffer.empty?
77
+ disable_write_watcher
78
+ on_write_complete
79
+ end
80
+ end
81
+ def send_request
82
+ @send_flag = true
83
+ @starttime = Time::now
84
+ super
85
+ end
86
+ def attached?
87
+ if @_connector
88
+ @_connector.attached?
89
+ elsif @_read_watcher
90
+ @_read_watcher.attached?
91
+ elsif @_resolver
92
+ @_resolver.attached
93
+ else
94
+ super
95
+ end
96
+ end
97
+ def on_body_data(data)
98
+ @content += data
99
+ end
100
+ def on_request_complete
101
+ @response_time = Time::now - @starttime
102
+ self.close
103
+ end
104
+ def on_connect_failed
105
+ @exception = SocketError::new('connection error')
106
+ on_error('')
107
+ end
108
+ def on_resolve_failed
109
+ @exception = SocketError::new('dns error')
110
+ on_error('')
111
+ end
112
+ def on_failure
113
+ @exception = SocketError::new
114
+ on_error('')
115
+ end
116
+ def on_error(reason='error')
117
+ unless @starttime.nil?
118
+ @response_time = Time::now - @starttime
119
+ else
120
+ @response_time = 0
121
+ end
122
+ close if @_io and !@_io.closed?
123
+ @requested = false
124
+ @exception = reason if @exception.nil?
125
+ @busy = false
126
+ end
127
+ def to_response_object
128
+ r = @response_object
129
+ r.body = @content.to_s
130
+ r.status = @response_header.http_status.to_i
131
+ r.content_type = @response_header["CONTENT_TYPE"].to_s
132
+ r.location = @response_header["LOCATION"]
133
+ r.time = @response_time
134
+ r
135
+ end
136
+ def attach lp
137
+ @loop = lp unless @loop
138
+ if @_connector
139
+ @_connector.attach lp
140
+ elsif @_read_watcher
141
+ @_read_watcher.attach(lp)
142
+ elsif @_resolver
143
+ @_resolver.attache lp
144
+ else
145
+ return
146
+ end
147
+ end
148
+ =begin
149
+ def parse_response_header
150
+ return false unless parse_header(@response_header)
151
+
152
+ unless @response_header.http_status and @response_header.http_reason
153
+ on_error "no HTTP response"
154
+ @state = :invalid
155
+ return false
156
+ end
157
+
158
+ on_response_header(@response_header)
159
+
160
+ @state = :body
161
+ @bytes_remaining = @response_header.content_length
162
+
163
+ true
164
+ end
165
+ =end
166
+ =begin
167
+ def parse_header(header)
168
+ return false if @data.empty?
169
+
170
+ key = nil
171
+ if idx = @data.to_str.index("\r\n\r\n")
172
+ ctx = idx + 4
173
+ key = @data.to_str[0, ctx]
174
+ #key = Digest::MD5::digest(@data.to_str[0, ctx])
175
+ if obj = searchcache(key)
176
+ @parser_nbytes = 0
177
+ @data.read(ctx)
178
+ @parser.reset
179
+ @response_header = obj
180
+ return true
181
+ end
182
+ end
183
+ begin
184
+ @parser_nbytes = @parser.execute(header, @data.to_str, @parser_nbytes)
185
+ rescue Rev::HttpClientParserError
186
+ on_error "invalid HTTP format, parsing fails"
187
+ @state = :invalid
188
+ end
189
+
190
+ return false unless @parser.finished?
191
+
192
+ if key
193
+ insertcache(key, header)
194
+ end
195
+
196
+ # Clear parsed data from the buffer
197
+ @data.read(@parser_nbytes)
198
+ @parser.reset
199
+ @parser_nbytes = 0
200
+
201
+ true
202
+ end
203
+ =end
204
+ @@_cache = {}
205
+ @@_cache_keys = []
206
+ @@_cache_max = 200
207
+ def insertcache key, data
208
+ @@_cache[key] = data.dup
209
+ if @@_cache_keys.size > @@_cache_max
210
+ @@_cache.delete(@@_cache_keys.shift)
211
+ end
212
+ end
213
+ def searchcache key
214
+ if @@_cache.has_key?(key)
215
+ @@_cache_keys << key
216
+ @@_cache[key]
217
+ else
218
+ nil
219
+ end
220
+ end
221
+ def free
222
+ @content = ''
223
+ #@response_header = nil
224
+ #@chunk_header = nil
225
+ @response_time = nil
226
+ @_write_buffer.clear
227
+ #@_write_buffer = nil
228
+ @_read_watcher.detach if @_read_watcher.attached?
229
+ #@_read_watcher = nil
230
+ @_write_watcher.detach if @_write_watcher.attached?
231
+ #@_write_watcher = nil
232
+ @data.clear
233
+ #@data = nil
234
+ #@path = nil
235
+ #@method = nil
236
+ #@options = nil
237
+ #@starttime = nil
238
+ #@_io = nil
239
+ @writable_flag = nil
240
+ @send_flag = nil
241
+ @connected = false
242
+ end
243
+ end
244
+ class RevHttpClient < RevHttpConnection
245
+ def self::create host, port
246
+ #o = self::create_from_port(host, port)
247
+ o = self::new([host, port])
248
+ o.attach(Rev::Loop::default)
249
+ o.prepare(host, port)
250
+ o
251
+ end
252
+ attr_reader :result, :complete
253
+ attr_accessor :timeout, :useragent, :tfactory, :client_queue
254
+ def prepare host, port
255
+ init
256
+ @host = host
257
+ @port = port
258
+ @on_failure = nil
259
+ @on_success = nil
260
+ @on_finish = []
261
+ @client_queue = nil
262
+ _this = self
263
+ @queue = BaseHandler::get_handler('TaskQueue')
264
+ @method_handle_response = method(:handle_response)
265
+ #以下のバグへの対応
266
+ #http://redmine.ruby-lang.org/issues/show/3786
267
+ @method_timeout = lambda{
268
+ _this.handle_timeout
269
+ }
270
+ #@method_timeout = method(:timeout)
271
+ #@method_call_on_success = method(:call_on_success)
272
+ #@method_call_on_failure = method(:call_on_failure)
273
+ end
274
+ def timeout= timeout
275
+ @timeout = timeout
276
+ end
277
+ def set_headers header
278
+ @headers = header
279
+ end
280
+ def set_header key, value
281
+ @headers[key] = value
282
+ end
283
+ def request_send methods, path, body = nil
284
+ @busy = true
285
+ #puts "req: #{object_id}"
286
+ if body
287
+ options = {
288
+ :head => @headers,
289
+ :body => body
290
+ }
291
+ @headers['content-type'] = 'application/x-www-form-urlencoded'
292
+ else
293
+ options = {
294
+ :head => @headers,
295
+ }
296
+ end
297
+ @timer = @tfactory.get
298
+ @timer.on_timer(&@method_timeout)
299
+ @exception = nil
300
+ begin
301
+ request(methods, path, options)
302
+ rescue
303
+ on_error("x")
304
+ end
305
+ end
306
+ def handle_timeout
307
+ @exception = TimeoutError::new('timeout')
308
+ self.on_error
309
+ end
310
+ def set_callback on_success, on_failure
311
+ @on_success = on_success
312
+ @on_failure = on_failure
313
+ end
314
+ def has_callback
315
+ !@on_success.nil? and !@on_failure.nil?
316
+ end
317
+ def set_on_finish on_finish
318
+ @on_finish << on_finish
319
+ end
320
+ def on_finish
321
+ unless @on_finish.empty?
322
+ @on_finish.shift.call
323
+ end
324
+ end
325
+ def on_error(reason='error')
326
+ $REQUEST_COUNT += 1
327
+ super
328
+ @tfactory.collect(@timer) if @timer
329
+ @timer = nil
330
+ @busy = false
331
+ @response = @response_object
332
+ @response.time = @response_time
333
+ @on_failure.call(@exception, @response) if @on_failure
334
+ @exception = nil
335
+ end
336
+ def send_request_header
337
+ #無駄な処理を省くため上書き
338
+ head = @options[:head]
339
+ body = @options[:body]
340
+
341
+ # Set the Content-Length if it hasn't been specified already and a body was given
342
+ # Default to Connection: close
343
+
344
+ # Build the request
345
+ request_header = HTTP_REQUEST_HEADER % [@method, @path]
346
+ request_header << encode_field('Content-Length', (body ? body.length : 0)) << encode_field('Connection', 'close')
347
+ for k, v in head
348
+ request_header << encode_field(k, v)
349
+ end
350
+ request_header << CRLF
351
+ write request_header
352
+ end
353
+ def handle_response
354
+ @tfactory.collect(@timer)
355
+ @client_queue.collect(self)
356
+ #@timer = nil
357
+ @queue.add([@on_success, [self.to_response_object]])
358
+ #@busy = false
359
+ end
360
+ def on_request_complete
361
+ super
362
+ return if @exception
363
+ $REQUEST_COUNT += 1
364
+ @tfactory.collect(@timer)
365
+ @client_queue.collect(self)
366
+ @queue.add([@on_success, [self.to_response_object]])
367
+ #handle_response
368
+ #@queue.add([@method_handle_response, ])
369
+ end
370
+ end
371
+ end
@@ -0,0 +1,70 @@
1
+ #rev向きモンキーパッチ
2
+ module Rev
3
+ class TCPSocket
4
+ def self.connect(addr, port, *args)
5
+ #DNS解決済み。ip v4しかこないことを前提する
6
+ family = ::Socket::AF_INET
7
+ return super(TCPConnectSocket.new(family, addr, port), *args) # this creates a 'real' write buffer so we're ok there with regards to already having a write buffer from the get go
8
+ end
9
+ class TCPConnectSocket
10
+ @@_cache = {}
11
+ def initialize(family, addr, port, host = addr)
12
+ #バグがあったので上書き
13
+ @host, @addr, @port = host, addr, port
14
+ @address_family = nil
15
+
16
+ @socket = super(family, ::Socket::SOCK_STREAM, 0)
17
+ begin
18
+ key = port.to_s + addr
19
+ if @@_cache[key]
20
+ addrin = @@_cache[key]
21
+ else
22
+ addrin = @@_cache[key] = ::Socket.sockaddr_in(port, addr)
23
+ end
24
+ @socket.connect_nonblock(addrin)
25
+ rescue Errno::EINPROGRESS
26
+ end
27
+ end
28
+ end
29
+ end
30
+ class HttpClient
31
+ def on_connect
32
+ @connected = true
33
+ send_request if @method and @path
34
+ end
35
+ def failedtrue
36
+ end
37
+ end
38
+ class Socket
39
+ def connectornil
40
+ @_connector = nil
41
+ end
42
+ end
43
+ class Socket::Connector
44
+ def on_writable
45
+ evl = evloop
46
+ detach
47
+
48
+ if connect_successful?
49
+ #@rev_socket.instance_eval { @_connector = nil }
50
+ @rev_socket.connectornil
51
+ @rev_socket.attach(evl)
52
+ @ruby_socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, [1].pack("l"))
53
+ @ruby_socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true)
54
+
55
+ @rev_socket.on_connect
56
+ else
57
+ #@rev_socket.instance_eval { @_failed = true }
58
+ @rev_socket.failedtrue
59
+ @rev_socket.on_connect_failed
60
+ end
61
+ end
62
+ end
63
+ class IO
64
+ end
65
+ class IO::Watcher
66
+ #__send__は重い
67
+ def on_readable; @rev_io.on_readable; end
68
+ def on_writable; @rev_io.on_writable; end
69
+ end
70
+ end
@@ -0,0 +1,39 @@
1
+ module InternetHakai
2
+ class RevPipe
3
+ extend Rev::Meta
4
+ def initialize
5
+ r, w = ::IO::pipe
6
+ @reader = RWatcher::new(r)
7
+ @writer = Rev::IO::new(w)
8
+ end
9
+ attr_reader :reader
10
+ def attach(loop)
11
+ @loop = loop
12
+ @reader.attach(@loop) unless @reader.attached?
13
+ @writer.attach(@loop) unless @writer.attached?
14
+ end
15
+ def write(data)
16
+ @writer.write(data)
17
+ end
18
+ def on_read &block
19
+ @reader.on_read(&block)
20
+ end
21
+ end
22
+ class RWatcher < Rev::IOWatcher
23
+ extend Rev::Meta
24
+ def initialize r
25
+ @reader = r
26
+ super(r)
27
+ end
28
+ def on_read(data); end
29
+ event_callback :on_read
30
+ def on_readable
31
+ begin
32
+ on_read(@reader.read_nonblock(Rev::IO::INPUT_SIZE))
33
+ rescue Errno::EAGAIN
34
+ # in case there are spurious wakeups from forked processs
35
+ return
36
+ end
37
+ end
38
+ end
39
+ end