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