gotime-moneta 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +56 -0
- data/Rakefile +60 -0
- data/TODO +4 -0
- data/lib/moneta.rb +76 -0
- data/lib/moneta/basic_file.rb +113 -0
- data/lib/moneta/berkeley.rb +53 -0
- data/lib/moneta/couch.rb +63 -0
- data/lib/moneta/datamapper.rb +117 -0
- data/lib/moneta/file.rb +91 -0
- data/lib/moneta/lmc.rb +52 -0
- data/lib/moneta/memcache.rb +53 -0
- data/lib/moneta/memory.rb +11 -0
- data/lib/moneta/mongodb.rb +58 -0
- data/lib/moneta/redis.rb +67 -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
- data/lib/moneta/xattr.rb +58 -0
- data/lib/moneta/yaml.rb +92 -0
- metadata +89 -0
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
|
data/lib/moneta/xattr.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
begin
|
2
|
+
require "xattr"
|
3
|
+
rescue LoadError
|
4
|
+
puts "You need the xattr gem to use the Xattr moneta store"
|
5
|
+
exit
|
6
|
+
end
|
7
|
+
require "fileutils"
|
8
|
+
|
9
|
+
module Moneta
|
10
|
+
class Xattr
|
11
|
+
include Defaults
|
12
|
+
|
13
|
+
def initialize(options = {})
|
14
|
+
file = options[:file]
|
15
|
+
@hash = ::Xattr.new(file)
|
16
|
+
FileUtils.mkdir_p(::File.dirname(file))
|
17
|
+
FileUtils.touch(file)
|
18
|
+
unless options[:skip_expires]
|
19
|
+
@expiration = Moneta::Xattr.new(:file => "#{file}_expiration", :skip_expires => true)
|
20
|
+
self.extend(Expires)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Implementation
|
25
|
+
|
26
|
+
def key?(key)
|
27
|
+
@hash.list.include?(key)
|
28
|
+
end
|
29
|
+
|
30
|
+
alias has_key? key?
|
31
|
+
|
32
|
+
def [](key)
|
33
|
+
return nil unless key?(key)
|
34
|
+
Marshal.load(@hash.get(key))
|
35
|
+
end
|
36
|
+
|
37
|
+
def []=(key, value)
|
38
|
+
@hash.set(key, Marshal.dump(value))
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete(key)
|
42
|
+
return nil unless key?(key)
|
43
|
+
value = self[key]
|
44
|
+
@hash.remove(key)
|
45
|
+
value
|
46
|
+
end
|
47
|
+
|
48
|
+
def clear
|
49
|
+
@hash.list.each do |item|
|
50
|
+
@hash.remove(item)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
include Implementation
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
data/lib/moneta/yaml.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
module Moneta
|
5
|
+
class YAML
|
6
|
+
class Expiration
|
7
|
+
def initialize(file)
|
8
|
+
@file = file
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](key)
|
12
|
+
yaml[key]['expires'] if yaml.has_key?(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(key, value)
|
16
|
+
hash = yaml
|
17
|
+
if hash.has_key?(key)
|
18
|
+
hash[key]['expires'] = value
|
19
|
+
save(hash)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete(key)
|
24
|
+
hash = yaml
|
25
|
+
if hash.has_key?(key)
|
26
|
+
hash[key].delete("expires")
|
27
|
+
save(hash)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def yaml
|
33
|
+
::YAML.load_file(@file)
|
34
|
+
end
|
35
|
+
|
36
|
+
def save(hash)
|
37
|
+
::File.open(@file, "w") { |file| file << hash.to_yaml }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(options = {})
|
42
|
+
@file = File.expand_path(options[:path])
|
43
|
+
unless ::File.exists?(@file)
|
44
|
+
File.open(@file, "w") { |file| file << {}.to_yaml }
|
45
|
+
end
|
46
|
+
|
47
|
+
@expiration = Expiration.new(@file)
|
48
|
+
end
|
49
|
+
|
50
|
+
module Implementation
|
51
|
+
def key?(key)
|
52
|
+
yaml.has_key?(key)
|
53
|
+
end
|
54
|
+
|
55
|
+
alias has_key? key?
|
56
|
+
|
57
|
+
def [](key)
|
58
|
+
yaml[key]['value'] if yaml.has_key?(key)
|
59
|
+
end
|
60
|
+
|
61
|
+
def []=(key, value)
|
62
|
+
hash = yaml
|
63
|
+
(hash[key] ||= {})['value'] = value
|
64
|
+
save(hash)
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete(key)
|
68
|
+
hash = yaml
|
69
|
+
value = self[key]
|
70
|
+
hash.delete(key)
|
71
|
+
save(hash)
|
72
|
+
value
|
73
|
+
end
|
74
|
+
|
75
|
+
def clear
|
76
|
+
save
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
def yaml
|
81
|
+
::YAML.load_file(@file)
|
82
|
+
end
|
83
|
+
|
84
|
+
def save(hash = {})
|
85
|
+
::File.open(@file, "w") { |file| file << hash.to_yaml }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
include Implementation
|
89
|
+
include Defaults
|
90
|
+
include Expires
|
91
|
+
end
|
92
|
+
end
|