arya-pandemic 0.5.0 → 0.5.1

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.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('pandemic', '0.5.0') do |p|
5
+ Echoe.new('pandemic', '0.5.1') do |p|
6
6
  p.description = "A framework for distributing work for real-time services and offline tasks."
7
7
  p.url = "https://github.com/arya/pandemic/"
8
8
  p.author = "Arya Asemanfar"
@@ -30,6 +30,7 @@ require 'pandemic/client_side/pandemize'
30
30
  TCP_NO_DELAY_AVAILABLE =
31
31
  RUBY_VERSION < '1.9' ? Socket.constants.include?('TCP_NODELAY') : Socket.constants.include?(:TCP_NODELAY)
32
32
 
33
+ MONITOR_TIMEOUT_AVAILABLE = (RUBY_VERSION < '1.9')
33
34
  def epidemic!(options = {})
34
35
  if $pandemic_logger.nil?
35
36
  $pandemic_logger = Logger.new(options[:log_file] || "pandemic.log")
@@ -12,7 +12,7 @@ module Pandemic
12
12
  @max_connections = options[:max_connections] || 10
13
13
  @min_connections = options[:min_connections] || 1
14
14
  @connect_at_define = options.include?(:connect_at_define) ? options[:connect_at_define] : true
15
- @timeout = options[:timeout] || 3
15
+ @timeout = MONITOR_TIMEOUT_AVAILABLE ? options[:timeout] || 3 : nil
16
16
  end
17
17
 
18
18
  def add_connection!
@@ -2,6 +2,7 @@ module Pandemic
2
2
  module ServerSide
3
3
  class Client
4
4
  REQUEST_FLAGS = {:async => 'a'}
5
+ EMPTY_STRING = ""
5
6
  REQUEST_REGEXP = /^([0-9]+)(?: ([#{REQUEST_FLAGS.values.join('')}]*))?$/
6
7
  class DisconnectClient < Exception; end
7
8
  include Util
@@ -22,21 +23,21 @@ module Pandemic
22
23
  @listener_thread = Thread.new do
23
24
  begin
24
25
  while @server.running
25
- debug("Waiting for incoming request")
26
+ # debug("Waiting for incoming request")
26
27
  request = @connection.gets
27
- info("Received incoming request")
28
+ # info("Received incoming request")
28
29
  @received_requests += 1
29
30
 
30
31
  if request.nil?
31
- debug("Incoming request is nil")
32
+ # debug("Incoming request is nil")
32
33
  @connection.close
33
34
  @connection = nil
34
35
  break
35
36
  elsif request.strip! =~ REQUEST_REGEXP
36
- size, flags = $1.to_i, $2.to_s.split("")
37
- debug("Reading request body (size #{size})")
37
+ size, flags = $1.to_i, $2.to_s.split(EMPTY_STRING)
38
+ # debug("Reading request body (size #{size})")
38
39
  body = @connection.read(size)
39
- debug("Finished reading request body")
40
+ # debug("Finished reading request body")
40
41
  if flags.include?(REQUEST_FLAGS[:async])
41
42
  Thread.new do
42
43
  handle_request(body)
@@ -45,18 +46,18 @@ module Pandemic
45
46
  else
46
47
  response = handle_request(body)
47
48
  if response
48
- debug("Writing response to client")
49
+ # debug("Writing response to client")
49
50
 
50
51
  # the connection could be closed, we'll let it be rescued if it is.
51
52
  @connection.write("#{response.size}\n#{response}")
52
53
  @connection.flush
53
- debug("Finished writing response to client")
54
+ # debug("Finished writing response to client")
54
55
  else
55
- debug("Writing error code to client")
56
+ # debug("Writing error code to client")
56
57
 
57
58
  @connection.write("-1\n")
58
59
  @connection.flush
59
- debug("Finished writing error code to client")
60
+ # debug("Finished writing error code to client")
60
61
  end
61
62
  @responded_requests.inc
62
63
  end
@@ -29,18 +29,18 @@ module Pandemic
29
29
  end
30
30
 
31
31
  def client_request(request, body)
32
- debug("Sending client's request to peer")
33
- debug("Connection pool has #{@connection_pool.available_count} of #{@connection_pool.connections_count} connections available")
32
+ # debug("Sending client's request to peer")
33
+ # debug("Connection pool has #{@connection_pool.available_count} of #{@connection_pool.connections_count} connections available")
34
34
  # TODO: Consider adding back threads here if it will be faster that way in Ruby 1.9
35
35
  @connection_pool.with_connection do |connection|
36
36
  if connection && !connection.closed?
37
37
  @pending_requests.synchronize do
38
38
  @pending_requests[request.hash] = request
39
39
  end
40
- debug("Writing client's request")
40
+ # debug("Writing client's request")
41
41
  connection.write("PROCESS #{request.hash} #{body.size}\n#{body}")
42
42
  connection.flush
43
- debug("Finished writing client's request")
43
+ # debug("Finished writing client's request")
44
44
  end # TODO: else? fail silently? reconnect?
45
45
  end
46
46
  end
@@ -55,15 +55,15 @@ module Pandemic
55
55
  begin
56
56
  debug("Incoming connection thread started")
57
57
  while @server.running
58
- debug("Listening for incoming requests")
58
+ # debug("Listening for incoming requests")
59
59
  request = connection.gets
60
- debug("Read incoming request from peer")
60
+ # debug("Read incoming request from peer")
61
61
 
62
62
  if request.nil?
63
- debug("Incoming connection request is nil")
63
+ # debug("Incoming connection request is nil")
64
64
  break
65
65
  else
66
- debug("Received incoming (#{request.strip})")
66
+ # debug("Received incoming (#{request.strip})")
67
67
  handle_incoming_request(request, connection) if request =~ /^PROCESS/
68
68
  handle_incoming_response(request, connection) if request =~ /^RESPONSE/
69
69
  end
@@ -114,23 +114,23 @@ module Pandemic
114
114
  end
115
115
 
116
116
  def handle_incoming_request(request, connection)
117
- debug("Identified as request")
117
+ # debug("Identified as request")
118
118
  if request.strip =~ /^PROCESS ([A-Za-z0-9]+) ([0-9]+)$/
119
119
  hash = $1
120
120
  size = $2.to_i
121
- debug("Incoming request: #{hash} #{size}")
121
+ # debug("Incoming request: #{hash} #{size}")
122
122
  begin
123
- debug("Reading request body")
123
+ # debug("Reading request body")
124
124
  request_body = connection.read(size)
125
- debug("Finished reading request body")
125
+ # debug("Finished reading request body")
126
126
  rescue EOFError, TruncatedDataError
127
- debug("Failed to read request body")
127
+ # debug("Failed to read request body")
128
128
  # TODO: what to do here?
129
129
  return false
130
130
  rescue Exception => e
131
131
  warn("Unhandled exception in incoming request read:\n#{e.inspect}\n#{e.backtrace.join("\n")}")
132
132
  end
133
- debug("Processing body")
133
+ # debug("Processing body")
134
134
  process_request(hash, request_body)
135
135
  else
136
136
  warn("Malformed incoming request: #{request.strip}")
@@ -143,13 +143,13 @@ module Pandemic
143
143
  if response.strip =~ /^RESPONSE ([A-Za-z0-9]+) ([0-9]+)$/
144
144
  hash = $1
145
145
  size = $2.to_i
146
- debug("Incoming response: #{hash} #{size}")
146
+ # debug("Incoming response: #{hash} #{size}")
147
147
  begin
148
- debug("Reading response body")
148
+ # debug("Reading response body")
149
149
  response_body = connection.read(size)
150
- debug("Finished reading response body")
150
+ # debug("Finished reading response body")
151
151
  rescue EOFError, TruncatedDataError
152
- debug("Failed to read response body")
152
+ # debug("Failed to read response body")
153
153
  # TODO: what to do here?
154
154
  return false
155
155
  rescue Exception => e
@@ -167,14 +167,14 @@ module Pandemic
167
167
  def process_request(hash, body)
168
168
  Thread.new do
169
169
  begin
170
- debug("Starting processing thread (#{hash})")
170
+ # debug("Starting processing thread (#{hash})")
171
171
  response = @server.process(body)
172
- debug("Processing finished (#{hash})")
172
+ # debug("Processing finished (#{hash})")
173
173
  @connection_pool.with_connection do |connection|
174
- debug( "Sending response (#{hash})")
174
+ # debug( "Sending response (#{hash})")
175
175
  connection.write("RESPONSE #{hash} #{response.size}\n#{response}")
176
176
  connection.flush
177
- debug( "Finished sending response (#{hash})")
177
+ # debug( "Finished sending response (#{hash})")
178
178
  end
179
179
  rescue Exception => e
180
180
  warn("Unhandled exception in process request thread:\n#{e.inspect}\n#{e.backtrace.join("\n")}")
@@ -185,10 +185,10 @@ module Pandemic
185
185
  def process_response(hash, body)
186
186
  Thread.new do
187
187
  begin
188
- debug("Finding original request (#{hash})")
188
+ # debug("Finding original request (#{hash})")
189
189
  original_request = @pending_requests.synchronize { @pending_requests.delete(hash) }
190
190
  if original_request
191
- debug("Found original request, adding response")
191
+ # debug("Found original request, adding response")
192
192
  original_request.add_response(body)
193
193
  else
194
194
  warn("Original response not found (#{hash})")
@@ -32,10 +32,10 @@ module Pandemic
32
32
  @@late_responses.inc
33
33
  return
34
34
  end
35
- debug("Adding response")
35
+ # debug("Adding response")
36
36
  @responses << response
37
37
  if @max_responses && @responses.size >= @max_responses
38
- debug("Hit max responses, waking up waiting thread")
38
+ # debug("Hit max responses, waking up waiting thread")
39
39
  wakeup_waiting_thread
40
40
  @complete = true
41
41
  end
@@ -62,6 +62,12 @@ module Pandemic
62
62
  return if @complete
63
63
  if Config.response_timeout <= 0
64
64
  @waiter.wait
65
+ elsif !MONITOR_TIMEOUT_AVAILABLE
66
+ Thread.new do
67
+ sleep Config.response_timeout
68
+ wakeup_waiting_thread
69
+ end
70
+ @waiter.wait
65
71
  else
66
72
  @waiter.wait(Config.response_timeout)
67
73
  end
@@ -57,14 +57,14 @@ module Pandemic
57
57
  @running = true
58
58
  @running_since = Time.now
59
59
 
60
- debug("Connecting to peers")
60
+ # debug("Connecting to peers")
61
61
  @peers.values.each { |peer| peer.connect }
62
62
 
63
63
  @listener_thread = Thread.new do
64
64
  begin
65
65
  while @running
66
66
  begin
67
- debug("Listening")
67
+ # debug("Listening")
68
68
  conn = @listener.accept
69
69
  Thread.new(conn) { |c| handle_connection(c) }
70
70
  rescue Errno::ECONNABORTED, Errno::EINTR # TODO: what else can wrong here? this should be more robust.
@@ -95,15 +95,15 @@ module Pandemic
95
95
  connection.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if TCP_NO_DELAY_AVAILABLE
96
96
 
97
97
  identification = connection.gets.strip
98
- info("Incoming connection from #{connection.peeraddr.values_at(3,1).join(":")} (#{identification})")
98
+ # info("Incoming connection from #{connection.peeraddr.values_at(3,1).join(":")} (#{identification})")
99
99
  if identification =~ /^SERVER ([a-zA-Z0-9.]+:[0-9]+)$/
100
- debug("Recognized as peer")
100
+ # debug("Recognized as peer")
101
101
  host, port = host_port($1)
102
102
  matching_peer = @peers.values.detect { |peer| [peer.host, peer.port] == [host, port] }
103
103
  if matching_peer
104
- debug("Found matching peer")
104
+ # debug("Found matching peer")
105
105
  else
106
- debug("Didn't find matching peer, adding it")
106
+ # debug("Didn't find matching peer, adding it")
107
107
  matching_peer = @peers.synchronize do
108
108
  hostport = "#{host}:#{port}"
109
109
  @servers.push(hostport) unless @servers.include?(hostport)
@@ -112,13 +112,13 @@ module Pandemic
112
112
  end
113
113
  matching_peer.add_incoming_connection(connection)
114
114
  elsif identification =~ /^CLIENT$/
115
- debug("Recognized as client")
115
+ # debug("Recognized as client")
116
116
  @clients_mutex.synchronize do
117
117
  @clients << Client.new(connection, self).listen
118
118
  @total_clients += 1
119
119
  end
120
120
  elsif identification =~ /^stats$/
121
- debug("Stats request received")
121
+ # debug("Stats request received")
122
122
  print_stats(connection)
123
123
  else
124
124
  debug("Unrecognized connection. Closing.")
@@ -130,10 +130,10 @@ module Pandemic
130
130
  end
131
131
 
132
132
  def handle_client_request(request)
133
- info("Handling client request")
133
+ # info("Handling client request")
134
134
  map = @handler_instance.partition(request, connection_statuses)
135
135
  request.max_responses = map.size
136
- debug("Sending client request to #{map.size} handlers (#{request.hash})")
136
+ # debug("Sending client request to #{map.size} handlers (#{request.hash})")
137
137
 
138
138
  map.each do |peer, body|
139
139
  if @peers[peer]
@@ -142,7 +142,7 @@ module Pandemic
142
142
  end
143
143
 
144
144
  if map[signature]
145
- debug("Processing #{request.hash}")
145
+ # debug("Processing #{request.hash}")
146
146
  Thread.new do
147
147
  begin
148
148
  request.add_response(self.process(map[signature]))
@@ -154,10 +154,10 @@ module Pandemic
154
154
 
155
155
  @requests_per_second.hit
156
156
 
157
- debug("Waiting for responses")
157
+ # debug("Waiting for responses")
158
158
  request.wait_for_responses
159
159
 
160
- debug("Done waiting for responses, calling reduce")
160
+ # debug("Done waiting for responses, calling reduce")
161
161
  @handler_instance.reduce(request)
162
162
  end
163
163
 
@@ -173,7 +173,7 @@ module Pandemic
173
173
  end
174
174
 
175
175
  def signature
176
- "#{@host}:#{@port}"
176
+ @signature ||= "#{@host}:#{@port}"
177
177
  end
178
178
 
179
179
  def connection_statuses
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{pandemic}
5
- s.version = "0.5.0"
5
+ s.version = "0.5.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Arya Asemanfar"]
9
- s.date = %q{2009-08-07}
9
+ s.date = %q{2009-08-09}
10
10
  s.description = %q{A framework for distributing work for real-time services and offline tasks.}
11
11
  s.email = %q{aryaasemanfar@gmail.com}
12
12
  s.extra_rdoc_files = ["lib/pandemic/client_side/cluster_connection.rb", "lib/pandemic/client_side/config.rb", "lib/pandemic/client_side/connection.rb", "lib/pandemic/client_side/connection_proxy.rb", "lib/pandemic/client_side/pandemize.rb", "lib/pandemic/connection_pool.rb", "lib/pandemic/mutex_counter.rb", "lib/pandemic/requests_per_second.rb", "lib/pandemic/server_side/client.rb", "lib/pandemic/server_side/config.rb", "lib/pandemic/server_side/handler.rb", "lib/pandemic/server_side/peer.rb", "lib/pandemic/server_side/processor.rb", "lib/pandemic/server_side/request.rb", "lib/pandemic/server_side/server.rb", "lib/pandemic/util.rb", "lib/pandemic.rb", "README.markdown"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: arya-pandemic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Arya Asemanfar
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-08-07 00:00:00 -07:00
12
+ date: 2009-08-09 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency