riakpb 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|