better-riak-client 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/LICENSE +16 -0
  2. data/README.markdown +198 -0
  3. data/RELEASE_NOTES.md +211 -0
  4. data/better-riak-client.gemspec +61 -0
  5. data/erl_src/riak_kv_test014_backend.beam +0 -0
  6. data/erl_src/riak_kv_test014_backend.erl +189 -0
  7. data/erl_src/riak_kv_test_backend.beam +0 -0
  8. data/erl_src/riak_kv_test_backend.erl +697 -0
  9. data/erl_src/riak_search_test_backend.beam +0 -0
  10. data/erl_src/riak_search_test_backend.erl +175 -0
  11. data/lib/riak/bucket.rb +221 -0
  12. data/lib/riak/client/beefcake/messages.rb +213 -0
  13. data/lib/riak/client/beefcake/object_methods.rb +111 -0
  14. data/lib/riak/client/beefcake_protobuffs_backend.rb +226 -0
  15. data/lib/riak/client/decaying.rb +36 -0
  16. data/lib/riak/client/excon_backend.rb +162 -0
  17. data/lib/riak/client/feature_detection.rb +88 -0
  18. data/lib/riak/client/http_backend/configuration.rb +211 -0
  19. data/lib/riak/client/http_backend/key_streamer.rb +43 -0
  20. data/lib/riak/client/http_backend/object_methods.rb +106 -0
  21. data/lib/riak/client/http_backend/request_headers.rb +34 -0
  22. data/lib/riak/client/http_backend/transport_methods.rb +201 -0
  23. data/lib/riak/client/http_backend.rb +340 -0
  24. data/lib/riak/client/net_http_backend.rb +82 -0
  25. data/lib/riak/client/node.rb +115 -0
  26. data/lib/riak/client/protobuffs_backend.rb +173 -0
  27. data/lib/riak/client/search.rb +91 -0
  28. data/lib/riak/client.rb +540 -0
  29. data/lib/riak/cluster.rb +151 -0
  30. data/lib/riak/core_ext/blank.rb +53 -0
  31. data/lib/riak/core_ext/deep_dup.rb +13 -0
  32. data/lib/riak/core_ext/extract_options.rb +7 -0
  33. data/lib/riak/core_ext/json.rb +15 -0
  34. data/lib/riak/core_ext/slice.rb +18 -0
  35. data/lib/riak/core_ext/stringify_keys.rb +10 -0
  36. data/lib/riak/core_ext/symbolize_keys.rb +10 -0
  37. data/lib/riak/core_ext/to_param.rb +31 -0
  38. data/lib/riak/core_ext.rb +7 -0
  39. data/lib/riak/encoding.rb +6 -0
  40. data/lib/riak/failed_request.rb +81 -0
  41. data/lib/riak/i18n.rb +5 -0
  42. data/lib/riak/json.rb +52 -0
  43. data/lib/riak/link.rb +94 -0
  44. data/lib/riak/locale/en.yml +53 -0
  45. data/lib/riak/locale/fr.yml +52 -0
  46. data/lib/riak/map_reduce/filter_builder.rb +103 -0
  47. data/lib/riak/map_reduce/phase.rb +98 -0
  48. data/lib/riak/map_reduce.rb +225 -0
  49. data/lib/riak/map_reduce_error.rb +7 -0
  50. data/lib/riak/node/configuration.rb +293 -0
  51. data/lib/riak/node/console.rb +133 -0
  52. data/lib/riak/node/control.rb +207 -0
  53. data/lib/riak/node/defaults.rb +83 -0
  54. data/lib/riak/node/generation.rb +106 -0
  55. data/lib/riak/node/log.rb +34 -0
  56. data/lib/riak/node/version.rb +43 -0
  57. data/lib/riak/node.rb +38 -0
  58. data/lib/riak/robject.rb +318 -0
  59. data/lib/riak/search.rb +3 -0
  60. data/lib/riak/serializers.rb +74 -0
  61. data/lib/riak/stamp.rb +77 -0
  62. data/lib/riak/test_server.rb +89 -0
  63. data/lib/riak/util/escape.rb +76 -0
  64. data/lib/riak/util/headers.rb +53 -0
  65. data/lib/riak/util/multipart/stream_parser.rb +62 -0
  66. data/lib/riak/util/multipart.rb +52 -0
  67. data/lib/riak/util/tcp_socket_extensions.rb +58 -0
  68. data/lib/riak/util/translation.rb +19 -0
  69. data/lib/riak/version.rb +3 -0
  70. data/lib/riak/walk_spec.rb +105 -0
  71. data/lib/riak.rb +21 -0
  72. metadata +348 -0
@@ -0,0 +1,175 @@
1
+ %% -------------------------------------------------------------------
2
+ %%
3
+ %% Copyright (c) 2007-2010 Basho Technologies, Inc. All Rights Reserved.
4
+ %%
5
+ %% -------------------------------------------------------------------
6
+
7
+ -module(riak_search_test_backend).
8
+ -behavior(riak_search_backend).
9
+
10
+ -export([
11
+ reset/0,
12
+ start/2,
13
+ stop/1,
14
+ index/2,
15
+ delete/2,
16
+ stream/6,
17
+ range/8,
18
+ info/5,
19
+ fold/3,
20
+ is_empty/1,
21
+ drop/1
22
+ ]).
23
+ -export([
24
+ stream_results/3
25
+ ]).
26
+
27
+ -include_lib("riak_search/include/riak_search.hrl").
28
+ -define(T(P), list_to_atom("rs" ++ integer_to_list(P))).
29
+ -record(state, {partition, table}).
30
+
31
+ reset() ->
32
+ {ok, Ring} = riak_core_ring_manager:get_my_ring(),
33
+ [ catch ets:delete_all_objects(?T(P)) ||
34
+ P <- riak_core_ring:my_indices(Ring) ],
35
+ riak_search_config:clear(),
36
+ ok.
37
+
38
+ start(Partition, _Config) ->
39
+ Table = ets:new(?T(Partition),
40
+ [named_table, public, ordered_set]),
41
+ {ok, #state{partition=Partition, table=Table}}.
42
+
43
+ stop(State) ->
44
+ maybe_delete(State).
45
+
46
+ index(IFTVPKList, #state{table=Table}=State) ->
47
+ lists:foreach(
48
+ fun({I, F, T, V, P, K}) ->
49
+ Key = {b(I), b(F), b(T), b(V)},
50
+ case ets:lookup(Table, Key) of
51
+ [{_, _, ExistingKeyClock}] ->
52
+ if ExistingKeyClock > K ->
53
+ %% stored data is newer
54
+ ok;
55
+ true ->
56
+ %% stored data is older
57
+ ets:update_element(Table, Key,
58
+ [{2, P},{3, K}])
59
+ end;
60
+ [] ->
61
+ ets:insert(Table, {Key, P, K})
62
+ end
63
+ end,
64
+ IFTVPKList),
65
+ {reply, {indexed, node()}, State}.
66
+
67
+ delete(IFTVKList, State) ->
68
+ Table = State#state.table,
69
+ lists:foreach(fun(IFTVK) -> delete_fun(IFTVK, Table) end, IFTVKList),
70
+ {reply, {deleted, node()}, State}.
71
+
72
+ delete_fun({I, F, T, V, K}, Table) ->
73
+ Key = {b(I), b(F), b(T), b(V)},
74
+ case ets:lookup(Table, Key) of
75
+ [{Key, _Props, ExistingKeyClock}] ->
76
+ if ExistingKeyClock > K ->
77
+ %% stored data is newer
78
+ ok;
79
+ true ->
80
+ %% stored data is older
81
+ ets:delete(Table, Key)
82
+ end;
83
+ [] ->
84
+ ok
85
+ end;
86
+ delete_fun({I, F, T, V, _P, K}, Table) ->
87
+ %% copied idea from merge_index_backend
88
+ %% other operations include Props, though delete shouldn't
89
+ delete_fun({I, F, T, V, K}, Table).
90
+
91
+ info(Index, Field, Term, Sender, State) ->
92
+ Count = ets:select_count(State#state.table,
93
+ [{{{b(Index), b(Field), b(Term), '_'},
94
+ '_', '_'},
95
+ [],[true]}]),
96
+ riak_search_backend:info_response(Sender, [{Term, node(), Count}]),
97
+ noreply.
98
+
99
+ -define(STREAM_SIZE, 100).
100
+
101
+ range(Index, Field, StartTerm, EndTerm, _Size, FilterFun, Sender, State) ->
102
+ ST = b(StartTerm),
103
+ ET = b(EndTerm),
104
+ spawn(riak_search_ets_backend, stream_results,
105
+ [Sender,
106
+ FilterFun,
107
+ ets:select(State#state.table,
108
+ [{{{b(Index), b(Field), '$1', '$2'}, '$3', '_'},
109
+ [{'>=', '$1', ST}, {'=<', '$1', ET}],
110
+ [{{'$2', '$3'}}]}],
111
+ ?STREAM_SIZE)]),
112
+ noreply.
113
+
114
+ stream(Index, Field, Term, FilterFun, Sender, State) ->
115
+ spawn(riak_search_ets_backend, stream_results,
116
+ [Sender,
117
+ FilterFun,
118
+ ets:select(State#state.table,
119
+ [{{{b(Index), b(Field), b(Term), '$1'}, '$2', '_'},
120
+ [], [{{'$1', '$2'}}]}],
121
+ ?STREAM_SIZE)]),
122
+ noreply.
123
+
124
+ stream_results(Sender, FilterFun, {Results0, Continuation}) ->
125
+ case lists:filter(fun({V,P}) -> FilterFun(V, P) end, Results0) of
126
+ [] ->
127
+ ok;
128
+ Results ->
129
+ riak_search_backend:response_results(Sender, Results)
130
+ end,
131
+ stream_results(Sender, FilterFun, ets:select(Continuation));
132
+ stream_results(Sender, _, '$end_of_table') ->
133
+ riak_search_backend:response_done(Sender).
134
+
135
+ fold(FoldFun, Acc, State) ->
136
+ Fun = fun({{I,F,T,V},P,K}, {OuterAcc, {{I,{F,T}},InnerAcc}}) ->
137
+ %% same IFT, just accumulate doc/props/clock
138
+ {OuterAcc, {{I,{F,T}},[{V,P,K}|InnerAcc]}};
139
+ ({{I,F,T,V},P,K}, {OuterAcc, {FoldKey, VPKList}}) ->
140
+ %% finished a string of IFT, send it off
141
+ %% (sorted order is assumed)
142
+ NewOuterAcc = FoldFun(FoldKey, VPKList, OuterAcc),
143
+ {NewOuterAcc, {{I,{F,T}},[{V,P,K}]}};
144
+ ({{I,F,T,V},P,K}, {OuterAcc, undefined}) ->
145
+ %% first round through the fold - just start building
146
+ {OuterAcc, {{I,{F,T}},[{V,P,K}]}}
147
+ end,
148
+ {OuterAcc0, Final} = ets:foldl(Fun, {Acc, undefined}, State#state.table),
149
+ OuterAcc = case Final of
150
+ {FoldKey, VPKList} ->
151
+ %% one last IFT to send off
152
+ FoldFun(FoldKey, VPKList, OuterAcc0);
153
+ undefined ->
154
+ %% this partition was empty
155
+ OuterAcc0
156
+ end,
157
+ {reply, OuterAcc, State}.
158
+
159
+ is_empty(State) ->
160
+ 0 == ets:info(State#state.table, size).
161
+
162
+ drop(State) ->
163
+ maybe_delete(State).
164
+
165
+ maybe_delete(State) ->
166
+ case lists:member(State#state.table, ets:all()) of
167
+ true ->
168
+ ets:delete(State#state.table),
169
+ ok;
170
+ false ->
171
+ ok
172
+ end.
173
+
174
+ b(Binary) when is_binary(Binary) -> Binary;
175
+ b(List) when is_list(List) -> iolist_to_binary(List).
@@ -0,0 +1,221 @@
1
+ require 'riak/util/translation'
2
+ require 'riak/client'
3
+ require 'riak/robject'
4
+ require 'riak/failed_request'
5
+
6
+ module Riak
7
+ # Represents and encapsulates operations on a Riak bucket. You may retrieve a bucket
8
+ # using {Client#bucket}, or create it manually and retrieve its meta-information later.
9
+ class Bucket
10
+ include Util::Translation
11
+
12
+ # (Riak Search) The precommit specification for kv/search integration
13
+ SEARCH_PRECOMMIT_HOOK = {"mod" => "riak_search_kv_hook", "fun" => "precommit"}
14
+
15
+ # @return [Riak::Client] the associated client
16
+ attr_reader :client
17
+
18
+ # @return [String] the bucket name
19
+ attr_reader :name
20
+
21
+ # Create a Riak bucket manually.
22
+ # @param [Client] client the {Riak::Client} for this bucket
23
+ # @param [String] name the name of the bucket
24
+ def initialize(client, name)
25
+ raise ArgumentError, t("client_type", :client => client.inspect) unless Client === client
26
+ raise ArgumentError, t("string_type", :string => name.inspect) unless String === name
27
+ @client, @name = client, name
28
+ end
29
+
30
+ # Retrieves a list of keys in this bucket.
31
+ # If a block is given, keys will be streamed through
32
+ # the block (useful for large buckets). When streaming,
33
+ # results of the operation will not be returned to the caller.
34
+ # @yield [Array<String>] a list of keys from the current chunk
35
+ # @return [Array<String>] Keys in this bucket
36
+ # @note This operation has serious performance implications and
37
+ # should not be used in production applications.
38
+ def keys(&block)
39
+ warn(t('list_keys', :backtrace => caller.join("\n "))) unless Riak.disable_list_keys_warnings
40
+ if block_given?
41
+ @client.list_keys(self, &block)
42
+ else
43
+ @client.list_keys(self)
44
+ end
45
+ end
46
+
47
+ # Sets internal properties on the bucket
48
+ # Note: this results in a request to the Riak server!
49
+ # @param [Hash] properties new properties for the bucket
50
+ # @option properties [Fixnum] :n_val (3) The N value (replication factor)
51
+ # @option properties [true,false] :allow_mult (false) Whether to permit object siblings
52
+ # @option properties [true,false] :last_write_wins (false) Whether to ignore vclocks
53
+ # @option properties [Array<Hash>] :precommit ([]) precommit hooks
54
+ # @option properties [Array<Hash>] :postcommit ([])postcommit hooks
55
+ # @option properties [Fixnum,String] :r ("quorum") read quorum (numeric or
56
+ # symbolic)
57
+ # @option properties [Fixnum,String] :w ("quorum") write quorum (numeric or
58
+ # symbolic)
59
+ # @option properties [Fixnum,String] :dw ("quorum") durable write quorum
60
+ # (numeric or symbolic)
61
+ # @option properties [Fixnum,String] :rw ("quorum") delete quorum (numeric or
62
+ # symbolic)
63
+ # @return [Hash] the merged bucket properties
64
+ # @raise [FailedRequest] if the new properties were not accepted by the Riakserver
65
+ # @see #n_value, #allow_mult, #r, #w, #dw, #rw
66
+ def props=(properties)
67
+ raise ArgumentError, t("hash_type", :hash => properties.inspect) unless Hash === properties
68
+ props.merge!(properties)
69
+ @client.set_bucket_props(self, properties)
70
+ props
71
+ end
72
+ alias :'properties=' :'props='
73
+
74
+ # @return [Hash] Internal Riak bucket properties.
75
+ # @see #props=
76
+ def props
77
+ @props ||= @client.get_bucket_props(self)
78
+ end
79
+ alias :properties :props
80
+
81
+ # Retrieve an object from within the bucket.
82
+ # @param [String] key the key of the object to retrieve
83
+ # @param [Hash] options query parameters for the request
84
+ # @option options [Fixnum] :r - the read quorum for the request - how many nodes should concur on the read
85
+ # @return [Riak::RObject] the object
86
+ # @raise [FailedRequest] if the object is not found or some other error occurs
87
+ def get(key, options={})
88
+ @client.get_object(self, key, options)
89
+ end
90
+ alias :[] :get
91
+
92
+ # Create a new blank object
93
+ # @param [String] key the key of the new object
94
+ # @return [RObject] the new, unsaved object
95
+ def new(key=nil)
96
+ RObject.new(self, key).tap do |obj|
97
+ obj.content_type = "application/json"
98
+ end
99
+ end
100
+
101
+ # Fetches an object if it exists, otherwise creates a new one with the given key
102
+ # @param [String] key the key to fetch or create
103
+ # @return [RObject] the new or existing object
104
+ def get_or_new(key, options={})
105
+ begin
106
+ get(key, options)
107
+ rescue Riak::FailedRequest => fr
108
+ if fr.not_found?
109
+ new(key)
110
+ else
111
+ raise fr
112
+ end
113
+ end
114
+ end
115
+
116
+ # Checks whether an object exists in Riak.
117
+ # @param [String] key the key to check
118
+ # @param [Hash] options quorum options
119
+ # @option options [Fixnum] :r - the read quorum value for the request (R)
120
+ # @return [true, false] whether the key exists in this bucket
121
+ def exists?(key, options={})
122
+ begin
123
+ get(key, options)
124
+ true
125
+ rescue Riak::FailedRequest
126
+ false
127
+ end
128
+ end
129
+ alias :exist? :exists?
130
+
131
+ # Deletes a key from the bucket
132
+ # @param [String] key the key to delete
133
+ # @param [Hash] options quorum options
134
+ # @option options [Fixnum] :rw - the read/write quorum for the
135
+ # delete
136
+ # @option options [String] :vclock - the vector clock of the
137
+ # object being deleted
138
+ def delete(key, options={})
139
+ client.delete_object(self, key, options)
140
+ end
141
+
142
+ # Queries a secondary index on the bucket.
143
+ # @note This will only work if your Riak installation supports 2I.
144
+ # @param [String] index the name of the index
145
+ # @param [String,Integer,Range] query the value of the index, or a
146
+ # Range of values to query
147
+ # @return [Array<String>] a list of keys that match the index
148
+ # query
149
+ def get_index(index, query)
150
+ client.get_index(self, index, query)
151
+ end
152
+
153
+ # @return [true, false] whether the bucket allows divergent siblings
154
+ def allow_mult
155
+ props['allow_mult']
156
+ end
157
+
158
+ # Set the allow_mult property. *NOTE* This will result in a PUT request to Riak.
159
+ # @param [true, false] value whether the bucket should allow siblings
160
+ def allow_mult=(value)
161
+ self.props = {'allow_mult' => value}
162
+ value
163
+ end
164
+
165
+ # @return [Fixnum] the N value, or number of replicas for this bucket
166
+ def n_value
167
+ props['n_val']
168
+ end
169
+ alias :n_val :n_value
170
+
171
+ # Set the N value (number of replicas). *NOTE* This will result in a PUT request to Riak.
172
+ # Setting this value after the bucket has objects stored in it may have unpredictable results.
173
+ # @param [Fixnum] value the number of replicas the bucket should keep of each object
174
+ def n_value=(value)
175
+ self.props = {'n_val' => value}
176
+ value
177
+ end
178
+ alias :'n_val=' :'n_value='
179
+
180
+ %w(r w dw rw).each do |q|
181
+ define_method(q) { props[q] }
182
+ define_method("#{q}=") { |value|
183
+ self.props = { q => value }
184
+ value
185
+ }
186
+ end
187
+
188
+ # (Riak Search) Installs a precommit hook that automatically indexes objects
189
+ # into riak_search.
190
+ def enable_index!
191
+ unless is_indexed?
192
+ self.props = {"precommit" => (props['precommit'] + [SEARCH_PRECOMMIT_HOOK]), "search" => true}
193
+ end
194
+ end
195
+
196
+ # (Riak Search) Removes the precommit hook that automatically indexes objects
197
+ # into riak_search.
198
+ def disable_index!
199
+ if is_indexed?
200
+ self.props = {"precommit" => (props['precommit'] - [SEARCH_PRECOMMIT_HOOK]), "search" => false}
201
+ end
202
+ end
203
+
204
+ # (Riak Search) Detects whether the bucket is automatically indexed into
205
+ # riak_search.
206
+ # @return [true,false] whether the bucket includes the search indexing hook
207
+ def is_indexed?
208
+ props['search'] == true || props['precommit'].include?(SEARCH_PRECOMMIT_HOOK)
209
+ end
210
+
211
+ # @return [String] a representation suitable for IRB and debugging output
212
+ def inspect
213
+ "#<Riak::Bucket {#{name}}#{" keys=[#{keys.join(',')}]" if defined?(@keys)}>"
214
+ end
215
+
216
+ # @return [true,false] whether the other is equivalent
217
+ def ==(other)
218
+ Bucket === other && other.client == client && other.name == name
219
+ end
220
+ end
221
+ end
@@ -0,0 +1,213 @@
1
+ require 'beefcake'
2
+
3
+ module Riak
4
+ class Client
5
+ # @private
6
+ class BeefcakeProtobuffsBackend
7
+ # Embedded messages
8
+ class RpbPair
9
+ include Beefcake::Message
10
+ required :key, :bytes, 1
11
+ optional :value, :bytes, 2
12
+ end
13
+
14
+ class RpbBucketProps
15
+ include Beefcake::Message
16
+ optional :n_val, :uint32, 1
17
+ optional :allow_mult, :bool, 2
18
+ end
19
+
20
+ class RpbLink
21
+ include Beefcake::Message
22
+ optional :bucket, :bytes, 1
23
+ optional :key, :bytes, 2
24
+ optional :tag, :bytes, 3
25
+ end
26
+
27
+ class RpbContent
28
+ include Beefcake::Message
29
+ required :value, :bytes, 1
30
+ optional :content_type, :bytes, 2
31
+ optional :charset, :bytes, 3
32
+ optional :content_encoding, :bytes, 4
33
+ optional :vtag, :bytes, 5
34
+ repeated :links, RpbLink, 6
35
+ optional :last_mod, :uint32, 7
36
+ optional :last_mod_usecs, :uint32, 8
37
+ repeated :usermeta, RpbPair, 9
38
+ repeated :indexes, RpbPair, 10
39
+ end
40
+
41
+ # Primary messages
42
+ class RpbErrorResp
43
+ include Beefcake::Message
44
+ required :errmsg, :bytes, 1
45
+ required :errcode, :uint32, 2
46
+ end
47
+
48
+ class RpbGetClientIdResp
49
+ include Beefcake::Message
50
+ required :client_id, :bytes, 1
51
+ end
52
+
53
+ class RpbSetClientIdReq
54
+ include Beefcake::Message
55
+ required :client_id, :bytes, 1
56
+ end
57
+
58
+ class RpbGetServerInfoResp
59
+ include Beefcake::Message
60
+ optional :node, :bytes, 1
61
+ optional :server_version, :bytes, 2
62
+ end
63
+
64
+ class RpbGetReq
65
+ include Beefcake::Message
66
+ required :bucket, :bytes, 1
67
+ required :key, :bytes, 2
68
+ optional :r, :uint32, 3
69
+ optional :pr, :uint32, 4
70
+ optional :basic_quorum, :bool, 5
71
+ optional :notfound_ok, :bool, 6
72
+ optional :if_modified, :bytes, 7
73
+ optional :head, :bool, 8
74
+ optional :deletedvclock, :bool, 9
75
+ end
76
+
77
+ class RpbGetResp
78
+ include Beefcake::Message
79
+ repeated :content, RpbContent, 1
80
+ optional :vclock, :bytes, 2
81
+ optional :unchanged, :bool, 3
82
+ end
83
+
84
+ class RpbPutReq
85
+ include Beefcake::Message
86
+ required :bucket, :bytes, 1
87
+ optional :key, :bytes, 2
88
+ optional :vclock, :bytes, 3
89
+ required :content, RpbContent, 4
90
+ optional :w, :uint32, 5
91
+ optional :dw, :uint32, 6
92
+ optional :returnbody, :bool, 7
93
+ optional :pw, :uint32, 8
94
+ optional :if_not_modified, :bool, 9
95
+ optional :if_none_match, :bool, 10
96
+ optional :return_head, :bool, 11
97
+ end
98
+
99
+ class RpbPutResp
100
+ include Beefcake::Message
101
+ repeated :content, RpbContent, 1
102
+ optional :vclock, :bytes, 2
103
+ optional :key, :bytes, 3
104
+ end
105
+
106
+ class RpbDelReq
107
+ include Beefcake::Message
108
+ required :bucket, :bytes, 1
109
+ required :key, :bytes, 2
110
+ optional :rw, :uint32, 3
111
+ optional :vclock, :bytes, 4
112
+ optional :r, :uint32, 5
113
+ optional :w, :uint32, 6
114
+ optional :pr, :uint32, 7
115
+ optional :pw, :uint32, 8
116
+ optional :dw, :uint32, 9
117
+ end
118
+
119
+ class RpbListBucketsResp
120
+ include Beefcake::Message
121
+ repeated :buckets, :bytes, 1
122
+ end
123
+
124
+ class RpbListKeysReq
125
+ include Beefcake::Message
126
+ required :bucket, :bytes, 1
127
+ end
128
+
129
+ class RpbListKeysResp
130
+ include Beefcake::Message
131
+ repeated :keys, :bytes, 1
132
+ optional :done, :bool, 2
133
+ end
134
+
135
+ class RpbGetBucketReq
136
+ include Beefcake::Message
137
+ required :bucket, :bytes, 1
138
+ end
139
+
140
+ class RpbGetBucketResp
141
+ include Beefcake::Message
142
+ required :props, RpbBucketProps, 1
143
+ end
144
+
145
+ class RpbSetBucketReq
146
+ include Beefcake::Message
147
+ required :bucket, :bytes, 1
148
+ required :props, RpbBucketProps, 2
149
+ end
150
+
151
+ class RpbMapRedReq
152
+ include Beefcake::Message
153
+ required :request, :bytes, 1
154
+ required :content_type, :bytes, 2
155
+ end
156
+
157
+ class RpbMapRedResp
158
+ include Beefcake::Message
159
+ optional :phase, :uint32, 1
160
+ optional :response, :bytes, 2
161
+ optional :done, :bool, 3
162
+ end
163
+
164
+ class RpbIndexReq
165
+ include Beefcake::Message
166
+ module IndexQueryType
167
+ EQ = 0
168
+ RANGE = 1
169
+ end
170
+
171
+ required :bucket, :bytes, 1
172
+ required :index, :bytes, 2
173
+ required :qtype, IndexQueryType, 3
174
+ optional :key, :bytes, 4
175
+ optional :range_min, :bytes, 5
176
+ optional :range_max, :bytes, 6
177
+ end
178
+
179
+ class RpbIndexResp
180
+ include Beefcake::Message
181
+ repeated :keys, :bytes, 1
182
+ end
183
+
184
+ class RpbSearchDoc
185
+ include Beefcake::Message
186
+ # We have to name this differently than the .proto file does
187
+ # because Beefcake uses 'fields' as an instance method.
188
+ repeated :properties, RpbPair, 1
189
+ end
190
+
191
+ class RpbSearchQueryReq
192
+ include Beefcake::Message
193
+ required :q, :bytes, 1
194
+ required :index, :bytes, 2
195
+ optional :rows, :uint32, 3
196
+ optional :start, :uint32, 4
197
+ optional :sort, :bytes, 5
198
+ optional :filter, :bytes, 6
199
+ optional :df, :bytes, 7
200
+ optional :op, :bytes, 8
201
+ repeated :fl, :bytes, 9
202
+ optional :presort, :bytes, 10
203
+ end
204
+
205
+ class RpbSearchQueryResp
206
+ include Beefcake::Message
207
+ repeated :docs, RpbSearchDoc, 1, :default => []
208
+ optional :max_score, :float, 2
209
+ optional :num_found, :uint32, 3
210
+ end
211
+ end
212
+ end
213
+ end