benschwarz-moneta 0.6.0 → 0.6.1
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/Rakefile +1 -1
- data/lib/moneta/basic_file.rb +111 -0
- data/lib/moneta/berkeley.rb +53 -0
- data/lib/moneta/couch.rb +63 -0
- data/lib/moneta/lmc.rb +52 -0
- data/lib/moneta/mongodb.rb +58 -0
- data/lib/moneta/redis.rb +49 -0
- data/lib/moneta/rufus.rb +41 -0
- data/lib/moneta/s3.rb +162 -0
- data/lib/moneta/sdbm.rb +33 -0
- data/lib/moneta/tyrant.rb +58 -0
- metadata +14 -4
data/Rakefile
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Basic File Store
|
|
3
|
+
# by Hampton Catlin
|
|
4
|
+
#
|
|
5
|
+
# This cache simply uses a directory that it creates
|
|
6
|
+
# and manages to keep your file stores.
|
|
7
|
+
#
|
|
8
|
+
# Specify :skip_expires => true if you aren't using
|
|
9
|
+
# expiration as this will slightly decrease your file size
|
|
10
|
+
# and memory footprint of the library
|
|
11
|
+
#
|
|
12
|
+
# You can optionally also specify a :namespace
|
|
13
|
+
# option that will create a subfolder.
|
|
14
|
+
#
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
require 'fileutils'
|
|
18
|
+
require File.join(File.dirname(__FILE__), "..", "moneta.rb")
|
|
19
|
+
|
|
20
|
+
module Moneta
|
|
21
|
+
class BasicFile
|
|
22
|
+
include Defaults
|
|
23
|
+
|
|
24
|
+
def initialize(options = {})
|
|
25
|
+
@namespace = options[:namespace]
|
|
26
|
+
@directory = ::File.join(options[:path], @namespace.to_s)
|
|
27
|
+
|
|
28
|
+
@expires = !options[:skip_expires]
|
|
29
|
+
|
|
30
|
+
ensure_directory_created(@directory)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def key?(key)
|
|
34
|
+
!self[key].nil?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
alias has_key? key?
|
|
38
|
+
|
|
39
|
+
def [](key)
|
|
40
|
+
if ::File.exist?(path(key))
|
|
41
|
+
data = raw_get(key)
|
|
42
|
+
if @expires
|
|
43
|
+
if data[:expires_at].nil? || data[:expires_at] > Time.now
|
|
44
|
+
data[:value]
|
|
45
|
+
else
|
|
46
|
+
delete!(key)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def raw_get(key)
|
|
53
|
+
Marshal.load(::File.read(path(key)))
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def []=(key, value)
|
|
57
|
+
store(key, value)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def store(key, value, options = {})
|
|
61
|
+
ensure_directory_created(::File.dirname(path(key)))
|
|
62
|
+
::File.open(path(key), "w") do |file|
|
|
63
|
+
if @expires
|
|
64
|
+
data = {:value => value}
|
|
65
|
+
if options[:expires_in]
|
|
66
|
+
data[:expires_at] = Time.now + options[:expires_in]
|
|
67
|
+
end
|
|
68
|
+
contents = Marshal.dump(data)
|
|
69
|
+
else
|
|
70
|
+
contents = Marshal.dump(value)
|
|
71
|
+
end
|
|
72
|
+
file.puts(contents)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def update_key(key, options)
|
|
77
|
+
store(key, self[key], options)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def delete!(key)
|
|
81
|
+
FileUtils.rm(path(key))
|
|
82
|
+
nil
|
|
83
|
+
rescue Errno::ENOENT
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def delete(key)
|
|
87
|
+
value = self[key]
|
|
88
|
+
delete!(key)
|
|
89
|
+
value
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def clear
|
|
93
|
+
FileUtils.rm_rf(@directory)
|
|
94
|
+
FileUtils.mkdir(@directory)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
98
|
+
def path(key)
|
|
99
|
+
::File.join(@directory, key.to_s)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def ensure_directory_created(directory_path)
|
|
103
|
+
if ::File.file?(directory_path)
|
|
104
|
+
raise StandardError, "The path you supplied #{directory_path} is a file"
|
|
105
|
+
elsif !::File.exists?(directory_path)
|
|
106
|
+
FileUtils.mkdir_p(directory_path)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bdb'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need bdb gem to use Bdb moneta store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
|
|
10
|
+
class Berkeley
|
|
11
|
+
include Defaults
|
|
12
|
+
|
|
13
|
+
def initialize(options={})
|
|
14
|
+
file = @file = options[:file]
|
|
15
|
+
@db = Bdb::Db.new()
|
|
16
|
+
@db.open(nil, file, nil, Bdb::Db::BTREE, Bdb::DB_CREATE, 0)
|
|
17
|
+
unless options[:skip_expires]
|
|
18
|
+
@expiration = Moneta::Berkeley.new(:file => "#{file}_expiration", :skip_expires => true )
|
|
19
|
+
self.extend(StringExpires)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module Implementation
|
|
24
|
+
def key?(key)
|
|
25
|
+
nil | self[key]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
alias has_key? key?
|
|
29
|
+
|
|
30
|
+
def []=(key,value)
|
|
31
|
+
@db[key] = value
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def [](key)
|
|
35
|
+
@db[key]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def delete(key)
|
|
39
|
+
value = self[key]
|
|
40
|
+
@db.del(nil,key,0) if value
|
|
41
|
+
value
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def clear
|
|
45
|
+
@db.truncate(nil)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include Implementation
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
data/lib/moneta/couch.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "couchrest"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need the couchrest gem to use the CouchDB store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
class Couch
|
|
10
|
+
include Defaults
|
|
11
|
+
|
|
12
|
+
def initialize(options = {})
|
|
13
|
+
@db = ::CouchRest.database!(options[:db])
|
|
14
|
+
unless options[:skip_expires]
|
|
15
|
+
@expiration = Moneta::Couch.new(:db => "#{options[:db]}_expiration", :skip_expires => true)
|
|
16
|
+
self.extend(StringExpires)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def key?(key)
|
|
21
|
+
!self[key].nil?
|
|
22
|
+
rescue RestClient::ResourceNotFound
|
|
23
|
+
false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
alias has_key? key?
|
|
27
|
+
|
|
28
|
+
def [](key)
|
|
29
|
+
@db.get(key)["data"]
|
|
30
|
+
rescue RestClient::ResourceNotFound
|
|
31
|
+
nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def []=(key, value)
|
|
35
|
+
@db.save_doc("_id" => key, :data => value)
|
|
36
|
+
rescue RestClient::RequestFailed
|
|
37
|
+
self[key]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def delete(key)
|
|
41
|
+
value = @db.get(key)
|
|
42
|
+
@db.delete_doc({"_id" => value["_id"], "_rev" => value["_rev"]}) if value
|
|
43
|
+
value["data"]
|
|
44
|
+
rescue RestClient::ResourceNotFound
|
|
45
|
+
nil
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def update_key(key, options = {})
|
|
49
|
+
val = self[key]
|
|
50
|
+
self.store(key, val, options)
|
|
51
|
+
rescue RestClient::ResourceNotFound
|
|
52
|
+
nil
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def clear
|
|
56
|
+
@db.recreate!
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def delete_store
|
|
60
|
+
@db.delete!
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/lib/moneta/lmc.rb
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "localmemcache"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need the localmemcache gem to use the LMC moneta store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
class Expiration
|
|
10
|
+
def initialize(hash)
|
|
11
|
+
@hash = hash
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def [](key) @hash["#{key}__!__expiration"] end
|
|
15
|
+
def []=(key, value) @hash["#{key}__!__expiration"] = value end
|
|
16
|
+
|
|
17
|
+
def delete(key)
|
|
18
|
+
key = "#{key}__!__expiration"
|
|
19
|
+
value = @hash[key]
|
|
20
|
+
@hash.delete(key)
|
|
21
|
+
value
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class LMC
|
|
26
|
+
include Defaults
|
|
27
|
+
|
|
28
|
+
module Implementation
|
|
29
|
+
def initialize(options = {})
|
|
30
|
+
@hash = LocalMemCache.new(:filename => options[:filename])
|
|
31
|
+
@expiration = Expiration.new(@hash)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def [](key) @hash[key] end
|
|
35
|
+
def []=(key, value) @hash[key] = value end
|
|
36
|
+
def clear() @hash.clear end
|
|
37
|
+
|
|
38
|
+
def key?(key)
|
|
39
|
+
@hash.keys.include?(key)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def delete(key)
|
|
43
|
+
value = @hash[key]
|
|
44
|
+
@hash.delete(key)
|
|
45
|
+
value
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
include Implementation
|
|
49
|
+
include StringExpires
|
|
50
|
+
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "mongo"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need the mongo gem to use the MongoDB moneta store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
class MongoDB
|
|
10
|
+
include Defaults
|
|
11
|
+
|
|
12
|
+
def initialize(options = {})
|
|
13
|
+
options = {
|
|
14
|
+
:host => ENV['MONGO_RUBY_DRIVER_HOST'] || 'localhost',
|
|
15
|
+
:port => ENV['MONGO_RUBY_DRIVER_PORT'] || XGen::Mongo::Driver::Mongo::DEFAULT_PORT,
|
|
16
|
+
:db => 'cache',
|
|
17
|
+
:collection => 'cache'
|
|
18
|
+
}.update(options)
|
|
19
|
+
conn = XGen::Mongo::Driver::Mongo.new(options[:host], options[:port])
|
|
20
|
+
@cache = conn.db(options[:db]).collection(options[:collection])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def key?(key)
|
|
24
|
+
!!self[key]
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def [](key)
|
|
28
|
+
res = @cache.find_first('_id' => key)
|
|
29
|
+
res = nil if res && res['expires'] && Time.now > res['expires']
|
|
30
|
+
res && res['data']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def []=(key, value)
|
|
34
|
+
store(key, value)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def delete(key)
|
|
38
|
+
value = self[key]
|
|
39
|
+
@cache.remove('_id' => key) if value
|
|
40
|
+
value
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def store(key, value, options = {})
|
|
44
|
+
exp = options[:expires_in] ? (Time.now + options[:expires_in]) : nil
|
|
45
|
+
@cache.repsert({ '_id' => key }, { '_id' => key, 'data' => value, 'expires' => exp })
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def update_key(key, options = {})
|
|
49
|
+
val = self[key]
|
|
50
|
+
self.store(key, val, options)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def clear
|
|
54
|
+
@cache.clear
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
data/lib/moneta/redis.rb
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "redis"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need the redis gem to use the Redis store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
class Redis
|
|
10
|
+
include Defaults
|
|
11
|
+
|
|
12
|
+
def initialize(options = {})
|
|
13
|
+
@cache = ::Redis.new(options)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def key?(key)
|
|
17
|
+
!@cache[key].nil?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
alias has_key? key?
|
|
21
|
+
|
|
22
|
+
def [](key)
|
|
23
|
+
@cache.get(key)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def []=(key, value)
|
|
27
|
+
store(key, value)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def delete(key)
|
|
31
|
+
value = @cache[key]
|
|
32
|
+
@cache.delete(key) if value
|
|
33
|
+
value
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def store(key, value, options = {})
|
|
37
|
+
@cache.set(key, value, options[:expires_in])
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def update_key(key, options = {})
|
|
41
|
+
val = @cache[key]
|
|
42
|
+
self.store(key, val, options)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def clear
|
|
46
|
+
@cache.flush_db
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/moneta/rufus.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "rufus/tokyo"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need the rufus gem to use the Rufus moneta store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
class BasicRufus < ::Rufus::Tokyo::Cabinet
|
|
10
|
+
include Defaults
|
|
11
|
+
|
|
12
|
+
def initialize(options = {})
|
|
13
|
+
file = options[:file]
|
|
14
|
+
super("#{file}.tch")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def key?(key)
|
|
18
|
+
!!self[key]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def [](key)
|
|
22
|
+
if val = super
|
|
23
|
+
Marshal.load(val.unpack("m")[0])
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def []=(key, value)
|
|
28
|
+
super(key, [Marshal.dump(value)].pack("m"))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class Rufus < BasicRufus
|
|
33
|
+
include Expires
|
|
34
|
+
|
|
35
|
+
def initialize(options = {})
|
|
36
|
+
file = options[:file]
|
|
37
|
+
@expiration = BasicRufus.new(:file => "#{file}_expires")
|
|
38
|
+
super
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
data/lib/moneta/s3.rb
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "right_aws"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need the RightScale AWS gem to use the S3 moneta store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
# An S3 implementation of Moneta
|
|
10
|
+
#
|
|
11
|
+
# Example usage:
|
|
12
|
+
#
|
|
13
|
+
# require 'rubygems'
|
|
14
|
+
# require 'moneta'
|
|
15
|
+
# require 'moneta/s3'
|
|
16
|
+
#
|
|
17
|
+
# store = Moneta::S3.new(
|
|
18
|
+
# :access_key_id => 'ACCESS_KEY_ID',
|
|
19
|
+
# :secret_access_key => 'SECRET_ACCESS_KEY',
|
|
20
|
+
# :bucket => 'a_bucket'
|
|
21
|
+
# )
|
|
22
|
+
# store['somefile']
|
|
23
|
+
class S3
|
|
24
|
+
# Initialize the Moneta::S3 store.
|
|
25
|
+
#
|
|
26
|
+
# Required values passed in the options hash:
|
|
27
|
+
# * <tt>:access_key_id</tt>: The access id key
|
|
28
|
+
# * <tt>:secret_access_key</tt>: The secret key
|
|
29
|
+
# * <tt>:bucket</tt>: The name of bucket. Will be created if it doesn't
|
|
30
|
+
# exist.
|
|
31
|
+
# * <tt>:multi_thread</tt>: Set to true if using threading
|
|
32
|
+
def initialize(options = {})
|
|
33
|
+
validate_options(options)
|
|
34
|
+
s3 = RightAws::S3.new(
|
|
35
|
+
options[:access_key_id],
|
|
36
|
+
options[:secret_access_key],
|
|
37
|
+
{
|
|
38
|
+
:logger => logger,
|
|
39
|
+
:multi_thread => options.delete(:multi_thread) || false
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
@bucket = s3.bucket(options.delete(:bucket), true)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def key?(key)
|
|
46
|
+
!s3_key(key).nil?
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
alias has_key? key?
|
|
50
|
+
|
|
51
|
+
def [](key)
|
|
52
|
+
get(key)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def []=(key, value)
|
|
56
|
+
store(key, value)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def delete(key)
|
|
60
|
+
k = s3_key(key)
|
|
61
|
+
if k
|
|
62
|
+
value = k.get
|
|
63
|
+
k.delete
|
|
64
|
+
value
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Store the key/value pair.
|
|
69
|
+
#
|
|
70
|
+
# Options:
|
|
71
|
+
# *<tt>:meta_headers</tt>: Meta headers passed to S3
|
|
72
|
+
# *<tt>:perms</tt>: Permissions passed to S3
|
|
73
|
+
# *<tt>:headers</tt>: Headers sent as part of the PUT request
|
|
74
|
+
# *<tt>:expires_in</tt>: Number of seconds until expiration
|
|
75
|
+
def store(key, value, options = {})
|
|
76
|
+
debug "store(key=#{key}, value=#{value}, options=#{options.inspect})"
|
|
77
|
+
meta_headers = meta_headers_from_options(options)
|
|
78
|
+
perms = options[:perms]
|
|
79
|
+
headers = options[:headers] || {}
|
|
80
|
+
|
|
81
|
+
case value
|
|
82
|
+
when IO
|
|
83
|
+
@bucket.put(key, value.read, meta_headers, perms, headers)
|
|
84
|
+
else
|
|
85
|
+
@bucket.put(key, value, meta_headers, perms, headers)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def update_key(key, options = {})
|
|
90
|
+
debug "update_key(key=#{key}, options=#{options.inspect})"
|
|
91
|
+
k = s3_key(key, false)
|
|
92
|
+
k.save_meta(meta_headers_from_options(options)) unless k.nil?
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def clear
|
|
96
|
+
@bucket.clear
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
protected
|
|
100
|
+
def logger
|
|
101
|
+
@logger ||= begin
|
|
102
|
+
logger = Logger.new(STDOUT)
|
|
103
|
+
logger.level = Logger::FATAL
|
|
104
|
+
logger
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
def validate_options(options)
|
|
110
|
+
unless options[:access_key_id]
|
|
111
|
+
raise RuntimeError, ":access_key_id is required in options"
|
|
112
|
+
end
|
|
113
|
+
unless options[:secret_access_key]
|
|
114
|
+
raise RuntimeError, ":secret_access_key is required in options"
|
|
115
|
+
end
|
|
116
|
+
unless options[:bucket]
|
|
117
|
+
raise RuntimeError, ":bucket is required in options"
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def get(key)
|
|
122
|
+
k = s3_key(key)
|
|
123
|
+
k.nil? ? nil : k.get
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def s3_key(key, nil_if_expired=true)
|
|
127
|
+
begin
|
|
128
|
+
s3_key = @bucket.key(key, true)
|
|
129
|
+
if s3_key.exists?
|
|
130
|
+
logger.debug "[Moneta::S3] key exists: #{key}"
|
|
131
|
+
if s3_key.meta_headers.has_key?('expires-at')
|
|
132
|
+
expires_at = Time.parse(s3_key.meta_headers['expires-at'])
|
|
133
|
+
if Time.now > expires_at && nil_if_expired
|
|
134
|
+
# TODO delete the object?
|
|
135
|
+
debug "key expired: #{key} (@#{s3_key.meta_headers['expires-at']})"
|
|
136
|
+
return nil
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
return s3_key
|
|
140
|
+
else
|
|
141
|
+
debug "key does not exist: #{key}"
|
|
142
|
+
end
|
|
143
|
+
rescue RightAws::AwsError => e
|
|
144
|
+
debug "key does not exist: #{key}"
|
|
145
|
+
end
|
|
146
|
+
nil
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def meta_headers_from_options(options={})
|
|
150
|
+
meta_headers = options[:meta_headers] || {}
|
|
151
|
+
if options[:expires_in]
|
|
152
|
+
meta_headers['expires-at'] = (Time.now + options[:expires_in]).rfc2822
|
|
153
|
+
end
|
|
154
|
+
debug "setting expires-at: #{meta_headers['expires-at']}"
|
|
155
|
+
meta_headers
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def debug(message)
|
|
159
|
+
logger.debug "[Moneta::S3] #{message}"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
end
|
data/lib/moneta/sdbm.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require "sdbm"
|
|
2
|
+
|
|
3
|
+
module Moneta
|
|
4
|
+
class BasicSDBM < ::SDBM
|
|
5
|
+
include Defaults
|
|
6
|
+
|
|
7
|
+
def [](key)
|
|
8
|
+
if val = super
|
|
9
|
+
Marshal.load(val)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def []=(key, value)
|
|
14
|
+
super(key, Marshal.dump(value))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def delete(key)
|
|
18
|
+
if val = super
|
|
19
|
+
Marshal.load(val)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class SDBM < BasicSDBM
|
|
25
|
+
include Expires
|
|
26
|
+
|
|
27
|
+
def initialize(options = {})
|
|
28
|
+
raise "No :file option specified" unless file = options[:file]
|
|
29
|
+
@expiration = BasicSDBM.new("#{file}_expires")
|
|
30
|
+
super(file)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require "rufus/tokyo/tyrant"
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts "You need the rufus gem to use the Tyrant moneta store"
|
|
5
|
+
exit
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
module Moneta
|
|
9
|
+
class Tyrant < ::Rufus::Tokyo::Tyrant
|
|
10
|
+
include Defaults
|
|
11
|
+
|
|
12
|
+
module Implementation
|
|
13
|
+
def initialize(options = {})
|
|
14
|
+
host = options[:host]
|
|
15
|
+
port = options[:port]
|
|
16
|
+
super(host, port)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def key?(key)
|
|
20
|
+
!!self[key]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def [](key)
|
|
24
|
+
if val = super
|
|
25
|
+
Marshal.load(val.unpack("m")[0])
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def []=(key, value)
|
|
30
|
+
super(key, [Marshal.dump(value)].pack("m"))
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
include Implementation
|
|
35
|
+
include Expires
|
|
36
|
+
|
|
37
|
+
def initialize(options = {})
|
|
38
|
+
super
|
|
39
|
+
@expiration = Expiration.new(options)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class Expiration < ::Rufus::Tokyo::Tyrant
|
|
43
|
+
include Implementation
|
|
44
|
+
|
|
45
|
+
def [](key)
|
|
46
|
+
super("#{key}__expiration")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def []=(key, value)
|
|
50
|
+
super("#{key}__expiration", value)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def delete(key)
|
|
54
|
+
super("#{key}__expiration")
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: benschwarz-moneta
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yehuda Katz
|
|
@@ -9,7 +9,7 @@ autorequire: moneta
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-
|
|
12
|
+
date: 2009-08-25 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies: []
|
|
15
15
|
|
|
@@ -29,13 +29,23 @@ files:
|
|
|
29
29
|
- Rakefile
|
|
30
30
|
- TODO
|
|
31
31
|
- lib/moneta
|
|
32
|
+
- lib/moneta/basic_file.rb
|
|
33
|
+
- lib/moneta/berkeley.rb
|
|
34
|
+
- lib/moneta/couch.rb
|
|
32
35
|
- lib/moneta/datamapper.rb
|
|
33
36
|
- lib/moneta/file.rb
|
|
37
|
+
- lib/moneta/lmc.rb
|
|
34
38
|
- lib/moneta/memcache.rb
|
|
35
39
|
- lib/moneta/memory.rb
|
|
40
|
+
- lib/moneta/mongodb.rb
|
|
41
|
+
- lib/moneta/redis.rb
|
|
42
|
+
- lib/moneta/rufus.rb
|
|
43
|
+
- lib/moneta/s3.rb
|
|
44
|
+
- lib/moneta/sdbm.rb
|
|
45
|
+
- lib/moneta/tyrant.rb
|
|
36
46
|
- lib/moneta/xattr.rb
|
|
37
47
|
- lib/moneta.rb
|
|
38
|
-
has_rdoc:
|
|
48
|
+
has_rdoc: false
|
|
39
49
|
homepage: http://www.yehudakatz.com
|
|
40
50
|
licenses:
|
|
41
51
|
post_install_message:
|
|
@@ -60,7 +70,7 @@ requirements: []
|
|
|
60
70
|
rubyforge_project:
|
|
61
71
|
rubygems_version: 1.3.5
|
|
62
72
|
signing_key:
|
|
63
|
-
specification_version:
|
|
73
|
+
specification_version: 3
|
|
64
74
|
summary: A unified interface to key/value stores
|
|
65
75
|
test_files: []
|
|
66
76
|
|