zerg_support 0.1.3 → 0.1.4

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/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