gqtp 1.0.5 → 1.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a9646329d91fbafd50713cb36cd0a29805f955fc
4
+ data.tar.gz: d4a1e5c555ee1463d29a4817d5232e05122b20fb
5
+ SHA512:
6
+ metadata.gz: 4e97a85e004db92b0d58a9cb624ede027b1ba44d50547526bbec6e0605a96d721b04ad993129ec827959cc050fdad6723ffa0cafedf350cc70c1c1f4fef51646
7
+ data.tar.gz: 3e6daac1d896ff3ca752bb55a479b6ec1aa7dd4603bc3a28745cd86bdedca95a988da795683e5947edb556326e24d5c5bb8663a4c904d5e0368376b55227549d
data/README.md CHANGED
@@ -22,7 +22,7 @@ for high concurrency use.
22
22
 
23
23
  ### Client
24
24
 
25
- client = GQTP::Client.new(:address => "192.168.0.1", :port => 10041)
25
+ client = GQTP::Client.new(:host => "192.168.0.1", :port => 10043)
26
26
  request = client.send("status") do |header, body|
27
27
  p body # => "{\"alloc_count\":163,...}"
28
28
  end
@@ -30,7 +30,7 @@ for high concurrency use.
30
30
 
31
31
  ### Server
32
32
 
33
- server = GQTP::Server.new(:address => "192.168.0.1", :port => 10041)
33
+ server = GQTP::Server.new(:host => "192.168.0.1", :port => 10043)
34
34
  server.on_request do |request, client|
35
35
  body = "{\"alloc_count\":163,...}"
36
36
  header = GQTP::Header.new
@@ -45,10 +45,10 @@ for high concurrency use.
45
45
 
46
46
  ### Proxy
47
47
 
48
- proxy = GQTP::Proxy.new(:listen_address => "127.0.0.1",
49
- :listen_port => 10041,
50
- :upstream_address => "192.168.0.1",
51
- :upstream_port => 10041)
48
+ proxy = GQTP::Proxy.new(:listen_host => "127.0.0.1",
49
+ :listen_port => 10043,
50
+ :upstream_host => "192.168.0.1",
51
+ :upstream_port => 10043)
52
52
  proxy.run.wait
53
53
 
54
54
  ## Dependencies
@@ -1,6 +1,6 @@
1
- # -*- coding: utf-8 -*-
1
+ # -*- coding: utf-8; mode: ruby -*-
2
2
  #
3
- # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -22,39 +22,40 @@ require "ostruct"
22
22
  require "gqtp"
23
23
 
24
24
  options = OpenStruct.new
25
- options.listen_address = "0.0.0.0"
26
- options.listen_port = 10041
27
- options.upstream_address = nil
28
- options.upstream_port = 10041
25
+ options.listen_host = "0.0.0.0"
26
+ options.listen_port = 10043
27
+ options.upstream_host = nil
28
+ options.upstream_port = 10043
29
29
  options.backend = :thread
30
30
 
31
31
  parser = OptionParser.new
32
- parser.on("--listen-address=ADDRESS",
33
- "IP address or host name to listen",
34
- "(#{options.listen_address})") do |address|
35
- options.listen_address = address
32
+ parser.on("--listen-host=HOST",
33
+ "IP host or host name to listen",
34
+ "(#{options.listen_host})") do |host|
35
+ options.listen_host = host
36
36
  end
37
37
  parser.on("--listen-port=PORT", Integer,
38
38
  "Port number to listen",
39
39
  "(#{options.listen_port})") do |port|
40
40
  options.listen_port = port
41
41
  end
42
- parser.on("--upstream-address=ADDRESS",
43
- "IP address or host name of upstream",
44
- "(#{options.upstream_address})") do |address|
45
- options.upstream_address = address
42
+ parser.on("--upstream-host=HOST",
43
+ "IP host or host name of upstream",
44
+ "(#{options.upstream_host})") do |host|
45
+ options.upstream_host = host
46
46
  end
47
47
  parser.on("--upstream-port=PORT", Integer,
48
48
  "Port number of upstream",
49
49
  "(#{options.upstream_port})") do |port|
50
50
  options.upstream_port = port
51
51
  end
52
- available_backends = ["thread", "synchronous", "coolio"].join(", ")
53
- parser.on("--backend=BACKEND",
52
+ available_backends = [:thread, :synchronous, :coolio, :eventmachine]
53
+ available_backends_label = available_backends.join(", ")
54
+ parser.on("--backend=BACKEND", available_backends,
54
55
  "Use BACKEND for connection",
55
- "[#{available_backends}]",
56
+ "[#{available_backends_label}]",
56
57
  "(#{options.backend})") do |backend|
57
- options.backend = backend.to_sym
58
+ options.backend = backend
58
59
  end
59
60
 
60
61
  begin
@@ -64,14 +65,24 @@ rescue OptionParser::ParseError
64
65
  exit(false)
65
66
  end
66
67
 
67
- if options.upstream_address.nil?
68
- puts("--upstream-address is required.")
68
+ if options.upstream_host.nil?
69
+ puts("--upstream-host is required.")
69
70
  exit(false)
70
71
  end
71
72
 
72
- proxy = GQTP::Proxy.new(:listen_address => options.listen_address,
73
+ proxy = GQTP::Proxy.new(:listen_host => options.listen_host,
73
74
  :listen_port => options.listen_port,
74
- :upstream_address => options.upstream_address,
75
+ :upstream_host => options.upstream_host,
75
76
  :upstream_port => options.upstream_port,
76
- :connection => options.backend)
77
- proxy.run.wait
77
+ :backend => options.backend)
78
+ begin
79
+ if options.backend == :eventmachine
80
+ require "eventmachine"
81
+ EventMachine.run do
82
+ proxy.run
83
+ end
84
+ else
85
+ proxy.run.wait
86
+ end
87
+ rescue Interrupt
88
+ end
@@ -1,5 +1,23 @@
1
1
  # News
2
2
 
3
+ ## 1.0.6: 2014-03-25
4
+
5
+ ### Improvements
6
+
7
+ * Added EventMachine backend.
8
+
9
+ ### Changes
10
+
11
+ * Changed the default port number to 10043 from 10041 because GQTP
12
+ server packages use 10043.
13
+ * Changed error class when unknown connection type is specified to
14
+ `GQTP::Client.new` to `ArgumentError` from `RuntimeError`.
15
+ * Wrapped internal error to `GQTP::ConnectionError`.
16
+ * Changed `:address` keyword to `:host` in `GQTP::Client.new`.
17
+ `:address` is still usable but it is deprecated.
18
+ * Changed connection backend module/directory name to `backend` from
19
+ `connection`.
20
+
3
21
  ## 1.0.5: 2013-09-18
4
22
 
5
23
  ### Improvements
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -19,7 +19,7 @@
19
19
  require "cool.io"
20
20
 
21
21
  module GQTP
22
- module Connection
22
+ module Backend
23
23
  module Coolio
24
24
  class Request
25
25
  def initialize(loop)
@@ -83,13 +83,13 @@ module GQTP
83
83
  end
84
84
 
85
85
  class Client
86
- attr_accessor :address, :port
86
+ attr_accessor :host, :port
87
87
  def initialize(options={})
88
88
  @options = options
89
- @address = options[:address] || "127.0.0.1"
90
- @port = options[:port] || 10041
89
+ @host = options[:host] || "127.0.0.1"
90
+ @port = options[:port] || 10043
91
91
  @loop = options[:loop] || ::Coolio::Loop.default
92
- @socket = Socket.connect(@address, @port)
92
+ @socket = Socket.connect(@host, @port)
93
93
  @socket.attach(@loop)
94
94
  end
95
95
 
@@ -107,16 +107,16 @@ module GQTP
107
107
  end
108
108
 
109
109
  class Server
110
- attr_accessor :address, :port
110
+ attr_accessor :host, :port
111
111
  def initialize(options={})
112
112
  @options = options
113
- @address = options[:address] || "0.0.0.0"
114
- @port = options[:port] || 10041
113
+ @host = options[:host] || "0.0.0.0"
114
+ @port = options[:port] || 10043
115
115
  @loop = options[:loop] || ::Coolio::Loop.default
116
116
  end
117
117
 
118
118
  def run
119
- @server = ::Coolio::TCPServer.new(@address, @port, Socket) do |client|
119
+ @server = ::Coolio::TCPServer.new(@host, @port, Socket) do |client|
120
120
  yield(client)
121
121
  end
122
122
  @server.attach(@loop)
@@ -0,0 +1,134 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2014 Kouhei Sutou <kou@clear-code.com>
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+
19
+ require "eventmachine"
20
+
21
+ module GQTP
22
+ module Backend
23
+ module Eventmachine
24
+ class Request
25
+ def wait
26
+ # Do nothing
27
+ end
28
+ end
29
+
30
+ module Handler
31
+ def post_init
32
+ @read_callbacks = []
33
+ @buffer = "".force_encoding("ASCII-8BIT")
34
+ end
35
+
36
+ def write(*chunks, &block)
37
+ chunks.each do |chunk|
38
+ send_data(chunk)
39
+ end
40
+ if block_given?
41
+ block.call
42
+ else
43
+ Request.new
44
+ end
45
+ end
46
+
47
+ def read(size, &block)
48
+ if @buffer.bytesize >= size
49
+ consume_data(size, block)
50
+ else
51
+ @read_callbacks << [size, block]
52
+ end
53
+ if block_given?
54
+ nil
55
+ else
56
+ Request.new
57
+ end
58
+ end
59
+
60
+ def receive_data(data)
61
+ @buffer << data
62
+ until @read_callbacks.empty?
63
+ size, callback = @read_callbacks.first
64
+ break if @buffer.bytesize < size
65
+ @read_callbacks.shift
66
+ consume_data(size, callback)
67
+ end
68
+ end
69
+
70
+ private
71
+ def consume_data(size, callback)
72
+ data = @buffer[0, size]
73
+ @buffer = @buffer[size..-1]
74
+ callback.call(data)
75
+ end
76
+ end
77
+
78
+ class Client
79
+ attr_accessor :host, :port
80
+ def initialize(options={})
81
+ @options = options
82
+ @host = options[:host] || "127.0.0.1"
83
+ @port = options[:port] || 10043
84
+ @connection = EventMachine.connect(@host, @port, Handler)
85
+ end
86
+
87
+ def write(*chunks, &block)
88
+ @connection.write(*chunks, &block)
89
+ end
90
+
91
+ def read(size, &block)
92
+ @connection.read(size, &block)
93
+ end
94
+
95
+ def close
96
+ @connection.close_connection_after_writing
97
+ end
98
+ end
99
+
100
+ module ServerHandler
101
+ include Handler
102
+
103
+ def initialize(client_handler)
104
+ super()
105
+ @client_handler = client_handler
106
+ end
107
+
108
+ def post_init
109
+ super
110
+ @client_handler.call(self)
111
+ end
112
+ end
113
+
114
+ class Server
115
+ attr_accessor :host, :port
116
+ def initialize(options={})
117
+ @options = options
118
+ @host = options[:host] || "0.0.0.0"
119
+ @port = options[:port] || 10043
120
+ end
121
+
122
+ def run(&block)
123
+ @signature =
124
+ EventMachine.start_server(@host, @port, ServerHandler, block)
125
+ Request.new
126
+ end
127
+
128
+ def shutdown
129
+ EventMachine.stop_server(@signature)
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -17,7 +17,7 @@
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module GQTP
20
- module Connection
20
+ module Backend
21
21
  module Synchronous
22
22
  class Request
23
23
  def initialize(data)
@@ -58,12 +58,16 @@ module GQTP
58
58
  end
59
59
 
60
60
  class Client
61
- attr_accessor :address, :port
61
+ attr_accessor :host, :port
62
62
  def initialize(options={})
63
63
  @options = options
64
- @address = options[:address] || "127.0.0.1"
65
- @port = options[:port] || 10041
66
- @socket = TCPSocket.open(@address, @port)
64
+ @host = options[:host] || "127.0.0.1"
65
+ @port = options[:port] || 10043
66
+ begin
67
+ @socket = TCPSocket.open(@host, @port)
68
+ rescue SystemCallError
69
+ raise ConnectionError.new(@host, @port, $!)
70
+ end
67
71
  @io = IO.new(@socket)
68
72
  end
69
73
 
@@ -81,16 +85,16 @@ module GQTP
81
85
  end
82
86
 
83
87
  class Server
84
- attr_accessor :address, :port
88
+ attr_accessor :host, :port
85
89
  def initialize(options={})
86
90
  @options = options
87
- @address = options[:address] || "0.0.0.0"
88
- @port = options[:port] || 10041
91
+ @host = options[:host] || "0.0.0.0"
92
+ @port = options[:port] || 10043
89
93
  @backlog = options[:backlog] || 128
90
94
  end
91
95
 
92
96
  def run
93
- @server = TCPServer.new(@address, @port)
97
+ @server = TCPServer.new(@host, @port)
94
98
  @server.listen(@backlog)
95
99
  loop do
96
100
  client = @server.accept
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,7 @@ require "socket"
20
20
  require "thread"
21
21
 
22
22
  module GQTP
23
- module Connection
23
+ module Backend
24
24
  module Thread
25
25
  class Request
26
26
  def initialize(thread)
@@ -69,12 +69,16 @@ module GQTP
69
69
  end
70
70
 
71
71
  class Client
72
- attr_accessor :address, :port
72
+ attr_accessor :host, :port
73
73
  def initialize(options={})
74
74
  @options = options
75
- @address = options[:address] || "127.0.0.1"
76
- @port = options[:port] || 10041
77
- @socket = TCPSocket.open(@address, @port)
75
+ @host = options[:host] || "127.0.0.1"
76
+ @port = options[:port] || 10043
77
+ begin
78
+ @socket = TCPSocket.open(@host, @port)
79
+ rescue SystemCallError
80
+ raise ConnectionError.new(@host, @port, $!)
81
+ end
78
82
  @io = IO.new(@socket)
79
83
  end
80
84
 
@@ -92,16 +96,16 @@ module GQTP
92
96
  end
93
97
 
94
98
  class Server
95
- attr_accessor :address, :port
99
+ attr_accessor :host, :port
96
100
  def initialize(options={})
97
101
  @options = options
98
- @address = options[:address] || "0.0.0.0"
99
- @port = options[:port] || 10041
102
+ @host = options[:host] || "0.0.0.0"
103
+ @port = options[:port] || 10043
100
104
  @backlog = options[:backlog] || 128
101
105
  end
102
106
 
103
107
  def run
104
- @server = TCPServer.new(@address, @port)
108
+ @server = TCPServer.new(@host, @port)
105
109
  @server.listen(@backlog)
106
110
  thread = ::Thread.new do
107
111
  loop do
@@ -21,12 +21,12 @@ require "gqtp/sequential-request"
21
21
 
22
22
  module GQTP
23
23
  class Client
24
- attr_accessor :address, :port
24
+ attr_accessor :host, :port
25
25
  def initialize(options={})
26
26
  @options = options.dup
27
- @options[:address] ||= "127.0.0.1"
28
- @options[:port] ||= 10041
29
- @connection = create_connection
27
+ @options[:host] ||= @options[:address] || "127.0.0.1"
28
+ @options[:port] ||= 10043
29
+ @backend = create_backend
30
30
  end
31
31
 
32
32
  def send(body, options={}, &block)
@@ -35,13 +35,13 @@ module GQTP
35
35
 
36
36
  if block_given?
37
37
  sequential_request = SequentialRequest.new
38
- write_request = @connection.write(header.pack, body) do
38
+ write_request = @backend.write(header.pack, body) do
39
39
  sequential_request << read(&block)
40
40
  end
41
41
  sequential_request << write_request
42
42
  sequential_request
43
43
  else
44
- @connection.write(header.pack, body)
44
+ @backend.write(header.pack, body)
45
45
  end
46
46
  end
47
47
 
@@ -51,9 +51,9 @@ module GQTP
51
51
  response_body = nil
52
52
 
53
53
  sequential_request = SequentialRequest.new
54
- read_header_request = @connection.read(Header.size) do |header|
54
+ read_header_request = @backend.read(Header.size) do |header|
55
55
  parser << header
56
- read_body_request = @connection.read(parser.header.size) do |body|
56
+ read_body_request = @backend.read(parser.header.size) do |body|
57
57
  response_body = body
58
58
  yield(parser.header, response_body) if block_given?
59
59
  end
@@ -88,11 +88,8 @@ module GQTP
88
88
  sync = !block_given?
89
89
  sequential_request = SequentialRequest.new
90
90
  quit_request = send("quit", :header => header_for_close) do
91
- ack_request = send("ACK", :header => header_for_close) do
92
- @connection.close
93
- yield if block_given?
94
- end
95
- sequential_request << ack_request
91
+ @backend.close
92
+ yield if block_given?
96
93
  end
97
94
  sequential_request << quit_request
98
95
 
@@ -105,18 +102,19 @@ module GQTP
105
102
  end
106
103
 
107
104
  private
108
- def create_connection
109
- connection = @options[:connection] || :thread
105
+ def create_backend
106
+ # :connection is just for backward compatibility.
107
+ backend = @options[:backend] || @options[:connection] || :thread
110
108
 
111
109
  begin
112
- require "gqtp/connection/#{connection}"
110
+ require "gqtp/backend/#{backend}"
113
111
  rescue LoadError
114
- raise "unknown connection: <#{connection.inspect}>"
112
+ raise ArgumentError, "unknown backend: <#{backend.inspect}>: #{$!}"
115
113
  end
116
114
 
117
- module_name = connection.to_s.capitalize
118
- connection_module = GQTP::Connection::const_get(module_name)
119
- connection_module::Client.new(@options)
115
+ module_name = backend.to_s.capitalize
116
+ backend_module = GQTP::Backend.const_get(module_name)
117
+ backend_module::Client.new(@options)
120
118
  end
121
119
 
122
120
  def header_for_close
@@ -16,9 +16,20 @@
16
16
  # License along with this library; if not, write to the Free Software
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
- require "gqtp/header"
20
-
21
19
  module GQTP
22
20
  class Error < StandardError
23
21
  end
22
+
23
+ class ConnectionError < Error
24
+ attr_reader :host
25
+ attr_reader :port
26
+ attr_reader :detail
27
+ def initialize(host, port, detail)
28
+ @host = host
29
+ @port = port
30
+ @detail = detail
31
+ super("Failed to connect to <#{@host}:#{@port}>: " +
32
+ "#{@detail.message} (#{@detail.class})")
33
+ end
34
+ end
24
35
  end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -20,29 +20,32 @@ require "gqtp/server"
20
20
 
21
21
  module GQTP
22
22
  class Proxy
23
- attr_accessor :listen_address, :listen_port
24
- attr_accessor :upstream_address, :upstream_port
23
+ attr_accessor :listen_host, :listen_port
24
+ attr_accessor :upstream_host, :upstream_port
25
25
  def initialize(options={})
26
26
  @options = options.dup
27
- @listen_address = @options[:listen_address] || "0.0.0.0"
28
- @listen_port = @options[:listen_port] || 10041
29
- @upstream_address = @options[:upstream_address] || "127.0.0.1"
30
- @upstream_port = @options[:upstream_port] || 10041
31
- @connection = @options[:connection] || :thread
32
- @server = Server.new(:address => @listen_address,
27
+ @listen_host = @options[:listen_host] || @options[:listen_address]
28
+ @listen_host ||= "0.0.0.0"
29
+ @listen_port = @options[:listen_port] || 10043
30
+ @upstream_host = @options[:upstream_host] || @options[:upstream_address]
31
+ @upstream_host ||= "127.0.0.1"
32
+ @upstream_port = @options[:upstream_port] || 10043
33
+ # :connection is just for backward compatibility.
34
+ @backend = @options[:backend] || @options[:connection] || :thread
35
+ @server = Server.new(:host => @listen_host,
33
36
  :port => @listen_port,
34
- :connection => @connection)
37
+ :backend => @backend)
35
38
  end
36
39
 
37
40
  def run
38
41
  @server.on_connect do |client|
39
- create_connection
42
+ create_backend
40
43
  end
41
- @server.on_request do |request, client, connection|
42
- connection.write(request.header.pack, request.body) do
43
- connection.read(Header.size) do |header|
44
+ @server.on_request do |request, client, backend|
45
+ backend.write(request.header.pack, request.body) do
46
+ backend.read(Header.size) do |header|
44
47
  response_header = Header.parse(header)
45
- connection.read(response_header.size) do |body|
48
+ backend.read(response_header.size) do |body|
46
49
  client.write(header, body) do
47
50
  end
48
51
  end
@@ -57,18 +60,18 @@ module GQTP
57
60
  end
58
61
 
59
62
  private
60
- def create_connection
63
+ def create_backend
61
64
  begin
62
- require "gqtp/connection/#{@connection}"
65
+ require "gqtp/backend/#{@backend}"
63
66
  rescue LoadError
64
- raise "unknown connection: <#{@connection.inspect}>"
67
+ raise ArgumentError, "unknown backend: <#{@backend.inspect}>: #{$!}"
65
68
  end
66
69
 
67
- require "gqtp/connection/#{@connection}"
68
- module_name = @connection.to_s.capitalize
69
- connection_module = GQTP::Connection::const_get(module_name)
70
- connection_module::Client.new(:address => @upstream_address,
71
- :port => @upstream_port)
70
+ require "gqtp/backend/#{@backend}"
71
+ module_name = @backend.to_s.capitalize
72
+ backend_module = GQTP::Backend::const_get(module_name)
73
+ backend_module::Client.new(:host => @upstream_host,
74
+ :port => @upstream_port)
72
75
  end
73
76
  end
74
77
  end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -20,24 +20,24 @@ require "gqtp/header"
20
20
 
21
21
  module GQTP
22
22
  class Server
23
- attr_accessor :address, :port
23
+ attr_accessor :host, :port
24
24
  def initialize(options={})
25
25
  @options = options.dup
26
- @options[:address] ||= "0.0.0.0"
27
- @options[:port] ||= 10041
26
+ @options[:host] ||= @options[:address] || "0.0.0.0"
27
+ @options[:port] ||= 10043
28
28
  @on_request = nil
29
29
  @on_connect = nil
30
30
  end
31
31
 
32
32
  def run
33
- @connection = create_connection
34
- @connection.run do |client|
33
+ @backend = create_backend
34
+ @backend.run do |client|
35
35
  process_request(client, on_connect(client))
36
36
  end
37
37
  end
38
38
 
39
39
  def shutdown
40
- @connection.shutdown
40
+ @backend.shutdown
41
41
  end
42
42
 
43
43
  def on_connect(*arguments, &block)
@@ -63,18 +63,19 @@ module GQTP
63
63
  end
64
64
 
65
65
  private
66
- def create_connection
67
- connection = @options[:connection] || :thread
66
+ def create_backend
67
+ # :connection is just for backward compatibility.
68
+ backend = @options[:backend] || @options[:connection] || :thread
68
69
 
69
70
  begin
70
- require "gqtp/connection/#{connection}"
71
+ require "gqtp/backend/#{backend}"
71
72
  rescue LoadError
72
- raise "unknown connection: <#{connection.inspect}>"
73
+ raise ArgumentError, "unknown backend: <#{backend.inspect}>: #{$!}"
73
74
  end
74
75
 
75
- module_name = connection.to_s.capitalize
76
- connection_module = GQTP::Connection::const_get(module_name)
77
- connection_module::Server.new(@options)
76
+ module_name = backend.to_s.capitalize
77
+ backend_module = GQTP::Backend::const_get(module_name)
78
+ backend_module::Server.new(@options)
78
79
  end
79
80
 
80
81
  def process_request(client, connect_info)
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -17,5 +17,5 @@
17
17
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
18
 
19
19
  module GQTP
20
- VERSION = "1.0.5"
20
+ VERSION = "1.0.6"
21
21
  end
@@ -1,6 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  #
3
- # Copyright (C) 2012-2013 Kouhei Sutou <kou@clear-code.com>
3
+ # Copyright (C) 2012-2014 Kouhei Sutou <kou@clear-code.com>
4
4
  #
5
5
  # This library is free software; you can redistribute it and/or
6
6
  # modify it under the terms of the GNU Lesser General Public
@@ -21,80 +21,97 @@ require "socket"
21
21
  require "gqtp/client"
22
22
 
23
23
  class ClientTest < Test::Unit::TestCase
24
- def setup
25
- @address = "127.0.0.1"
26
- @server = TCPServer.new(@address, 0)
27
- @port = @server.addr[1]
28
-
29
- @request_body = nil
30
- @response_body = nil
31
- @thread = Thread.new do
32
- client = @server.accept
33
- @server.close
34
-
35
- process_client(client)
24
+ class CreateBackendTest < self
25
+ def test_unknown
26
+ message = "unknown backend: <\"unknown\">: " +
27
+ "cannot load such file -- gqtp/backend/unknown"
28
+ assert_raise(ArgumentError.new(message)) do
29
+ GQTP::Client.new(:backend => "unknown")
30
+ end
31
+ end
36
32
 
37
- client.close
33
+ def test_no_server
34
+ server = TCPServer.new("127.0.0.1", 0)
35
+ free_port = server.addr[1]
36
+ server.close
37
+ assert_raise(GQTP::ConnectionError) do
38
+ GQTP::Client.new(:port => free_port)
39
+ end
38
40
  end
39
41
  end
40
42
 
41
- def teardown
42
- @thread.kill
43
- end
43
+ class RequestTest < self
44
+ def setup
45
+ @host = "127.0.0.1"
46
+ @server = TCPServer.new(@host, 0)
47
+ @port = @server.addr[1]
44
48
 
45
- def test_sync
46
- @response_body = "[false]"
47
- client = GQTP::Client.new(:address => @address, :port => @port)
48
- client.send("status")
49
- header, body = client.read
50
- assert_equal(["status", @response_body.bytesize, @response_body],
51
- [@request_body, header.size, body])
52
- end
49
+ @request_body = nil
50
+ @response_body = nil
51
+ @thread = Thread.new do
52
+ client = @server.accept
53
+ @server.close
54
+
55
+ process_client(client)
53
56
 
54
- def test_async
55
- @response_body = "[false]"
56
- client = GQTP::Client.new(:address => @address, :port => @port)
57
- request = client.send("status") do |header, body|
58
- assert_equal(["status", @response_body.bytesize, @response_body],
59
- [@request_body, header.size, body])
57
+ client.close
58
+ end
60
59
  end
61
- request.wait
62
- end
63
60
 
64
- private
65
- def process_client(client)
66
- header = GQTP::Header.parse(client.read(GQTP::Header.size))
67
- @request_body = client.read(header.size)
61
+ def teardown
62
+ @thread.kill
63
+ end
68
64
 
69
- response_header = GQTP::Header.new
70
- response_header.size = @response_body.bytesize
71
- client.write(response_header.pack)
72
- client.write(@response_body)
73
- end
65
+ private
66
+ def process_client(client)
67
+ header = GQTP::Header.parse(client.read(GQTP::Header.size))
68
+ @request_body = client.read(header.size)
74
69
 
75
- class CloseTest < self
76
- def test_sync
77
- @response_body = "[]"
78
- client = GQTP::Client.new(:address => @address, :port => @port)
79
- assert_true(client.close)
70
+ response_header = GQTP::Header.new
71
+ response_header.size = @response_body.bytesize
72
+ client.write(response_header.pack)
73
+ client.write(@response_body)
80
74
  end
81
75
 
82
- def test_async
83
- @response_body = "[]"
84
- client = GQTP::Client.new(:address => @address, :port => @port)
85
- closed = false
86
- close_request = client.close do
87
- closed = true
76
+ class SendTest < self
77
+ def test_sync
78
+ @response_body = "[false]"
79
+ client = GQTP::Client.new(:host => @host, :port => @port)
80
+ client.send("status")
81
+ header, body = client.read
82
+ assert_equal(["status", @response_body.bytesize, @response_body],
83
+ [@request_body, header.size, body])
84
+ end
85
+
86
+ def test_async
87
+ @response_body = "[false]"
88
+ client = GQTP::Client.new(:host => @host, :port => @port)
89
+ request = client.send("status") do |header, body|
90
+ assert_equal(["status", @response_body.bytesize, @response_body],
91
+ [@request_body, header.size, body])
92
+ end
93
+ request.wait
88
94
  end
89
- assert_false(closed)
90
- close_request.wait
91
- assert_true(closed)
92
95
  end
93
96
 
94
- private
95
- def process_client(client)
96
- super(client)
97
- super(client)
97
+ class CloseTest < self
98
+ def test_sync
99
+ @response_body = "[]"
100
+ client = GQTP::Client.new(:host => @host, :port => @port)
101
+ assert_true(client.close)
102
+ end
103
+
104
+ def test_async
105
+ @response_body = "[]"
106
+ client = GQTP::Client.new(:host => @host, :port => @port)
107
+ closed = false
108
+ close_request = client.close do
109
+ closed = true
110
+ end
111
+ assert_false(closed)
112
+ close_request.wait
113
+ assert_true(closed)
114
+ end
98
115
  end
99
116
  end
100
117
  end
metadata CHANGED
@@ -1,119 +1,103 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gqtp
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
5
- prerelease:
4
+ version: 1.0.6
6
5
  platform: ruby
7
6
  authors:
8
7
  - Kouhei Sutou
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-09-18 00:00:00.000000000 Z
11
+ date: 2014-03-25 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: test-unit
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: test-unit-notify
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: packnga
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  - !ruby/object:Gem::Dependency
95
84
  name: redcarpet
96
85
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
86
  requirements:
99
- - - ! '>='
87
+ - - '>='
100
88
  - !ruby/object:Gem::Version
101
89
  version: '0'
102
90
  type: :development
103
91
  prerelease: false
104
92
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
93
  requirements:
107
- - - ! '>='
94
+ - - '>='
108
95
  - !ruby/object:Gem::Version
109
96
  version: '0'
110
- description: ! 'Gqtp gem provides both GQTP client, GQTP server and GQTP proxy
111
-
97
+ description: |
98
+ Gqtp gem provides both GQTP client, GQTP server and GQTP proxy
112
99
  implementations. They provide asynchronous API. You can use gqtp gem
113
-
114
100
  for high concurrency use.
115
-
116
- '
117
101
  email:
118
102
  - kou@clear-code.com
119
103
  executables:
@@ -131,11 +115,12 @@ files:
131
115
  - lib/gqtp/error.rb
132
116
  - lib/gqtp/version.rb
133
117
  - lib/gqtp/proxy.rb
118
+ - lib/gqtp/backend/coolio.rb
119
+ - lib/gqtp/backend/thread.rb
120
+ - lib/gqtp/backend/synchronous.rb
121
+ - lib/gqtp/backend/eventmachine.rb
134
122
  - lib/gqtp/sequential-request.rb
135
123
  - lib/gqtp/server.rb
136
- - lib/gqtp/connection/coolio.rb
137
- - lib/gqtp/connection/thread.rb
138
- - lib/gqtp/connection/synchronous.rb
139
124
  - lib/gqtp/client.rb
140
125
  - lib/gqtp.rb
141
126
  - doc/text/news.md
@@ -149,27 +134,26 @@ files:
149
134
  homepage: https://github.com/ranguba/gqtp
150
135
  licenses:
151
136
  - LGPLv2.1 or later
137
+ metadata: {}
152
138
  post_install_message:
153
139
  rdoc_options: []
154
140
  require_paths:
155
141
  - lib
156
142
  required_ruby_version: !ruby/object:Gem::Requirement
157
- none: false
158
143
  requirements:
159
- - - ! '>='
144
+ - - '>='
160
145
  - !ruby/object:Gem::Version
161
146
  version: '0'
162
147
  required_rubygems_version: !ruby/object:Gem::Requirement
163
- none: false
164
148
  requirements:
165
- - - ! '>='
149
+ - - '>='
166
150
  - !ruby/object:Gem::Version
167
151
  version: '0'
168
152
  requirements: []
169
153
  rubyforge_project:
170
- rubygems_version: 1.8.23
154
+ rubygems_version: 2.0.14
171
155
  signing_key:
172
- specification_version: 3
156
+ specification_version: 4
173
157
  summary: Gqtp gem is a [GQTP (Groonga Query Transfer Protocol)](http://groonga.org/docs/spec/gqtp.html)
174
158
  Ruby implementation.
175
159
  test_files: