moneta 0.6.0 → 0.7.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.
- data/.gitignore +7 -0
- data/.travis.yml +39 -0
- data/Gemfile +61 -0
- data/LICENSE +2 -2
- data/README.md +450 -0
- data/Rakefile +29 -51
- data/SPEC.md +75 -0
- data/benchmarks/run.rb +195 -0
- data/lib/action_dispatch/middleware/session/moneta_store.rb +11 -0
- data/lib/active_support/cache/moneta_store.rb +55 -0
- data/lib/moneta.rb +121 -67
- data/lib/moneta/adapters/activerecord.rb +87 -0
- data/lib/moneta/adapters/cassandra.rb +91 -0
- data/lib/moneta/adapters/client.rb +69 -0
- data/lib/moneta/adapters/cookie.rb +35 -0
- data/lib/moneta/adapters/couch.rb +57 -0
- data/lib/moneta/adapters/datamapper.rb +75 -0
- data/lib/moneta/adapters/dbm.rb +25 -0
- data/lib/moneta/adapters/file.rb +79 -0
- data/lib/moneta/adapters/fog.rb +51 -0
- data/lib/moneta/adapters/gdbm.rb +25 -0
- data/lib/moneta/adapters/hbase.rb +101 -0
- data/lib/moneta/adapters/leveldb.rb +35 -0
- data/lib/moneta/adapters/localmemcache.rb +28 -0
- data/lib/moneta/adapters/lruhash.rb +85 -0
- data/lib/moneta/adapters/memcached.rb +11 -0
- data/lib/moneta/adapters/memcached_dalli.rb +69 -0
- data/lib/moneta/adapters/memcached_native.rb +70 -0
- data/lib/moneta/adapters/memory.rb +10 -0
- data/lib/moneta/adapters/mongo.rb +50 -0
- data/lib/moneta/adapters/null.rb +30 -0
- data/lib/moneta/adapters/pstore.rb +69 -0
- data/lib/moneta/adapters/redis.rb +68 -0
- data/lib/moneta/adapters/riak.rb +57 -0
- data/lib/moneta/adapters/sdbm.rb +35 -0
- data/lib/moneta/adapters/sequel.rb +79 -0
- data/lib/moneta/adapters/sqlite.rb +65 -0
- data/lib/moneta/adapters/tokyocabinet.rb +41 -0
- data/lib/moneta/adapters/yaml.rb +15 -0
- data/lib/moneta/base.rb +78 -0
- data/lib/moneta/builder.rb +39 -0
- data/lib/moneta/cache.rb +84 -0
- data/lib/moneta/expires.rb +71 -0
- data/lib/moneta/lock.rb +25 -0
- data/lib/moneta/logger.rb +61 -0
- data/lib/moneta/mixins.rb +65 -0
- data/lib/moneta/net.rb +18 -0
- data/lib/moneta/optionmerger.rb +39 -0
- data/lib/moneta/proxy.rb +86 -0
- data/lib/moneta/server.rb +81 -0
- data/lib/moneta/shared.rb +60 -0
- data/lib/moneta/stack.rb +78 -0
- data/lib/moneta/transformer.rb +159 -0
- data/lib/moneta/transformer/config.rb +42 -0
- data/lib/moneta/transformer/helper.rb +37 -0
- data/lib/moneta/version.rb +5 -0
- data/lib/moneta/wrapper.rb +33 -0
- data/lib/rack/cache/moneta.rb +93 -0
- data/lib/rack/moneta_cookies.rb +64 -0
- data/lib/rack/session/moneta.rb +63 -0
- data/moneta.gemspec +19 -0
- data/spec/action_dispatch/fixtures/session_autoload_test/foo.rb +10 -0
- data/spec/action_dispatch/session_moneta_store_spec.rb +196 -0
- data/spec/active_support/cache_moneta_store_spec.rb +197 -0
- data/spec/generate.rb +1489 -0
- data/spec/helper.rb +91 -0
- data/spec/moneta/adapter_activerecord_spec.rb +32 -0
- data/spec/moneta/adapter_cassandra_spec.rb +30 -0
- data/spec/moneta/adapter_client_spec.rb +19 -0
- data/spec/moneta/adapter_cookie_spec.rb +18 -0
- data/spec/moneta/adapter_couch_spec.rb +18 -0
- data/spec/moneta/adapter_datamapper_spec.rb +49 -0
- data/spec/moneta/adapter_dbm_spec.rb +18 -0
- data/spec/moneta/adapter_file_spec.rb +18 -0
- data/spec/moneta/adapter_fog_spec.rb +23 -0
- data/spec/moneta/adapter_gdbm_spec.rb +18 -0
- data/spec/moneta/adapter_hbase_spec.rb +18 -0
- data/spec/moneta/adapter_leveldb_spec.rb +18 -0
- data/spec/moneta/adapter_localmemcache_spec.rb +18 -0
- data/spec/moneta/adapter_lruhash_spec.rb +31 -0
- data/spec/moneta/adapter_memcached_dalli_spec.rb +30 -0
- data/spec/moneta/adapter_memcached_native_spec.rb +31 -0
- data/spec/moneta/adapter_memcached_spec.rb +30 -0
- data/spec/moneta/adapter_memory_spec.rb +39 -0
- data/spec/moneta/adapter_mongo_spec.rb +18 -0
- data/spec/moneta/adapter_pstore_spec.rb +21 -0
- data/spec/moneta/adapter_redis_spec.rb +30 -0
- data/spec/moneta/adapter_riak_spec.rb +22 -0
- data/spec/moneta/adapter_sdbm_spec.rb +18 -0
- data/spec/moneta/adapter_sequel_spec.rb +18 -0
- data/spec/moneta/adapter_sqlite_spec.rb +18 -0
- data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +18 -0
- data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +18 -0
- data/spec/moneta/adapter_yaml_spec.rb +21 -0
- data/spec/moneta/cache_file_memory_spec.rb +34 -0
- data/spec/moneta/cache_memory_null_spec.rb +23 -0
- data/spec/moneta/expires_file_spec.rb +76 -0
- data/spec/moneta/expires_memory_spec.rb +65 -0
- data/spec/moneta/lock_spec.rb +42 -0
- data/spec/moneta/null_adapter_spec.rb +26 -0
- data/spec/moneta/optionmerger_spec.rb +92 -0
- data/spec/moneta/proxy_expires_memory_spec.rb +55 -0
- data/spec/moneta/proxy_redis_spec.rb +23 -0
- data/spec/moneta/shared_spec.rb +30 -0
- data/spec/moneta/simple_activerecord_spec.rb +51 -0
- data/spec/moneta/simple_activerecord_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_cassandra_spec.rb +52 -0
- data/spec/moneta/simple_client_tcp_spec.rb +67 -0
- data/spec/moneta/simple_client_unix_spec.rb +53 -0
- data/spec/moneta/simple_couch_spec.rb +51 -0
- data/spec/moneta/simple_couch_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_datamapper_spec.rb +53 -0
- data/spec/moneta/simple_datamapper_with_expires_spec.rb +54 -0
- data/spec/moneta/simple_datamapper_with_repository_spec.rb +53 -0
- data/spec/moneta/simple_dbm_spec.rb +51 -0
- data/spec/moneta/simple_dbm_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_file_spec.rb +51 -0
- data/spec/moneta/simple_file_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_fog_spec.rb +56 -0
- data/spec/moneta/simple_fog_with_expires_spec.rb +58 -0
- data/spec/moneta/simple_gdbm_spec.rb +51 -0
- data/spec/moneta/simple_gdbm_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_hashfile_spec.rb +51 -0
- data/spec/moneta/simple_hashfile_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_hbase_spec.rb +51 -0
- data/spec/moneta/simple_hbase_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_leveldb_spec.rb +51 -0
- data/spec/moneta/simple_leveldb_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_localmemcache_spec.rb +51 -0
- data/spec/moneta/simple_localmemcache_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_lruhash_spec.rb +51 -0
- data/spec/moneta/simple_lruhash_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_memcached_dalli_spec.rb +52 -0
- data/spec/moneta/simple_memcached_native_spec.rb +52 -0
- data/spec/moneta/simple_memcached_spec.rb +52 -0
- data/spec/moneta/simple_memory_spec.rb +51 -0
- data/spec/moneta/simple_memory_with_compress_spec.rb +51 -0
- data/spec/moneta/simple_memory_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +37 -0
- data/spec/moneta/simple_memory_with_json_serializer_spec.rb +28 -0
- data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +35 -0
- data/spec/moneta/simple_memory_with_prefix_spec.rb +51 -0
- data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +51 -0
- data/spec/moneta/simple_mongo_spec.rb +51 -0
- data/spec/moneta/simple_mongo_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_null_spec.rb +36 -0
- data/spec/moneta/simple_pstore_spec.rb +51 -0
- data/spec/moneta/simple_pstore_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_redis_spec.rb +52 -0
- data/spec/moneta/simple_riak_spec.rb +55 -0
- data/spec/moneta/simple_riak_with_expires_spec.rb +56 -0
- data/spec/moneta/simple_sdbm_spec.rb +51 -0
- data/spec/moneta/simple_sdbm_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_sequel_spec.rb +51 -0
- data/spec/moneta/simple_sequel_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_sqlite_spec.rb +51 -0
- data/spec/moneta/simple_sqlite_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_tokyocabinet_spec.rb +51 -0
- data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +52 -0
- data/spec/moneta/simple_yaml_spec.rb +50 -0
- data/spec/moneta/simple_yaml_with_expires_spec.rb +51 -0
- data/spec/moneta/stack_file_memory_spec.rb +25 -0
- data/spec/moneta/stack_memory_file_spec.rb +24 -0
- data/spec/moneta/transformer_bencode_spec.rb +30 -0
- data/spec/moneta/transformer_bert_spec.rb +30 -0
- data/spec/moneta/transformer_bson_spec.rb +30 -0
- data/spec/moneta/transformer_bzip2_spec.rb +27 -0
- data/spec/moneta/transformer_json_spec.rb +30 -0
- data/spec/moneta/transformer_lzma_spec.rb +27 -0
- data/spec/moneta/transformer_lzo_spec.rb +27 -0
- data/spec/moneta/transformer_marshal_base64_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_escape_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_hmac_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_md5_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_md5_spread_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_prefix_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_rmd160_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha1_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha256_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha384_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_sha512_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_truncate_spec.rb +54 -0
- data/spec/moneta/transformer_marshal_uuencode_spec.rb +54 -0
- data/spec/moneta/transformer_msgpack_spec.rb +30 -0
- data/spec/moneta/transformer_ox_spec.rb +51 -0
- data/spec/moneta/transformer_quicklz_spec.rb +27 -0
- data/spec/moneta/transformer_snappy_spec.rb +27 -0
- data/spec/moneta/transformer_tnet_spec.rb +30 -0
- data/spec/moneta/transformer_yaml_spec.rb +51 -0
- data/spec/moneta/transformer_zlib_spec.rb +27 -0
- data/spec/monetaspecs.rb +2663 -0
- data/spec/rack/cache_moneta_spec.rb +355 -0
- data/spec/rack/moneta_cookies_spec.rb +81 -0
- data/spec/rack/session_moneta_spec.rb +305 -0
- metadata +359 -56
- data/README +0 -51
- data/TODO +0 -4
- data/lib/moneta/basic_file.rb +0 -111
- data/lib/moneta/berkeley.rb +0 -53
- data/lib/moneta/couch.rb +0 -63
- data/lib/moneta/datamapper.rb +0 -117
- data/lib/moneta/file.rb +0 -91
- data/lib/moneta/lmc.rb +0 -52
- data/lib/moneta/memcache.rb +0 -52
- data/lib/moneta/memory.rb +0 -11
- data/lib/moneta/mongodb.rb +0 -58
- data/lib/moneta/redis.rb +0 -49
- data/lib/moneta/rufus.rb +0 -41
- data/lib/moneta/s3.rb +0 -162
- data/lib/moneta/sdbm.rb +0 -33
- data/lib/moneta/tyrant.rb +0 -58
- data/lib/moneta/xattr.rb +0 -58
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'fog'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# Fog backend (Cloud storage services)
|
|
6
|
+
# @api public
|
|
7
|
+
class Fog < Base
|
|
8
|
+
# Constructor
|
|
9
|
+
#
|
|
10
|
+
# @param [Hash] options
|
|
11
|
+
#
|
|
12
|
+
# Options:
|
|
13
|
+
# * :dir - Fog directory
|
|
14
|
+
# * Other options passed to Fog::Storage#new
|
|
15
|
+
def initialize(options = {})
|
|
16
|
+
raise ArgumentError, 'Option :dir is required' unless dir = options.delete(:dir)
|
|
17
|
+
storage = ::Fog::Storage.new(options)
|
|
18
|
+
@directory = storage.directories.create(:key => dir)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def key?(key, options = {})
|
|
22
|
+
@directory.files.head(key) != nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def load(key, options = {})
|
|
26
|
+
value = @directory.files.get(key)
|
|
27
|
+
value && value.body
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def delete(key, options = {})
|
|
31
|
+
if value = @directory.files.get(key)
|
|
32
|
+
body = value.body
|
|
33
|
+
value.destroy
|
|
34
|
+
body
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def store(key, value, options = {})
|
|
39
|
+
@directory.files.create(:key => key, :body => value)
|
|
40
|
+
value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def clear(options = {})
|
|
44
|
+
@directory.files.all.each do |file|
|
|
45
|
+
file.destroy
|
|
46
|
+
end
|
|
47
|
+
self
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'gdbm'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# GDBM backend
|
|
6
|
+
# @api public
|
|
7
|
+
class GDBM < Memory
|
|
8
|
+
# Constructor
|
|
9
|
+
#
|
|
10
|
+
# @param [Hash] options
|
|
11
|
+
#
|
|
12
|
+
# Options:
|
|
13
|
+
# * :file - Database file
|
|
14
|
+
def initialize(options = {})
|
|
15
|
+
raise ArgumentError, 'Option :file is required' unless options[:file]
|
|
16
|
+
@hash = ::GDBM.new(options[:file])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def close
|
|
20
|
+
@hash.close
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'hbaserb'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# HBase thrift backend
|
|
6
|
+
# @api public
|
|
7
|
+
class HBase < Base
|
|
8
|
+
# Constructor
|
|
9
|
+
#
|
|
10
|
+
# @param [Hash] options
|
|
11
|
+
#
|
|
12
|
+
# Options:
|
|
13
|
+
# * :host - Server host name (default 127.0.0.1)
|
|
14
|
+
# * :port - Server port (default 9090)
|
|
15
|
+
# * :table - Table name (default moneta)
|
|
16
|
+
# * :column_family - Column family (default moneta)
|
|
17
|
+
# * :column - Column (default value)
|
|
18
|
+
def initialize(options = {})
|
|
19
|
+
options[:host] ||= '127.0.0.1'
|
|
20
|
+
options[:port] ||= '9090'
|
|
21
|
+
options[:table] ||= 'moneta'
|
|
22
|
+
options[:column] ||= 'value'
|
|
23
|
+
cf = (options[:column_family] || 'moneta')
|
|
24
|
+
@db = HBaseRb::Client.new(options[:host], options[:port])
|
|
25
|
+
@db.create_table(options[:table], cf) unless @db.has_table?(options[:table])
|
|
26
|
+
@table = @db.get_table(options[:table])
|
|
27
|
+
@column = "#{cf}:#{options[:column]}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def key?(key, options = {})
|
|
31
|
+
@table.get(key, @column).first != nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def load(key, options = {})
|
|
35
|
+
cell = @table.get(key, @column).first
|
|
36
|
+
cell && unpack(cell.value)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def store(key, value, options = {})
|
|
40
|
+
@table.mutate_row(key, @column => pack(value))
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def increment(key, amount = 1, options = {})
|
|
45
|
+
result = @table.atomic_increment(key, @column, amount)
|
|
46
|
+
# HACK: Throw error if applied to invalid value
|
|
47
|
+
if result == 0
|
|
48
|
+
value = load(key)
|
|
49
|
+
raise 'Tried to increment non integer value' unless value.to_s == value.to_i.to_s
|
|
50
|
+
end
|
|
51
|
+
result
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def delete(key, options = {})
|
|
55
|
+
if value = load(key, options)
|
|
56
|
+
@table.delete_row(key)
|
|
57
|
+
unpack(value)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def clear(options = {})
|
|
62
|
+
@table.create_scanner do |row|
|
|
63
|
+
@table.delete_row(row.row)
|
|
64
|
+
end
|
|
65
|
+
self
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def close
|
|
69
|
+
@db.close
|
|
70
|
+
nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def pack(value)
|
|
76
|
+
intvalue = value.to_i
|
|
77
|
+
if intvalue >= 0 && intvalue <= 0xFFFFFFFFFFFFFFFF && intvalue.to_s == value
|
|
78
|
+
# Pack as 8 byte big endian
|
|
79
|
+
[intvalue].pack('Q>')
|
|
80
|
+
elsif value.bytesize >= 8
|
|
81
|
+
# Add nul character to make value distinguishable from integer
|
|
82
|
+
value << "\0"
|
|
83
|
+
else
|
|
84
|
+
value
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def unpack(value)
|
|
89
|
+
if value.bytesize == 8
|
|
90
|
+
# Unpack 8 byte big endian
|
|
91
|
+
value.unpack('Q>').first.to_s
|
|
92
|
+
elsif value.bytesize >= 9 && value[-1] == ?\0
|
|
93
|
+
# Remove nul character
|
|
94
|
+
value[0..-2]
|
|
95
|
+
else
|
|
96
|
+
value
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'leveldb'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# LevelDB backend
|
|
6
|
+
# @api public
|
|
7
|
+
class LevelDB < Memory
|
|
8
|
+
# Constructor
|
|
9
|
+
#
|
|
10
|
+
# @param [Hash] options
|
|
11
|
+
#
|
|
12
|
+
# Options:
|
|
13
|
+
# * :dir - Database path
|
|
14
|
+
# * All other options passed to LevelDB::DB#new
|
|
15
|
+
def initialize(options = {})
|
|
16
|
+
raise ArgumentError, 'Option :dir is required' unless options[:dir]
|
|
17
|
+
@hash = ::LevelDB::DB.new(options[:dir])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def key?(key, options = {})
|
|
21
|
+
@hash.includes?(key)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def clear(options = {})
|
|
25
|
+
@hash.each {|k,v| delete(k, options) }
|
|
26
|
+
self
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def close
|
|
30
|
+
@hash.close
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'localmemcache'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# LocalMemCache backend
|
|
6
|
+
# @api public
|
|
7
|
+
class LocalMemCache < Base
|
|
8
|
+
include Mixins::HashAdapter
|
|
9
|
+
|
|
10
|
+
# Constructor
|
|
11
|
+
#
|
|
12
|
+
# @param [Hash] options
|
|
13
|
+
#
|
|
14
|
+
# Options:
|
|
15
|
+
# * :file - Database file
|
|
16
|
+
def initialize(options = {})
|
|
17
|
+
raise ArgumentError, 'Option :file is required' unless options[:file]
|
|
18
|
+
@hash = ::LocalMemCache.new(:filename => options[:file])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def delete(key, options = {})
|
|
22
|
+
value = load(key, options)
|
|
23
|
+
@hash.delete(key)
|
|
24
|
+
value
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Moneta
|
|
2
|
+
module Adapters
|
|
3
|
+
# LRUHash backend
|
|
4
|
+
#
|
|
5
|
+
# Based on Hashery::LRUHash but simpler and measures memory usage instead of hash size.
|
|
6
|
+
#
|
|
7
|
+
# @api public
|
|
8
|
+
class LRUHash < Base
|
|
9
|
+
include Mixins::IncrementSupport
|
|
10
|
+
|
|
11
|
+
# Constructor
|
|
12
|
+
#
|
|
13
|
+
# @param [Hash] options
|
|
14
|
+
#
|
|
15
|
+
# Options:
|
|
16
|
+
# * :max_size - Maximum byte size of hash values (default 1024000)
|
|
17
|
+
def initialize(options = {})
|
|
18
|
+
@max_size = options[:max_size] || 1024000
|
|
19
|
+
clear
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def key?(key, options = {})
|
|
23
|
+
@entry.key?(key)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def load(key, options = {})
|
|
27
|
+
if entry = @entry[key]
|
|
28
|
+
entry.insert_after(@list)
|
|
29
|
+
entry.value
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def store(key, value, options = {})
|
|
34
|
+
if entry = @entry[key]
|
|
35
|
+
@size -= entry.value.bytesize
|
|
36
|
+
else
|
|
37
|
+
@entry[key] = entry = Entry.new
|
|
38
|
+
entry.key = key
|
|
39
|
+
end
|
|
40
|
+
entry.value = value
|
|
41
|
+
@size += entry.value.bytesize
|
|
42
|
+
entry.insert_after(@list)
|
|
43
|
+
delete(@list.prev.key) while @list.next != @list.prev && @size > @max_size
|
|
44
|
+
value
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def delete(key, options = {})
|
|
48
|
+
if entry = @entry.delete(key)
|
|
49
|
+
@size -= entry.value.bytesize
|
|
50
|
+
entry.unlink
|
|
51
|
+
entry.value
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def clear(options = {})
|
|
56
|
+
@entry, @size = {}, 0
|
|
57
|
+
@list = Entry.new
|
|
58
|
+
@list.prev = @list.next = @list
|
|
59
|
+
self
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
class Entry
|
|
65
|
+
attr_accessor :key, :value, :prev, :next
|
|
66
|
+
|
|
67
|
+
def unlink
|
|
68
|
+
@prev.next = @next if @prev
|
|
69
|
+
@next.prev = @prev if @next
|
|
70
|
+
@prev = @next = nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def insert_after(entry)
|
|
74
|
+
if entry.next != self
|
|
75
|
+
unlink
|
|
76
|
+
@next = entry.next
|
|
77
|
+
@prev = entry
|
|
78
|
+
entry.next.prev = self
|
|
79
|
+
entry.next = self
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require 'dalli'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# Memcached backend (using gem dalli)
|
|
6
|
+
# @api public
|
|
7
|
+
class MemcachedDalli < Base
|
|
8
|
+
# Constructor
|
|
9
|
+
#
|
|
10
|
+
# @param [Hash] options
|
|
11
|
+
#
|
|
12
|
+
# Options:
|
|
13
|
+
# * :server - Memcached server (default localhost:11211)
|
|
14
|
+
# * :expires - Default expiration time (default none)
|
|
15
|
+
# * Other options passed to Dalli::Client#new
|
|
16
|
+
def initialize(options = {})
|
|
17
|
+
options[:expires_in] = options.delete(:expires)
|
|
18
|
+
server = options.delete(:server) || 'localhost:11211'
|
|
19
|
+
@cache = ::Dalli::Client.new(server, options)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def load(key, options = {})
|
|
23
|
+
value = @cache.get(key)
|
|
24
|
+
if value && options.include?(:expires)
|
|
25
|
+
store(key, value, options)
|
|
26
|
+
else
|
|
27
|
+
value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def store(key, value, options = {})
|
|
32
|
+
@cache.set(key, value, options[:expires], :raw => true)
|
|
33
|
+
value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def delete(key, options = {})
|
|
37
|
+
value = @cache.get(key)
|
|
38
|
+
@cache.delete(key)
|
|
39
|
+
value
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def increment(key, amount = 1, options = {})
|
|
43
|
+
# FIXME: There is a Dalli bug, load(key) returns a wrong value after increment
|
|
44
|
+
# therefore we set default = nil and create the counter manually
|
|
45
|
+
result = if amount >= 0
|
|
46
|
+
@cache.incr(key, amount, options[:expires], nil)
|
|
47
|
+
else
|
|
48
|
+
@cache.decr(key, -amount, options[:expires], nil)
|
|
49
|
+
end
|
|
50
|
+
if result
|
|
51
|
+
result
|
|
52
|
+
else
|
|
53
|
+
store(key, amount, options)
|
|
54
|
+
amount
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def clear(options = {})
|
|
59
|
+
@cache.flush_all
|
|
60
|
+
self
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def close
|
|
64
|
+
@cache.close
|
|
65
|
+
nil
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require 'memcached'
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
module Adapters
|
|
5
|
+
# Memcached backend (using gem memcached)
|
|
6
|
+
# @api public
|
|
7
|
+
class MemcachedNative < Base
|
|
8
|
+
# Constructor
|
|
9
|
+
#
|
|
10
|
+
# @param [Hash] options
|
|
11
|
+
#
|
|
12
|
+
# Options:
|
|
13
|
+
# * :server - Memcached server (default localhost:11211)
|
|
14
|
+
# * :namespace - Key namespace
|
|
15
|
+
# * :expires - Default expiration time (default 604800)
|
|
16
|
+
# * Other options passed to Memcached#new
|
|
17
|
+
def initialize(options = {})
|
|
18
|
+
server = options.delete(:server) || 'localhost:11211'
|
|
19
|
+
@expires = options.delete(:expires) || 604800
|
|
20
|
+
options.merge!(:prefix_key => options.delete(:namespace)) if options[:namespace]
|
|
21
|
+
@cache = ::Memcached.new(server, options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def load(key, options = {})
|
|
25
|
+
value = @cache.get(key, false)
|
|
26
|
+
if value && options.include?(:expires)
|
|
27
|
+
store(key, value, options)
|
|
28
|
+
else
|
|
29
|
+
value
|
|
30
|
+
end
|
|
31
|
+
rescue ::Memcached::NotFound
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def store(key, value, options = {})
|
|
35
|
+
# TTL must be Fixnum
|
|
36
|
+
@cache.set(key, value, options[:expires] || @expires, false)
|
|
37
|
+
value
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def delete(key, options = {})
|
|
41
|
+
value = @cache.get(key, false)
|
|
42
|
+
@cache.delete(key)
|
|
43
|
+
value
|
|
44
|
+
rescue ::Memcached::NotFound
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def increment(key, amount = 1, options = {})
|
|
48
|
+
result = if amount >= 0
|
|
49
|
+
@cache.increment(key, amount)
|
|
50
|
+
else
|
|
51
|
+
@cache.decrement(key, -amount)
|
|
52
|
+
end
|
|
53
|
+
# HACK: Throw error if applied to invalid value
|
|
54
|
+
if result == 0
|
|
55
|
+
value = @cache.get(key, false) rescue nil
|
|
56
|
+
raise 'Tried to increment non integer value' unless value.to_s == value.to_i.to_s
|
|
57
|
+
end
|
|
58
|
+
result
|
|
59
|
+
rescue ::Memcached::NotFound => ex
|
|
60
|
+
store(key, amount.to_s, options)
|
|
61
|
+
amount
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def clear(options = {})
|
|
65
|
+
@cache.flush
|
|
66
|
+
self
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|