gqtp 1.0.5 → 1.0.6

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.
@@ -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: