moneta 1.4.2 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +35 -38
- data/CHANGES +9 -0
- data/CONTRIBUTORS +2 -0
- data/Gemfile +143 -55
- data/README.md +5 -4
- data/lib/moneta/adapter.rb +52 -0
- data/lib/moneta/adapters/activerecord.rb +77 -68
- data/lib/moneta/adapters/activesupportcache.rb +22 -31
- data/lib/moneta/adapters/cassandra.rb +114 -116
- data/lib/moneta/adapters/client.rb +17 -18
- data/lib/moneta/adapters/couch.rb +31 -26
- data/lib/moneta/adapters/datamapper.rb +9 -5
- data/lib/moneta/adapters/daybreak.rb +15 -21
- data/lib/moneta/adapters/dbm.rb +6 -12
- data/lib/moneta/adapters/file.rb +21 -13
- data/lib/moneta/adapters/fog.rb +5 -6
- data/lib/moneta/adapters/gdbm.rb +6 -12
- data/lib/moneta/adapters/hbase.rb +10 -12
- data/lib/moneta/adapters/kyotocabinet.rb +22 -27
- data/lib/moneta/adapters/leveldb.rb +14 -20
- data/lib/moneta/adapters/lmdb.rb +19 -22
- data/lib/moneta/adapters/localmemcache.rb +7 -13
- data/lib/moneta/adapters/lruhash.rb +20 -20
- data/lib/moneta/adapters/memcached/dalli.rb +25 -33
- data/lib/moneta/adapters/memcached/native.rb +14 -20
- data/lib/moneta/adapters/memory.rb +5 -7
- data/lib/moneta/adapters/mongo.rb +53 -52
- data/lib/moneta/adapters/pstore.rb +21 -27
- data/lib/moneta/adapters/redis.rb +42 -37
- data/lib/moneta/adapters/restclient.rb +17 -25
- data/lib/moneta/adapters/riak.rb +8 -9
- data/lib/moneta/adapters/sdbm.rb +6 -12
- data/lib/moneta/adapters/sequel/mysql.rb +8 -8
- data/lib/moneta/adapters/sequel/postgres.rb +17 -17
- data/lib/moneta/adapters/sequel/postgres_hstore.rb +47 -47
- data/lib/moneta/adapters/sequel/sqlite.rb +9 -9
- data/lib/moneta/adapters/sequel.rb +56 -65
- data/lib/moneta/adapters/sqlite.rb +37 -35
- data/lib/moneta/adapters/tdb.rb +8 -14
- data/lib/moneta/adapters/tokyocabinet.rb +19 -17
- data/lib/moneta/adapters/tokyotyrant.rb +29 -30
- data/lib/moneta/adapters/yaml.rb +1 -5
- data/lib/moneta/config.rb +101 -0
- data/lib/moneta/expires.rb +0 -1
- data/lib/moneta/expires_support.rb +3 -4
- data/lib/moneta/pool.rb +1 -1
- data/lib/moneta/proxy.rb +29 -0
- data/lib/moneta/server.rb +21 -14
- data/lib/moneta/version.rb +1 -1
- data/lib/moneta/wrapper.rb +5 -0
- data/lib/moneta.rb +2 -0
- data/moneta.gemspec +1 -0
- data/spec/moneta/adapters/client/client_helper.rb +4 -3
- data/spec/moneta/adapters/faraday_helper.rb +3 -2
- data/spec/moneta/adapters/lruhash/adapter_lruhash_spec.rb +10 -6
- data/spec/moneta/adapters/mongo/adapter_mongo_spec.rb +2 -2
- data/spec/moneta/config_spec.rb +219 -0
- data/spec/moneta/proxies/transformer/transformer_bson_spec.rb +3 -1
- data/spec/moneta/proxies/transformer/transformer_marshal_escape_spec.rb +2 -0
- data/spec/rack/session_moneta_spec.rb +44 -25
- data/spec/restserver.rb +3 -14
- metadata +24 -6
@@ -4,16 +4,31 @@ module Moneta
|
|
4
4
|
module Adapters
|
5
5
|
# Sequel backend
|
6
6
|
# @api public
|
7
|
-
class Sequel
|
8
|
-
include Defaults
|
9
|
-
|
7
|
+
class Sequel < Adapter
|
10
8
|
autoload :MySQL, 'moneta/adapters/sequel/mysql'
|
11
9
|
autoload :Postgres, 'moneta/adapters/sequel/postgres'
|
12
10
|
autoload :PostgresHStore, 'moneta/adapters/sequel/postgres_hstore'
|
13
11
|
autoload :SQLite, 'moneta/adapters/sequel/sqlite'
|
14
12
|
|
15
13
|
supports :create, :increment, :each_key
|
16
|
-
|
14
|
+
|
15
|
+
config :table, default: :moneta, coerce: :to_sym
|
16
|
+
config :optimize, default: true
|
17
|
+
config :create_table, default: true
|
18
|
+
config :key_column, default: :k
|
19
|
+
config :value_column, default: :v
|
20
|
+
config :hstore, coerce: :to_s
|
21
|
+
config :each_key_server
|
22
|
+
|
23
|
+
backend do |db:, extensions: [], connection_validation_timeout: nil, **options|
|
24
|
+
::Sequel.connect(db, options).tap do |backend|
|
25
|
+
extensions.map(&:to_sym).each(&backend.method(:extension))
|
26
|
+
|
27
|
+
if connection_validation_timeout
|
28
|
+
backend.pool.connection_validation_timeout = connection_validation_timeout
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
17
32
|
|
18
33
|
# @param [Hash] options
|
19
34
|
# @option options [String] :db Sequel database
|
@@ -22,7 +37,7 @@ module Moneta
|
|
22
37
|
# @option options [Integer] :connection_validation_timeout (nil) Sequel connection_validation_timeout
|
23
38
|
# @option options [Sequel::Database] :backend Use existing backend instance
|
24
39
|
# @option options [Boolean] :optimize (true) Set to false to prevent database-specific optimisations
|
25
|
-
# @option options [Proc, Boolean] :create_table Provide a Proc for creating the table, or
|
40
|
+
# @option options [Proc, Boolean] :create_table (true) Provide a Proc for creating the table, or
|
26
41
|
# set to false to disable table creation all together. If a Proc is given, it will be
|
27
42
|
# called regardless of whether the table exists already.
|
28
43
|
# @option options [Symbol] :key_column (:k) The name of the key column
|
@@ -37,32 +52,21 @@ module Moneta
|
|
37
52
|
# in conjunction with Sequel's `:servers` option
|
38
53
|
# @option options All other options passed to `Sequel#connect`
|
39
54
|
def initialize(options = {})
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
@backend = options.delete(:backend) ||
|
44
|
-
connect(extensions: extensions, connection_validation_timeout: connection_validation_timeout, **options)
|
45
|
-
|
46
|
-
if hstore = options.delete(:hstore)
|
47
|
-
@row = hstore.to_s
|
55
|
+
super
|
56
|
+
|
57
|
+
if config.hstore
|
48
58
|
extend Sequel::PostgresHStore
|
49
|
-
elsif optimize
|
59
|
+
elsif config.optimize
|
50
60
|
add_optimizations
|
51
61
|
end
|
52
62
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
@each_key_server = options.delete(:each_key_server)
|
57
|
-
|
58
|
-
create_proc = options.delete(:create_table)
|
59
|
-
if create_proc == nil
|
63
|
+
if config.create_table.respond_to?(:call)
|
64
|
+
config.create_table.call(backend)
|
65
|
+
elsif config.create_table
|
60
66
|
create_table
|
61
|
-
elsif create_proc
|
62
|
-
create_proc.call(@backend)
|
63
67
|
end
|
64
68
|
|
65
|
-
@table =
|
69
|
+
@table = backend[config.table]
|
66
70
|
prepare_statements
|
67
71
|
end
|
68
72
|
|
@@ -74,7 +78,7 @@ module Moneta
|
|
74
78
|
# (see Proxy#load)
|
75
79
|
def load(key, options = {})
|
76
80
|
if row = @load.call(key: key)
|
77
|
-
row[value_column]
|
81
|
+
row[config.value_column]
|
78
82
|
end
|
79
83
|
end
|
80
84
|
|
@@ -100,9 +104,9 @@ module Moneta
|
|
100
104
|
|
101
105
|
# (see Proxy#increment)
|
102
106
|
def increment(key, amount = 1, options = {})
|
103
|
-
|
107
|
+
backend.transaction do
|
104
108
|
if existing = @load_for_update.call(key: key)
|
105
|
-
existing_value = existing[value_column]
|
109
|
+
existing_value = existing[config.value_column]
|
106
110
|
amount += Integer(existing_value)
|
107
111
|
raise IncrementError, "no update" unless @increment_update.call(
|
108
112
|
key: key,
|
@@ -135,13 +139,13 @@ module Moneta
|
|
135
139
|
|
136
140
|
# (see Proxy#close)
|
137
141
|
def close
|
138
|
-
|
142
|
+
backend.disconnect
|
139
143
|
nil
|
140
144
|
end
|
141
145
|
|
142
146
|
# (see Proxy#slice)
|
143
147
|
def slice(*keys, **options)
|
144
|
-
@slice.all(keys).map! { |row| [row[key_column], row[value_column]] }
|
148
|
+
@slice.all(keys).map! { |row| [row[config.key_column], row[config.value_column]] }
|
145
149
|
end
|
146
150
|
|
147
151
|
# (see Proxy#values_at)
|
@@ -165,10 +169,10 @@ module Moneta
|
|
165
169
|
|
166
170
|
# (see Proxy#merge!)
|
167
171
|
def merge!(pairs, options = {})
|
168
|
-
|
172
|
+
backend.transaction do
|
169
173
|
existing = Hash[slice_for_update(pairs)]
|
170
174
|
update_pairs, insert_pairs = pairs.partition { |k, _| existing.key?(k) }
|
171
|
-
@table.import([key_column, value_column], blob_pairs(insert_pairs))
|
175
|
+
@table.import([config.key_column, config.value_column], blob_pairs(insert_pairs))
|
172
176
|
|
173
177
|
if block_given?
|
174
178
|
update_pairs.map! do |key, new_value|
|
@@ -187,8 +191,10 @@ module Moneta
|
|
187
191
|
# (see Proxy#each_key)
|
188
192
|
def each_key
|
189
193
|
return enum_for(:each_key) { @table.count } unless block_given?
|
190
|
-
|
191
|
-
|
194
|
+
|
195
|
+
key_column = config.key_column
|
196
|
+
if config.each_key_server
|
197
|
+
@table.server(config.each_key_server).order(key_column).select(key_column).paged_each do |row|
|
192
198
|
yield row[key_column]
|
193
199
|
end
|
194
200
|
else
|
@@ -201,21 +207,6 @@ module Moneta
|
|
201
207
|
|
202
208
|
protected
|
203
209
|
|
204
|
-
# @api private
|
205
|
-
def connect(db:, extensions: nil, connection_validation_timeout: nil, **options)
|
206
|
-
other_cols = [:table, :create_table, :key_column, :value_column, :hstore]
|
207
|
-
::Sequel.connect(db, options.reject { |k,| other_cols.member?(k) }).tap do |backend|
|
208
|
-
if extensions
|
209
|
-
raise ArgumentError, 'Option :extensions must be an Array' unless extensions.is_a?(Array)
|
210
|
-
extensions.map(&:to_sym).each(&backend.method(:extension))
|
211
|
-
end
|
212
|
-
|
213
|
-
if connection_validation_timeout
|
214
|
-
backend.pool.connection_validation_timeout = connection_validation_timeout
|
215
|
-
end
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
210
|
# @api private
|
220
211
|
def add_optimizations
|
221
212
|
case backend.database_type
|
@@ -243,9 +234,9 @@ module Moneta
|
|
243
234
|
end
|
244
235
|
|
245
236
|
def create_table
|
246
|
-
key_column =
|
247
|
-
value_column =
|
248
|
-
|
237
|
+
key_column = config.key_column
|
238
|
+
value_column = config.value_column
|
239
|
+
backend.create_table?(config.table) do
|
249
240
|
String key_column, null: false, primary_key: true
|
250
241
|
File value_column
|
251
242
|
end
|
@@ -253,7 +244,7 @@ module Moneta
|
|
253
244
|
|
254
245
|
def slice_for_update(pairs)
|
255
246
|
@slice_for_update.all(pairs.map { |k, _| k }.to_a).map! do |row|
|
256
|
-
[row[key_column], row[value_column]]
|
247
|
+
[row[config.key_column], row[config.value_column]]
|
257
248
|
end
|
258
249
|
end
|
259
250
|
|
@@ -266,7 +257,7 @@ module Moneta
|
|
266
257
|
end
|
267
258
|
|
268
259
|
def statement_id(id)
|
269
|
-
"moneta_#{
|
260
|
+
"moneta_#{config.table}_#{id}".to_sym
|
270
261
|
end
|
271
262
|
|
272
263
|
def prepare_statements
|
@@ -281,49 +272,49 @@ module Moneta
|
|
281
272
|
|
282
273
|
def prepare_key
|
283
274
|
@key = @table
|
284
|
-
.where(key_column => :$key).select(1)
|
275
|
+
.where(config.key_column => :$key).select(1)
|
285
276
|
.prepare(:first, statement_id(:key))
|
286
277
|
end
|
287
278
|
|
288
279
|
def prepare_load
|
289
280
|
@load = @table
|
290
|
-
.where(key_column => :$key).select(value_column)
|
281
|
+
.where(config.key_column => :$key).select(config.value_column)
|
291
282
|
.prepare(:first, statement_id(:load))
|
292
283
|
end
|
293
284
|
|
294
285
|
def prepare_store
|
295
286
|
@store_update = @table
|
296
|
-
.where(key_column => :$key)
|
297
|
-
.prepare(:update, statement_id(:store_update), value_column => :$value)
|
287
|
+
.where(config.key_column => :$key)
|
288
|
+
.prepare(:update, statement_id(:store_update), config.value_column => :$value)
|
298
289
|
end
|
299
290
|
|
300
291
|
def prepare_create
|
301
292
|
@create = @table
|
302
|
-
.prepare(:insert, statement_id(:create), key_column => :$key, value_column => :$value)
|
293
|
+
.prepare(:insert, statement_id(:create), config.key_column => :$key, config.value_column => :$value)
|
303
294
|
end
|
304
295
|
|
305
296
|
def prepare_increment
|
306
297
|
@load_for_update = @table
|
307
|
-
.where(key_column => :$key).for_update
|
308
|
-
.select(value_column)
|
298
|
+
.where(config.key_column => :$key).for_update
|
299
|
+
.select(config.value_column)
|
309
300
|
.prepare(:first, statement_id(:load_for_update))
|
310
301
|
@increment_update ||= @table
|
311
|
-
.where(key_column => :$key, value_column => :$value)
|
312
|
-
.prepare(:update, statement_id(:increment_update), value_column => :$new_value)
|
302
|
+
.where(config.key_column => :$key, config.value_column => :$value)
|
303
|
+
.prepare(:update, statement_id(:increment_update), config.value_column => :$new_value)
|
313
304
|
end
|
314
305
|
|
315
306
|
def prepare_delete
|
316
|
-
@delete = @table.where(key_column => :$key)
|
307
|
+
@delete = @table.where(config.key_column => :$key)
|
317
308
|
.prepare(:delete, statement_id(:delete))
|
318
309
|
end
|
319
310
|
|
320
311
|
def prepare_slice
|
321
312
|
@slice_for_update = ::Sequel::Dataset::PlaceholderLiteralizer.loader(@table) do |pl, ds|
|
322
|
-
ds.filter(key_column => pl.arg).select(key_column, value_column).for_update
|
313
|
+
ds.filter(config.key_column => pl.arg).select(config.key_column, config.value_column).for_update
|
323
314
|
end
|
324
315
|
|
325
316
|
@slice = ::Sequel::Dataset::PlaceholderLiteralizer.loader(@table) do |pl, ds|
|
326
|
-
ds.filter(key_column => pl.arg).select(key_column, value_column)
|
317
|
+
ds.filter(config.key_column => pl.arg).select(config.key_column, config.value_column)
|
327
318
|
end
|
328
319
|
end
|
329
320
|
|
@@ -4,12 +4,16 @@ module Moneta
|
|
4
4
|
module Adapters
|
5
5
|
# Sqlite3 backend
|
6
6
|
# @api public
|
7
|
-
class Sqlite
|
8
|
-
include Defaults
|
7
|
+
class Sqlite < Adapter
|
9
8
|
include IncrementSupport
|
10
9
|
|
11
10
|
supports :create, :each_key
|
12
|
-
|
11
|
+
|
12
|
+
config :table, default: 'moneta'
|
13
|
+
config :busy_timeout, default: 1000
|
14
|
+
config :journal_mode
|
15
|
+
|
16
|
+
backend { |file:| ::SQLite3::Database.new(file) }
|
13
17
|
|
14
18
|
# @param [Hash] options
|
15
19
|
# @option options [String] :file Database file
|
@@ -18,31 +22,29 @@ module Moneta
|
|
18
22
|
# @option options [::Sqlite3::Database] :backend Use existing backend instance
|
19
23
|
# @option options [String, Symbol] :journal_mode Set the journal mode for the connection
|
20
24
|
def initialize(options = {})
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
@backend.execute("create table if not exists #{@table} (k blob not null primary key, v blob)")
|
29
|
-
if journal_mode = options[:journal_mode]
|
30
|
-
@backend.journal_mode = journal_mode.to_s
|
25
|
+
super
|
26
|
+
|
27
|
+
backend.busy_timeout(config.busy_timeout)
|
28
|
+
backend.execute("create table if not exists #{config.table} (k blob not null primary key, v blob)")
|
29
|
+
|
30
|
+
if journal_mode = config.journal_mode
|
31
|
+
backend.journal_mode = journal_mode.to_s
|
31
32
|
end
|
33
|
+
|
32
34
|
@stmts =
|
33
|
-
[@exists =
|
34
|
-
@select =
|
35
|
-
@replace =
|
36
|
-
@delete =
|
37
|
-
@clear =
|
38
|
-
@create =
|
39
|
-
@keys =
|
40
|
-
@count =
|
41
|
-
|
42
|
-
version =
|
35
|
+
[@exists = backend.prepare("select exists(select 1 from #{config.table} where k = ?)"),
|
36
|
+
@select = backend.prepare("select v from #{config.table} where k = ?"),
|
37
|
+
@replace = backend.prepare("replace into #{config.table} values (?, ?)"),
|
38
|
+
@delete = backend.prepare("delete from #{config.table} where k = ?"),
|
39
|
+
@clear = backend.prepare("delete from #{config.table}"),
|
40
|
+
@create = backend.prepare("insert into #{config.table} values (?, ?)"),
|
41
|
+
@keys = backend.prepare("select k from #{config.table}"),
|
42
|
+
@count = backend.prepare("select count(*) from #{config.table}")]
|
43
|
+
|
44
|
+
version = backend.execute("select sqlite_version()").first.first
|
43
45
|
if @can_upsert = ::Gem::Version.new(version) >= ::Gem::Version.new('3.24.0')
|
44
|
-
@stmts << (@increment =
|
45
|
-
insert into #{
|
46
|
+
@stmts << (@increment = backend.prepare <<-SQL)
|
47
|
+
insert into #{config.table} values (?, ?)
|
46
48
|
on conflict (k)
|
47
49
|
do update set v = cast(cast(v as integer) + ? as blob)
|
48
50
|
where v = '0' or v = X'30' or cast(v as integer) != 0
|
@@ -76,8 +78,8 @@ module Moneta
|
|
76
78
|
|
77
79
|
# (see Proxy#increment)
|
78
80
|
def increment(key, amount = 1, options = {})
|
79
|
-
|
80
|
-
|
81
|
+
backend.transaction(:exclusive) { return super } unless @can_upsert
|
82
|
+
backend.transaction do
|
81
83
|
@increment.execute!(key, amount.to_s, amount)
|
82
84
|
return Integer(load(key))
|
83
85
|
end
|
@@ -103,14 +105,14 @@ module Moneta
|
|
103
105
|
# (see Proxy#close)
|
104
106
|
def close
|
105
107
|
@stmts.each { |s| s.close }
|
106
|
-
|
108
|
+
backend.close
|
107
109
|
nil
|
108
110
|
end
|
109
111
|
|
110
112
|
# (see Proxy#slice)
|
111
113
|
def slice(*keys, **options)
|
112
|
-
query = "select k, v from #{
|
113
|
-
|
114
|
+
query = "select k, v from #{config.table} where k in (#{(['?'] * keys.length).join(',')})"
|
115
|
+
backend.execute(query, keys)
|
114
116
|
end
|
115
117
|
|
116
118
|
# (see Proxy#values_at)
|
@@ -134,7 +136,7 @@ module Moneta
|
|
134
136
|
|
135
137
|
# (see Proxy#merge!)
|
136
138
|
def merge!(pairs, options = {})
|
137
|
-
transaction =
|
139
|
+
transaction = backend.transaction if block_given?
|
138
140
|
|
139
141
|
if block_given?
|
140
142
|
existing = Hash[slice(*pairs.map { |k, _| k }.to_a)]
|
@@ -146,13 +148,13 @@ module Moneta
|
|
146
148
|
pairs = pairs.to_a
|
147
149
|
end
|
148
150
|
|
149
|
-
query = "replace into #{
|
150
|
-
|
151
|
+
query = "replace into #{config.table} (k, v) values" + (['(?, ?)'] * pairs.length).join(',')
|
152
|
+
backend.query(query, pairs.flatten).close
|
151
153
|
rescue
|
152
|
-
|
154
|
+
backend.rollback if transaction
|
153
155
|
raise
|
154
156
|
else
|
155
|
-
|
157
|
+
backend.commit if transaction
|
156
158
|
self
|
157
159
|
end
|
158
160
|
|
data/lib/moneta/adapters/tdb.rb
CHANGED
@@ -4,34 +4,28 @@ module Moneta
|
|
4
4
|
module Adapters
|
5
5
|
# TDB backend
|
6
6
|
# @api public
|
7
|
-
class TDB
|
8
|
-
include Defaults
|
7
|
+
class TDB < Adapter
|
9
8
|
include HashAdapter
|
10
9
|
include IncrementSupport
|
11
10
|
include EachKeySupport
|
12
11
|
|
13
12
|
supports :create
|
14
13
|
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
begin
|
21
|
-
raise ArgumentError, 'Option :file is required' unless file = options.delete(:file)
|
22
|
-
::TDB.new(file, options)
|
23
|
-
end
|
24
|
-
end
|
14
|
+
# @!method initialize(options = {})
|
15
|
+
# @param [Hash] options
|
16
|
+
# @option options [String] :file Database file
|
17
|
+
# @option options [::TDB] :backend Use existing backend instance
|
18
|
+
backend { |file:, **options| ::TDB.new(file, options) }
|
25
19
|
|
26
20
|
# (see Proxy#close)
|
27
21
|
def close
|
28
|
-
|
22
|
+
backend.close
|
29
23
|
nil
|
30
24
|
end
|
31
25
|
|
32
26
|
# (see Proxy#create)
|
33
27
|
def create(key, value, options = {})
|
34
|
-
|
28
|
+
backend.insert!(key, value)
|
35
29
|
true
|
36
30
|
rescue ::TDB::ERR::EXISTS
|
37
31
|
false
|
@@ -4,29 +4,31 @@ module Moneta
|
|
4
4
|
module Adapters
|
5
5
|
# TokyoCabinet backend
|
6
6
|
# @api public
|
7
|
-
class TokyoCabinet
|
8
|
-
include Defaults
|
7
|
+
class TokyoCabinet < Adapter
|
9
8
|
include HashAdapter
|
10
9
|
include IncrementSupport
|
11
10
|
include CreateSupport
|
12
11
|
include EachKeySupport
|
13
12
|
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
# @!method initialize(options = {})
|
14
|
+
# @param [Hash] options
|
15
|
+
# @option options [String] :file Database file
|
16
|
+
# @option options [Symbol] :type (:hdb) Database type (:bdb and :hdb possible)
|
17
|
+
# @option options [::TokyoCabinet::*DB] :backend Use existing backend instance
|
18
|
+
backend do |file:, type: :hdb|
|
19
|
+
case type
|
20
|
+
when :bdb
|
21
|
+
::TokyoCabinet::BDB.new.tap do |backend|
|
22
|
+
backend.open(file, ::TokyoCabinet::BDB::OWRITER | ::TokyoCabinet::BDB::OCREAT) or
|
23
|
+
raise backend.errmsg(backend.ecode)
|
24
|
+
end
|
25
|
+
when :hdb
|
26
|
+
::TokyoCabinet::HDB.new.tap do |backend|
|
27
|
+
backend.open(file, ::TokyoCabinet::HDB::OWRITER | ::TokyoCabinet::HDB::OCREAT) or
|
28
|
+
raise backend.errmsg(backend.ecode)
|
29
|
+
end
|
21
30
|
else
|
22
|
-
raise ArgumentError,
|
23
|
-
if options[:type] == :bdb
|
24
|
-
@backend = ::TokyoCabinet::BDB.new
|
25
|
-
@backend.open(options[:file], ::TokyoCabinet::BDB::OWRITER | ::TokyoCabinet::BDB::OCREAT)
|
26
|
-
else
|
27
|
-
@backend = ::TokyoCabinet::HDB.new
|
28
|
-
@backend.open(options[:file], ::TokyoCabinet::HDB::OWRITER | ::TokyoCabinet::HDB::OCREAT)
|
29
|
-
end or raise @backend.errmsg(@backend.ecode)
|
31
|
+
raise ArgumentError, ":type must be :bdb or :hdb"
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
@@ -10,51 +10,50 @@ module Moneta
|
|
10
10
|
module Adapters
|
11
11
|
# TokyoTyrant backend
|
12
12
|
# @api public
|
13
|
-
class TokyoTyrant
|
14
|
-
include Defaults
|
13
|
+
class TokyoTyrant < Adapter
|
15
14
|
include HashAdapter
|
16
15
|
|
17
16
|
# error code: no record found
|
18
17
|
ENOREC = 7
|
19
18
|
|
20
19
|
supports :create, :increment
|
21
|
-
|
20
|
+
|
21
|
+
backend do |host: '127.0.0.1', port: 1978|
|
22
|
+
if defined?(::TokyoTyrant::RDB)
|
23
|
+
# Use ruby client
|
24
|
+
::TokyoTyrant::RDB.new.tap do |backend|
|
25
|
+
backend.open(host, port) or raise backend.errmsg
|
26
|
+
end
|
27
|
+
else
|
28
|
+
# Use native client
|
29
|
+
::TokyoTyrant::DB.new(host, port)
|
30
|
+
end
|
31
|
+
end
|
22
32
|
|
23
33
|
# @param [Hash] options
|
24
34
|
# @option options [String] :host ('127.0.0.1') Server host name
|
25
35
|
# @option options [Integer] :port (1978) Server port
|
26
36
|
# @option options [::TokyoTyrant::RDB] :backend Use existing backend instance
|
27
37
|
def initialize(options = {})
|
28
|
-
|
29
|
-
|
30
|
-
if options[:backend]
|
31
|
-
@backend = options[:backend]
|
32
|
-
elsif defined?(::TokyoTyrant::RDB)
|
33
|
-
# Use ruby client
|
34
|
-
@backend = ::TokyoTyrant::RDB.new
|
35
|
-
@backend.open(options[:host], options[:port]) or error
|
36
|
-
else
|
37
|
-
# Use native client
|
38
|
-
@backend = ::TokyoTyrant::DB.new(options[:host], options[:port])
|
39
|
-
end
|
40
|
-
@native = @backend.class.name != 'TokyoTyrant::RDB'
|
38
|
+
super
|
39
|
+
@native = backend.class.name != 'TokyoTyrant::RDB'
|
41
40
|
probe = '__tokyotyrant_endianness_probe'
|
42
|
-
|
43
|
-
|
44
|
-
@pack =
|
41
|
+
backend.delete(probe)
|
42
|
+
backend.addint(probe, 1)
|
43
|
+
@pack = backend.delete(probe) == [1].pack('l>') ? 'l>' : 'l<'
|
45
44
|
end
|
46
45
|
|
47
46
|
# (see Proxy#load)
|
48
47
|
def load(key, options = {})
|
49
|
-
value =
|
48
|
+
value = backend[key]
|
50
49
|
# raise if there is an error and the error is not "no record"
|
51
|
-
error if value == nil &&
|
50
|
+
error if value == nil && backend.ecode != ENOREC
|
52
51
|
value && unpack(value)
|
53
52
|
end
|
54
53
|
|
55
54
|
# (see Proxy#store)
|
56
55
|
def store(key, value, options = {})
|
57
|
-
|
56
|
+
backend.put(key, pack(value)) or error
|
58
57
|
value
|
59
58
|
end
|
60
59
|
|
@@ -62,14 +61,14 @@ module Moneta
|
|
62
61
|
def delete(key, options = {})
|
63
62
|
value = load(key, options)
|
64
63
|
if value
|
65
|
-
|
64
|
+
backend.delete(key) or error
|
66
65
|
value
|
67
66
|
end
|
68
67
|
end
|
69
68
|
|
70
69
|
# (see Proxy#increment)
|
71
70
|
def increment(key, amount = 1, options = {})
|
72
|
-
|
71
|
+
backend.addint(key, amount) or error
|
73
72
|
end
|
74
73
|
|
75
74
|
# (see Proxy#create)
|
@@ -77,18 +76,18 @@ module Moneta
|
|
77
76
|
if @native
|
78
77
|
begin
|
79
78
|
# Native client throws an exception
|
80
|
-
|
79
|
+
backend.putkeep(key, pack(value))
|
81
80
|
rescue TokyoTyrantError
|
82
81
|
false
|
83
82
|
end
|
84
83
|
else
|
85
|
-
|
84
|
+
backend.putkeep(key, pack(value))
|
86
85
|
end
|
87
86
|
end
|
88
87
|
|
89
88
|
# (see Proxy#close)
|
90
89
|
def close
|
91
|
-
|
90
|
+
backend.close
|
92
91
|
nil
|
93
92
|
end
|
94
93
|
|
@@ -96,10 +95,10 @@ module Moneta
|
|
96
95
|
def slice(*keys, **options)
|
97
96
|
hash =
|
98
97
|
if @native
|
99
|
-
|
98
|
+
backend.mget(*keys)
|
100
99
|
else
|
101
100
|
hash = Hash[keys.map { |key| [key] }]
|
102
|
-
raise unless
|
101
|
+
raise unless backend.mget(hash) >= 0
|
103
102
|
hash
|
104
103
|
end
|
105
104
|
|
@@ -142,7 +141,7 @@ module Moneta
|
|
142
141
|
end
|
143
142
|
|
144
143
|
def error
|
145
|
-
raise "#{
|
144
|
+
raise "#{backend.class.name} error: #{backend.errmsg}"
|
146
145
|
end
|
147
146
|
end
|
148
147
|
end
|
data/lib/moneta/adapters/yaml.rb
CHANGED