zerg_support 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,5 @@
1
+ v0.1.4. SocketFactory issues: no lingering, proper closing.
2
+
1
3
  v0.1.3. Anti-zombie protection in spawn.
2
4
 
3
5
  v0.1.2. Removed Ruby warnings (change accidentally left out of v0.1.1).
data/Rakefile CHANGED
@@ -3,7 +3,7 @@ gem 'echoe'
3
3
  require 'echoe'
4
4
 
5
5
  Echoe.new('zerg_support') do |p|
6
- p.project = 'zerglings' # rubyforge project
6
+ p.project = 'zerglings' # rubyforge project
7
7
 
8
8
  p.author = 'Victor Costan'
9
9
  p.email = 'victor@zergling.net'
@@ -10,7 +10,7 @@ module FrameProtocol
10
10
 
11
11
  i = 0
12
12
  loop do
13
- while @frame_protocol_buffer.nil? and i < data.size
13
+ while @frame_protocol_buffer.nil? and i < data.length
14
14
  @frame_protocol_varsize << data[i]
15
15
  if (data[i] & 0x80) == 0
16
16
  @frame_protocol_bytes_left =
@@ -21,15 +21,16 @@ module FrameProtocol
21
21
  end
22
22
 
23
23
  return if @frame_protocol_buffer.nil?
24
- break if @frame_protocol_bytes_left > data.size - i
24
+ break if @frame_protocol_bytes_left > data.length - i
25
25
 
26
- received_frame @frame_protocol_buffer + data[i, @frame_protocol_bytes_left]
26
+ received_frame @frame_protocol_buffer +
27
+ data[i, @frame_protocol_bytes_left]
27
28
  @frame_protocol_varsize, @frame_protocol_buffer = '', nil
28
29
  i += @frame_protocol_bytes_left
29
30
  end
30
31
 
31
32
  @frame_protocol_buffer << data[i..-1]
32
- @frame_protocol_bytes_left -= data.size-i
33
+ @frame_protocol_bytes_left -= data.length - i
33
34
  end
34
35
 
35
36
  # Override to process incoming frames.
@@ -94,6 +94,15 @@ module SocketFactory
94
94
  BasicSocket.do_not_reverse_lookup = true
95
95
  end
96
96
  end
97
+
98
+ if options[:linger]
99
+ socket.setsockopt Socket::SOL_SOCKET, Socket::SO_LINGER,
100
+ [1, options[:linger]].pack('ii')
101
+ else
102
+ # No lingering sockets.
103
+ socket.setsockopt Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack('ii')
104
+ sugar_socket_close socket
105
+ end
97
106
  end
98
107
 
99
108
  # Hacks a socket's accept method so that new sockets have the given flags set.
@@ -116,6 +125,15 @@ module SocketFactory
116
125
  super(*args)
117
126
  end
118
127
  end
128
+
129
+ # Sugar-coat the socket's close() call with the proper way to close a socket.
130
+ def self.sugar_socket_close(socket)
131
+ def socket.close
132
+ shutdown rescue nil
133
+ recv 1 rescue nil
134
+ super
135
+ end
136
+ end
119
137
 
120
138
  # Binds a socket to an address based on the options.
121
139
  def self.bind(socket, options)
@@ -23,7 +23,7 @@ module ProtocolAdapter
23
23
  # Receives an object from a socket.
24
24
  define_method :"recv_#{object_name}" do
25
25
  @zerg_protocol_adapter_state ||= state_class.new self
26
- while @zerg_protocol_adapter_state.recv_object_buffer.length == 0
26
+ while @zerg_protocol_adapter_state.recv_object_buffer.empty?
27
27
  data = recv 65536
28
28
  return nil if data.length == 0 # Other side closed socket.
29
29
  @zerg_protocol_adapter_state.received_bytes data
@@ -51,7 +51,14 @@ module ProtocolAdapter
51
51
 
52
52
  # Called by the protocol when an entire object is available.
53
53
  def send_bytes(data)
54
- @target.send data, 0
54
+ # NOTE: need to chunk the data so kernel buffers don't overflow.
55
+ # Found out about this the hard way -- sending 150k in one call
56
+ # drops data.
57
+ i = 0
58
+ while i < data.length
59
+ @target.send data[i, 65536], 0
60
+ i += 65536
61
+ end
55
62
  end
56
63
  end
57
64
  end
@@ -98,9 +98,9 @@ else
98
98
 
99
99
  Kernel.exec(*([binary] + args))
100
100
  end
101
-
102
101
  # Get rid of zombies.
103
- Process.detach child_pid
102
+ Process.detach child_pid if options[:pgroup]
103
+
104
104
  end
105
105
 
106
106
  return child_pid
@@ -101,7 +101,8 @@ module FrameProtocolTestMethods
101
101
  def test_natural_encoding
102
102
  table = [[0, "\0"], [1, "\x01"], [127, "\x7f"], [128, "\x80\x01"],
103
103
  [65535, "\xff\xff\x03"], [0xf0f0f0, "\xf0\xe1\xc3\x07"],
104
- [0xaa55aa55aa55, "\xd5\xd4\xd6\xd2\xda\xca\x2a"]]
104
+ [0xaa55aa55aa55, "\xd5\xd4\xd6\xd2\xda\xca\x2a"],
105
+ [148296, "\310\206\t"]]
105
106
  table.each do |entry|
106
107
  assert_equal entry.last, FP.encode_natural(entry.first)
107
108
  assert_equal entry.first, FP.decode_natural(entry.last)
@@ -10,11 +10,14 @@ class SocketFactoryTest < Test::Unit::TestCase
10
10
  OPAdapter = Zerg::Support::Sockets::ProtocolAdapter.adapter_module OP
11
11
 
12
12
  def setup
13
+ super
14
+ @thread_abort = Thread.abort_on_exception
13
15
  Thread.abort_on_exception = true
14
16
  end
15
17
 
16
18
  def teardown
17
-
19
+ Thread.abort_on_exception = @thread_abort
20
+ super
18
21
  end
19
22
 
20
23
  def test_host_from_address
@@ -54,21 +57,21 @@ class SocketFactoryTest < Test::Unit::TestCase
54
57
  client_options ||= server_options
55
58
  test_port = 31996
56
59
 
57
- cli_gold = { :request_type => 1, :request_name => "moo" }
58
- srv_gold = { :response_type => 2, :response_value => [true, 314] }
60
+ cli_gold = { :request_type => 1, :request_name => "moo",
61
+ :blob => 'abc' * 43000 }
62
+ srv_gold = { :response_type => 2, :response_value => [true, 314],
63
+ :rblob => 'xyz' * 41000 }
59
64
  cli_hash = nil
60
65
 
61
66
  # Server thread.
67
+ server = SF.socket({:in_addr => ":#{test_port}"}.merge server_options)
62
68
  Thread.new do
63
- server = SF.socket({:in_addr => ":#{test_port}"}.merge server_options)
64
69
  server.listen
65
70
  serv_client, client_addrinfo = server.accept
66
71
  serv_client.extend OPAdapter
67
72
  cli_hash = serv_client.recv_object
68
73
  serv_client.send_object srv_gold
69
74
  serv_client.close
70
-
71
- server.close
72
75
  end
73
76
 
74
77
  # Client.
@@ -78,6 +81,7 @@ class SocketFactoryTest < Test::Unit::TestCase
78
81
  client.send_object cli_gold
79
82
  srv_hash = client.recv_object
80
83
  client.close
84
+ server.close
81
85
 
82
86
  # Checks
83
87
  assert_equal cli_gold, cli_hash, "Client -> server failed"
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{zerg_support}
5
- s.version = "0.1.3"
5
+ s.version = "0.1.4"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Victor Costan"]
9
- s.date = %q{2009-11-09}
9
+ s.date = %q{2009-11-11}
10
10
  s.description = %q{Support libraries used by Zergling.Net deployment code.}
11
11
  s.email = %q{victor@zergling.net}
12
12
  s.extra_rdoc_files = ["CHANGELOG", "lib/zerg_support/event_machine/connection_mocks.rb", "lib/zerg_support/event_machine/protocol_adapter.rb", "lib/zerg_support/gems.rb", "lib/zerg_support/open_ssh.rb", "lib/zerg_support/process.rb", "lib/zerg_support/protocols/frame_protocol.rb", "lib/zerg_support/protocols/object_protocol.rb", "lib/zerg_support/socket_factory.rb", "lib/zerg_support/sockets/protocol_adapter.rb", "lib/zerg_support/sockets/socket_mocks.rb", "lib/zerg_support/spawn.rb", "lib/zerg_support.rb", "LICENSE", "README"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zerg_support
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Costan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-09 00:00:00 -05:00
12
+ date: 2009-11-11 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency