moneta 0.7.6 → 0.7.8
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.
- data/CHANGES +15 -0
- data/README.md +160 -50
- data/Rakefile +11 -2
- data/SPEC.md +7 -2
- data/lib/moneta.rb +7 -1
- data/lib/moneta/adapters/activerecord.rb +27 -3
- data/lib/moneta/adapters/cassandra.rb +1 -1
- data/lib/moneta/adapters/client.rb +8 -2
- data/lib/moneta/adapters/cookie.rb +1 -1
- data/lib/moneta/adapters/couch.rb +2 -1
- data/lib/moneta/adapters/datamapper.rb +16 -0
- data/lib/moneta/adapters/daybreak.rb +19 -1
- data/lib/moneta/adapters/file.rb +12 -0
- data/lib/moneta/adapters/hbase.rb +1 -2
- data/lib/moneta/adapters/lruhash.rb +4 -1
- data/lib/moneta/adapters/memcached.rb +7 -3
- data/lib/moneta/adapters/memcached/dalli.rb +8 -2
- data/lib/moneta/adapters/memcached/native.rb +10 -3
- data/lib/moneta/adapters/memory.rb +1 -0
- data/lib/moneta/adapters/mongo.rb +32 -5
- data/lib/moneta/adapters/pstore.rb +13 -2
- data/lib/moneta/adapters/redis.rb +19 -0
- data/lib/moneta/adapters/restclient.rb +1 -1
- data/lib/moneta/adapters/sequel.rb +20 -6
- data/lib/moneta/adapters/sqlite.rb +13 -1
- data/lib/moneta/adapters/tokyocabinet.rb +5 -0
- data/lib/moneta/cache.rb +10 -0
- data/lib/moneta/expires.rb +19 -22
- data/lib/moneta/lock.rb +2 -2
- data/lib/moneta/mixins.rb +33 -11
- data/lib/moneta/optionmerger.rb +1 -1
- data/lib/moneta/proxy.rb +13 -8
- data/lib/moneta/server.rb +13 -6
- data/lib/moneta/shared.rb +6 -10
- data/lib/moneta/synchronize.rb +125 -0
- data/lib/moneta/transformer.rb +50 -42
- data/lib/moneta/transformer/config.rb +34 -32
- data/lib/moneta/utils.rb +20 -0
- data/lib/moneta/version.rb +1 -1
- data/lib/moneta/weak.rb +17 -0
- data/lib/moneta/wrapper.rb +5 -0
- data/lib/rack/moneta_cookies.rb +2 -2
- data/lib/rack/moneta_store.rb +4 -4
- data/script/benchmarks +3 -9
- data/script/generate-specs +278 -41
- data/script/install-bundle +2 -2
- data/spec/moneta/adapter_activerecord_spec.rb +1 -0
- data/spec/moneta/adapter_cassandra_spec.rb +1 -0
- data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +1 -0
- data/spec/moneta/adapter_client_spec.rb +1 -0
- data/spec/moneta/adapter_cookie_spec.rb +1 -0
- data/spec/moneta/adapter_couch_spec.rb +1 -0
- data/spec/moneta/adapter_datamapper_spec.rb +1 -0
- data/spec/moneta/adapter_daybreak_spec.rb +1 -0
- data/spec/moneta/adapter_dbm_spec.rb +1 -0
- data/spec/moneta/adapter_file_spec.rb +1 -0
- data/spec/moneta/adapter_fog_spec.rb +1 -0
- data/spec/moneta/adapter_gdbm_spec.rb +1 -1
- data/spec/moneta/adapter_hbase_spec.rb +1 -0
- data/spec/moneta/adapter_leveldb_spec.rb +1 -0
- data/spec/moneta/adapter_localmemcache_spec.rb +1 -0
- data/spec/moneta/adapter_lruhash_spec.rb +1 -0
- data/spec/moneta/adapter_memcached_dalli_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_native_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_spec.rb +2 -0
- data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_memory_spec.rb +1 -0
- data/spec/moneta/adapter_mongo_spec.rb +2 -0
- data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_pstore_spec.rb +1 -0
- data/spec/moneta/adapter_redis_spec.rb +2 -0
- data/spec/moneta/adapter_redis_with_default_expires_spec.rb +2 -0
- data/spec/moneta/adapter_restclient_spec.rb +1 -0
- data/spec/moneta/adapter_riak_spec.rb +1 -0
- data/spec/moneta/adapter_sdbm_spec.rb +1 -0
- data/spec/moneta/adapter_sequel_spec.rb +1 -0
- data/spec/moneta/adapter_sqlite_spec.rb +1 -0
- data/spec/moneta/adapter_tdb_spec.rb +1 -0
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +1 -0
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +1 -0
- data/spec/moneta/adapter_yaml_spec.rb +1 -0
- data/spec/moneta/cache_file_memory_spec.rb +1 -0
- data/spec/moneta/cache_memory_null_spec.rb +1 -0
- data/spec/moneta/expires_file_spec.rb +3 -1
- data/spec/moneta/expires_memory_spec.rb +2 -0
- data/spec/moneta/expires_memory_with_default_expires_spec.rb +2 -0
- data/spec/moneta/lock_spec.rb +1 -0
- data/spec/moneta/mutex_spec.rb +71 -0
- data/spec/moneta/null_adapter_spec.rb +1 -0
- data/spec/moneta/optionmerger_spec.rb +5 -7
- data/spec/moneta/pool_spec.rb +1 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +2 -0
- data/spec/moneta/proxy_redis_spec.rb +2 -0
- data/spec/moneta/semaphore_spec.rb +84 -0
- data/spec/moneta/{shared_spec.rb → shared_tcp_spec.rb} +4 -3
- data/spec/moneta/shared_unix_spec.rb +37 -0
- data/spec/moneta/simple_activerecord_spec.rb +1 -0
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_cassandra_spec.rb +1 -0
- data/spec/moneta/simple_client_tcp_spec.rb +1 -0
- data/spec/moneta/simple_client_unix_spec.rb +3 -2
- data/spec/moneta/simple_couch_spec.rb +1 -0
- data/spec/moneta/simple_couch_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_datamapper_spec.rb +1 -0
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +1 -0
- data/spec/moneta/simple_daybreak_spec.rb +1 -0
- data/spec/moneta/simple_daybreak_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_dbm_spec.rb +1 -0
- data/spec/moneta/simple_dbm_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_file_spec.rb +1 -0
- data/spec/moneta/simple_file_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_fog_spec.rb +1 -0
- data/spec/moneta/simple_fog_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_gdbm_spec.rb +1 -0
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_hashfile_spec.rb +1 -0
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_hbase_spec.rb +1 -0
- data/spec/moneta/simple_hbase_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_leveldb_spec.rb +1 -0
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_localmemcache_spec.rb +1 -0
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_lruhash_spec.rb +1 -0
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_memcached_dalli_spec.rb +2 -0
- data/spec/moneta/simple_memcached_native_spec.rb +2 -0
- data/spec/moneta/simple_memcached_spec.rb +2 -0
- data/spec/moneta/simple_memory_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_compress_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_prefix_spec.rb +1 -0
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +1 -0
- data/spec/moneta/simple_mongo_spec.rb +2 -0
- data/spec/moneta/simple_null_spec.rb +1 -0
- data/spec/moneta/simple_pstore_spec.rb +1 -0
- data/spec/moneta/simple_pstore_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_redis_spec.rb +2 -0
- data/spec/moneta/simple_restclient_spec.rb +1 -0
- data/spec/moneta/simple_riak_spec.rb +1 -0
- data/spec/moneta/simple_riak_with_expires_spec.rb +2 -1
- data/spec/moneta/simple_sdbm_spec.rb +1 -0
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_sequel_spec.rb +1 -0
- data/spec/moneta/simple_sequel_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_sqlite_spec.rb +1 -0
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_tdb_spec.rb +1 -0
- data/spec/moneta/simple_tdb_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_tokyocabinet_spec.rb +1 -0
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +3 -1
- data/spec/moneta/simple_yaml_spec.rb +1 -0
- data/spec/moneta/simple_yaml_with_expires_spec.rb +3 -1
- data/spec/moneta/stack_file_memory_spec.rb +1 -0
- data/spec/moneta/stack_memory_file_spec.rb +1 -0
- data/spec/moneta/transformer_bencode_spec.rb +1 -0
- data/spec/moneta/transformer_bert_spec.rb +1 -0
- data/spec/moneta/transformer_bson_spec.rb +1 -0
- data/spec/moneta/transformer_bzip2_spec.rb +1 -0
- data/spec/moneta/transformer_json_spec.rb +1 -0
- data/spec/moneta/transformer_key_inspect_spec.rb +73 -0
- data/spec/moneta/transformer_key_marshal_spec.rb +1 -0
- data/spec/moneta/transformer_key_to_s_spec.rb +1 -0
- data/spec/moneta/transformer_key_yaml_spec.rb +1 -0
- data/spec/moneta/transformer_lzma_spec.rb +1 -0
- data/spec/moneta/transformer_lzo_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_base64_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_escape_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_hmac_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_md5_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_prefix_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha1_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha256_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha384_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_sha512_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_truncate_spec.rb +1 -0
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +1 -0
- data/spec/moneta/transformer_msgpack_spec.rb +1 -0
- data/spec/moneta/transformer_ox_spec.rb +1 -0
- data/spec/moneta/transformer_quicklz_spec.rb +1 -0
- data/spec/moneta/transformer_snappy_spec.rb +1 -0
- data/spec/moneta/transformer_tnet_spec.rb +1 -0
- data/spec/moneta/transformer_value_marshal_spec.rb +1 -0
- data/spec/moneta/transformer_value_yaml_spec.rb +1 -0
- data/spec/moneta/transformer_yaml_spec.rb +1 -0
- data/spec/moneta/transformer_zlib_spec.rb +1 -0
- data/spec/moneta/weak_create_spec.rb +114 -0
- data/spec/moneta/weak_increment_spec.rb +114 -0
- data/spec/monetaspecs.rb +75 -2
- data/spec/rack/moneta_cookies_spec.rb +1 -1
- metadata +20 -4
|
@@ -20,7 +20,8 @@ module Moneta
|
|
|
20
20
|
[@select = @db.prepare("select v from #{table} where k = ?"),
|
|
21
21
|
@replace = @db.prepare("replace into #{table} values (?, ?)"),
|
|
22
22
|
@delete = @db.prepare("delete from #{table} where k = ?"),
|
|
23
|
-
@clear = @db.prepare("delete from #{table}")
|
|
23
|
+
@clear = @db.prepare("delete from #{table}"),
|
|
24
|
+
@create = @db.prepare("insert into #{table} values (?, ?)")]
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
# (see Proxy#key?)
|
|
@@ -58,6 +59,17 @@ module Moneta
|
|
|
58
59
|
self
|
|
59
60
|
end
|
|
60
61
|
|
|
62
|
+
# (see Default#create)
|
|
63
|
+
def create(key, value, options = {})
|
|
64
|
+
@create.execute!(key,value)
|
|
65
|
+
true
|
|
66
|
+
rescue SQLite3::ConstraintException
|
|
67
|
+
# If you know a better way to detect whether an insert-ignore
|
|
68
|
+
# suceeded, please tell me.
|
|
69
|
+
@create.reset!
|
|
70
|
+
false
|
|
71
|
+
end
|
|
72
|
+
|
|
61
73
|
# (see Proxy#close)
|
|
62
74
|
def close
|
|
63
75
|
@stmts.each {|s| s.close }
|
data/lib/moneta/cache.rb
CHANGED
|
@@ -73,6 +73,16 @@ module Moneta
|
|
|
73
73
|
@backend.increment(key, amount, options)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
# (see Proxy#create)
|
|
77
|
+
def create(key, value, options = {})
|
|
78
|
+
if @backend.create(key, value, options)
|
|
79
|
+
@cache.store(key, value, options)
|
|
80
|
+
true
|
|
81
|
+
else
|
|
82
|
+
false
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
76
86
|
# (see Proxy#delete)
|
|
77
87
|
def delete(key, options = {})
|
|
78
88
|
@cache.delete(key, options)
|
data/lib/moneta/expires.rb
CHANGED
|
@@ -21,8 +21,7 @@ module Moneta
|
|
|
21
21
|
# Transformer might raise exception
|
|
22
22
|
load_entry(key, options) != nil
|
|
23
23
|
rescue Exception
|
|
24
|
-
|
|
25
|
-
super(key, options)
|
|
24
|
+
super(key, Utils.without(options, :expires))
|
|
26
25
|
end
|
|
27
26
|
|
|
28
27
|
# (see Proxy#load)
|
|
@@ -36,11 +35,7 @@ module Moneta
|
|
|
36
35
|
def store(key, value, options = {})
|
|
37
36
|
return super if options.include?(:raw)
|
|
38
37
|
expires = expires_at(options)
|
|
39
|
-
|
|
40
|
-
options = options.dup
|
|
41
|
-
options.delete(:expires)
|
|
42
|
-
end
|
|
43
|
-
store_entry(key, value, expires, options)
|
|
38
|
+
super(key, new_entry(value, expires), Utils.without(options, :expires))
|
|
44
39
|
value
|
|
45
40
|
end
|
|
46
41
|
|
|
@@ -51,14 +46,18 @@ module Moneta
|
|
|
51
46
|
value if !expires || Time.now.to_i <= expires
|
|
52
47
|
end
|
|
53
48
|
|
|
49
|
+
# (see Proxy#store)
|
|
50
|
+
def create(key, value, options = {})
|
|
51
|
+
return super if options.include?(:raw)
|
|
52
|
+
expires = expires_at(options)
|
|
53
|
+
@adapter.create(key, new_entry(value, expires), Utils.without(options, :expires))
|
|
54
|
+
end
|
|
55
|
+
|
|
54
56
|
private
|
|
55
57
|
|
|
56
58
|
def load_entry(key, options)
|
|
57
59
|
new_expires = expires_at(options, nil)
|
|
58
|
-
|
|
59
|
-
options = options.dup
|
|
60
|
-
options.delete(:expires)
|
|
61
|
-
end
|
|
60
|
+
options = Utils.without(options, :expires)
|
|
62
61
|
entry = @adapter.load(key, options)
|
|
63
62
|
if entry != nil
|
|
64
63
|
value, expires = entry
|
|
@@ -66,7 +65,7 @@ module Moneta
|
|
|
66
65
|
delete(key)
|
|
67
66
|
nil
|
|
68
67
|
elsif new_expires != nil
|
|
69
|
-
|
|
68
|
+
@adapter.store(key, new_entry(value, new_expires), options)
|
|
70
69
|
entry
|
|
71
70
|
else
|
|
72
71
|
entry
|
|
@@ -74,16 +73,14 @@ module Moneta
|
|
|
74
73
|
end
|
|
75
74
|
end
|
|
76
75
|
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
end
|
|
86
|
-
@adapter.store(key, entry, options)
|
|
76
|
+
def new_entry(value, expires)
|
|
77
|
+
if expires
|
|
78
|
+
[value, expires.to_i]
|
|
79
|
+
elsif Array === value || value == nil
|
|
80
|
+
[value]
|
|
81
|
+
else
|
|
82
|
+
value
|
|
83
|
+
end
|
|
87
84
|
end
|
|
88
85
|
end
|
|
89
86
|
end
|
data/lib/moneta/lock.rb
CHANGED
|
@@ -6,10 +6,10 @@ module Moneta
|
|
|
6
6
|
class Lock < Wrapper
|
|
7
7
|
# @param [Moneta store] adapter The underlying store
|
|
8
8
|
# @param [Hash] options
|
|
9
|
-
# @option options [String] :mutex (Mutex.new) Mutex object
|
|
9
|
+
# @option options [String] :mutex (::Mutex.new) Mutex object
|
|
10
10
|
def initialize(adapter, options = {})
|
|
11
11
|
super
|
|
12
|
-
@lock = options[:mutex] || Mutex.new
|
|
12
|
+
@lock = options[:mutex] || ::Mutex.new
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
protected
|
data/lib/moneta/mixins.rb
CHANGED
|
@@ -24,7 +24,7 @@ module Moneta
|
|
|
24
24
|
def raw
|
|
25
25
|
@raw_store ||=
|
|
26
26
|
begin
|
|
27
|
-
store = with(:raw => true, :only => [:load, :store, :delete])
|
|
27
|
+
store = with(:raw => true, :only => [:load, :store, :create, :delete])
|
|
28
28
|
store.instance_variable_set(:@raw_store, store)
|
|
29
29
|
store
|
|
30
30
|
end
|
|
@@ -45,7 +45,7 @@ module Moneta
|
|
|
45
45
|
# @return [OptionMerger]
|
|
46
46
|
# @api public
|
|
47
47
|
def expires(expires)
|
|
48
|
-
with(:expires => expires, :only => [:store, :increment])
|
|
48
|
+
with(:expires => expires, :only => [:store, :create, :increment])
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
@@ -58,8 +58,8 @@ module Moneta
|
|
|
58
58
|
#
|
|
59
59
|
# @param [Object] key
|
|
60
60
|
# @param [Hash] options
|
|
61
|
-
# @option options [Integer] :expires Update expiration time (See
|
|
62
|
-
# @option options [String] :prefix Prefix key (See
|
|
61
|
+
# @option options [Integer] :expires Update expiration time (See {Expires})
|
|
62
|
+
# @option options [String] :prefix Prefix key (See {Transformer})
|
|
63
63
|
# @option options Other options as defined by the adapters or middleware
|
|
64
64
|
# @return [Boolean]
|
|
65
65
|
# @api public
|
|
@@ -149,6 +149,19 @@ module Moneta
|
|
|
149
149
|
def []=(key, value)
|
|
150
150
|
store(key, value)
|
|
151
151
|
end
|
|
152
|
+
|
|
153
|
+
# Atomically sets a key to value if it's not set.
|
|
154
|
+
#
|
|
155
|
+
# @note Not every Moneta store implements this method,
|
|
156
|
+
# a NotImplementedError is raised if it is not supported.
|
|
157
|
+
# @param [Object] key
|
|
158
|
+
# @param [Object] value
|
|
159
|
+
# @param [Hash] options
|
|
160
|
+
# @return [Boolean] key was set
|
|
161
|
+
# @api public
|
|
162
|
+
def create(key, value, options = {})
|
|
163
|
+
raise NotImplementedError, 'create is not supported'
|
|
164
|
+
end
|
|
152
165
|
end
|
|
153
166
|
|
|
154
167
|
# @api private
|
|
@@ -156,17 +169,26 @@ module Moneta
|
|
|
156
169
|
# (see Defaults#increment)
|
|
157
170
|
# @api public
|
|
158
171
|
def increment(key, amount = 1, options = {})
|
|
159
|
-
value =
|
|
172
|
+
value = Utils.to_int(load(key, options)) + amount
|
|
160
173
|
store(key, value.to_s, options)
|
|
161
174
|
value
|
|
162
175
|
end
|
|
176
|
+
end
|
|
163
177
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
178
|
+
# Implements simple create using key? and store.
|
|
179
|
+
#
|
|
180
|
+
# This is sufficient for non-shared stores or if atomicity is not required.
|
|
181
|
+
# @api private
|
|
182
|
+
module CreateSupport
|
|
183
|
+
# (see Default#create)
|
|
184
|
+
# @api public
|
|
185
|
+
def create(key, value, options = {})
|
|
186
|
+
if key? key
|
|
187
|
+
false
|
|
188
|
+
else
|
|
189
|
+
store(key, value, options)
|
|
190
|
+
true
|
|
191
|
+
end
|
|
170
192
|
end
|
|
171
193
|
end
|
|
172
194
|
|
data/lib/moneta/optionmerger.rb
CHANGED
data/lib/moneta/proxy.rb
CHANGED
|
@@ -22,6 +22,11 @@ module Moneta
|
|
|
22
22
|
adapter.increment(key, amount, options)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# (see Defaults#create)
|
|
26
|
+
def create(key, value, options = {})
|
|
27
|
+
adapter.create(key, value, options)
|
|
28
|
+
end
|
|
29
|
+
|
|
25
30
|
# (see Defaults#close)
|
|
26
31
|
def close
|
|
27
32
|
adapter.close
|
|
@@ -31,9 +36,9 @@ module Moneta
|
|
|
31
36
|
#
|
|
32
37
|
# @param [Object] key
|
|
33
38
|
# @param [Hash] options
|
|
34
|
-
# @option options [Integer] :expires Update expiration time (See
|
|
35
|
-
# @option options [Boolean] :raw Raw access without value transformation (See
|
|
36
|
-
# @option options [String] :prefix Prefix key (See
|
|
39
|
+
# @option options [Integer] :expires Update expiration time (See {Expires})
|
|
40
|
+
# @option options [Boolean] :raw Raw access without value transformation (See {Transformer})
|
|
41
|
+
# @option options [String] :prefix Prefix key (See {Transformer})
|
|
37
42
|
# @option options Other options as defined by the adapters or middleware
|
|
38
43
|
# @return [Object] value
|
|
39
44
|
# @api public
|
|
@@ -46,9 +51,9 @@ module Moneta
|
|
|
46
51
|
# @param [Object] key
|
|
47
52
|
# @param [Object] value
|
|
48
53
|
# @param [Hash] options
|
|
49
|
-
# @option options [Integer] :expires Set expiration time (See
|
|
50
|
-
# @option options [Boolean] :raw Raw access without value transformation (See
|
|
51
|
-
# @option options [String] :prefix Prefix key (See
|
|
54
|
+
# @option options [Integer] :expires Set expiration time (See {Expires})
|
|
55
|
+
# @option options [Boolean] :raw Raw access without value transformation (See {Transformer})
|
|
56
|
+
# @option options [String] :prefix Prefix key (See {Transformer})
|
|
52
57
|
# @option options Other options as defined by the adapters or middleware
|
|
53
58
|
# @return value
|
|
54
59
|
# @api public
|
|
@@ -61,8 +66,8 @@ module Moneta
|
|
|
61
66
|
# @param [Object] key
|
|
62
67
|
# @return [Object] current value
|
|
63
68
|
# @param [Hash] options
|
|
64
|
-
# @option options [Boolean] :raw Raw access without value transformation (See
|
|
65
|
-
# @option options [String] :prefix Prefix key (See
|
|
69
|
+
# @option options [Boolean] :raw Raw access without value transformation (See {Transformer})
|
|
70
|
+
# @option options [String] :prefix Prefix key (See {Transformer})
|
|
66
71
|
# @option options Other options as defined by the adapters or middleware
|
|
67
72
|
# @api public
|
|
68
73
|
def delete(key, options = {})
|
data/lib/moneta/server.rb
CHANGED
|
@@ -6,12 +6,12 @@ module Moneta
|
|
|
6
6
|
class Server
|
|
7
7
|
# @param [Hash] options
|
|
8
8
|
# @option options [Integer] :port (9000) TCP port
|
|
9
|
-
# @option options [String] :
|
|
9
|
+
# @option options [String] :socket Alternative Unix socket file name
|
|
10
10
|
def initialize(store, options = {})
|
|
11
11
|
@store = store
|
|
12
12
|
@server =
|
|
13
|
-
if @
|
|
14
|
-
UNIXServer.open(@
|
|
13
|
+
if @socket = options[:socket]
|
|
14
|
+
UNIXServer.open(@socket)
|
|
15
15
|
else
|
|
16
16
|
TCPServer.open(options[:port] || DEFAULT_PORT)
|
|
17
17
|
end
|
|
@@ -38,7 +38,7 @@ module Moneta
|
|
|
38
38
|
mainloop
|
|
39
39
|
end
|
|
40
40
|
ensure
|
|
41
|
-
File.unlink(@
|
|
41
|
+
File.unlink(@socket) if @socket
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
@@ -58,8 +58,15 @@ module Moneta
|
|
|
58
58
|
def mainloop
|
|
59
59
|
client = accept
|
|
60
60
|
handle(client) if client
|
|
61
|
+
rescue SignalException => ex
|
|
62
|
+
warn "Moneta::Server - #{ex.message}"
|
|
63
|
+
raise if ex.signo == 15 # SIGTERM
|
|
64
|
+
rescue IOError => ex
|
|
65
|
+
warn "Moneta::Server - #{ex.message}" unless ex.message =~ /closed/
|
|
66
|
+
@clients.delete(client) if client
|
|
67
|
+
@clients.reject!(&:closed?)
|
|
61
68
|
rescue Exception => ex
|
|
62
|
-
warn ex.message
|
|
69
|
+
warn "Moneta::Server - #{ex.message}"
|
|
63
70
|
write(client, Error.new(ex.message)) if client
|
|
64
71
|
end
|
|
65
72
|
|
|
@@ -85,7 +92,7 @@ module Moneta
|
|
|
85
92
|
def handle(client)
|
|
86
93
|
method, *args = read(client)
|
|
87
94
|
case method
|
|
88
|
-
when :key?, :load, :delete, :increment
|
|
95
|
+
when :key?, :load, :delete, :increment, :create
|
|
89
96
|
write(client, @store.send(method, *args))
|
|
90
97
|
when :store, :clear
|
|
91
98
|
@store.send(method, *args)
|
data/lib/moneta/shared.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Moneta
|
|
|
14
14
|
# @param [Hash] options
|
|
15
15
|
# @option options [Integer] :port (9000) TCP port
|
|
16
16
|
# @option options [String] :host Server hostname
|
|
17
|
-
# @option options [String] :
|
|
17
|
+
# @option options [String] :socket Unix socket file name
|
|
18
18
|
def initialize(options = {}, &block)
|
|
19
19
|
@options = options
|
|
20
20
|
@builder = Builder.new(&block)
|
|
@@ -38,8 +38,9 @@ module Moneta
|
|
|
38
38
|
def wrap(*args)
|
|
39
39
|
@adapter ||= Adapters::Client.new(@options)
|
|
40
40
|
yield
|
|
41
|
-
rescue
|
|
42
|
-
|
|
41
|
+
rescue Errno::ECONNREFUSED, Errno::ENOENT => ex
|
|
42
|
+
tries ||= 0
|
|
43
|
+
warn "Moneta::Shared - Failed to connect: #{ex.message}" if tries > 0
|
|
43
44
|
begin
|
|
44
45
|
# TODO: Implement this using forking (MRI) and threading (JRuby)
|
|
45
46
|
# to get maximal performance
|
|
@@ -48,16 +49,11 @@ module Moneta
|
|
|
48
49
|
@thread = Thread.new { @server.run }
|
|
49
50
|
sleep 0.1 until @server.running?
|
|
50
51
|
rescue Exception => ex
|
|
51
|
-
warn "Failed to start server: #{ex.message}"
|
|
52
|
+
warn "Moneta::Shared - Failed to start server: #{ex.message}"
|
|
52
53
|
@adapter.close if @adapter
|
|
53
54
|
@adapter = nil
|
|
54
55
|
end
|
|
55
|
-
tries
|
|
56
|
-
if (tries += 1) > 2
|
|
57
|
-
raise
|
|
58
|
-
else
|
|
59
|
-
retry
|
|
60
|
-
end
|
|
56
|
+
(tries += 1) < 3 ? retry : raise
|
|
61
57
|
end
|
|
62
58
|
end
|
|
63
59
|
end
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module Moneta
|
|
2
|
+
# Base class for {Mutex} and {Semaphore}
|
|
3
|
+
# @api private
|
|
4
|
+
class SynchronizePrimitive
|
|
5
|
+
# Synchronize block
|
|
6
|
+
#
|
|
7
|
+
# @api public
|
|
8
|
+
# @yieldparam Synchronized block
|
|
9
|
+
# @return [Object] result of block
|
|
10
|
+
def synchronize
|
|
11
|
+
enter
|
|
12
|
+
yield
|
|
13
|
+
ensure
|
|
14
|
+
leave
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Try to enter critical section (nonblocking)
|
|
18
|
+
#
|
|
19
|
+
# @api public
|
|
20
|
+
# @return [Boolean] true if the lock was acquired
|
|
21
|
+
def try_enter
|
|
22
|
+
raise 'Already locked' if @locked
|
|
23
|
+
enter_primitive ? @locked = true : false
|
|
24
|
+
end
|
|
25
|
+
alias_method :try_lock, :try_enter
|
|
26
|
+
|
|
27
|
+
# Enter critical section (blocking)
|
|
28
|
+
#
|
|
29
|
+
# @api public
|
|
30
|
+
# @param [Number] timeout Maximum time to wait
|
|
31
|
+
# @param [Number] wait Sleep time between tries to acquire lock
|
|
32
|
+
# @return [Boolean] true if the lock was aquired
|
|
33
|
+
def enter(timeout = nil, wait = 0.01)
|
|
34
|
+
total = 0
|
|
35
|
+
while !timeout || total < timeout
|
|
36
|
+
return true if try_enter
|
|
37
|
+
sleep(wait)
|
|
38
|
+
total += wait
|
|
39
|
+
end
|
|
40
|
+
false
|
|
41
|
+
end
|
|
42
|
+
alias_method :lock, :enter
|
|
43
|
+
|
|
44
|
+
# Leave critical section
|
|
45
|
+
#
|
|
46
|
+
# @api public
|
|
47
|
+
def leave
|
|
48
|
+
raise 'Not locked' unless @locked
|
|
49
|
+
leave_primitive
|
|
50
|
+
@locked = false
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
alias_method :unlock, :leave
|
|
54
|
+
|
|
55
|
+
# Is the lock acquired?
|
|
56
|
+
#
|
|
57
|
+
# @api public
|
|
58
|
+
def locked?
|
|
59
|
+
@locked
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Distributed/shared store-wide mutex
|
|
64
|
+
#
|
|
65
|
+
# @example Use `Moneta::Mutex`
|
|
66
|
+
# mutex = Moneta::Mutex.new(store, 'mutex')
|
|
67
|
+
# mutex.synchronize do
|
|
68
|
+
# # Synchronized access
|
|
69
|
+
# store['counter'] += 1
|
|
70
|
+
# end
|
|
71
|
+
#
|
|
72
|
+
# @api public
|
|
73
|
+
class Mutex < SynchronizePrimitive
|
|
74
|
+
# @param [Moneta store] store The store we want to lock
|
|
75
|
+
# @param [Object] lock Key of the lock entry
|
|
76
|
+
def initialize(store, lock)
|
|
77
|
+
@store, @lock = store, lock
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
protected
|
|
81
|
+
|
|
82
|
+
def enter_primitive
|
|
83
|
+
@store.create(@lock, '', :expires => false)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def leave_primitive
|
|
87
|
+
@store.delete(@lock)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Distributed/shared store-wide semaphore
|
|
92
|
+
#
|
|
93
|
+
# @example Use `Moneta::Semaphore`
|
|
94
|
+
# semaphore = Moneta::Semaphore.new(store, 'semaphore', 2)
|
|
95
|
+
# semaphore.synchronize do
|
|
96
|
+
# # Synchronized access
|
|
97
|
+
# ...
|
|
98
|
+
# end
|
|
99
|
+
#
|
|
100
|
+
# @api public
|
|
101
|
+
class Semaphore < SynchronizePrimitive
|
|
102
|
+
# @param [Moneta store] store The store we want to lock
|
|
103
|
+
# @param [Object] counter Key of the counter entry
|
|
104
|
+
# @param [Fixnum] max Maximum number of threads which are allowed to enter the critical section
|
|
105
|
+
def initialize(store, counter, max = 1)
|
|
106
|
+
@store, @counter, @max = store, counter, max
|
|
107
|
+
@store.increment(@counter, 0, :expires => false) # Ensure that counter exists
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
protected
|
|
111
|
+
|
|
112
|
+
def enter_primitive
|
|
113
|
+
if @store.increment(@counter, 1) <= @max
|
|
114
|
+
true
|
|
115
|
+
else
|
|
116
|
+
@store.decrement(@counter)
|
|
117
|
+
false
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def leave_primitive
|
|
122
|
+
@store.decrement(@counter)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|