riak-client 2.4.1 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.document +5 -5
- data/.gitignore +3 -0
- data/Gemfile +17 -17
- data/Guardfile +20 -20
- data/LICENSE.md +16 -16
- data/RELNOTES.md +4 -0
- data/Rakefile +6 -1
- data/lib/riak/client/beefcake/crdt/counter_loader.rb +18 -18
- data/lib/riak/client/beefcake/crdt/hyper_log_log_loader.rb +18 -0
- data/lib/riak/client/beefcake/crdt/map_loader.rb +64 -64
- data/lib/riak/client/beefcake/crdt_loader.rb +4 -1
- data/lib/riak/client/beefcake/crdt_operator.rb +13 -0
- data/lib/riak/client/beefcake/footer +4 -4
- data/lib/riak/client/beefcake/header +6 -6
- data/lib/riak/client/beefcake/messages.rb +67 -10
- data/lib/riak/client/decaying.rb +36 -36
- data/lib/riak/client/feature_detection.rb +120 -120
- data/lib/riak/client/instrumentation.rb +19 -19
- data/lib/riak/client/node.rb +49 -49
- data/lib/riak/client/search.rb +27 -27
- data/lib/riak/conflict.rb +13 -13
- data/lib/riak/core_ext.rb +7 -7
- data/lib/riak/core_ext/blank.rb +53 -53
- data/lib/riak/core_ext/extract_options.rb +7 -7
- data/lib/riak/core_ext/json.rb +15 -15
- data/lib/riak/core_ext/slice.rb +18 -18
- data/lib/riak/core_ext/stringify_keys.rb +10 -10
- data/lib/riak/core_ext/symbolize_keys.rb +10 -10
- data/lib/riak/core_ext/to_param.rb +31 -31
- data/lib/riak/crdt.rb +23 -21
- data/lib/riak/crdt/base.rb +1 -1
- data/lib/riak/crdt/hyper_log_log.rb +97 -0
- data/lib/riak/crdt/operation.rb +19 -19
- data/lib/riak/encoding.rb +6 -6
- data/lib/riak/errors/backend_creation.rb +9 -9
- data/lib/riak/errors/connection_error.rb +50 -50
- data/lib/riak/errors/protobuffs_error.rb +11 -11
- data/lib/riak/i18n.rb +7 -7
- data/lib/riak/instrumentation.rb +6 -6
- data/lib/riak/json.rb +52 -52
- data/lib/riak/list_buckets.rb +28 -28
- data/lib/riak/locale/en.yml +1 -0
- data/lib/riak/locale/fr.yml +51 -51
- data/lib/riak/map_reduce/results.rb +49 -49
- data/lib/riak/map_reduce_error.rb +7 -7
- data/lib/riak/multiget.rb +122 -122
- data/lib/riak/robject.rb +17 -1
- data/lib/riak/search/result_document.rb +9 -0
- data/lib/riak/stamp.rb +77 -77
- data/lib/riak/tombstone.rb +13 -0
- data/lib/riak/util/tcp_socket_extensions.rb +58 -58
- data/lib/riak/version.rb +1 -1
- data/spec/failover/failover.rb +59 -59
- data/spec/fixtures/bitcask.txt +25 -25
- data/spec/fixtures/multipart-basic-conflict.txt +15 -15
- data/spec/fixtures/multipart-blank.txt +7 -7
- data/spec/fixtures/multipart-mapreduce.txt +10 -10
- data/spec/fixtures/multipart-with-body.txt +16 -16
- data/spec/fixtures/multipart-with-marked-tombstones.txt +17 -17
- data/spec/fixtures/multipart-with-unmarked-tombstone.txt +16 -16
- data/spec/fixtures/server.cert.crt +15 -15
- data/spec/fixtures/server.cert.key +15 -15
- data/spec/fixtures/test.pem +1 -1
- data/spec/integration/riak/bucket_types_spec.rb +38 -0
- data/spec/integration/riak/crdt/configuration_spec.rb +4 -3
- data/spec/integration/riak/crdt_spec.rb +70 -0
- data/spec/integration/riak/encodings/crdt_spec.rb +29 -3
- data/spec/integration/riak/encodings/yz_spec.rb +2 -1
- data/spec/integration/riak/preflist_spec.rb +15 -3
- data/spec/integration/riak/protobuffs/timeouts_spec.rb +1 -1
- data/spec/integration/riak/security_spec.rb +11 -6
- data/spec/integration/riak/threading_spec.rb +154 -150
- data/spec/integration/yokozuna/index_spec.rb +61 -61
- data/spec/integration/yokozuna/queries_spec.rb +1 -1
- data/spec/integration/yokozuna/schema_spec.rb +49 -49
- data/spec/riak/beefcake_protobuffs_backend/crdt_operator_spec.rb +22 -0
- data/spec/riak/core_ext/to_param_spec.rb +15 -15
- data/spec/riak/crdt/hyper_log_log_spec.rb +56 -0
- data/spec/riak/crdt/inner_counter_spec.rb +21 -21
- data/spec/riak/crdt/inner_set_spec.rb +33 -33
- data/spec/riak/crdt/set_spec.rb +61 -61
- data/spec/riak/crdt/shared_examples.rb +14 -0
- data/spec/riak/escape_spec.rb +72 -72
- data/spec/riak/feature_detection_spec.rb +77 -77
- data/spec/riak/index_collection_spec.rb +53 -53
- data/spec/riak/instrumentation_spec.rb +124 -124
- data/spec/riak/link_spec.rb +85 -85
- data/spec/riak/list_buckets_spec.rb +41 -41
- data/spec/riak/node_spec.rb +26 -26
- data/spec/riak/robject_spec.rb +45 -0
- data/spec/support/certs/README.md +12 -12
- data/spec/support/certs/ca.crt +21 -21
- data/spec/support/certs/client.crl +13 -13
- data/spec/support/certs/client.crt +94 -94
- data/spec/support/certs/client.csr +18 -18
- data/spec/support/certs/client.key +27 -27
- data/spec/support/certs/empty_ca.crt +21 -21
- data/spec/support/certs/server.crl +13 -13
- data/spec/support/certs/server.crt +94 -94
- data/spec/support/certs/server.key +27 -27
- data/spec/support/crdt_search_fixtures.rb +1 -1
- data/spec/support/integration_setup.rb +10 -10
- data/spec/support/test_client.rb +1 -1
- data/spec/support/test_client.yml.example +10 -10
- metadata +10 -3
data/lib/riak/locale/en.yml
CHANGED
@@ -102,6 +102,7 @@ en:
|
|
102
102
|
serialize_big_integer: "%{bignum} is out of range for sint64 field"
|
103
103
|
serialize_complex_number: "Cannot serialize Complex numbers"
|
104
104
|
serialize_rational_number: "Cannot serialize Rational numbers without losing precision"
|
105
|
+
tombstone_object: "The object is a tombstone (has vclock but no values) and cannot be treated singly or saved: %{robject}"
|
105
106
|
too_few_arguments: "too few arguments: %{params}"
|
106
107
|
walk_spec_invalid_unless_link: "WalkSpec is only valid for a function when the type is :link"
|
107
108
|
wrong_argument_count_walk_spec: "wrong number of arguments (one Hash or bucket,tag,keep required)"
|
data/lib/riak/locale/fr.yml
CHANGED
@@ -1,51 +1,51 @@
|
|
1
|
-
fr:
|
2
|
-
riak:
|
3
|
-
backwards_clock: "L'horloge système a reculé. La génération des ID échouera pour les %{delay} millisecondes à venir."
|
4
|
-
bucket_link_conversion: "Ne peut convertir un lien de bucket vers un walk spec"
|
5
|
-
client_type: "argument invalide : %{client} n'est pas un Riak::Client"
|
6
|
-
conflict_resolver_invalid: "Le résolveur (%{resolver}) n'a pas répondu à :call"
|
7
|
-
content_type_undefined: "content_type n'est pas défini !"
|
8
|
-
deprecated:
|
9
|
-
port: "DEPRECATION: Riak::Client#port ne doit plus être utilisé (deprecated), utilisez #http_port ou #pb_port pour spécifier le protocol.\n%{backtrace}"
|
10
|
-
search: "DEPRECATION: Les fonctionnalités Riak Search sont désormais inclues dans le client principal. Vous n'avez plus besoin d'inclure 'riak/search'.\n%{backtrace}"
|
11
|
-
empty_map_reduce_query: "Spécifiez une ou plusieurs requêtes pour MapReduce."
|
12
|
-
failed_request: "La requête client a échouée."
|
13
|
-
filter_needs_block: "Le filtre %{filter} nécessite un bloc."
|
14
|
-
filter_arity_mismatch: "Le filtre %{filter} nécessite %{expected} arguments. Seulement %{received} ont été fournis."
|
15
|
-
full_bucket_mapred: "Les MapReduce sur un bucket complet, y compris les filtres de clé, invoque 'list-keys' qui est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
|
16
|
-
hash_type: "argument invalide : %{hash} n'est pas un Hash"
|
17
|
-
http_configuration: "Le moteur HTTP %{backend} ne peut être utilisé. Merci de vérifier ses dépendances et/ou sa configuration."
|
18
|
-
http_failed_request: "%{expected} attendu depuis Riak mais %{code} reçu. %{body}"
|
19
|
-
hostname_invalid: "host doit être un nom d'hôte valide"
|
20
|
-
protocol_invalid: "'%{invalid}' n'est pas un protocole valide. Les valeurs possibles sont %{valid}"
|
21
|
-
invalid_basic_auth: "L'authentification basique doit être utilisée comme ceci : 'user:pass'"
|
22
|
-
invalid_client_id: "ID client invalide, doit être une chaîne ou un entier entre 0 et %{max_id}"
|
23
|
-
invalid_io_object: "Object de type IO invalide assigné à RObject#data. Il devrait plutôt être assigné à raw_data"
|
24
|
-
invalid_function_value: "Valeur invalide pour la fonction : %{value}"
|
25
|
-
invalid_options: "Options de configuration invalides."
|
26
|
-
invalid_phase_type: "type doit être :map, :reduce, ou :link"
|
27
|
-
invalid_ssl_verify_mode: "%{invalid} n'est pas une option :verify_mode valide pour SSL. Les options valides sont 'peer' and 'none'."
|
28
|
-
invalid_index_query: "%{value} n'est pas un term de requête valide. Seules les String, Integer et Range de ces types sont autorisés"
|
29
|
-
indexes_unsupported: "Le serveur Riak ne supporte pas les index secondaires."
|
30
|
-
loading_bucket: "pendant le chargement du bucket '%{name}'"
|
31
|
-
list_buckets: "Riak::Client#buckets est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
|
32
|
-
list_keys: "Riak::Bucket#keys est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
|
33
|
-
missing_block: "Un bloc doit être fourni."
|
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"
|
35
|
-
module_function_pair_required: "la fonction doit avoir deux élément lorsqu'elle est définie par un tableau"
|
36
|
-
not_found: "L'objet demandé n'a pas été trouvé."
|
37
|
-
no_pipes: "Ne peut trouver ou ne peut ouvrir un pipe pour la console Riak dans %{path}."
|
38
|
-
port_invalid: "le port doit être un entier entre 0 et 65535"
|
39
|
-
protobuffs_failed_request: "Riak a retourné le code d'erreur %{code} au lieu d'une réponse réussie. %{body}"
|
40
|
-
request_body_type: "Le corps de la requête doit être une chaine ou répondre à :read."
|
41
|
-
search_unsupported: "Le serveur Riak ne supporte pas la recherche."
|
42
|
-
search_docs_require_id: "Search index documents must include the 'id' field."
|
43
|
-
search_remove_requires_id_or_query: "Les documents d'index de recherche doivent avoir des clés 'id' ou 'query'"
|
44
|
-
serializer_not_implemented: "Aucun sérialiseur n'a été défini pour le type de contenu %{content_type}"
|
45
|
-
source_and_root_required: "La configuration de Riak::Node configuration doit inclure les clés :source and :root."
|
46
|
-
stale_write_prevented: "Le client a empêché une écriture périmée."
|
47
|
-
stored_function_invalid: "Une fonction définie par un hash doit avoir :bucket et :key"
|
48
|
-
string_type: "invalid_argument %{string} n'est pas une String"
|
49
|
-
too_few_arguments: "pas assez d'arguments : %{params}"
|
50
|
-
walk_spec_invalid_unless_link: "Le WalkSpec n'est valide pour une fonction que lorsque le type est :link"
|
51
|
-
wrong_argument_count_walk_spec: "nombre d'argument invalide (un Hash ou bucket,tag,keep requis)"
|
1
|
+
fr:
|
2
|
+
riak:
|
3
|
+
backwards_clock: "L'horloge système a reculé. La génération des ID échouera pour les %{delay} millisecondes à venir."
|
4
|
+
bucket_link_conversion: "Ne peut convertir un lien de bucket vers un walk spec"
|
5
|
+
client_type: "argument invalide : %{client} n'est pas un Riak::Client"
|
6
|
+
conflict_resolver_invalid: "Le résolveur (%{resolver}) n'a pas répondu à :call"
|
7
|
+
content_type_undefined: "content_type n'est pas défini !"
|
8
|
+
deprecated:
|
9
|
+
port: "DEPRECATION: Riak::Client#port ne doit plus être utilisé (deprecated), utilisez #http_port ou #pb_port pour spécifier le protocol.\n%{backtrace}"
|
10
|
+
search: "DEPRECATION: Les fonctionnalités Riak Search sont désormais inclues dans le client principal. Vous n'avez plus besoin d'inclure 'riak/search'.\n%{backtrace}"
|
11
|
+
empty_map_reduce_query: "Spécifiez une ou plusieurs requêtes pour MapReduce."
|
12
|
+
failed_request: "La requête client a échouée."
|
13
|
+
filter_needs_block: "Le filtre %{filter} nécessite un bloc."
|
14
|
+
filter_arity_mismatch: "Le filtre %{filter} nécessite %{expected} arguments. Seulement %{received} ont été fournis."
|
15
|
+
full_bucket_mapred: "Les MapReduce sur un bucket complet, y compris les filtres de clé, invoque 'list-keys' qui est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
|
16
|
+
hash_type: "argument invalide : %{hash} n'est pas un Hash"
|
17
|
+
http_configuration: "Le moteur HTTP %{backend} ne peut être utilisé. Merci de vérifier ses dépendances et/ou sa configuration."
|
18
|
+
http_failed_request: "%{expected} attendu depuis Riak mais %{code} reçu. %{body}"
|
19
|
+
hostname_invalid: "host doit être un nom d'hôte valide"
|
20
|
+
protocol_invalid: "'%{invalid}' n'est pas un protocole valide. Les valeurs possibles sont %{valid}"
|
21
|
+
invalid_basic_auth: "L'authentification basique doit être utilisée comme ceci : 'user:pass'"
|
22
|
+
invalid_client_id: "ID client invalide, doit être une chaîne ou un entier entre 0 et %{max_id}"
|
23
|
+
invalid_io_object: "Object de type IO invalide assigné à RObject#data. Il devrait plutôt être assigné à raw_data"
|
24
|
+
invalid_function_value: "Valeur invalide pour la fonction : %{value}"
|
25
|
+
invalid_options: "Options de configuration invalides."
|
26
|
+
invalid_phase_type: "type doit être :map, :reduce, ou :link"
|
27
|
+
invalid_ssl_verify_mode: "%{invalid} n'est pas une option :verify_mode valide pour SSL. Les options valides sont 'peer' and 'none'."
|
28
|
+
invalid_index_query: "%{value} n'est pas un term de requête valide. Seules les String, Integer et Range de ces types sont autorisés"
|
29
|
+
indexes_unsupported: "Le serveur Riak ne supporte pas les index secondaires."
|
30
|
+
loading_bucket: "pendant le chargement du bucket '%{name}'"
|
31
|
+
list_buckets: "Riak::Client#buckets est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
|
32
|
+
list_keys: "Riak::Bucket#keys est une opération coûteuse et ne doit pas être utilisée en production.\n %{backtrace}"
|
33
|
+
missing_block: "Un bloc doit être fourni."
|
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"
|
35
|
+
module_function_pair_required: "la fonction doit avoir deux élément lorsqu'elle est définie par un tableau"
|
36
|
+
not_found: "L'objet demandé n'a pas été trouvé."
|
37
|
+
no_pipes: "Ne peut trouver ou ne peut ouvrir un pipe pour la console Riak dans %{path}."
|
38
|
+
port_invalid: "le port doit être un entier entre 0 et 65535"
|
39
|
+
protobuffs_failed_request: "Riak a retourné le code d'erreur %{code} au lieu d'une réponse réussie. %{body}"
|
40
|
+
request_body_type: "Le corps de la requête doit être une chaine ou répondre à :read."
|
41
|
+
search_unsupported: "Le serveur Riak ne supporte pas la recherche."
|
42
|
+
search_docs_require_id: "Search index documents must include the 'id' field."
|
43
|
+
search_remove_requires_id_or_query: "Les documents d'index de recherche doivent avoir des clés 'id' ou 'query'"
|
44
|
+
serializer_not_implemented: "Aucun sérialiseur n'a été défini pour le type de contenu %{content_type}"
|
45
|
+
source_and_root_required: "La configuration de Riak::Node configuration doit inclure les clés :source and :root."
|
46
|
+
stale_write_prevented: "Le client a empêché une écriture périmée."
|
47
|
+
stored_function_invalid: "Une fonction définie par un hash doit avoir :bucket et :key"
|
48
|
+
string_type: "invalid_argument %{string} n'est pas une String"
|
49
|
+
too_few_arguments: "pas assez d'arguments : %{params}"
|
50
|
+
walk_spec_invalid_unless_link: "Le WalkSpec n'est valide pour une fonction que lorsque le type est :link"
|
51
|
+
wrong_argument_count_walk_spec: "nombre d'argument invalide (un Hash ou bucket,tag,keep requis)"
|
@@ -1,49 +1,49 @@
|
|
1
|
-
module Riak
|
2
|
-
class MapReduce
|
3
|
-
# @api private
|
4
|
-
# Collects and normalizes results from MapReduce requests
|
5
|
-
class Results
|
6
|
-
# Creates a new result collector
|
7
|
-
# @param [MapReduce] mr the MapReduce query
|
8
|
-
def initialize(mr)
|
9
|
-
@keep_count = mr.query.select {|p| p.keep }.size
|
10
|
-
@hash = create_results_hash(mr.query)
|
11
|
-
end
|
12
|
-
|
13
|
-
# Adds a new result to the collector
|
14
|
-
# @param [Fixnum] phase the phase index
|
15
|
-
# @param [Array] result the phase result
|
16
|
-
def add(phase, result)
|
17
|
-
@hash[phase] += result
|
18
|
-
end
|
19
|
-
|
20
|
-
# Coalesces the query results
|
21
|
-
# @return [Array] the query results, coalesced according to the
|
22
|
-
# phase configuration
|
23
|
-
def report
|
24
|
-
if @keep_count > 1
|
25
|
-
@hash.to_a.sort.map {|(num, results)| results }
|
26
|
-
else
|
27
|
-
@hash[@hash.keys.first]
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
def create_results_hash(query)
|
33
|
-
# When the query is empty, only bucket/key pairs are returned,
|
34
|
-
# but implicitly in phase 0.
|
35
|
-
return { 0 => [] } if query.empty?
|
36
|
-
|
37
|
-
# Pre-populate the hash with empty results for kept phases.
|
38
|
-
# Additionally, the last phase is always implictly kept, even
|
39
|
-
# when keep is false.
|
40
|
-
query.inject({}) do |hash, phase|
|
41
|
-
if phase.keep || query[-1] == phase
|
42
|
-
hash[query.index(phase)] = []
|
43
|
-
end
|
44
|
-
hash
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
1
|
+
module Riak
|
2
|
+
class MapReduce
|
3
|
+
# @api private
|
4
|
+
# Collects and normalizes results from MapReduce requests
|
5
|
+
class Results
|
6
|
+
# Creates a new result collector
|
7
|
+
# @param [MapReduce] mr the MapReduce query
|
8
|
+
def initialize(mr)
|
9
|
+
@keep_count = mr.query.select {|p| p.keep }.size
|
10
|
+
@hash = create_results_hash(mr.query)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Adds a new result to the collector
|
14
|
+
# @param [Fixnum] phase the phase index
|
15
|
+
# @param [Array] result the phase result
|
16
|
+
def add(phase, result)
|
17
|
+
@hash[phase] += result
|
18
|
+
end
|
19
|
+
|
20
|
+
# Coalesces the query results
|
21
|
+
# @return [Array] the query results, coalesced according to the
|
22
|
+
# phase configuration
|
23
|
+
def report
|
24
|
+
if @keep_count > 1
|
25
|
+
@hash.to_a.sort.map {|(num, results)| results }
|
26
|
+
else
|
27
|
+
@hash[@hash.keys.first]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def create_results_hash(query)
|
33
|
+
# When the query is empty, only bucket/key pairs are returned,
|
34
|
+
# but implicitly in phase 0.
|
35
|
+
return { 0 => [] } if query.empty?
|
36
|
+
|
37
|
+
# Pre-populate the hash with empty results for kept phases.
|
38
|
+
# Additionally, the last phase is always implictly kept, even
|
39
|
+
# when keep is false.
|
40
|
+
query.inject({}) do |hash, phase|
|
41
|
+
if phase.keep || query[-1] == phase
|
42
|
+
hash[query.index(phase)] = []
|
43
|
+
end
|
44
|
+
hash
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'riak/util/translation'
|
2
|
-
|
3
|
-
module Riak
|
4
|
-
# Raised when an error occurred in the Javascript map-reduce chain.
|
5
|
-
# The message will be the body of the JSON error response.
|
6
|
-
class MapReduceError < StandardError; end
|
7
|
-
end
|
1
|
+
require 'riak/util/translation'
|
2
|
+
|
3
|
+
module Riak
|
4
|
+
# Raised when an error occurred in the Javascript map-reduce chain.
|
5
|
+
# The message will be the body of the JSON error response.
|
6
|
+
class MapReduceError < StandardError; end
|
7
|
+
end
|
data/lib/riak/multiget.rb
CHANGED
@@ -1,122 +1,122 @@
|
|
1
|
-
require 'riak/client'
|
2
|
-
require 'riak/bucket'
|
3
|
-
|
4
|
-
module Riak
|
5
|
-
# Coordinates a parallel fetch operation for multiple values.
|
6
|
-
class Multiget
|
7
|
-
include Util::Translation
|
8
|
-
|
9
|
-
# @return [Riak::Client] the associated client
|
10
|
-
attr_reader :client
|
11
|
-
|
12
|
-
# @return [Array<Bucket, String>] fetch_list an {Array} of {Bucket} and {String} keys to fetch
|
13
|
-
attr_reader :fetch_list
|
14
|
-
|
15
|
-
# @return [Hash<fetch_list_entry, RObject] result_hash a {Hash} of {Bucket} and {String} key pairs to {RObject} instances
|
16
|
-
attr_accessor :result_hash
|
17
|
-
|
18
|
-
# @return [Boolean] finished if the fetch operation has completed
|
19
|
-
attr_reader :finished
|
20
|
-
|
21
|
-
# @return [Integer] The number of threads to use
|
22
|
-
attr_accessor :thread_count
|
23
|
-
|
24
|
-
# Perform a Riak Multiget operation.
|
25
|
-
# @param [Client] client the {Riak::Client} that will perform the multiget
|
26
|
-
# @param [Array<Bucket, String>] fetch_list an {Array} of {Bucket} and {String} keys to fetch
|
27
|
-
# @return [Hash<fetch_list_entry, RObject] result_hash a {Hash} of {Bucket} and {String} key pairs to {RObject} instances
|
28
|
-
def self.get_all(client, fetch_list)
|
29
|
-
multi = new client, fetch_list
|
30
|
-
multi.fetch
|
31
|
-
multi.results
|
32
|
-
end
|
33
|
-
|
34
|
-
# Create a Riak Multiget operation.
|
35
|
-
# @param [Client] client the {Riak::Client} that will perform the multiget
|
36
|
-
# @param [Array<Bucket, String>] fetch_list an {Array} of {Bucket} and {String} keys to fetch
|
37
|
-
def initialize(client, fetch_list)
|
38
|
-
raise ArgumentError, t('client_type', :client => client.inspect) unless client.is_a? Riak::Client
|
39
|
-
raise ArgumentError, t('array_type', :array => fetch_list.inspect) unless fetch_list.is_a? Array
|
40
|
-
|
41
|
-
validate_fetch_list fetch_list
|
42
|
-
@client, @fetch_list = client, fetch_list.uniq
|
43
|
-
self.result_hash = Hash.new
|
44
|
-
@finished = false
|
45
|
-
self.thread_count = client.multiget_threads
|
46
|
-
end
|
47
|
-
|
48
|
-
# Starts the parallelized fetch operation
|
49
|
-
# @raise [ArgumentError] when a non-positive-Integer count is given
|
50
|
-
def fetch
|
51
|
-
queue = fetch_list.dup
|
52
|
-
queue_mutex = Mutex.new
|
53
|
-
result_mutex = Mutex.new
|
54
|
-
|
55
|
-
unless thread_count.is_a?(Integer) && thread_count > 0
|
56
|
-
raise ArgumentError, t("invalid_multiget_thread_count")
|
57
|
-
end
|
58
|
-
|
59
|
-
@threads = 1.upto(thread_count).map do |_node|
|
60
|
-
Thread.new do
|
61
|
-
loop do
|
62
|
-
pair = queue_mutex.synchronize do
|
63
|
-
queue.shift
|
64
|
-
end
|
65
|
-
|
66
|
-
break if pair.nil?
|
67
|
-
|
68
|
-
found = attempt_fetch(*pair)
|
69
|
-
result_mutex.synchronize do
|
70
|
-
result_hash[pair] = found
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def results
|
78
|
-
wait_for_finish
|
79
|
-
result_hash
|
80
|
-
end
|
81
|
-
|
82
|
-
def finished?
|
83
|
-
set_finished_for_thread_liveness
|
84
|
-
finished
|
85
|
-
end
|
86
|
-
|
87
|
-
def wait_for_finish
|
88
|
-
return if finished?
|
89
|
-
@threads.each {|t| t.join }
|
90
|
-
@finished = true
|
91
|
-
end
|
92
|
-
|
93
|
-
private
|
94
|
-
|
95
|
-
def attempt_fetch(bucket, key)
|
96
|
-
bucket[key]
|
97
|
-
rescue Riak::FailedRequest => e
|
98
|
-
raise e unless e.not_found?
|
99
|
-
nil
|
100
|
-
end
|
101
|
-
|
102
|
-
def set_finished_for_thread_liveness
|
103
|
-
return if @finished # already done
|
104
|
-
|
105
|
-
all_dead = @threads.none? {|t| t.alive? }
|
106
|
-
return unless all_dead # still working
|
107
|
-
|
108
|
-
@finished = true
|
109
|
-
return
|
110
|
-
end
|
111
|
-
|
112
|
-
def validate_fetch_list(fetch_list)
|
113
|
-
return unless erroneous = fetch_list.detect do |e|
|
114
|
-
bucket, key = e
|
115
|
-
next true unless bucket.is_a? Bucket
|
116
|
-
next true unless key.is_a? String
|
117
|
-
end
|
118
|
-
|
119
|
-
raise ArgumentError, t('fetch_list_type', :problem => erroneous)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
1
|
+
require 'riak/client'
|
2
|
+
require 'riak/bucket'
|
3
|
+
|
4
|
+
module Riak
|
5
|
+
# Coordinates a parallel fetch operation for multiple values.
|
6
|
+
class Multiget
|
7
|
+
include Util::Translation
|
8
|
+
|
9
|
+
# @return [Riak::Client] the associated client
|
10
|
+
attr_reader :client
|
11
|
+
|
12
|
+
# @return [Array<Bucket, String>] fetch_list an {Array} of {Bucket} and {String} keys to fetch
|
13
|
+
attr_reader :fetch_list
|
14
|
+
|
15
|
+
# @return [Hash<fetch_list_entry, RObject] result_hash a {Hash} of {Bucket} and {String} key pairs to {RObject} instances
|
16
|
+
attr_accessor :result_hash
|
17
|
+
|
18
|
+
# @return [Boolean] finished if the fetch operation has completed
|
19
|
+
attr_reader :finished
|
20
|
+
|
21
|
+
# @return [Integer] The number of threads to use
|
22
|
+
attr_accessor :thread_count
|
23
|
+
|
24
|
+
# Perform a Riak Multiget operation.
|
25
|
+
# @param [Client] client the {Riak::Client} that will perform the multiget
|
26
|
+
# @param [Array<Bucket, String>] fetch_list an {Array} of {Bucket} and {String} keys to fetch
|
27
|
+
# @return [Hash<fetch_list_entry, RObject] result_hash a {Hash} of {Bucket} and {String} key pairs to {RObject} instances
|
28
|
+
def self.get_all(client, fetch_list)
|
29
|
+
multi = new client, fetch_list
|
30
|
+
multi.fetch
|
31
|
+
multi.results
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a Riak Multiget operation.
|
35
|
+
# @param [Client] client the {Riak::Client} that will perform the multiget
|
36
|
+
# @param [Array<Bucket, String>] fetch_list an {Array} of {Bucket} and {String} keys to fetch
|
37
|
+
def initialize(client, fetch_list)
|
38
|
+
raise ArgumentError, t('client_type', :client => client.inspect) unless client.is_a? Riak::Client
|
39
|
+
raise ArgumentError, t('array_type', :array => fetch_list.inspect) unless fetch_list.is_a? Array
|
40
|
+
|
41
|
+
validate_fetch_list fetch_list
|
42
|
+
@client, @fetch_list = client, fetch_list.uniq
|
43
|
+
self.result_hash = Hash.new
|
44
|
+
@finished = false
|
45
|
+
self.thread_count = client.multiget_threads
|
46
|
+
end
|
47
|
+
|
48
|
+
# Starts the parallelized fetch operation
|
49
|
+
# @raise [ArgumentError] when a non-positive-Integer count is given
|
50
|
+
def fetch
|
51
|
+
queue = fetch_list.dup
|
52
|
+
queue_mutex = Mutex.new
|
53
|
+
result_mutex = Mutex.new
|
54
|
+
|
55
|
+
unless thread_count.is_a?(Integer) && thread_count > 0
|
56
|
+
raise ArgumentError, t("invalid_multiget_thread_count")
|
57
|
+
end
|
58
|
+
|
59
|
+
@threads = 1.upto(thread_count).map do |_node|
|
60
|
+
Thread.new do
|
61
|
+
loop do
|
62
|
+
pair = queue_mutex.synchronize do
|
63
|
+
queue.shift
|
64
|
+
end
|
65
|
+
|
66
|
+
break if pair.nil?
|
67
|
+
|
68
|
+
found = attempt_fetch(*pair)
|
69
|
+
result_mutex.synchronize do
|
70
|
+
result_hash[pair] = found
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def results
|
78
|
+
wait_for_finish
|
79
|
+
result_hash
|
80
|
+
end
|
81
|
+
|
82
|
+
def finished?
|
83
|
+
set_finished_for_thread_liveness
|
84
|
+
finished
|
85
|
+
end
|
86
|
+
|
87
|
+
def wait_for_finish
|
88
|
+
return if finished?
|
89
|
+
@threads.each {|t| t.join }
|
90
|
+
@finished = true
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def attempt_fetch(bucket, key)
|
96
|
+
bucket[key]
|
97
|
+
rescue Riak::FailedRequest => e
|
98
|
+
raise e unless e.not_found?
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
def set_finished_for_thread_liveness
|
103
|
+
return if @finished # already done
|
104
|
+
|
105
|
+
all_dead = @threads.none? {|t| t.alive? }
|
106
|
+
return unless all_dead # still working
|
107
|
+
|
108
|
+
@finished = true
|
109
|
+
return
|
110
|
+
end
|
111
|
+
|
112
|
+
def validate_fetch_list(fetch_list)
|
113
|
+
return unless erroneous = fetch_list.detect do |e|
|
114
|
+
bucket, key = e
|
115
|
+
next true unless bucket.is_a? Bucket
|
116
|
+
next true unless key.is_a? String
|
117
|
+
end
|
118
|
+
|
119
|
+
raise ArgumentError, t('fetch_list_type', :problem => erroneous)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|