Bring fraggle-block up to date with latest doozerd #2

Merged
merged 8 commits into from Apr 10, 2012
View
6 README.md
@@ -24,3 +24,9 @@ A synchronous Ruby client for [Doozer](https://github.com/ha/doozer).
=> nil
See [examples](https://github.com/dylanegan/fraggle-block/tree/master/examples) for more.
+
+
+# Generate ProtoBuf code
+
+BEEFCAKE_NAMESPACE=Fraggle::Block protoc --beefcake_out lib/fraggle/block/ -I . msg.proto
+
View
1 fraggle-block.gemspec
@@ -20,7 +20,6 @@ Gem::Specification.new do |s|
s.require_paths = ["lib"]
s.add_dependency "beefcake", "~>0.3"
- s.add_dependency "system_timer", "1.0"
s.add_development_dependency "turn"
end
View
4 lib/fraggle/block.rb
@@ -3,7 +3,7 @@
module Fraggle
module Block
- DEFAULT_URI = "doozerd:?" + [
+ DEFAULT_URI = "doozer:?" + [
"ca=127.0.0.1:8046",
"ca=127.0.0.1:8041",
"ca=127.0.0.1:8042",
@@ -24,7 +24,7 @@ def self.connect(uri=nil)
module URI
def self.parse(u)
- if u =~ /^doozerd:\?(.*)$/
+ if u =~ /^doozer:\?(.*)$/
parts = $1.split("&")
parts.inject([]) do |m, pt|
k, v = pt.split("=")
View
27 lib/fraggle/block/client.rb
@@ -12,6 +12,9 @@ class OutOfNodes < StandardError; end
def initialize(addrs = [])
@addrs = addrs
+ if not @addrs or @addrs.length == 0
+ raise "No doozer servers to connect to"
+ end
connect
end
@@ -40,9 +43,22 @@ def del(path, rev)
send(request).first
end
- def walk(path, rev = nil)
- request = Request.new(:path => path, :rev => rev, :verb => WALK)
- send(request)
+ def walk(path, rev = nil, offset = 0)
+ all_responses = []
+ done = false
+ while not done
+ request = Request.new(:path => path, :rev => rev, :verb => WALK, :offset => offset)
+ responses = send(request)
+ responses.each do |response|
+ if response.err_code == Response::Err::RANGE
+ done = true
+ break
+ end
+ all_responses.push response
+ offset += 1
+ end
+ end
+ return all_responses
end
def disconnect
@@ -57,7 +73,7 @@ def reconnect
def connect
begin
host, port = @addrs.shift.split(':')
- @connection = connection_to(host, port)
+ @connection = connection_to(host, port.to_i)
find_all_of_the_nodes
rescue => e
retry if @addrs.any?
@@ -70,7 +86,8 @@ def connection_to(host, port)
end
def find_all_of_the_nodes
- walk('/ctl/node/*/addr').each do |node|
+ response = rev()
+ walk('/ctl/node/*/addr', response.rev).each do |node|
@addrs << node.value unless @addrs.include? node.value
end
end
View
35 lib/fraggle/block/connection.rb
@@ -1,6 +1,5 @@
require 'fraggle/block/msg.pb'
require 'socket'
-require "system_timer"
module Fraggle
module Block
@@ -18,11 +17,24 @@ def address
end
def connect
- SystemTimer.timeout_after(10) do
- s = TCPSocket.new(@host, @port)
- s.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
- s
+ # http://stackoverflow.com/questions/231647/how-do-i-set-the-socket-timeout-in-ruby
+ timeout = 10
+ addr = Socket.getaddrinfo(@host, nil)
+ sock = Socket.new(Socket.const_get(addr[0][0]), Socket::SOCK_STREAM, 0)
+
+ begin
+ sock.connect_nonblock(Socket.pack_sockaddr_in(@port, addr[0][3]))
+ rescue Errno::EINPROGRESS
+ resp = IO.select(nil, [sock], nil, timeout.to_i)
+ if resp.nil?
+ raise Errno::ECONNREFUSED
+ end
+ begin
+ sock.connect_nonblock(Socket.pack_sockaddr_in(@port, addr[0][3]))
+ rescue Errno::EISCONN
end
+ end
+ sock
end
def disconnect
@@ -38,14 +50,11 @@ def send(req)
def read
responses = []
- loop do
- head = @sock.read(4)
- length = head.unpack("N")[0]
- data = @sock.read(length)
- response = Response.decode(data)
- responses << response if response.valid?
- break if response.done?
- end
+ head = @sock.read(4)
+ length = head.unpack("N")[0]
+ data = @sock.read(length)
+ response = Response.decode(data)
+ responses << response if response.valid?
responses
end
end
View
19 lib/fraggle/block/msg.pb.rb
@@ -1,4 +1,4 @@
-## Generated from msg.proto for proto
+## Generated from msg.proto for server
require "beefcake"
module Fraggle
@@ -11,23 +11,21 @@ module Verb
GET = 1
SET = 2
DEL = 3
- ESET = 4
REV = 5
+ WAIT = 6
NOP = 7
- WATCH = 8
WALK = 9
- CANCEL = 10
GETDIR = 14
STAT = 16
+ ACCESS = 99
end
- required :tag, :int32, 1
- required :verb, Request::Verb, 2
+ optional :tag, :int32, 1
+ optional :verb, Request::Verb, 2
optional :path, :string, 4
optional :value, :bytes, 5
optional :other_tag, :int32, 6
optional :offset, :int32, 7
- optional :limit, :int32, 8
optional :rev, :int64, 9
end
@@ -39,18 +37,19 @@ module Err
OTHER = 127
TAG_IN_USE = 1
UNKNOWN_VERB = 2
- REDIRECT = 3
+ READONLY = 3
TOO_LATE = 4
REV_MISMATCH = 5
BAD_PATH = 6
MISSING_ARG = 7
+ RANGE = 8
NOTDIR = 20
ISDIR = 21
NOENT = 22
end
- required :tag, :int32, 1
- required :flags, :int32, 2
+ optional :tag, :int32, 1
+ optional :flags, :int32, 2
optional :rev, :int64, 3
optional :path, :string, 5
optional :value, :bytes, 6
View
9 lib/fraggle/block/response.rb
@@ -1,15 +1,8 @@
module Fraggle
module Block
class Response
- VALID = 1
- DONE = 2
-
def valid?
- (flags & VALID) > 0
- end
-
- def done?
- (flags & DONE) > 0
+ true
end
end
end
View
57 msg.proto
@@ -0,0 +1,57 @@
+package server;
+
+// see doc/proto.md
+message Request {
+ optional int32 tag = 1;
+
+ enum Verb {
+ GET = 1;
+ SET = 2;
+ DEL = 3;
+ REV = 5;
+ WAIT = 6;
+ NOP = 7;
+ WALK = 9;
+ GETDIR = 14;
+ STAT = 16;
+ ACCESS = 99;
+ }
+ optional Verb verb = 2;
+
+ optional string path = 4;
+ optional bytes value = 5;
+ optional int32 other_tag = 6;
+
+ optional int32 offset = 7;
+
+ optional int64 rev = 9;
+}
+
+// see doc/proto.md
+message Response {
+ optional int32 tag = 1;
+ optional int32 flags = 2;
+
+ optional int64 rev = 3;
+ optional string path = 5;
+ optional bytes value = 6;
+ optional int32 len = 8;
+
+ enum Err {
+ // don't use value 0
+ OTHER = 127;
+ TAG_IN_USE = 1;
+ UNKNOWN_VERB = 2;
+ READONLY = 3;
+ TOO_LATE = 4;
+ REV_MISMATCH = 5;
+ BAD_PATH = 6;
+ MISSING_ARG = 7;
+ RANGE = 8;
+ NOTDIR = 20;
+ ISDIR = 21;
+ NOENT = 22;
+ }
+ optional Err err_code = 100;
+ optional string err_detail = 101;
+}