riakpb 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +30 -0
- data/README.rdoc +156 -0
- data/Rakefile +43 -0
- data/lib/riak/bucket.rb +177 -0
- data/lib/riak/client/rpc.rb +127 -0
- data/lib/riak/client.rb +227 -0
- data/lib/riak/client_pb.rb +372 -0
- data/lib/riak/failed_exchange.rb +21 -0
- data/lib/riak/failed_request.rb +22 -0
- data/lib/riak/i18n.rb +7 -0
- data/lib/riak/key.rb +284 -0
- data/lib/riak/locale/en.yml +37 -0
- data/lib/riak/riak_content.rb +219 -0
- data/lib/riak/sibling_error.rb +16 -0
- data/lib/riak/util/decode.rb +37 -0
- data/lib/riak/util/encode.rb +31 -0
- data/lib/riak/util/message_code.rb +73 -0
- data/lib/riak/util/translation.rb +16 -0
- data/lib/riak.rb +34 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/riak/bucket_spec.rb +118 -0
- data/spec/riak/client_spec.rb +212 -0
- data/spec/riak/key_spec.rb +54 -0
- data/spec/riak/map_reduce_spec.rb +4 -0
- data/spec/riak/riak_content_spec.rb +88 -0
- data/spec/riak/rpc_spec.rb +17 -0
- data/spec/spec_helper.rb +25 -0
- metadata +121 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
lib/riak.rb
|
6
|
+
lib/riak/client.rb
|
7
|
+
lib/riak/client/rpc.rb
|
8
|
+
lib/riak/client_pb.rb
|
9
|
+
lib/riak/bucket.rb
|
10
|
+
lib/riak/key.rb
|
11
|
+
lib/riak/riak_content.rb
|
12
|
+
lib/riak/i18n.rb
|
13
|
+
lib/riak/locale/en.yml
|
14
|
+
lib/riak/util/decode.rb
|
15
|
+
lib/riak/util/encode.rb
|
16
|
+
lib/riak/util/message_code.rb
|
17
|
+
lib/riak/util/translation.rb
|
18
|
+
lib/riak/failed_exchange.rb
|
19
|
+
lib/riak/failed_request.rb
|
20
|
+
lib/riak/sibling_error.rb
|
21
|
+
script/console
|
22
|
+
script/destroy
|
23
|
+
script/generate
|
24
|
+
spec/spec_helper.rb
|
25
|
+
spec/riak/client_spec.rb
|
26
|
+
spec/riak/rpc_spec.rb
|
27
|
+
spec/riak/bucket_spec.rb
|
28
|
+
spec/riak/key_spec.rb
|
29
|
+
spec/riak/riak_content_spec.rb
|
30
|
+
spec/riak/map_reduce_spec.rb
|
data/README.rdoc
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
= riak Ruby Protocol Buffers Client
|
2
|
+
|
3
|
+
* http://github.com/aitrus/riak-pbclient
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
This is a Ruby client for Riak, using protocol buffers instead of REST. It offers some benefit in terms of speed and it abstracts Buckets/Keys differently than does the REST client. Different != Better.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
* It can list buckets! Huzzah!
|
12
|
+
* You can destroy a bucket, which basically lists its keys and iterates over them--deleting each.
|
13
|
+
* It works, which surely counts for something.
|
14
|
+
* It's still rough around the edges, but certainly usable. I'm attempting to polish it, though <b>suggestions welcome</b>.
|
15
|
+
|
16
|
+
== SYNOPSIS:
|
17
|
+
|
18
|
+
This is a work in progress and I am current improving the rspec and the documentation, but please have fun and give me some feedback. The below examples give you an overview on how to use this package.
|
19
|
+
|
20
|
+
=== Connect to riak and ping it:
|
21
|
+
|
22
|
+
>> client = Riak::Client.new # Riak::Client.new({:host => "ubuntu01", :port => 1234})
|
23
|
+
=> #<Riak::Client:0x0000010328a040 @host="127.0.0.1", @port=8087, @w=nil, @dw=nil, @buckets=[], @bucket_cache={}>
|
24
|
+
>> client.ping?
|
25
|
+
=> true
|
26
|
+
|
27
|
+
=== List Buckets within riak:
|
28
|
+
<i>Not suggested for use in production</i>
|
29
|
+
|
30
|
+
>> client = Riak::Client.new
|
31
|
+
=> #<Riak::Client:0x00000101439a78 @host="127.0.0.1", @port=8087, @w=nil, @dw=nil, @buckets=[], @bucket_cache={}>
|
32
|
+
>> client.buckets
|
33
|
+
=> ["hb", "goog"]
|
34
|
+
|
35
|
+
=== Fetch a Bucket:
|
36
|
+
|
37
|
+
>> bucket = client["goog"]
|
38
|
+
=> #<Riak::Bucket name=goog, props={n_val=>3, allow_mult=false}>
|
39
|
+
|
40
|
+
=== Destroy a Bucket:
|
41
|
+
|
42
|
+
>> bucket.destroy!
|
43
|
+
=> true
|
44
|
+
|
45
|
+
=== List Keys within the Bucket:
|
46
|
+
|
47
|
+
>> bucket = client["goog"]
|
48
|
+
=> #<Riak::Bucket name=goog, props={n_val=>3, allow_mult=false}>
|
49
|
+
>> bucket.keys
|
50
|
+
=> ["2010-05-03", "2010-03-24", "2010-03-05", "2010-02-25", <b>SNIP 80~ Lines</b>, "2005-02-10", "2005-01-04"]
|
51
|
+
|
52
|
+
=== Fetch a Key:
|
53
|
+
|
54
|
+
>> key = bucket["2010-04-12"]
|
55
|
+
=> #<Riak::Key name="2010-04-12", vclock="k\xCEa```\xCC`\xCA\x05R,\xCC\xF3{*2\x98\x12\x19\xF3X\x19N\xCF\xEB8\xCA\x97\x05\x00", contents=[#<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="3pbhcnmUtPZvXBSCmo5ESs", links=[], last_mod=1276388043, last_mod_usecs=65345, usermeta={}>]>
|
56
|
+
|
57
|
+
=== Fetch a Key's Content:
|
58
|
+
<i>Differs from the REST client. Key+RiakContent = ROjbect</i>
|
59
|
+
|
60
|
+
>> rcon = key.content
|
61
|
+
=> #<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="3pbhcnmUtPZvXBSCmo5ESs", links=[], last_mod=1276388043, last_mod_usecs=65345, usermeta={}>
|
62
|
+
|
63
|
+
=== Play with the RiakContent's data and save it:
|
64
|
+
|
65
|
+
>> rcon.value
|
66
|
+
=> {"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}
|
67
|
+
>> rcon.value.class
|
68
|
+
=> Hash
|
69
|
+
>> rcon.value["Date"]
|
70
|
+
=> Mon, 12 Apr 2010
|
71
|
+
>> rcon.value["Date"] += 1.day
|
72
|
+
=> Tue, 13 Apr 2010
|
73
|
+
>> rcon
|
74
|
+
=> #<#Riak::RiakContent value={"Date"=>Tue, 13 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="3pbhcnmUtPZvXBSCmo5ESs", links=[], last_mod=1276388043, last_mod_usecs=65345, usermeta={}>
|
75
|
+
>> rcon.save
|
76
|
+
=> true
|
77
|
+
>> key = bucket["2010-04-12"]
|
78
|
+
=> #<Riak::Key name="2010-04-12", vclock="k\xCEa```\xCA`\xCA\x05R,\xCC\xF3{*2\x98\x12\x19\xF3X\x19N\xCF\xEB8\xCA\a\x13\xFE\x9A\xF3\x05*|x)P8\v\x00", contents=[#<#Riak::RiakContent value={"Date"=>Tue, 13 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="2wCEI09OVZEUcHozcm9XCX", links=[], last_mod=1276389827, last_mod_usecs=762316, usermeta={}>]>
|
79
|
+
>> rcon = key.content
|
80
|
+
=> #<#Riak::RiakContent value={"Date"=>Tue, 13 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="2wCEI09OVZEUcHozcm9XCX", links=[], last_mod=1276389827, last_mod_usecs=762316, usermeta={}>
|
81
|
+
>> rcon.value["Date"] -= 1.day
|
82
|
+
=> Mon, 12 Apr 2010
|
83
|
+
>> rcon.save
|
84
|
+
=> true
|
85
|
+
>> key = bucket["2010-04-12"]
|
86
|
+
=> #<Riak::Key name="2010-04-12", vclock="k\xCEa```\xCA`\xCA\x05R,\xCC\xF3{*2\x98\x12\x19\xF3X\x19N\xCF\xEB8\xCA\a\x13\xFE\x9A\xF3\x05(\xCC\x04\x14~\xBC\x14(\x9C\x05\x00", contents=[#<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="264RmLHrCK89zvhtq4n6Fj", links=[], last_mod=1276389859, last_mod_usecs=810556, usermeta={}>]>
|
87
|
+
>> rcon = key.content
|
88
|
+
=> #<#Riak::RiakContent value={"Date"=>Mon, 12 Apr 2010, "Open"=>"567.35", "High"=>"574.00", "Low"=>"566.22", "Close"=>"572.73", "Volume"=>"2352400", "Adj Close"=>"572.73"}, content_type="application/json", vtag="264RmLHrCK89zvhtq4n6Fj", links=[], last_mod=1276389859, last_mod_usecs=810556, usermeta={}>
|
89
|
+
>>
|
90
|
+
|
91
|
+
=== MapReduce:
|
92
|
+
|
93
|
+
I'm working on ways to simplify M/R requests. It works the same as in ripple. Largely because it's ripped off from it, with very few changes (so far).
|
94
|
+
|
95
|
+
=== Load the GOOG stocks from the riak Fast Track:
|
96
|
+
|
97
|
+
require 'riak'
|
98
|
+
require 'csv'
|
99
|
+
|
100
|
+
client = Riak::Client.new
|
101
|
+
bucket = client["goog"]
|
102
|
+
|
103
|
+
CSV.foreach('goog.csv', :headers => true) do |row|
|
104
|
+
puts row.first[1].to_s
|
105
|
+
key = bucket[row.first[1].to_s]
|
106
|
+
key.content.value = Hash[row.to_a]
|
107
|
+
key.save
|
108
|
+
end
|
109
|
+
|
110
|
+
== REQUIREMENTS:
|
111
|
+
|
112
|
+
* Rspec >= 2.0.0.beta.9
|
113
|
+
* ActiveSupport >= 3.0.0.beta3
|
114
|
+
* [Rakefile] hoe >= 2.1.0
|
115
|
+
* [Rakefile] newgem
|
116
|
+
|
117
|
+
== INSTALL:
|
118
|
+
|
119
|
+
git clone git://github.com/aitrus/riak-pbclient.git
|
120
|
+
cd riak-pbclient
|
121
|
+
rake gem
|
122
|
+
[sudo] gem install -l riak-X.Y.Z.gem
|
123
|
+
|
124
|
+
== LINKS:
|
125
|
+
|
126
|
+
* Riak Fast Track: https://wiki.basho.com/display/RIAK/The+Riak+Fast+Track
|
127
|
+
* Riak Fast Track GOOG data: https://wiki.basho.com/display/RIAK/Loading+Data+and+Running+MapReduce+Queries
|
128
|
+
* Ruby Client for Riak's REST Interface: http://github.com/seancribbs/ripple
|
129
|
+
|
130
|
+
== THANKS:
|
131
|
+
|
132
|
+
This is my first public open source whatever, and I appreciate the people in #riak who tolerated me.
|
133
|
+
|
134
|
+
== LICENSE:
|
135
|
+
|
136
|
+
Copyright 2010:
|
137
|
+
Scott Gonyea
|
138
|
+
Sean Cribbs, Sonian Inc.
|
139
|
+
Basho Technologies, Inc.
|
140
|
+
|
141
|
+
The riak-pbclient was pieced together by Scott Gonyea. Big chunks
|
142
|
+
of code were lifted / refactored from the riak-client project, by
|
143
|
+
Sean Cribbs. Lots of pieces are my own work, but it doesn't really
|
144
|
+
matter to me.
|
145
|
+
|
146
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
147
|
+
you may not use this file except in compliance with the License.
|
148
|
+
You may obtain a copy of the License at
|
149
|
+
|
150
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
151
|
+
|
152
|
+
Unless required by applicable law or agreed to in writing, software
|
153
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
154
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
155
|
+
See the License for the specific language governing permissions and
|
156
|
+
limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
gem 'hoe', '>= 2.1.0'
|
3
|
+
require 'hoe'
|
4
|
+
require 'fileutils'
|
5
|
+
require './lib/riak'
|
6
|
+
|
7
|
+
Hoe.plugin :newgem
|
8
|
+
# Hoe.plugin :website
|
9
|
+
# Hoe.plugin :cucumberfeatures
|
10
|
+
|
11
|
+
# Generate all the Rake tasks
|
12
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
13
|
+
$hoe = Hoe.spec 'riakpb' do
|
14
|
+
self.developer 'Scott Gonyea', 'me@sgonyea.com'
|
15
|
+
self.rubyforge_name = self.name
|
16
|
+
self.summary = 'riak-pbclient is a protocol buffer client for Riak--the distributed database by Basho.'
|
17
|
+
self.url = 'http://github.com/aitrus/riak-pbclient'
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rspec/core'
|
21
|
+
require 'rspec/core/rake_task'
|
22
|
+
|
23
|
+
desc "Run Unit Specs Only"
|
24
|
+
Rspec::Core::RakeTask.new(:spec) do |spec|
|
25
|
+
spec.pattern = "spec/riak/**/*_spec.rb"
|
26
|
+
end
|
27
|
+
|
28
|
+
namespace :spec do
|
29
|
+
desc "Run Integration Specs Only"
|
30
|
+
Rspec::Core::RakeTask.new(:integration) do |spec|
|
31
|
+
spec.pattern = "spec/integration/**/*_spec.rb"
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Run All Specs"
|
35
|
+
Rspec::Core::RakeTask.new(:all) do |spec|
|
36
|
+
spec.pattern = Rake::FileList["spec/**/*_spec.rb"]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
41
|
+
# remove_task :default
|
42
|
+
# task :default => [:spec, :features]
|
43
|
+
|
data/lib/riak/bucket.rb
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
require 'riak'
|
2
|
+
|
3
|
+
module Riak
|
4
|
+
# Represents and encapsulates operations on a Riak bucket. You may retrieve a bucket
|
5
|
+
# using {Client#bucket}, or create it manually and retrieve its meta-information later.
|
6
|
+
class Bucket
|
7
|
+
include Util::Translation
|
8
|
+
include Util::MessageCode
|
9
|
+
|
10
|
+
# @return [Riak::Client] the associated client
|
11
|
+
attr_reader :client
|
12
|
+
|
13
|
+
# @return [String] the bucket name
|
14
|
+
attr_reader :name
|
15
|
+
|
16
|
+
# @return [Fixnum] the number of replicas for objects in this bucket
|
17
|
+
attr_reader :n_val
|
18
|
+
|
19
|
+
# @return [TrueClass/FalseClass] whether or not a key's siblings are to be retrieved
|
20
|
+
attr_reader :allow_mult
|
21
|
+
|
22
|
+
attr_reader :key_cache
|
23
|
+
|
24
|
+
# Create a Riak bucket manually.
|
25
|
+
# @param [Client] client the {Riak::Client} for this bucket
|
26
|
+
# @param [String] name the name of the bucket
|
27
|
+
def initialize(client, name, options={})
|
28
|
+
options.assert_valid_keys(:n_val, :allow_mult)
|
29
|
+
raise ArgumentError, t("client_type", :client => client.inspect) unless client.is_a?(Client)
|
30
|
+
raise ArgumentError, t("string_type", :string => name.inspect) unless name.is_a?(String)
|
31
|
+
|
32
|
+
@client = client
|
33
|
+
@name = name
|
34
|
+
@n_val = options[:n_val] || nil
|
35
|
+
@allow_mult = options[:allow_mult] || nil
|
36
|
+
@key_cache = Hash.new{|k,v| k[v] = Riak::Key.new(self, v)}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Load information for the bucket from a response given by the {Riak::Client::HTTPBackend}.
|
40
|
+
# Used mostly internally - use {Riak::Client#bucket} to get a {Bucket} instance.
|
41
|
+
# @param [RpbHash] response a response from {Riak::Client::HTTPBackend}
|
42
|
+
# @return [Bucket] self
|
43
|
+
# @see Client#bucket
|
44
|
+
def load(response)
|
45
|
+
raise ArgumentError, t("response_type") unless response.is_a?(Riak::RpbGetBucketResp)
|
46
|
+
|
47
|
+
self.n_val = response.props.n_val
|
48
|
+
self.allow_mult = response.props.allow_mult
|
49
|
+
|
50
|
+
return(self)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Accesses or retrieves a list of keys in this bucket. Needs to have expiration / cacheing, though not now.
|
54
|
+
# @return [Array<String>] Keys in this bucket
|
55
|
+
def keys
|
56
|
+
@keys ||= @client.keys_in @name
|
57
|
+
end
|
58
|
+
|
59
|
+
# Accesses or retrieves a list of keys in this bucket. Needs to have expiration / cacheing, though not now.
|
60
|
+
# @return [Array<String>] Keys in this bucket
|
61
|
+
def keys!
|
62
|
+
@keys = @client.keys_in @name
|
63
|
+
end
|
64
|
+
|
65
|
+
# Retrieve an object from within the bucket.
|
66
|
+
# @param [String] key the key of the object to retrieve
|
67
|
+
# @param [Fixnum] r - the read quorum for the request - how many nodes should concur on the read
|
68
|
+
# @return [Riak::Key] the object
|
69
|
+
def key(key, options={})
|
70
|
+
raise ArgumentError, t("fixnum_invalid", :num => options[:r]) unless options[:r].is_a?(NilClass) or options[:r].is_a?(Fixnum)
|
71
|
+
raise ArgumentError, t("string_invalid", :string => key) unless key.is_a?(String)
|
72
|
+
|
73
|
+
if options[:safely] == true and not @key_cache[key].empty?
|
74
|
+
return(@key_cache[key])
|
75
|
+
end
|
76
|
+
|
77
|
+
response = @client.get_request @name, key, options[:r]
|
78
|
+
|
79
|
+
@key_cache[key].load(response)
|
80
|
+
end
|
81
|
+
alias :[] :key
|
82
|
+
|
83
|
+
# Retrieve an object from within the bucket. Will raise an error message if key does not exist.
|
84
|
+
# @param [String] key the key of the object to retrieve
|
85
|
+
# @param [Fixnum] quorum - the read quorum for the request - how many nodes should concur on the read
|
86
|
+
# @return [Riak::Key] the object
|
87
|
+
def key!(key, r=nil)
|
88
|
+
raise ArgumentError, t("string_invalid", :string => key) unless key.is_a?(String)
|
89
|
+
raise ArgumentError, t("fixnum_invalid", :num => r) unless r.is_a?(Fixnum)
|
90
|
+
|
91
|
+
response = @client.get_request @name, key, r
|
92
|
+
|
93
|
+
Riak::Key.new(self, key).load!(response)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Retrieves a Key from the given Bucket. Originally written for link retrieval.
|
97
|
+
# @param [String] bucket the name of the bucket, in which the Key is contained
|
98
|
+
# @param [String] key the name of the key to retrieve
|
99
|
+
# @option options [Fixnum] :quorum read quorum- num of replicas need to agree when retrieving the object
|
100
|
+
# @return [Riak::Key] the object
|
101
|
+
def get_linked(bucket, key, options=nil)
|
102
|
+
@client[bucket].key(key, options)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Retrieves a Key from the given Bucket. Originally written for link retrieval.
|
106
|
+
# Inserts a key in this bucket's namespace, into riak.
|
107
|
+
# @option options [Fixnum] :w (write quorum) how many replicas to write to before returning a successful response.
|
108
|
+
# @option options [Fixnum :dw how many replicas to commit to durable storage before returning a successful response.
|
109
|
+
# @option options [Boolean] :return_body whether to return the contents of the stored object.
|
110
|
+
# @return [RpbPutResp] the response confirming Key storage and (optionally) the Key's updated/new data.
|
111
|
+
def store(options)
|
112
|
+
options[:bucket] = @name
|
113
|
+
@client.put_request(options)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Deletes a key from the bucket
|
117
|
+
# @param [String] key the key to delete
|
118
|
+
# @param [Hash] options quorum options
|
119
|
+
# @option options [Fixnum] :rw - the read/write quorum for the delete
|
120
|
+
def delete(key, rw=nil)
|
121
|
+
key = key.name if key.is_a?(Riak::Key)
|
122
|
+
|
123
|
+
@client.del_request(@name, key, rw)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Wipes out all keys stored in the bucket, as of execution
|
127
|
+
# @param [String] key the key to delete
|
128
|
+
# @param [Hash] options quorum options
|
129
|
+
# @option options [Fixnum] :rw - the read/write quorum for the delete
|
130
|
+
def destroy!(rw=nil)
|
131
|
+
keys!
|
132
|
+
|
133
|
+
@keys.each do |key|
|
134
|
+
@client.del_request(@name, key, rw)
|
135
|
+
end
|
136
|
+
# super.destroy
|
137
|
+
end
|
138
|
+
|
139
|
+
# @return [true, false] whether the bucket allows divergent siblings
|
140
|
+
def allow_mult
|
141
|
+
@allow_mult
|
142
|
+
end
|
143
|
+
|
144
|
+
# Set the allow_mult property. *NOTE* This will result in a PUT request to Riak.
|
145
|
+
# @param [true, false] value whether the bucket should allow siblings
|
146
|
+
def allow_mult=(value)
|
147
|
+
return(@allow_mult = value) if value.is_a?(TrueClass) or value.is_a?(FalseClass)
|
148
|
+
|
149
|
+
raise ArgumentError, t("boolean_type")
|
150
|
+
end
|
151
|
+
|
152
|
+
# @return [Fixnum] the N value, or number of replicas for this bucket
|
153
|
+
def n_val
|
154
|
+
@n_val
|
155
|
+
end
|
156
|
+
|
157
|
+
# Set the N value (number of replicas).
|
158
|
+
# Saving this value after the bucket has objects stored in it may have unpredictable results.
|
159
|
+
# @param [Fixnum] value the number of replicas the bucket should keep of each object
|
160
|
+
def n_val=(value)
|
161
|
+
raise ArgumentError, t("fixnum_type", :value => value) unless value.is_a?(Fixnum)
|
162
|
+
|
163
|
+
@n_val = value
|
164
|
+
end
|
165
|
+
|
166
|
+
# @return [String] a representation suitable for IRB and debugging output
|
167
|
+
def inspect
|
168
|
+
"#<Riak::Bucket name=#{@name}, props={n_val=>#{@n_val}, allow_mult=#{@allow_mult}}>"
|
169
|
+
end
|
170
|
+
|
171
|
+
# @return [String] a representation suitable for IRB and debugging output, including keys within this bucket
|
172
|
+
def inspect!
|
173
|
+
"#<Riak::Bucket name=#{@name}, props={n_val=>#{@n_val}, allow_mult=#{@allow_mult}}, keys=#{keys.inspect}>"
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# Special thanks to:
|
2
|
+
#
|
3
|
+
# - Radar in #ruby-lang
|
4
|
+
# - xnotdotorg / arilerner[at]gmail.com -
|
5
|
+
# http://blog.xnot.org/2008/11/16/communicating-from-ruby-to-erlang/
|
6
|
+
#
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
module Riak
|
10
|
+
class Client
|
11
|
+
class Rpc
|
12
|
+
include Riak::Util::MessageCode
|
13
|
+
include Riak::Util::Translation
|
14
|
+
include Riak::Util::Encode
|
15
|
+
include Riak::Util::Decode
|
16
|
+
|
17
|
+
RECV_LIMIT=1638400
|
18
|
+
|
19
|
+
attr_reader :req_message, :response, :resp_message_codes, :resp_message, :status
|
20
|
+
|
21
|
+
# Establishes a Client ID with the Riak node, for the life of the RPC connection.
|
22
|
+
# @param [Client] the Riak::Client object in which this Rpc instance lives
|
23
|
+
def initialize(client)
|
24
|
+
@status = false
|
25
|
+
@client = client
|
26
|
+
@client_id = request(Util::MessageCode::GET_CLIENT_ID_REQUEST).client_id
|
27
|
+
@set_client_id = Riak::RpbSetClientIdReq.new(:client_id => @client_id)
|
28
|
+
|
29
|
+
# Request / Response Data
|
30
|
+
@resp_message_codes = -1
|
31
|
+
@resp_message = ''
|
32
|
+
@req_message_code = -1
|
33
|
+
@req_message = ''
|
34
|
+
@response = ''
|
35
|
+
end
|
36
|
+
|
37
|
+
# Clears the request / response data, in preparation for a new request
|
38
|
+
def clear
|
39
|
+
@resp_message_codes = -1
|
40
|
+
@resp_message = ''
|
41
|
+
@req_message_code = -1
|
42
|
+
@req_message = ''
|
43
|
+
@response = ''
|
44
|
+
@status = false
|
45
|
+
end
|
46
|
+
|
47
|
+
# Opens a TCPSocket connection with the riak host/node
|
48
|
+
# @yield [TCPSocket] hands off the socket connection
|
49
|
+
# @return [TCPSocket] data that was exchanged with the host/node
|
50
|
+
def with_socket(&block)
|
51
|
+
socket = TCPSocket.open(@client.host, @client.port)
|
52
|
+
set_client_id(socket) if @set_client_id
|
53
|
+
|
54
|
+
out = yield(socket)
|
55
|
+
socket.close
|
56
|
+
|
57
|
+
return(out)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Sets the Client ID for the TCPSocket session
|
61
|
+
# @param [TCPSocket] socket connection for which the Client ID will be set
|
62
|
+
# @return [True/False] whether or not the set client id request succeeded
|
63
|
+
def set_client_id(socket)
|
64
|
+
@set_c_id_req ||= assemble_request( Util::MessageCode::SET_CLIENT_ID_REQUEST,
|
65
|
+
@set_client_id.serialize_to_string)
|
66
|
+
|
67
|
+
socket.send(@set_c_id_req, 0)
|
68
|
+
set_c_id_resp = socket.recv(RECV_LIMIT)
|
69
|
+
|
70
|
+
resp_code, resp_msg = decode_message(set_c_id_resp)
|
71
|
+
|
72
|
+
return(resp_code == Util::MessageCode::SET_CLIENT_ID_RESPONSE)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Sends the request to the riak node
|
76
|
+
# @param [Fixnum] mc The message code that identifies the request
|
77
|
+
# @param [Protobuf::Message] pb_msg The protobuf message, if applicable, for the message code
|
78
|
+
# @return [True/False] whether or not the set client id request succeeded
|
79
|
+
def request(mc, pb_msg=nil)
|
80
|
+
clear
|
81
|
+
|
82
|
+
@req_message_code = mc
|
83
|
+
@response = RESPONSE_CLASS_FOR[mc].new unless RESPONSE_CLASS_FOR[mc].nil?
|
84
|
+
|
85
|
+
with_socket do |socket|
|
86
|
+
begin
|
87
|
+
@req_message = assemble_request mc, (pb_msg.serialize_to_string rescue '')
|
88
|
+
|
89
|
+
socket.send(@req_message, 0)
|
90
|
+
self.response = socket.recv(RECV_LIMIT)
|
91
|
+
|
92
|
+
end while(false == (@response.done rescue true))
|
93
|
+
end # with_socket
|
94
|
+
|
95
|
+
return(@response)
|
96
|
+
end # stream_request
|
97
|
+
|
98
|
+
# Handles the response from the Riak node
|
99
|
+
# @param [String] value The message returned from the Riak node over the TCP Socket
|
100
|
+
# @return [Protobuf::Message] @response the processed response (if any) from the Riak node
|
101
|
+
def response=(value)
|
102
|
+
@resp_message = value
|
103
|
+
|
104
|
+
response_chunk, @resp_message_codes = decode_message(value)
|
105
|
+
|
106
|
+
@resp_message_codes.each do |resp_mc|
|
107
|
+
if resp_mc.equal?(ERROR_RESPONSE)
|
108
|
+
raise FailedRequest.new(MC_RESPONSE_FOR[@req_message_code], @resp_message_codes, response_chunk)
|
109
|
+
end
|
110
|
+
|
111
|
+
# The below should never really happen
|
112
|
+
if resp_mc != MC_RESPONSE_FOR[@req_message_code]
|
113
|
+
raise FailedExchange.new(MC_RESPONSE_FOR[@req_message_code], @resp_message_codes, response_chunk, "failed_request")
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
if response_chunk.size > 0
|
118
|
+
@response.parse_from_string response_chunk
|
119
|
+
end
|
120
|
+
|
121
|
+
@status = true
|
122
|
+
return(@response)
|
123
|
+
end
|
124
|
+
|
125
|
+
end # class Client
|
126
|
+
end # module Rpc
|
127
|
+
end # module RiakPbclient
|