moneta 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +1 -0
- data/CHANGES +21 -10
- data/README.md +1 -1
- data/SPEC.md +4 -12
- data/lib/moneta.rb +7 -5
- data/lib/moneta/adapters/activerecord.rb +9 -3
- data/lib/moneta/adapters/cassandra.rb +9 -4
- data/lib/moneta/adapters/client.rb +9 -3
- data/lib/moneta/adapters/cookie.rb +3 -0
- data/lib/moneta/adapters/couch.rb +8 -3
- data/lib/moneta/adapters/datamapper.rb +8 -3
- data/lib/moneta/adapters/dbm.rb +1 -2
- data/lib/moneta/adapters/file.rb +9 -4
- data/lib/moneta/adapters/fog.rb +8 -3
- data/lib/moneta/adapters/gdbm.rb +1 -2
- data/lib/moneta/adapters/hbase.rb +10 -3
- data/lib/moneta/adapters/leveldb.rb +3 -2
- data/lib/moneta/adapters/localmemcache.rb +4 -4
- data/lib/moneta/adapters/lruhash.rb +8 -4
- data/lib/moneta/adapters/memcached/dalli.rb +10 -4
- data/lib/moneta/adapters/memcached/native.rb +9 -4
- data/lib/moneta/adapters/memory.rb +8 -3
- data/lib/moneta/adapters/mongo.rb +7 -3
- data/lib/moneta/adapters/null.rb +8 -1
- data/lib/moneta/adapters/pstore.rb +9 -3
- data/lib/moneta/adapters/redis.rb +10 -4
- data/lib/moneta/adapters/riak.rb +12 -7
- data/lib/moneta/adapters/sdbm.rb +1 -2
- data/lib/moneta/adapters/sequel.rb +9 -3
- data/lib/moneta/adapters/sqlite.rb +10 -4
- data/lib/moneta/adapters/tokyocabinet.rb +2 -2
- data/lib/moneta/builder.rb +11 -7
- data/lib/moneta/cache.rb +16 -6
- data/lib/moneta/expires.rb +12 -6
- data/lib/moneta/lock.rb +0 -2
- data/lib/moneta/logger.rb +0 -2
- data/lib/moneta/mixins.rb +175 -47
- data/lib/moneta/optionmerger.rb +2 -0
- data/lib/moneta/proxy.rb +14 -30
- data/lib/moneta/server.rb +0 -2
- data/lib/moneta/shared.rb +1 -3
- data/lib/moneta/stack.rb +20 -10
- data/lib/moneta/transformer.rb +84 -61
- data/lib/moneta/version.rb +1 -1
- data/lib/rack/moneta_rest.rb +56 -0
- data/moneta.gemspec +1 -1
- data/spec/active_support/cache_moneta_store_spec.rb +4 -4
- data/spec/generate.rb +216 -203
- data/spec/helper.rb +0 -6
- data/spec/moneta/adapter_cassandra_spec.rb +2 -2
- data/spec/moneta/adapter_datamapper_spec.rb +1 -1
- data/spec/moneta/adapter_lruhash_spec.rb +1 -1
- data/spec/moneta/adapter_memcached_dalli_spec.rb +2 -2
- data/spec/moneta/adapter_memcached_native_spec.rb +2 -2
- data/spec/moneta/adapter_memcached_spec.rb +2 -2
- data/spec/moneta/adapter_redis_spec.rb +2 -2
- data/spec/moneta/cache_file_memory_spec.rb +3 -3
- data/spec/moneta/expires_file_spec.rb +4 -4
- data/spec/moneta/expires_memory_spec.rb +2 -2
- data/spec/moneta/optionmerger_spec.rb +6 -6
- data/spec/moneta/shared_spec.rb +1 -1
- data/spec/moneta/simple_client_tcp_spec.rb +1 -1
- data/spec/moneta/transformer_key_marshal_spec.rb +109 -0
- data/spec/moneta/transformer_key_yaml_spec.rb +109 -0
- data/spec/moneta/transformer_marshal_spec.rb +109 -0
- data/spec/moneta/transformer_value_marshal_spec.rb +109 -0
- data/spec/moneta/transformer_value_yaml_spec.rb +109 -0
- data/spec/monetaspecs.rb +14460 -3956
- metadata +16 -6
- data/lib/moneta/base.rb +0 -98
- data/lib/moneta/net.rb +0 -22
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
- README.md SPEC.md CHANGES LICENSE
|
data/CHANGES
CHANGED
@@ -1,18 +1,29 @@
|
|
1
|
+
master
|
2
|
+
|
3
|
+
* Renamed WithOptions to OptionSupport
|
4
|
+
* Refactored Base in Defaults mixin
|
5
|
+
* Removed Transformer option :quiet
|
6
|
+
* Transformer might raise an exception if an invalid value is transformed
|
7
|
+
* Expires middleware only wraps Arrays and nils in an Array if
|
8
|
+
no expiration time is given (backward compatible change)
|
9
|
+
* Moneta middlewares are not allowed to modify option hash given to functions
|
10
|
+
like #load and #store
|
11
|
+
|
1
12
|
0.7.1
|
2
13
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
14
|
+
* Memcached: Use binary protocol and no base64 encoding of the keys
|
15
|
+
* Transformer: Remove newlines from base64 encodes values
|
16
|
+
* Server: Add method #run which will block and #running? to allow forking
|
17
|
+
* SDBM: #store might raise errors (Don't use SDBM, it is unstable!)
|
18
|
+
* Add #decrement method
|
19
|
+
* Fix #fetch to handle false correctly
|
20
|
+
* Fix Expires middleware to handle boolean and nil values correctly
|
21
|
+
* Base64 encode Riak keys since Riak needs valid UTF-8 for the REST interface
|
11
22
|
|
12
23
|
0.7.0
|
13
24
|
|
14
|
-
|
25
|
+
* Major rewrite by Daniel Mendler
|
15
26
|
|
16
27
|
0.6.0
|
17
28
|
|
18
|
-
|
29
|
+
* First public release by Yehuda Katz
|
data/README.md
CHANGED
@@ -303,7 +303,7 @@ store['key'] # returns nil
|
|
303
303
|
store['subkey'] # returns 'value'
|
304
304
|
|
305
305
|
# Set expiration time for all keys
|
306
|
-
short_lived_store =
|
306
|
+
short_lived_store = store.expires(60)
|
307
307
|
short_lived_store['key'] = 'value'
|
308
308
|
~~~
|
309
309
|
|
data/SPEC.md
CHANGED
@@ -1,16 +1,8 @@
|
|
1
1
|
# Moneta Specification
|
2
2
|
|
3
|
-
The purpose of the moneta specification is to create a general-purpose API for interacting with key-value stores. In general, libraries that need to interact with key-value stores should be able to specify that they can use any "moneta-compliant store".
|
4
|
-
|
5
|
-
# Moneta Executable Specs
|
6
|
-
|
7
|
-
Moneta ships with a set of executable specs which you can use to verify spec-compliance with your moneta adapter.
|
8
|
-
|
9
|
-
# Requirements for a Moneta Adapter
|
10
|
-
|
11
3
|
(See RFC 2119 for use of MUST, SHOULD, MAY, MUST NOT, and SHOULD NOT)
|
12
4
|
|
13
|
-
|
5
|
+
The purpose of the moneta specification is to create a general-purpose API for interacting with key-value stores. In general, libraries that need to interact with key-value stores should be able to specify that they can use any "moneta-compliant store". Moneta ships with a set of executable specs which you can use to verify spec-compliance with your moneta adapter.
|
14
6
|
|
15
7
|
## Class Methods
|
16
8
|
|
@@ -62,9 +54,9 @@ This method MUST accept negative values, but the result MUST be unsigned.
|
|
62
54
|
|
63
55
|
Completely empty all keys and values from the key-value-store. Adapters MAY allow a namespace during initialization, which can scope this operation to a particular subset of keys. After calling <code>clear</code>, a <code>[]</code> operation MUST return nil for every possible key, and a <code>key?</code> query MUST return false for every possible key.
|
64
56
|
|
65
|
-
|
57
|
+
## Additional Options Hashes
|
66
58
|
|
67
|
-
The following methods may all take an additional Hash as a final argument. This allows the client to send additional options which can be specified by the adapter (and which may be specified by extensions to this specification).
|
59
|
+
The following methods may all take an additional Hash as a final argument. This allows the client to send additional options which can be specified by the adapter (and which may be specified by extensions to this specification). The methods MUST NOT modify the supplied option hash.
|
68
60
|
|
69
61
|
* fetch
|
70
62
|
* load
|
@@ -76,6 +68,6 @@ The following methods may all take an additional Hash as a final argument. This
|
|
76
68
|
|
77
69
|
In the case of methods with optional arguments, the Hash MUST be provided as the final argument. Keys in this Hash MUST be Symbols.
|
78
70
|
|
79
|
-
|
71
|
+
## Atomicity
|
80
72
|
|
81
73
|
The base Moneta specification does not specify any atomicity guarantees. However, extensions to this spec may specify extensions that define additional guarantees for any of the defined operations.
|
data/lib/moneta.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
module Moneta
|
2
|
-
autoload :Base, 'moneta/base'
|
3
2
|
autoload :Builder, 'moneta/builder'
|
4
3
|
autoload :Cache, 'moneta/cache'
|
4
|
+
autoload :Defaults, 'moneta/mixins'
|
5
5
|
autoload :Expires, 'moneta/expires'
|
6
|
+
autoload :HashAdapter, 'moneta/mixins'
|
7
|
+
autoload :IncrementSupport, 'moneta/mixins'
|
6
8
|
autoload :Lock, 'moneta/lock'
|
7
9
|
autoload :Logger, 'moneta/logger'
|
8
|
-
autoload :
|
9
|
-
autoload :Net, 'moneta/net'
|
10
|
+
autoload :Net, 'moneta/mixins'
|
10
11
|
autoload :OptionMerger, 'moneta/optionmerger'
|
12
|
+
autoload :OptionSupport, 'moneta/mixins'
|
11
13
|
autoload :Proxy, 'moneta/proxy'
|
12
14
|
autoload :Server, 'moneta/server'
|
13
15
|
autoload :Shared, 'moneta/shared'
|
@@ -21,15 +23,15 @@ module Moneta
|
|
21
23
|
autoload :Client, 'moneta/adapters/client'
|
22
24
|
autoload :Cookie, 'moneta/adapters/cookie'
|
23
25
|
autoload :Couch, 'moneta/adapters/couch'
|
24
|
-
autoload :DataMapper, 'moneta/adapters/datamapper'
|
25
26
|
autoload :DBM, 'moneta/adapters/dbm'
|
27
|
+
autoload :DataMapper, 'moneta/adapters/datamapper'
|
26
28
|
autoload :File, 'moneta/adapters/file'
|
27
29
|
autoload :Fog, 'moneta/adapters/fog'
|
28
30
|
autoload :GDBM, 'moneta/adapters/gdbm'
|
29
31
|
autoload :HBase, 'moneta/adapters/hbase'
|
32
|
+
autoload :LRUHash, 'moneta/adapters/lruhash'
|
30
33
|
autoload :LevelDB, 'moneta/adapters/leveldb'
|
31
34
|
autoload :LocalMemCache, 'moneta/adapters/localmemcache'
|
32
|
-
autoload :LRUHash, 'moneta/adapters/lruhash'
|
33
35
|
autoload :Memcached, 'moneta/adapters/memcached'
|
34
36
|
autoload :MemcachedDalli, 'moneta/adapters/memcached/dalli'
|
35
37
|
autoload :MemcachedNative, 'moneta/adapters/memcached/native'
|
@@ -4,15 +4,15 @@ module Moneta
|
|
4
4
|
module Adapters
|
5
5
|
# ActiveRecord as key/value stores
|
6
6
|
# @api public
|
7
|
-
class ActiveRecord
|
7
|
+
class ActiveRecord
|
8
|
+
include Defaults
|
9
|
+
|
8
10
|
def self.tables
|
9
11
|
@tables ||= {}
|
10
12
|
end
|
11
13
|
|
12
14
|
attr_reader :table
|
13
15
|
|
14
|
-
# Constructor
|
15
|
-
#
|
16
16
|
# @param [Hash] options
|
17
17
|
# @option options [String] :table ('moneta') Table name
|
18
18
|
# @option options [Hash] :connection ActiveRecord connection configuration
|
@@ -36,15 +36,18 @@ module Moneta
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
# (see Proxy#key?)
|
39
40
|
def key?(key, options = {})
|
40
41
|
!@table.where(:k => key).empty?
|
41
42
|
end
|
42
43
|
|
44
|
+
# (see Proxy#load)
|
43
45
|
def load(key, options = {})
|
44
46
|
record = @table.select(:v).where(:k => key).first
|
45
47
|
record && record.v
|
46
48
|
end
|
47
49
|
|
50
|
+
# (see Proxy#store)
|
48
51
|
def store(key, value, options = {})
|
49
52
|
record = @table.select(:k).where(:k => key).first_or_initialize
|
50
53
|
record.v = value
|
@@ -52,6 +55,7 @@ module Moneta
|
|
52
55
|
value
|
53
56
|
end
|
54
57
|
|
58
|
+
# (see Proxy#delete)
|
55
59
|
def delete(key, options = {})
|
56
60
|
if record = @table.where(:k => key).first
|
57
61
|
record.destroy
|
@@ -59,6 +63,7 @@ module Moneta
|
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
66
|
+
# (see Proxy#increment)
|
62
67
|
def increment(key, amount = 1, options = {})
|
63
68
|
record = @table.where(:k => key).lock.first_or_initialize
|
64
69
|
value = record.v
|
@@ -70,6 +75,7 @@ module Moneta
|
|
70
75
|
intvalue
|
71
76
|
end
|
72
77
|
|
78
|
+
# (see Proxy#clear)
|
73
79
|
def clear(options = {})
|
74
80
|
@table.delete_all
|
75
81
|
self
|
@@ -7,15 +7,15 @@ module Moneta
|
|
7
7
|
module Adapters
|
8
8
|
# Cassandra backend
|
9
9
|
# @api public
|
10
|
-
class Cassandra
|
11
|
-
|
12
|
-
|
10
|
+
class Cassandra
|
11
|
+
include Defaults
|
12
|
+
|
13
13
|
# @param [Hash] options
|
14
14
|
# @option options [String] :keyspace ('moneta') Cassandra keyspace
|
15
15
|
# @option options [String] :column_family ('moneta') Cassandra column family
|
16
16
|
# @option options [String] :host ('127.0.0.1') Server host name
|
17
17
|
# @option options [Integer] :port (9160) Server port
|
18
|
-
# @option options [
|
18
|
+
# @option options [Integer] :expires Default expiration time
|
19
19
|
def initialize(options = {})
|
20
20
|
options[:host] ||= '127.0.0.1'
|
21
21
|
options[:port] ||= 9160
|
@@ -44,6 +44,7 @@ module Moneta
|
|
44
44
|
@client.keyspace = keyspace
|
45
45
|
end
|
46
46
|
|
47
|
+
# (see Proxy#key?)
|
47
48
|
def key?(key, options = {})
|
48
49
|
if @client.exists?(@cf, key)
|
49
50
|
if options.include?(:expires) && (value = load(key))
|
@@ -55,6 +56,7 @@ module Moneta
|
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
59
|
+
# (see Proxy#load)
|
58
60
|
def load(key, options = {})
|
59
61
|
value = @client.get(@cf, key)
|
60
62
|
if value
|
@@ -66,11 +68,13 @@ module Moneta
|
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
71
|
+
# (see Proxy#store)
|
69
72
|
def store(key, value, options = {})
|
70
73
|
@client.insert(@cf, key, {'value' => value}, :ttl => (options[:expires] || @expires))
|
71
74
|
value
|
72
75
|
end
|
73
76
|
|
77
|
+
# (see Proxy#delete)
|
74
78
|
def delete(key, options = {})
|
75
79
|
if value = load(key, options)
|
76
80
|
@client.remove(@cf, key)
|
@@ -78,6 +82,7 @@ module Moneta
|
|
78
82
|
end
|
79
83
|
end
|
80
84
|
|
85
|
+
# (see Proxy#clear)
|
81
86
|
def clear(options = {})
|
82
87
|
@client.each_key(@cf) do |key|
|
83
88
|
delete(key)
|
@@ -4,11 +4,10 @@ module Moneta
|
|
4
4
|
module Adapters
|
5
5
|
# Moneta client backend
|
6
6
|
# @api public
|
7
|
-
class Client
|
7
|
+
class Client
|
8
8
|
include Net
|
9
|
+
include Defaults
|
9
10
|
|
10
|
-
# Constructor
|
11
|
-
#
|
12
11
|
# @param [Hash] options
|
13
12
|
# @option options [Integer] :port (9000) TCP port
|
14
13
|
# @option options [String] :host ('127.0.0.1') Hostname
|
@@ -18,38 +17,45 @@ module Moneta
|
|
18
17
|
TCPSocket.open(options[:host] || '127.0.0.1', options[:port] || DEFAULT_PORT)
|
19
18
|
end
|
20
19
|
|
20
|
+
# (see Proxy#key?)
|
21
21
|
def key?(key, options = {})
|
22
22
|
write(@socket, [:key?, key, options])
|
23
23
|
read_result
|
24
24
|
end
|
25
25
|
|
26
|
+
# (see Proxy#load)
|
26
27
|
def load(key, options = {})
|
27
28
|
write(@socket, [:load, key, options])
|
28
29
|
read_result
|
29
30
|
end
|
30
31
|
|
32
|
+
# (see Proxy#store)
|
31
33
|
def store(key, value, options = {})
|
32
34
|
write(@socket, [:store, key, value, options])
|
33
35
|
read_result
|
34
36
|
value
|
35
37
|
end
|
36
38
|
|
39
|
+
# (see Proxy#delete)
|
37
40
|
def delete(key, options = {})
|
38
41
|
write(@socket, [:delete, key, options])
|
39
42
|
read_result
|
40
43
|
end
|
41
44
|
|
45
|
+
# (see Proxy#increment)
|
42
46
|
def increment(key, amount = 1, options = {})
|
43
47
|
write(@socket, [:increment, key, amount, options])
|
44
48
|
read_result
|
45
49
|
end
|
46
50
|
|
51
|
+
# (see Proxy#clear)
|
47
52
|
def clear(options = {})
|
48
53
|
write(@socket, [:clear, options])
|
49
54
|
read_result
|
50
55
|
self
|
51
56
|
end
|
52
57
|
|
58
|
+
# (see Proxy#close)
|
53
59
|
def close
|
54
60
|
@socket.close
|
55
61
|
nil
|
@@ -10,6 +10,7 @@ module Moneta
|
|
10
10
|
@options, @cookies = options, {}
|
11
11
|
end
|
12
12
|
|
13
|
+
# (see Proxy#store)
|
13
14
|
def store(key, value, options = {})
|
14
15
|
cookie = @options.merge(options)
|
15
16
|
cookie[:value] = value
|
@@ -18,11 +19,13 @@ module Moneta
|
|
18
19
|
super
|
19
20
|
end
|
20
21
|
|
22
|
+
# (see Proxy#delete)
|
21
23
|
def delete(key, options = {})
|
22
24
|
@cookies[key] = nil
|
23
25
|
super
|
24
26
|
end
|
25
27
|
|
28
|
+
# (see Proxy#clear)
|
26
29
|
def clear(options = {})
|
27
30
|
@hash.each_key { |key| @cookies[key] = nil }
|
28
31
|
super
|
@@ -4,9 +4,9 @@ module Moneta
|
|
4
4
|
module Adapters
|
5
5
|
# CouchDB backend
|
6
6
|
# @api public
|
7
|
-
class Couch
|
8
|
-
|
9
|
-
|
7
|
+
class Couch
|
8
|
+
include Defaults
|
9
|
+
|
10
10
|
# @param [Hash] options
|
11
11
|
# @option options [String] :db ('moneta') Couch database
|
12
12
|
def initialize(options = {})
|
@@ -14,18 +14,21 @@ module Moneta
|
|
14
14
|
@db = ::CouchRest.database!(options[:db])
|
15
15
|
end
|
16
16
|
|
17
|
+
# (see Proxy#key?)
|
17
18
|
def key?(key, options = {})
|
18
19
|
@db.get(key) != nil
|
19
20
|
rescue RestClient::ResourceNotFound
|
20
21
|
false
|
21
22
|
end
|
22
23
|
|
24
|
+
# (see Proxy#load)
|
23
25
|
def load(key, options = {})
|
24
26
|
@db.get(key)['value']
|
25
27
|
rescue RestClient::ResourceNotFound
|
26
28
|
nil
|
27
29
|
end
|
28
30
|
|
31
|
+
# (see Proxy#store)
|
29
32
|
def store(key, value, options = {})
|
30
33
|
doc = {'_id' => key, 'value' => value}
|
31
34
|
begin
|
@@ -38,6 +41,7 @@ module Moneta
|
|
38
41
|
value
|
39
42
|
end
|
40
43
|
|
44
|
+
# (see Proxy#delete)
|
41
45
|
def delete(key, options = {})
|
42
46
|
value = @db.get(key)
|
43
47
|
@db.delete_doc('_id' => value['_id'], '_rev' => value['_rev'])
|
@@ -46,6 +50,7 @@ module Moneta
|
|
46
50
|
nil
|
47
51
|
end
|
48
52
|
|
53
|
+
# (see Proxy#clear)
|
49
54
|
def clear(options = {})
|
50
55
|
@db.recreate!
|
51
56
|
self
|
@@ -5,15 +5,15 @@ module Moneta
|
|
5
5
|
module Adapters
|
6
6
|
# Datamapper backend
|
7
7
|
# @api public
|
8
|
-
class DataMapper
|
8
|
+
class DataMapper
|
9
|
+
include Defaults
|
10
|
+
|
9
11
|
class Store
|
10
12
|
include ::DataMapper::Resource
|
11
13
|
property :k, Text, :key => true
|
12
14
|
property :v, Text, :lazy => false
|
13
15
|
end
|
14
16
|
|
15
|
-
# Constructor
|
16
|
-
#
|
17
17
|
# @param [Hash] options
|
18
18
|
# @option options [String] :setup Datamapper setup string
|
19
19
|
# @option options [String/Symbol] :repository (:moneta) Repository name
|
@@ -26,10 +26,12 @@ module Moneta
|
|
26
26
|
context { Store.auto_upgrade! }
|
27
27
|
end
|
28
28
|
|
29
|
+
# (see Proxy#key?)
|
29
30
|
def key?(key, options = {})
|
30
31
|
context { Store.get(key) != nil }
|
31
32
|
end
|
32
33
|
|
34
|
+
# (see Proxy#load)
|
33
35
|
def load(key, options = {})
|
34
36
|
context do
|
35
37
|
record = Store.get(key)
|
@@ -37,6 +39,7 @@ module Moneta
|
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
42
|
+
# (see Proxy#store)
|
40
43
|
def store(key, value, options = {})
|
41
44
|
context do
|
42
45
|
if record = Store.get(key)
|
@@ -48,6 +51,7 @@ module Moneta
|
|
48
51
|
end
|
49
52
|
end
|
50
53
|
|
54
|
+
# (see Proxy#delete)
|
51
55
|
def delete(key, options = {})
|
52
56
|
context do
|
53
57
|
if record = Store.get(key)
|
@@ -58,6 +62,7 @@ module Moneta
|
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
65
|
+
# (see Proxy#clear)
|
61
66
|
def clear(options = {})
|
62
67
|
context { Store.all.destroy! }
|
63
68
|
self
|
data/lib/moneta/adapters/dbm.rb
CHANGED
@@ -5,8 +5,6 @@ module Moneta
|
|
5
5
|
# DBM backend (Berkeley DB)
|
6
6
|
# @api public
|
7
7
|
class DBM < Memory
|
8
|
-
# Constructor
|
9
|
-
#
|
10
8
|
# @param [Hash] options
|
11
9
|
# @option options [String] :file Database file
|
12
10
|
def initialize(options = {})
|
@@ -14,6 +12,7 @@ module Moneta
|
|
14
12
|
@hash = ::DBM.new(options[:file])
|
15
13
|
end
|
16
14
|
|
15
|
+
# (see Proxy#close)
|
17
16
|
def close
|
18
17
|
@hash.close
|
19
18
|
nil
|