riak-client 1.4.5 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (180) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/Gemfile +0 -1
  4. data/{LICENSE → LICENSE.md} +0 -0
  5. data/README.markdown +211 -66
  6. data/RELEASE_NOTES.md +22 -47
  7. data/Rakefile +45 -0
  8. data/lib/riak.rb +1 -1
  9. data/lib/riak/bucket.rb +2 -2
  10. data/lib/riak/client.rb +22 -195
  11. data/lib/riak/client/beefcake/crdt_loader.rb +127 -0
  12. data/lib/riak/client/beefcake/crdt_operator.rb +222 -0
  13. data/lib/riak/client/beefcake/footer +4 -0
  14. data/lib/riak/client/beefcake/header +6 -0
  15. data/lib/riak/client/beefcake/message_codes.rb +29 -0
  16. data/lib/riak/client/beefcake/message_overlay.rb +61 -0
  17. data/lib/riak/client/beefcake/messages.rb +733 -371
  18. data/lib/riak/client/beefcake/object_methods.rb +1 -1
  19. data/lib/riak/client/beefcake/protocol.rb +105 -0
  20. data/lib/riak/client/beefcake/socket.rb +243 -0
  21. data/lib/riak/client/beefcake_protobuffs_backend.rb +262 -122
  22. data/lib/riak/client/node.rb +4 -75
  23. data/lib/riak/client/protobuffs_backend.rb +6 -14
  24. data/lib/riak/client/search.rb +0 -64
  25. data/lib/riak/client/yokozuna.rb +52 -0
  26. data/lib/riak/counter.rb +1 -1
  27. data/lib/riak/crdt.rb +21 -0
  28. data/lib/riak/crdt/base.rb +97 -0
  29. data/lib/riak/crdt/batch_counter.rb +19 -0
  30. data/lib/riak/crdt/batch_map.rb +41 -0
  31. data/lib/riak/crdt/counter.rb +71 -0
  32. data/lib/riak/crdt/inner_counter.rb +74 -0
  33. data/lib/riak/crdt/inner_flag.rb +42 -0
  34. data/lib/riak/crdt/inner_map.rb +53 -0
  35. data/lib/riak/crdt/inner_register.rb +26 -0
  36. data/lib/riak/crdt/inner_set.rb +95 -0
  37. data/lib/riak/crdt/map.rb +88 -0
  38. data/lib/riak/crdt/operation.rb +19 -0
  39. data/lib/riak/crdt/set.rb +156 -0
  40. data/lib/riak/crdt/typed_collection.rb +131 -0
  41. data/lib/riak/errors/base.rb +9 -0
  42. data/lib/riak/errors/connection_error.rb +44 -0
  43. data/lib/riak/errors/crdt_error.rb +18 -0
  44. data/lib/riak/errors/failed_request.rb +56 -0
  45. data/lib/riak/errors/protobuffs_error.rb +11 -0
  46. data/lib/riak/i18n.rb +2 -0
  47. data/lib/riak/json.rb +1 -1
  48. data/lib/riak/locale/en.yml +26 -1
  49. data/lib/riak/locale/fr.yml +0 -1
  50. data/lib/riak/map_reduce.rb +1 -1
  51. data/lib/riak/map_reduce/results.rb +1 -1
  52. data/lib/riak/multiget.rb +1 -2
  53. data/lib/riak/rcontent.rb +8 -3
  54. data/lib/riak/robject.rb +2 -8
  55. data/lib/riak/secondary_index.rb +4 -4
  56. data/lib/riak/serializers.rb +1 -1
  57. data/lib/riak/util/escape.rb +3 -5
  58. data/lib/riak/version.rb +1 -1
  59. data/lib/riak/walk_spec.rb +7 -3
  60. data/riak-client.gemspec +10 -8
  61. data/spec/fixtures/bitcask.txt +25 -0
  62. data/spec/integration/riak/bucket_types_spec.rb +61 -0
  63. data/spec/integration/riak/counters_spec.rb +17 -32
  64. data/spec/integration/riak/crdt_spec.rb +181 -0
  65. data/spec/integration/riak/crdt_validation/map_spec.rb +63 -0
  66. data/spec/integration/riak/crdt_validation/set_spec.rb +122 -0
  67. data/spec/integration/riak/protobuffs_backends_spec.rb +9 -26
  68. data/spec/integration/riak/security_spec.rb +94 -0
  69. data/spec/integration/riak/threading_spec.rb +24 -67
  70. data/spec/integration/yokozuna/index_spec.rb +61 -0
  71. data/spec/integration/yokozuna/queries_spec.rb +116 -0
  72. data/spec/integration/yokozuna/schema_spec.rb +49 -0
  73. data/spec/riak/beefcake_protobuffs_backend/crdt_operator_spec.rb +222 -0
  74. data/spec/riak/beefcake_protobuffs_backend/object_methods_spec.rb +4 -4
  75. data/spec/riak/beefcake_protobuffs_backend/protocol_spec.rb +189 -0
  76. data/spec/riak/beefcake_protobuffs_backend/socket_spec.rb +151 -0
  77. data/spec/riak/beefcake_protobuffs_backend_spec.rb +68 -106
  78. data/spec/riak/bucket_spec.rb +81 -77
  79. data/spec/riak/client_spec.rb +43 -340
  80. data/spec/riak/core_ext/to_param_spec.rb +2 -2
  81. data/spec/riak/counter_spec.rb +20 -20
  82. data/spec/riak/crdt/counter_spec.rb +52 -0
  83. data/spec/riak/crdt/inner_counter_spec.rb +21 -0
  84. data/spec/riak/crdt/inner_flag_spec.rb +39 -0
  85. data/spec/riak/crdt/inner_map_spec.rb +47 -0
  86. data/spec/riak/crdt/inner_register_spec.rb +40 -0
  87. data/spec/riak/crdt/inner_set_spec.rb +33 -0
  88. data/spec/riak/crdt/map_spec.rb +77 -0
  89. data/spec/riak/crdt/set_spec.rb +58 -0
  90. data/spec/riak/crdt/shared_examples.rb +74 -0
  91. data/spec/riak/crdt/typed_collection_spec.rb +231 -0
  92. data/spec/riak/escape_spec.rb +33 -37
  93. data/spec/riak/feature_detection_spec.rb +45 -45
  94. data/spec/riak/index_collection_spec.rb +12 -12
  95. data/spec/riak/link_spec.rb +34 -34
  96. data/spec/riak/list_buckets_spec.rb +7 -7
  97. data/spec/riak/map_reduce/filter_builder_spec.rb +6 -6
  98. data/spec/riak/map_reduce/phase_spec.rb +35 -35
  99. data/spec/riak/map_reduce_spec.rb +89 -87
  100. data/spec/riak/multiget_spec.rb +20 -15
  101. data/spec/riak/node_spec.rb +5 -152
  102. data/spec/riak/robject_spec.rb +95 -108
  103. data/spec/riak/search_spec.rb +17 -139
  104. data/spec/riak/secondary_index_spec.rb +49 -49
  105. data/spec/riak/serializers_spec.rb +9 -9
  106. data/spec/riak/stamp_spec.rb +9 -9
  107. data/spec/riak/walk_spec_spec.rb +46 -46
  108. data/spec/spec_helper.rb +14 -22
  109. data/spec/support/certs/README.md +13 -0
  110. data/spec/support/certs/ca.crt +22 -0
  111. data/spec/support/certs/client.crt +95 -0
  112. data/spec/support/certs/client.key +27 -0
  113. data/spec/support/certs/empty_ca.crt +21 -0
  114. data/spec/support/certs/server.crl +13 -0
  115. data/spec/support/certs/server.crt +95 -0
  116. data/spec/support/certs/server.key +27 -0
  117. data/spec/support/integration_setup.rb +1 -1
  118. data/spec/support/search_corpus_setup.rb +29 -8
  119. data/spec/support/test_client.rb +46 -0
  120. data/spec/support/test_client.yml.example +10 -0
  121. data/spec/support/unified_backend_examples.rb +104 -83
  122. data/spec/support/version_filter.rb +2 -2
  123. data/spec/support/wait_until.rb +14 -0
  124. metadata +134 -132
  125. data/erl_src/riak_kv_test014_backend.beam +0 -0
  126. data/erl_src/riak_kv_test014_backend.erl +0 -189
  127. data/erl_src/riak_kv_test_backend.beam +0 -0
  128. data/erl_src/riak_kv_test_backend.erl +0 -731
  129. data/erl_src/riak_search_test_backend.beam +0 -0
  130. data/erl_src/riak_search_test_backend.erl +0 -175
  131. data/lib/riak/client/excon_backend.rb +0 -172
  132. data/lib/riak/client/http_backend.rb +0 -413
  133. data/lib/riak/client/http_backend/bucket_streamer.rb +0 -15
  134. data/lib/riak/client/http_backend/chunked_json_streamer.rb +0 -42
  135. data/lib/riak/client/http_backend/configuration.rb +0 -227
  136. data/lib/riak/client/http_backend/key_streamer.rb +0 -15
  137. data/lib/riak/client/http_backend/object_methods.rb +0 -114
  138. data/lib/riak/client/http_backend/request_headers.rb +0 -34
  139. data/lib/riak/client/http_backend/transport_methods.rb +0 -201
  140. data/lib/riak/client/instrumentation.rb +0 -25
  141. data/lib/riak/client/net_http_backend.rb +0 -82
  142. data/lib/riak/cluster.rb +0 -151
  143. data/lib/riak/failed_request.rb +0 -81
  144. data/lib/riak/instrumentation.rb +0 -6
  145. data/lib/riak/node.rb +0 -40
  146. data/lib/riak/node/configuration.rb +0 -304
  147. data/lib/riak/node/console.rb +0 -133
  148. data/lib/riak/node/control.rb +0 -207
  149. data/lib/riak/node/defaults.rb +0 -85
  150. data/lib/riak/node/generation.rb +0 -127
  151. data/lib/riak/node/log.rb +0 -34
  152. data/lib/riak/node/version.rb +0 -29
  153. data/lib/riak/search.rb +0 -3
  154. data/lib/riak/test_server.rb +0 -89
  155. data/lib/riak/util/headers.rb +0 -32
  156. data/lib/riak/util/multipart.rb +0 -52
  157. data/lib/riak/util/multipart/stream_parser.rb +0 -62
  158. data/spec/fixtures/munchausen.txt +0 -1033
  159. data/spec/integration/riak/cluster_spec.rb +0 -88
  160. data/spec/integration/riak/http_backends_spec.rb +0 -180
  161. data/spec/integration/riak/node_spec.rb +0 -170
  162. data/spec/integration/riak/test_server_spec.rb +0 -57
  163. data/spec/riak/excon_backend_spec.rb +0 -102
  164. data/spec/riak/headers_spec.rb +0 -21
  165. data/spec/riak/http_backend/configuration_spec.rb +0 -273
  166. data/spec/riak/http_backend/object_methods_spec.rb +0 -243
  167. data/spec/riak/http_backend/transport_methods_spec.rb +0 -97
  168. data/spec/riak/http_backend_spec.rb +0 -367
  169. data/spec/riak/instrumentation_spec.rb +0 -167
  170. data/spec/riak/multipart_spec.rb +0 -23
  171. data/spec/riak/net_http_backend_spec.rb +0 -15
  172. data/spec/riak/stream_parser_spec.rb +0 -53
  173. data/spec/support/drb_mock_server.rb +0 -39
  174. data/spec/support/http_backend_implementation_examples.rb +0 -253
  175. data/spec/support/mock_server.rb +0 -81
  176. data/spec/support/mocks.rb +0 -4
  177. data/spec/support/riak_test.rb +0 -77
  178. data/spec/support/sometimes.rb +0 -46
  179. data/spec/support/test_server.rb +0 -61
  180. data/spec/support/test_server.yml.example +0 -14
@@ -1,5 +1,7 @@
1
1
  require 'i18n'
2
2
 
3
+ I18n.config.enforce_available_locales = true unless I18n.config.enforce_available_locales == false
4
+
3
5
  Dir.glob(File.expand_path("../locale/*.yml", __FILE__)).each do |locale_file|
4
6
  I18n.load_path << locale_file
5
7
  end
@@ -9,7 +9,7 @@ require 'riak/core_ext/json'
9
9
  module Riak
10
10
  class << self
11
11
  # Options that will be passed to the JSON parser and encoder.
12
- # Defaults to {:max_nesting => 20}
12
+ # Defaults to `{:max_nesting => 20}`
13
13
  attr_accessor :json_options
14
14
  end
15
15
  self.json_options = {:max_nesting => 20}
@@ -9,6 +9,14 @@ en:
9
9
  counter:
10
10
  bucket_needs_allow_mult: "Counters require allow_mult to be enabled on their bucket."
11
11
  increment_by_integer: "Counters can only be incremented or decremented by integers."
12
+ crdt:
13
+ precondition_error: "Riak server returned precondition error: %{message}"
14
+ set_removal_without_context: "CRDT Sets do not support removal without context. Store and reload the set before removing members."
15
+ unknown_field: "Unknown field type %{symbol}, expected one of :counter, :map, or :set."
16
+ unknown_inner_field: "Unknown field type %{symbol}, expected one of :counter, :flag, :map, :register, or :set."
17
+ serialize_no_ops: "Can't serialize an empty list of CRDT operations."
18
+ flag:
19
+ not_boolean: "Flags can only be true or false."
12
20
  deprecated:
13
21
  port: "DEPRECATION: Riak::Client#port has been deprecated, use #http_port or #pb_port for the appropriate protocol.\n%{backtrace}"
14
22
  search: "DEPRECATION: Riak Search features are included in the main client, you no longer need to require 'riak/search'.\n%{backtrace}"
@@ -42,13 +50,19 @@ en:
42
50
  loading_bucket: "while loading bucket '%{name}'"
43
51
  list_buckets: "Riak::Client#buckets is an expensive operation that should not be used in production.\n %{backtrace}"
44
52
  list_keys: "Riak::Bucket#keys is an expensive operation that should not be used in production.\n %{backtrace}"
45
- luwak_unsupported: "Riak server does not support Luwak. Enable it in app.config before using."
46
53
  missing_block: "A block must be given."
47
54
  missing_host_and_port: "You must specify a host and port, or use the defaults of 127.0.0.1:8098"
48
55
  module_function_pair_required: "function must have two elements when an array"
49
56
  not_found: "The requested object was not found."
50
57
  no_pipes: "Could not find or open pipes for Riak console in %{path}."
51
58
  object_in_conflict: "The object is in conflict (has siblings) and cannot be treated singly or saved: %{robject}"
59
+ pbc:
60
+ failed_header: "Failed to receive a header from Riak."
61
+ unexpected_eof: "Unexpected EOF on PBC socket"
62
+ user_not_username: "Authentication hash expects :user, not :username."
63
+ wanted_index_resp: "Expected IndexResp during secondary index query"
64
+ wanted_dt_fetch_resp: "Expected PBC DtFetchResp during CRDT fetch"
65
+ wanted_dt_update_resp: "Expected PBC DtUpdateResp during CRDT update"
52
66
  port_invalid: "port must be an integer between 0 and 65535"
53
67
  protobuffs_failed_request: "Expected success from Riak but received %{code}. %{body}"
54
68
  protobuffs_configuration: "The %{backend} Protobuffs backend cannot be used. Please check its requirements."
@@ -58,6 +72,14 @@ en:
58
72
  search_remove_requires_id_or_query: "Search index documents to be removed must have 'id' or 'query' keys."
59
73
  serializer_not_implemented: "No serializer has been registered for content type %{content_type}"
60
74
  source_and_root_required: "Riak::Node configuration must include :source and :root keys."
75
+ ssl:
76
+ cert_host_mismatch: "The presented SSL/TLS certificate did not match the hostname."
77
+ cert_not_in_valid_range: "The presented SSL/TLS certificate is either expired or premature."
78
+ cert_revoked: "The presented SSL/TLS certificate has been revoked."
79
+ eof_during_init: "Unexpected EOF during SSL/TLS initialization."
80
+ read_data_error: "Tried to read cert or key from %{candidate}, caught error %{actual}."
81
+ unexpected_during_init: "Expected %{expected}, got %{actual} with body %{body} during SSL/TLS initialization."
82
+ unknown_key_type: "Can't figure out what the client key is. Expected it to be some kind of OpenSSL::PKey::PKey subclass, a filename string, or string data representing the key itself."
61
83
  stale_write_prevented: "Stale write prevented by client."
62
84
  stored_function_invalid: "function must have :bucket and :key when a hash"
63
85
  streaming_bucket_list_without_block: "Streaming bucket list was requested but no block was given."
@@ -67,3 +89,6 @@ en:
67
89
  wrong_argument_count_walk_spec: "wrong number of arguments (one Hash or bucket,tag,keep required)"
68
90
  zero_length_bucket: "bucket name cannot be a String of zero length"
69
91
  zero_length_key: "key cannot be a String of zero length"
92
+ zero_length_index: "index name cannot be a String of zero length"
93
+ zero_length_schema: "schema name cannot be a String of zero length"
94
+ zero_length_content: "content cannot be a String of zero length"
@@ -30,7 +30,6 @@ fr:
30
30
  loading_bucket: "pendant le chargement du bucket '%{name}'"
31
31
  list_buckets: "Riak::Client#buckets est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
32
32
  list_keys: "Riak::Bucket#keys est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
33
- luwak_unsupported: "Le serveur Riak ne supporte pas Luwak. Activez-le dans app.config avant de l'utiliser"
34
33
  missing_block: "Un bloc doit être fourni."
35
34
  missing_host_and_port: "Vous devez spécifier un hôte et un port, utiliser la valeur par défaut : 127.0.0.1:8098"
36
35
  module_function_pair_required: "la fonction doit avoir deux élément lorsqu'elle est définie par un tableau"
@@ -5,7 +5,7 @@ require 'riak/client'
5
5
  require 'riak/bucket'
6
6
  require 'riak/robject'
7
7
  require 'riak/walk_spec'
8
- require 'riak/failed_request'
8
+ require 'riak/errors/failed_request'
9
9
  require 'riak/map_reduce_error'
10
10
  require 'riak/map_reduce/phase'
11
11
  require 'riak/map_reduce/filter_builder'
@@ -12,7 +12,7 @@ module Riak
12
12
 
13
13
  # Adds a new result to the collector
14
14
  # @param [Fixnum] phase the phase index
15
- # @param [Array] data the phase result
15
+ # @param [Array] result the phase result
16
16
  def add(phase, result)
17
17
  @hash[phase] += result
18
18
  end
@@ -1,6 +1,5 @@
1
1
  require 'riak/client'
2
2
  require 'riak/bucket'
3
- require 'riak/cluster'
4
3
 
5
4
  module Riak
6
5
  # Coordinates a parallel fetch operation for multiple values.
@@ -25,7 +24,7 @@ module Riak
25
24
  # Perform a Riak Multiget operation.
26
25
  # @param [Client] client the {Riak::Client} that will perform the multiget
27
26
  # @param [Array<Bucket, String>] fetch_list an {Array} of {Bucket} and {String} keys to fetch
28
- # @return [Hash<fetch_list_entry, RObject] result_hash a {Hash} of {Bucket} and {String} key pairs to {Robject} instances
27
+ # @return [Hash<fetch_list_entry, RObject] result_hash a {Hash} of {Bucket} and {String} key pairs to {RObject} instances
29
28
  def self.get_all(client, fetch_list)
30
29
  multi = new client, fetch_list
31
30
  multi.fetch
@@ -68,7 +68,10 @@ module Riak
68
68
  @data
69
69
  end
70
70
 
71
- # @param [Object] unmarshaled form of the data to be stored in riak. Object will be serialized using {#serialize} if a known content_type is used. Setting this overrides values stored with {#raw_data=}
71
+ # @param [Object] new_data unmarshaled form of the data to be stored in
72
+ # Riak. Object will be serialized using {#serialize} if a known
73
+ # content_type is used. Setting this overrides values stored with
74
+ # {#raw_data=}
72
75
  # @return [Object] the object stored
73
76
  def data=(new_data)
74
77
  if new_data.respond_to?(:read)
@@ -89,7 +92,9 @@ module Riak
89
92
  @raw_data
90
93
  end
91
94
 
92
- # @param [String, IO-like] the raw data to be stored in riak at this key, will not be marshaled or manipulated prior to storage. Overrides any data stored by {#data=}
95
+ # @param [String, IO-like] new_raw_data the raw data to be stored in Riak
96
+ # at this key, will not be marshaled or manipulated prior to storage.
97
+ # Overrides any data stored by {#data=}
93
98
  # @return [String] the data stored
94
99
  def raw_data=(new_raw_data)
95
100
  @data = nil
@@ -130,7 +135,7 @@ module Riak
130
135
  "#<#{self.class.name} [#{@content_type}]:#{body}>"
131
136
  end
132
137
 
133
- # @hidden
138
+ # @api private
134
139
  def load_map_reduce_value(hash)
135
140
  metadata = hash['metadata']
136
141
  extract_if_present(metadata, 'X-Riak-VTag', :etag)
@@ -29,7 +29,8 @@ module Riak
29
29
  alias :vector_clock :vclock
30
30
  alias :vector_clock= :vclock=
31
31
 
32
- # @return [Boolean] whether to attempt to prevent stale writes using conditional PUT semantics, If-None-Match: * or If-Match: {#etag}
32
+ # @return [Boolean] whether to attempt to prevent stale writes using
33
+ # conditional PUT semantics, If-None-Match: * or If-Match: etag
33
34
  # @see http://wiki.basho.com/display/RIAK/REST+API#RESTAPI-Storeaneworexistingobjectwithakey Riak Rest API Docs
34
35
  attr_accessor :prevent_stale_writes
35
36
 
@@ -182,13 +183,6 @@ module Riak
182
183
  "#<#{self.class.name} {#{bucket.name}#{"," + @key if @key}} [#{body}]>"
183
184
  end
184
185
 
185
- # Walks links from this object to other objects in Riak.
186
- # @param [Array<Hash,WalkSpec>] link specifications for the query
187
- def walk(*params)
188
- specs = WalkSpec.normalize(*params)
189
- @bucket.client.link_walk(self, specs)
190
- end
191
-
192
186
  # Converts the object to a link suitable for linking other objects
193
187
  # to it
194
188
  # @param [String] tag the tag to apply to the link
@@ -5,10 +5,10 @@ module Riak
5
5
  include Client::FeatureDetection
6
6
 
7
7
  # Create a Riak Secondary Index operation
8
- # @param [Bucket] the {Riak::Bucket} we'll query against
9
- # @param [String] the index name
10
- # @param [String,Integer,Range<String,Integer>] a single value or
11
- # range of values to query for
8
+ # @param [Bucket] bucket the {Riak::Bucket} we'll query against
9
+ # @param [String] index the index name
10
+ # @param [String,Integer,Range<String,Integer>] query
11
+ # a single value or range of values to query for
12
12
  def initialize(bucket, index, query, options={})
13
13
  @bucket = bucket
14
14
  @client = @bucket.client
@@ -23,7 +23,7 @@ module Riak
23
23
 
24
24
  def serializer_for(content_type)
25
25
  serializers.fetch(content_type[/^[^;\s]+/]) do
26
- raise NotImplementedError.new(t('serializer_not_implemented', :content_type => content_type.inspect))
26
+ raise IOError.new(t('serializer_not_implemented', :content_type => content_type.inspect))
27
27
  end
28
28
  end
29
29
 
@@ -25,12 +25,12 @@ module Riak
25
25
  # being stored. This increases compatibility with the Protocol
26
26
  # Buffers transport and reduces inconsistency of link-walking
27
27
  # vs. regular operations. If the node you are connecting to has
28
- # set {http_url_encoding, on}, set this to true. Default is false.
28
+ # set `{http_url_encoding, on}`, set this to true. Default is false.
29
29
  # @return [true,false] Whether Riak decodes URL-encoded paths and headers
30
30
  attr_accessor :url_decoding
31
31
  end
32
32
 
33
- self.escaper = CGI
33
+ self.escaper = URI
34
34
  self.url_decoding = false
35
35
 
36
36
  module Util
@@ -52,9 +52,7 @@ module Riak
52
52
  # @return [String] the escaped path segment
53
53
  def escape(bucket_or_key)
54
54
  if Riak.escaper == URI
55
- Riak.escaper.escape(bucket_or_key.to_s).
56
- gsub(" ", "%20").gsub("+", "%2B").gsub("/", "%2F").
57
- gsub("[", "%5B").gsub("]", "%5D")
55
+ Riak.escaper.escape(bucket_or_key.to_s).gsub(" ", "%20").gsub("+", "%2B").gsub('/', "%2F")
58
56
  else #CGI
59
57
  Riak.escaper.escape(bucket_or_key.to_s).gsub("+", "%20").gsub('/', "%2F")
60
58
  end
@@ -1,3 +1,3 @@
1
1
  module Riak
2
- VERSION = "1.4.5"
2
+ VERSION = "2.0.0.rc1"
3
3
  end
@@ -6,10 +6,14 @@ module Riak
6
6
  # The specification of how to follow links from one object to another in Riak,
7
7
  # when using the link-walker resource.
8
8
  # Example link-walking operation:
9
- # GET /riak/artists/REM/albums,_,_/tracks,_,1
9
+ #
10
+ # GET /riak/artists/REM/albums,_,_/tracks,_,1
11
+ #
10
12
  # This operation would have two WalkSpecs:
11
- # Riak::WalkSpec.new({:bucket => 'albums'})
12
- # Riak::WalkSpec.new({:bucket => 'tracks', :result => true})
13
+ #
14
+ # Riak::WalkSpec.new({:bucket => 'albums'})
15
+ # Riak::WalkSpec.new({:bucket => 'tracks', :result => true})
16
+ #
13
17
  class WalkSpec
14
18
  include Util::Translation
15
19
  extend Util::Translation
@@ -12,18 +12,20 @@ Gem::Specification.new do |gem|
12
12
  gem.authors = ["Sean Cribbs", 'Bryce Kerley']
13
13
  gem.license = 'Apache 2.0'
14
14
 
15
+ gem.required_ruby_version = '>= 1.9.3'
16
+
15
17
  # Deps
16
- gem.add_development_dependency "rspec", "~>2.13.0"
17
- gem.add_development_dependency "fakeweb", ">=1.2"
18
- gem.add_development_dependency "rack", ">=1.0"
19
- gem.add_development_dependency "excon", ">=0.6.1"
20
- gem.add_development_dependency 'rake'
21
- gem.add_development_dependency "instrumentable", "~> 1.1.0"
18
+ gem.add_development_dependency "rspec", "~> 3.0.0"
19
+ gem.add_development_dependency 'rake', '~> 10.1.1'
20
+ gem.add_development_dependency 'yard', '~> 0.8.7'
21
+ gem.add_development_dependency 'redcarpet', '~> 3.0.0'
22
+ gem.add_development_dependency 'simplecov', '~> 0.8.2'
23
+
22
24
  gem.add_runtime_dependency "i18n", ">=0.4.0"
23
- gem.add_runtime_dependency "builder", ">= 2.1.2"
24
- gem.add_runtime_dependency "beefcake", "~>1.0.0"
25
+ gem.add_runtime_dependency "beefcake", ">= 1.0.0.pre1"
25
26
  gem.add_runtime_dependency "multi_json", "~>1.0"
26
27
  gem.add_runtime_dependency "innertube", "~>1.0.2"
28
+ gem.add_runtime_dependency 'r509-cert-validator', '~> 0.0.4'
27
29
 
28
30
  # Files
29
31
 
@@ -0,0 +1,25 @@
1
+ Bitcask is an Erlang application that provides an API for storing and retrieving key/value data into a log-structured hash table that provides very fast access. The design owes a lot to the principles found in log-structured file systems and draws inspiration from a number of designs that involve log file merging.
2
+
3
+ Strengths
4
+ Low latency per item read or written
5
+ This is due to the write-once, append-only nature of the Bitcask database files. High throughput, especially when writing an incoming stream of random items Because the data being written doesn't need to be ordered on disk and because the log structured design allows for minimal disk head movement during writes these operations generally saturate the I/O and disk bandwidth.
6
+
7
+ Ability to handle datasets larger than RAM w/o degradation
8
+ Because access to data in Bitcask is direct lookup from an in-memory hash table finding data on disk is very efficient, even when data sets are very large.
9
+
10
+ Single Seek to Retrieve Any Value
11
+ Bitcask's in-memory hash-table of keys point directly to locations on disk where the data lives. Bitcask never uses more than one disk seek to read a value and sometimes, due to file-system caching done by the operating system, even that isn't necessary.
12
+
13
+ Predictable Lookup and Insert Performance
14
+ As you might expect from the description above, read operations have a fixed, predictable behavior. What you might not expect is that this is also true for writes. Write operations are at most a seek to the end of the current file open writing and an append to that file.
15
+
16
+ Fast, bounded Crash Recovery
17
+ Due to the append-only write once nature of Bitcask files, recovery is easy and fast. The only items that might be lost are partially written records at the tail of the file last opened for writes. Recovery need only review the last record or two written and verify CRC data to ensure that the data is consistent.
18
+
19
+ Easy Backup
20
+ In most systems backup can be very complicated but here again Bitcask simplifies this process due to its append-only write once disk format. Any utility that archives or copies files in disk-block order will properly backup or copy a Bitcask database.
21
+
22
+ Weakness
23
+ Keys Must Fit In Memory
24
+ Bitcask keeps all keys in memory at all times, this means that your system must have enough memory to contain your entire keyspace with room for other operational components and operating system resident filesystem buffer space.
25
+
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'riak'
3
+
4
+ describe 'Bucket Types', test_client: true, integration: true do
5
+ let(:bucket){ random_bucket 'bucket_type_spec' }
6
+
7
+ describe 'performing key-value operations' do
8
+ # for the sake of having a non-default one, not search
9
+ let(:bucket_type){ 'yokozuna' }
10
+ let(:object) do
11
+ object = bucket.new random_key
12
+ object.data = 'hello'
13
+ object.content_type = 'text/plain'
14
+ object.store type: bucket_type
15
+ object
16
+ end
17
+
18
+ it 'only retrieves with a bucket type' do
19
+ expect{ bucket.get object.key, type: bucket_type }.to_not raise_error
20
+ expect{ bucket.get object.key }.to raise_error /not_found/
21
+ end
22
+
23
+ it 'deletes from the bucket only with a bucket type' do
24
+ expect(bucket.delete object.key).to eq true
25
+ expect{ bucket.get object.key, type: bucket_type }.to_not raise_error
26
+
27
+ expect{ bucket.delete object.key, type: bucket_type }.to_not raise_error
28
+ expect{ bucket.get object.key, type: bucket_type }.to raise_error /not_found/
29
+ end
30
+
31
+ it 'self-deletes only with a bucket type' do
32
+ expect(object.delete).to be
33
+ expect{ object.reload type: bucket_type }.to_not raise_error
34
+
35
+ expect(object.delete type: bucket_type).to be
36
+ expect{ object.reload type: bucket_type }.to raise_error /not_found/
37
+ end
38
+ end
39
+
40
+ describe 'performing CRDT set operations' do
41
+ let(:bucket_type){ Riak::Crdt::DEFAULT_BUCKET_TYPES[:set] }
42
+ let(:set) do
43
+ set = Riak::Crdt::Set.new bucket, random_key
44
+ set.add random_key
45
+ set
46
+ end
47
+
48
+ it 'retrieves the set blob via key-value using a bucket type' do
49
+ expect{ bucket.get set.key }.to raise_error /not_found/
50
+ expect(bucket.get set.key, type: bucket_type).to be
51
+ end
52
+
53
+ it 'deletes the set blob through the bucket type' do
54
+ expect(bucket.delete set.key).to be
55
+ expect{ bucket.get set.key, type: bucket_type }.to_not raise_error
56
+
57
+ expect(bucket.delete set.key, type: bucket_type).to be
58
+ expect{ bucket.get set.key, type: bucket_type }.to raise_error /not_found/
59
+ end
60
+ end
61
+ end
@@ -1,51 +1,36 @@
1
1
  require 'spec_helper'
2
2
  require 'riak'
3
3
 
4
- describe Riak::Counter, test_server: true, integration: true do
4
+ describe Riak::Counter, test_client: true, integration: true do
5
5
  before :all do
6
- opts = {
7
- http_port: test_server.http_port,
8
- pb_port: test_server.pb_port,
9
- protocol: 'pbc'
10
- }
11
- test_server.start
12
- @client = Riak::Client.new opts
13
- @bucket = @client['counter_spec']
6
+ @bucket = random_bucket 'counter_spec'
14
7
  @bucket.allow_mult = true
15
8
 
16
9
  @counter = Riak::Counter.new @bucket, 'counter_spec'
17
10
  end
18
11
 
12
+ it 'should read and update' do
13
+ initial = @counter.value
19
14
 
20
- ['pbc', 'http'].each do |protocol|
21
- describe protocol do
22
- before :all do
23
- @client.protocol = protocol
24
- end
25
- it 'should read and update' do
26
- initial = @counter.value
15
+ @counter.increment
16
+ @counter.increment
27
17
 
28
- @counter.increment
29
- @counter.increment
18
+ expect(@counter.value).to eq(initial + 2)
30
19
 
31
- @counter.value.should == (initial + 2)
20
+ @counter.decrement 2
32
21
 
33
- @counter.decrement 2
22
+ expect(@counter.value).to eq(initial)
34
23
 
35
- @counter.value.should == initial
24
+ 5.times do
25
+ amt = rand(10_000)
26
+
27
+ @counter.increment amt
28
+ expect(@counter.value).to eq(initial + amt)
36
29
 
37
- 5.times do
38
- amt = rand(10_000)
39
-
40
- @counter.increment amt
41
- @counter.value.should == (initial + amt)
30
+ @counter.decrement (amt * 2)
31
+ expect(@counter.value).to eq(initial - amt)
42
32
 
43
- @counter.decrement (amt * 2)
44
- @counter.value.should == (initial - amt)
45
-
46
- @counter.increment_and_return(amt).should == initial
47
- end
48
- end
33
+ expect(@counter.increment_and_return(amt)).to eq(initial)
49
34
  end
50
35
  end
51
36
  end
@@ -0,0 +1,181 @@
1
+ require 'spec_helper'
2
+ require 'riak'
3
+
4
+ describe "CRDTs", integration: true, test_client: true do
5
+ let(:bucket) { random_bucket }
6
+
7
+ describe 'configuration' do
8
+ it "should allow default bucket-types to be configured for each data type" do
9
+ expect(Riak::Crdt::Set.new(bucket, 'set').bucket_type).to eq 'sets'
10
+
11
+ Riak::Crdt::DEFAULT_BUCKET_TYPES[:set] = 'new_set_default'
12
+ expect(Riak::Crdt::Set.new(bucket, 'set').bucket_type).to eq 'new_set_default'
13
+
14
+ Riak::Crdt::DEFAULT_BUCKET_TYPES[:set] = 'sets'
15
+ expect(Riak::Crdt::Set.new(bucket, 'set').bucket_type).to eq 'sets'
16
+ end
17
+
18
+ it "should allow override bucket-types for instances" do
19
+ expect(Riak::Crdt::Set.new(bucket, 'set', 'other_bucket_type').bucket_type).to eq 'other_bucket_type'
20
+ end
21
+ end
22
+
23
+ describe 'an anonymous counter' do
24
+ subject { Riak::Crdt::Counter.new bucket, nil }
25
+ it 'accepts a Riak-assigned name' do
26
+ subject.increment
27
+ expect(subject.key).to be
28
+ expect(subject.value).to eq 1
29
+ end
30
+ end
31
+
32
+ describe 'counters' do
33
+ subject { Riak::Crdt::Counter.new bucket, random_key }
34
+ it 'should allow straightforward counter ops' do
35
+ start = subject.value
36
+ subject.increment
37
+ expect(subject.value).to eq(start + 1)
38
+ subject.increment
39
+ expect(subject.value).to eq(start + 2)
40
+ subject.increment -1
41
+ expect(subject.value).to eq(start + 1)
42
+ subject.decrement
43
+ expect(subject.value).to eq(start)
44
+ end
45
+
46
+ it 'should allow batched counter ops' do
47
+ start = subject.value
48
+ subject.batch do |s|
49
+ s.increment
50
+ s.increment 2
51
+ s.increment
52
+ s.increment
53
+ end
54
+ expect(subject.value).to eq(start + 5)
55
+ end
56
+ end
57
+ describe 'sets' do
58
+
59
+ subject { Riak::Crdt::Set.new bucket, random_key }
60
+
61
+ it 'should allow straightforward set ops' do
62
+ start = subject.members
63
+ addition = random_key
64
+
65
+ subject.add addition
66
+ expect(subject.include? addition).to be
67
+ expect(subject.members).to include(addition)
68
+
69
+ subject.remove addition
70
+ expect(subject.include? addition).to_not be
71
+ expect(subject.members).to_not include(addition)
72
+ expect(subject.members).to eq(start)
73
+ end
74
+
75
+ it 'lets Riak silently accept removals after reload' do
76
+ addition = random_key
77
+ subject.add addition
78
+
79
+ other = Riak::Crdt::Set.new subject.bucket, subject.key
80
+ expect{ other.remove addition }.to raise_error(Riak::CrdtError::SetRemovalWithoutContextError)
81
+ other.reload
82
+ expect{ other.remove addition }.to_not raise_error
83
+ other.reload
84
+ expect{ other.remove 'an element not in the set' }.to_not raise_error
85
+ end
86
+
87
+ it 'should allow batched set ops' do
88
+ subject.add 'zero'
89
+ subject.reload
90
+
91
+ subject.batch do |s|
92
+ s.add 'first'
93
+ s.remove 'zero'
94
+ end
95
+
96
+ expect(subject.members.to_a).to eq %w{first}
97
+ end
98
+ end
99
+ describe 'maps' do
100
+ subject { Riak::Crdt::Map.new bucket, random_key }
101
+
102
+ it 'should allow straightforward map ops' do
103
+ subject.registers['first'] = 'hello'
104
+ expect(subject.registers['first']).to eq('hello')
105
+
106
+ subject.sets['arnold'].add 'commando'
107
+ subject.sets['arnold'].add 'terminator'
108
+ expect(subject.sets['arnold'].members).to include('commando')
109
+ subject.sets['arnold'].remove 'commando'
110
+ expect(subject.sets['arnold'].members).to_not include('commando')
111
+ expect(subject.sets['arnold'].members).to include('terminator')
112
+
113
+ subject.maps['first'].registers['second'] = 'good evening'
114
+ subject.maps['first'].maps['third'].counters['fourth'].increment
115
+
116
+ expect(subject.maps['first'].registers['second']).to eq('good evening')
117
+ expect(subject.maps['first'].maps['third'].counters['fourth'].value).to eq(1)
118
+
119
+ subject.counters['hits'].increment
120
+ expect(subject.counters['hits'].value).to eq 1
121
+
122
+ subject.flags['yes'] = true
123
+ expect(subject.flags['yes']).to eq true
124
+
125
+ expect do
126
+ subject.registers.delete 'first'
127
+ subject.sets.delete 'arnold'
128
+ subject.maps.delete 'first'
129
+ subject.counters.delete 'hits'
130
+ subject.flags.delete 'yes'
131
+ end.to_not raise_error
132
+ end
133
+
134
+ it 'should allow batched map ops' do
135
+ subject.batch do |s|
136
+ s.registers['condiment'] = 'ketchup'
137
+ s.counters['banana'].increment
138
+ end
139
+
140
+ expect(subject.registers['condiment']).to eq 'ketchup'
141
+ expect(subject.counters['banana'].value).to eq 1
142
+ end
143
+
144
+ describe 'containing a map' do
145
+ it 'should bubble straightforward map ops up' do
146
+ street_map = subject.maps['street']
147
+
148
+ street_map.registers['bird'] = 'avenue'
149
+ street_map.flags['traffic_light'] = false
150
+
151
+ expect(subject.maps['street'])
152
+ end
153
+
154
+ it 'should include inner-map ops in the outer-map batch' do
155
+ subject.batch do |m|
156
+ m.maps['road'].counters['speedbumps'].increment 4
157
+ m.maps['road'].sets['signs'].add 'yield'
158
+ end
159
+
160
+ expect(subject.maps['road'].counters['speedbumps'].value).to eq 4
161
+ expect(subject.maps['road'].sets['signs'].include? 'yield').to be
162
+ end
163
+ end
164
+
165
+ describe 'containing a register' do
166
+ it 'should bubble straightforward register ops up' do
167
+ subject.registers['hkey_local_machine'] = 'registry'
168
+
169
+ expect(subject.registers['hkey_local_machine']).to eq 'registry'
170
+ end
171
+ end
172
+
173
+ describe 'containing a flag' do
174
+ it 'should bubble straightforward flag ops up' do
175
+ subject.flags['enable_magic'] = true
176
+
177
+ expect(subject.flags['enable_magic']).to be
178
+ end
179
+ end
180
+ end
181
+ end