moneta 0.7.8 → 0.7.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. data/.travis.yml +1 -0
  2. data/CHANGES +6 -0
  3. data/Gemfile +1 -0
  4. data/README.md +107 -40
  5. data/SPEC.md +8 -0
  6. data/lib/moneta.rb +6 -7
  7. data/lib/moneta/adapters/activerecord.rb +2 -0
  8. data/lib/moneta/adapters/client.rb +9 -0
  9. data/lib/moneta/adapters/datamapper.rb +2 -0
  10. data/lib/moneta/adapters/file.rb +2 -0
  11. data/lib/moneta/adapters/kyotocabinet.rb +39 -0
  12. data/lib/moneta/adapters/lruhash.rb +1 -1
  13. data/lib/moneta/adapters/memcached/dalli.rb +3 -5
  14. data/lib/moneta/adapters/memcached/native.rb +2 -0
  15. data/lib/moneta/adapters/mongo.rb +2 -0
  16. data/lib/moneta/adapters/pstore.rb +2 -0
  17. data/lib/moneta/adapters/redis.rb +3 -3
  18. data/lib/moneta/adapters/sequel.rb +2 -0
  19. data/lib/moneta/adapters/sqlite.rb +2 -0
  20. data/lib/moneta/adapters/tokyocabinet.rb +2 -3
  21. data/lib/moneta/adapters/yaml.rb +1 -1
  22. data/lib/moneta/cache.rb +5 -0
  23. data/lib/moneta/expires.rb +1 -0
  24. data/lib/moneta/mixins.rb +68 -1
  25. data/lib/moneta/proxy.rb +5 -0
  26. data/lib/moneta/server.rb +1 -1
  27. data/lib/moneta/stack.rb +16 -0
  28. data/lib/moneta/synchronize.rb +3 -1
  29. data/lib/moneta/version.rb +1 -1
  30. data/lib/moneta/weak.rb +15 -1
  31. data/lib/moneta/wrapper.rb +5 -0
  32. data/script/benchmarks +2 -0
  33. data/script/generate-specs +64 -37
  34. data/script/install-bundle +2 -1
  35. data/script/install-kyotocabinet +17 -0
  36. data/spec/moneta/adapter_activerecord_spec.rb +5 -0
  37. data/spec/moneta/adapter_cassandra_spec.rb +5 -0
  38. data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +5 -0
  39. data/spec/moneta/adapter_client_spec.rb +5 -0
  40. data/spec/moneta/adapter_cookie_spec.rb +5 -0
  41. data/spec/moneta/adapter_couch_spec.rb +5 -0
  42. data/spec/moneta/adapter_datamapper_spec.rb +5 -0
  43. data/spec/moneta/adapter_daybreak_spec.rb +5 -0
  44. data/spec/moneta/adapter_dbm_spec.rb +5 -0
  45. data/spec/moneta/adapter_file_spec.rb +5 -0
  46. data/spec/moneta/adapter_fog_spec.rb +5 -0
  47. data/spec/moneta/adapter_gdbm_spec.rb +5 -0
  48. data/spec/moneta/adapter_hbase_spec.rb +5 -0
  49. data/spec/moneta/adapter_kyotocabinet_spec.rb +29 -0
  50. data/spec/moneta/adapter_leveldb_spec.rb +5 -0
  51. data/spec/moneta/adapter_localmemcache_spec.rb +5 -0
  52. data/spec/moneta/adapter_lruhash_spec.rb +5 -0
  53. data/spec/moneta/adapter_memcached_dalli_spec.rb +5 -0
  54. data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +5 -0
  55. data/spec/moneta/adapter_memcached_native_spec.rb +5 -0
  56. data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +5 -0
  57. data/spec/moneta/adapter_memcached_spec.rb +5 -0
  58. data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +5 -0
  59. data/spec/moneta/adapter_memory_spec.rb +5 -0
  60. data/spec/moneta/adapter_mongo_spec.rb +5 -0
  61. data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +5 -0
  62. data/spec/moneta/adapter_pstore_spec.rb +5 -0
  63. data/spec/moneta/adapter_redis_spec.rb +5 -0
  64. data/spec/moneta/adapter_redis_with_default_expires_spec.rb +5 -0
  65. data/spec/moneta/adapter_restclient_spec.rb +5 -0
  66. data/spec/moneta/adapter_riak_spec.rb +5 -0
  67. data/spec/moneta/adapter_sdbm_spec.rb +5 -0
  68. data/spec/moneta/adapter_sequel_spec.rb +5 -0
  69. data/spec/moneta/adapter_sqlite_spec.rb +5 -0
  70. data/spec/moneta/adapter_tdb_spec.rb +5 -0
  71. data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +5 -0
  72. data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +5 -0
  73. data/spec/moneta/adapter_yaml_spec.rb +5 -0
  74. data/spec/moneta/cache_file_memory_spec.rb +5 -0
  75. data/spec/moneta/cache_memory_null_spec.rb +5 -0
  76. data/spec/moneta/expires_file_spec.rb +5 -0
  77. data/spec/moneta/expires_memory_spec.rb +5 -0
  78. data/spec/moneta/expires_memory_with_default_expires_spec.rb +5 -0
  79. data/spec/moneta/lock_spec.rb +5 -0
  80. data/spec/moneta/mutex_spec.rb +4 -0
  81. data/spec/moneta/null_adapter_spec.rb +4 -0
  82. data/spec/moneta/optionmerger_spec.rb +8 -0
  83. data/spec/moneta/pool_spec.rb +5 -0
  84. data/spec/moneta/proxy_expires_memory_spec.rb +5 -0
  85. data/spec/moneta/proxy_redis_spec.rb +5 -0
  86. data/spec/moneta/semaphore_spec.rb +4 -0
  87. data/spec/moneta/shared_tcp_spec.rb +5 -0
  88. data/spec/moneta/shared_unix_spec.rb +5 -0
  89. data/spec/moneta/simple_activerecord_spec.rb +5 -0
  90. data/spec/moneta/simple_activerecord_with_expires_spec.rb +5 -0
  91. data/spec/moneta/simple_cassandra_spec.rb +5 -0
  92. data/spec/moneta/simple_client_tcp_spec.rb +5 -0
  93. data/spec/moneta/simple_client_unix_spec.rb +5 -0
  94. data/spec/moneta/simple_couch_spec.rb +5 -0
  95. data/spec/moneta/simple_couch_with_expires_spec.rb +5 -0
  96. data/spec/moneta/simple_datamapper_spec.rb +5 -0
  97. data/spec/moneta/simple_datamapper_with_expires_spec.rb +5 -0
  98. data/spec/moneta/simple_datamapper_with_repository_spec.rb +5 -0
  99. data/spec/moneta/simple_daybreak_spec.rb +5 -0
  100. data/spec/moneta/simple_daybreak_with_expires_spec.rb +5 -0
  101. data/spec/moneta/simple_dbm_spec.rb +5 -0
  102. data/spec/moneta/simple_dbm_with_expires_spec.rb +5 -0
  103. data/spec/moneta/simple_file_spec.rb +5 -0
  104. data/spec/moneta/simple_file_with_expires_spec.rb +5 -0
  105. data/spec/moneta/simple_fog_spec.rb +5 -0
  106. data/spec/moneta/simple_fog_with_expires_spec.rb +5 -0
  107. data/spec/moneta/simple_gdbm_spec.rb +5 -0
  108. data/spec/moneta/simple_gdbm_with_expires_spec.rb +5 -0
  109. data/spec/moneta/simple_hashfile_spec.rb +5 -0
  110. data/spec/moneta/simple_hashfile_with_expires_spec.rb +5 -0
  111. data/spec/moneta/simple_hbase_spec.rb +5 -0
  112. data/spec/moneta/simple_hbase_with_expires_spec.rb +5 -0
  113. data/spec/moneta/simple_kyotocabinet_spec.rb +154 -0
  114. data/spec/moneta/simple_kyotocabinet_with_expires_spec.rb +156 -0
  115. data/spec/moneta/simple_leveldb_spec.rb +5 -0
  116. data/spec/moneta/simple_leveldb_with_expires_spec.rb +5 -0
  117. data/spec/moneta/simple_localmemcache_spec.rb +5 -0
  118. data/spec/moneta/simple_localmemcache_with_expires_spec.rb +5 -0
  119. data/spec/moneta/simple_lruhash_spec.rb +5 -0
  120. data/spec/moneta/simple_lruhash_with_expires_spec.rb +5 -0
  121. data/spec/moneta/simple_memcached_dalli_spec.rb +5 -0
  122. data/spec/moneta/simple_memcached_native_spec.rb +5 -0
  123. data/spec/moneta/simple_memcached_spec.rb +5 -0
  124. data/spec/moneta/simple_memory_spec.rb +5 -0
  125. data/spec/moneta/simple_memory_with_compress_spec.rb +5 -0
  126. data/spec/moneta/simple_memory_with_expires_spec.rb +5 -0
  127. data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +5 -0
  128. data/spec/moneta/simple_memory_with_json_serializer_spec.rb +5 -0
  129. data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +5 -0
  130. data/spec/moneta/simple_memory_with_prefix_spec.rb +5 -0
  131. data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +5 -0
  132. data/spec/moneta/simple_mongo_spec.rb +5 -0
  133. data/spec/moneta/simple_null_spec.rb +5 -0
  134. data/spec/moneta/simple_pstore_spec.rb +5 -0
  135. data/spec/moneta/simple_pstore_with_expires_spec.rb +5 -0
  136. data/spec/moneta/simple_redis_spec.rb +5 -0
  137. data/spec/moneta/simple_restclient_spec.rb +5 -0
  138. data/spec/moneta/simple_riak_spec.rb +5 -0
  139. data/spec/moneta/simple_riak_with_expires_spec.rb +5 -0
  140. data/spec/moneta/simple_sdbm_spec.rb +5 -0
  141. data/spec/moneta/simple_sdbm_with_expires_spec.rb +5 -0
  142. data/spec/moneta/simple_sequel_spec.rb +5 -0
  143. data/spec/moneta/simple_sequel_with_expires_spec.rb +5 -0
  144. data/spec/moneta/simple_sqlite_spec.rb +5 -0
  145. data/spec/moneta/simple_sqlite_with_expires_spec.rb +5 -0
  146. data/spec/moneta/simple_tdb_spec.rb +5 -0
  147. data/spec/moneta/simple_tdb_with_expires_spec.rb +5 -0
  148. data/spec/moneta/simple_tokyocabinet_spec.rb +5 -0
  149. data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +5 -0
  150. data/spec/moneta/simple_yaml_spec.rb +5 -0
  151. data/spec/moneta/simple_yaml_with_expires_spec.rb +5 -0
  152. data/spec/moneta/stack_file_memory_spec.rb +5 -0
  153. data/spec/moneta/stack_memory_file_spec.rb +7 -4
  154. data/spec/moneta/transformer_bencode_spec.rb +5 -0
  155. data/spec/moneta/transformer_bert_spec.rb +5 -0
  156. data/spec/moneta/transformer_bson_spec.rb +5 -0
  157. data/spec/moneta/transformer_bzip2_spec.rb +5 -0
  158. data/spec/moneta/transformer_json_spec.rb +5 -0
  159. data/spec/moneta/transformer_key_inspect_spec.rb +5 -0
  160. data/spec/moneta/transformer_key_marshal_spec.rb +5 -0
  161. data/spec/moneta/transformer_key_to_s_spec.rb +5 -0
  162. data/spec/moneta/transformer_key_yaml_spec.rb +5 -0
  163. data/spec/moneta/transformer_lzma_spec.rb +5 -0
  164. data/spec/moneta/transformer_lzo_spec.rb +5 -0
  165. data/spec/moneta/transformer_marshal_base64_spec.rb +5 -0
  166. data/spec/moneta/transformer_marshal_escape_spec.rb +5 -0
  167. data/spec/moneta/transformer_marshal_hmac_spec.rb +5 -0
  168. data/spec/moneta/transformer_marshal_md5_spec.rb +5 -0
  169. data/spec/moneta/transformer_marshal_md5_spread_spec.rb +5 -0
  170. data/spec/moneta/transformer_marshal_prefix_spec.rb +5 -0
  171. data/spec/moneta/transformer_marshal_rmd160_spec.rb +5 -0
  172. data/spec/moneta/transformer_marshal_sha1_spec.rb +5 -0
  173. data/spec/moneta/transformer_marshal_sha256_spec.rb +5 -0
  174. data/spec/moneta/transformer_marshal_sha384_spec.rb +5 -0
  175. data/spec/moneta/transformer_marshal_sha512_spec.rb +5 -0
  176. data/spec/moneta/transformer_marshal_spec.rb +5 -0
  177. data/spec/moneta/transformer_marshal_truncate_spec.rb +5 -0
  178. data/spec/moneta/transformer_marshal_uuencode_spec.rb +5 -0
  179. data/spec/moneta/transformer_msgpack_spec.rb +5 -0
  180. data/spec/moneta/transformer_ox_spec.rb +5 -0
  181. data/spec/moneta/transformer_quicklz_spec.rb +5 -0
  182. data/spec/moneta/transformer_snappy_spec.rb +5 -0
  183. data/spec/moneta/transformer_tnet_spec.rb +5 -0
  184. data/spec/moneta/transformer_value_marshal_spec.rb +5 -0
  185. data/spec/moneta/transformer_value_yaml_spec.rb +5 -0
  186. data/spec/moneta/transformer_yaml_spec.rb +5 -0
  187. data/spec/moneta/transformer_zlib_spec.rb +5 -0
  188. data/spec/moneta/weak_create_spec.rb +10 -91
  189. data/spec/moneta/weak_increment_spec.rb +10 -91
  190. data/spec/monetaspecs.rb +19 -0
  191. metadata +10 -2
data/.travis.yml CHANGED
@@ -9,6 +9,7 @@ rvm:
9
9
  before_install:
10
10
  - script/kill-travis
11
11
  - script/start-services
12
+ - script/install-kyotocabinet
12
13
  - sudo apt-get install -qq libtokyocabinet8 libtokyocabinet-dev liblzo2-dev libtdb-dev
13
14
  - script/install-bundle
14
15
  - script/upload-bundle
data/CHANGES CHANGED
@@ -1,3 +1,9 @@
1
+ 0.7.9
2
+
3
+ * Adapters::KyotoCabinet added
4
+ * Feature detection methods #features and #supports? added
5
+ * Validity checks added which check features
6
+
1
7
  0.7.8
2
8
 
3
9
  * Adapters::Memcached: switched to Dalli by default
data/Gemfile CHANGED
@@ -42,6 +42,7 @@ gem 'cassandra'
42
42
  gem 'tdb', :platforms => :ruby
43
43
  gem 'leveldb-ruby', :platforms => :ruby
44
44
  gem 'tokyocabinet', :platforms => :ruby
45
+ gem 'kyotocabinet-ruby', :platforms => :ruby, :github => 'minad/kyotocabinet-ruby'
45
46
  gem 'memcached', :platforms => :ruby
46
47
  gem 'jruby-memcached', :platforms => :jruby
47
48
  gem 'sqlite3', :platforms => :ruby
data/README.md CHANGED
@@ -29,6 +29,8 @@ same for template languages.
29
29
 
30
30
  Moneta is tested thoroughly using [Travis-CI](http://travis-ci.org/minad/moneta).
31
31
 
32
+ ------
33
+
32
34
  ## Getting started
33
35
 
34
36
  Install Moneta via Rubygems
@@ -61,14 +63,19 @@ store['key'] # returns 'value'
61
63
  store.close
62
64
  ~~~
63
65
 
66
+ ------
67
+
64
68
  ## Links
65
69
 
66
70
  * Source: <http://github.com/minad/moneta>
67
71
  * Bugs: <http://github.com/minad/moneta/issues>
72
+ * Tests and benchmarks: <http://travis-ci.org/minad/moneta>
68
73
  * API documentation:
69
74
  * Latest Gem: <http://rubydoc.info/gems/moneta/frames>
70
75
  * GitHub master: <http://rubydoc.info/github/minad/moneta/master/frames>
71
76
 
77
+ ------
78
+
72
79
  ## Supported backends
73
80
 
74
81
  Out of the box, it supports the following backends. Use the backend name symbol in the Moneta constructor (e.g. `Moneta.new(:Memory)`).
@@ -98,6 +105,7 @@ Out of the box, it supports the following backends. Use the backend name symbol
98
105
  * [Redis](http://redis.io/) (`:Redis`)
99
106
  * [Riak](http://docs.basho.com/) (`:Riak`)
100
107
  * [SDBM](http://www.ruby-doc.org/stdlib/libdoc/sdbm/rdoc/SDBM.html) (`:SDBM`)
108
+ * [KyotoCabinet](http://fallabs.com/kyotocabinet/) (`:KyotoCabinet`)
101
109
  * [TokyoCabinet](http://fallabs.com/tokyocabinet/) (`:TokyoCabinet`)
102
110
  * [Simple Samba database TDB](http://tdb.samba.org/) (`:TDB`)
103
111
  * Document databases:
@@ -117,53 +125,94 @@ to upgrade to a real key/value store.
117
125
 
118
126
  ### Backend feature matrix
119
127
 
128
+ __NOTE:__ <a name="backend-matrix">The backend matrix</a> is much more readable on rubydoc.info than on github. [Go there!](http://rubydoc.info/github/minad/moneta/master/file/README.md#backend-matrix)
129
+
120
130
  <table>
121
- <thead style="font-weight:bold"><tr><th>Adapter</th><th>Required gems</th><th>Multi-thread safe<sup>[1]</sup></th><th>Multi-process safe<sup>[2]</sup></th><th>Atomic increment<sup>[8]</sup></th><th>Atomic create<sup>[9]</sup></th><th>Native expires<sup>[3]</sup></th><th>Persistent</th><th>Description</th></tr></thead>
122
- <tbody>
123
- <tr><td>ActiveRecord</td><td>activerecord</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="https://rubygems.org/gems/activerecord">ActiveRecord</a> ORM</td></tr>
124
- <tr><td>Cassandra</td><td>cassandra</td><td style="text-align:center;color:blue">?</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td><a href="http://cassandra.apache.org/">Cassandra</a> distributed database</td></tr>
125
- <tr><td>Client</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:blue">?<sup>[5]</sup></td><td style="text-align:center;color:blue">?<sup>[5]</sup></td><td style="text-align:center;color:blue">?<sup>[5]</sup></td><td style="text-align:center;color:blue">?<sup>[5]</sup></td><td>Moneta client adapter</td></tr>
126
- <tr><td>Cookie</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:blue">(✓)<sup>[6]</sup></td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td>Cookie in memory store</td></tr>
127
- <tr><td>Couch</td><td>couchrest</td><td style="text-align:center;color:blue">?</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://couchdb.apache.org/">CouchDB</a> database</td></tr>
128
- <tr><td>DataMapper</td><td>dm-core, dm-migrations</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://datamapper.org/">DataMapper</a> ORM</td></tr>
129
- <tr><td>Daybreak</td><td>daybreak</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:blue">(✓)<sup>[7]</sup></td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td>Incredibly fast pure-ruby key/value store <a href="http://propublica.github.com/daybreak/">Daybreak</a></td></tr>
130
- <tr><td>DBM</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/dbm/rdoc/DBM.html">Berkeley DB</a></td></tr>
131
- <tr><td>File</td><td>-</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td>File store</td></tr>
132
- <tr><td>Fog</td><td>fog</td><td style="text-align:center;color:blue">?</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://fog.io/">Fog</a> cloud store</td></tr>
133
- <tr><td>GDBM</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/gdbm/rdoc/GDBM.html">GDBM</a> database</td></tr>
134
- <tr><td>HBase</td><td>hbase</td><td style="text-align:center;color:blue">?</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://hbase.apache.org/">HBase</a> database</td></tr>
135
- <tr><td>LevelDB</td><td>leveldb</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://code.google.com/p/leveldb/">LevelDB</a> database</td></tr>
136
- <tr><td>LocalMemCache</td><td>localmemcache</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://localmemcache.rubyforge.org/">LocalMemCache</a> database</td></tr>
137
- <tr><td>LRUHash</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:blue">(✓)<sup>[6]</sup></td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td>LRU memory store</td></tr>
138
- <tr><td>Memcached</td><td>dalli or memcached</td><td style="text-align:center;color:blue">?</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database</td></tr>
139
- <tr><td>MemcachedDalli</td><td>dalli</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database with Dalli library</td></tr>
140
- <tr><td>MemcachedNative</td><td>memcached</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗<sup>[4]</sup></td><td>Memcached database with native library</td></tr>
141
- <tr><td>Memory</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:blue">(✓)<sup>[6]</sup></td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td>Memory store</td></tr>
142
- <tr><td>Mongo</td><td>mongo</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td><a href="http://www.mongodb.org/">MongoDB</a> database</td></tr>
143
- <tr><td>Null</td><td>-</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td>No database</td></tr>
144
- <tr><td>PStore</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://ruby-doc.org/stdlib/libdoc/pstore/rdoc/PStore.html">PStore</a> store</td></tr>
145
- <tr><td>Redis</td><td>redis</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td><a href="http://redis.io/">Redis</a> database</td></tr>
146
- <tr><td>RestClient</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:blue">?<sup>[5]</sup></td><td>Moneta REST client adapter</td></tr>
147
- <tr><td>Riak</td><td>riak-client</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://docs.basho.com/">Riak</a> database</td></tr>
148
- <tr><td>SDBM</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/sdbm/rdoc/SDBM.html">SDBM</a> database</td></tr>
149
- <tr><td>Sequel</td><td>sequel</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://sequel.rubyforge.org/">Sequel</a> ORM</td></tr>
150
- <tr><td>Sqlite</td><td>sqlite3</td><td style="text-align:center;color:blue">?</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://sqlite.org/">Sqlite3</a> database</td></tr>
151
- <tr><td>TDB</td><td>tdb</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://tdb.samba.org/">TDB</a> database</td></tr>
152
- <tr><td>TokyoCabinet</td><td>tokoycabinet</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://fallabs.com/tokyocabinet/">TokyoCabinet</a> database</td></tr>
153
- <tr><td>YAML</td><td>-</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:green">✓</td><td style="text-align:center;color:red">✗</td><td style="text-align:center;color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/yaml/rdoc/YAML/Store.html">YAML</a> store</td></tr>
154
- </tbody>
131
+
132
+ <tr><th>Adapter</th><th>Required gems</th><th>Multi-thread safe<sup>[1]</sup></th><th>Multi-process safe<sup>[2]</sup></th><th>Atomic increment<sup>[8]</sup></th><th>Atomic create<sup>[9]</sup></th><th>Native expires<sup>[3]</sup></th><th>Persistent</th><th>Description</th></tr>
133
+
134
+ <tr><th colspan="2">Persistent stores</th><th colspan="7"></th></tr>
135
+
136
+ <tr><td>Mongo</td><td>mongo</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.mongodb.org/">MongoDB</a> database</td></tr>
137
+
138
+ <tr><td>Redis</td><td>redis</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://redis.io/">Redis</a> database</td></tr>
139
+
140
+ <tr><td>ActiveRecord</td><td>activerecord</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="https://rubygems.org/gems/activerecord">ActiveRecord</a> ORM</td></tr>
141
+
142
+ <tr><td>File</td><td>-</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td>File store</td></tr>
143
+
144
+ <tr><td>Sequel</td><td>sequel</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://sequel.rubyforge.org/">Sequel</a> ORM</td></tr>
145
+
146
+ <tr><td>Sqlite</td><td>sqlite3</td><td style="text-align:center;background:#55F">?</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://sqlite.org/">Sqlite3</a> database</td></tr>
147
+
148
+ <tr><td>PStore</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://ruby-doc.org/stdlib/libdoc/pstore/rdoc/PStore.html">PStore</a> store</td></tr>
149
+
150
+ <tr><td>YAML</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/yaml/rdoc/YAML/Store.html">YAML</a> store</td></tr>
151
+
152
+ <tr><td>Daybreak</td><td>daybreak</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[7]</sup></td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td>Incredibly fast pure-ruby key/value store <a href="http://propublica.github.com/daybreak/">Daybreak</a></td></tr>
153
+
154
+ <tr><td>DBM</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/dbm/rdoc/DBM.html">Berkeley DB</a></td></tr>
155
+
156
+ <tr><td>GDBM</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/gdbm/rdoc/GDBM.html">GDBM</a> database</td></tr>
157
+
158
+ <tr><td>LevelDB</td><td>leveldb</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://code.google.com/p/leveldb/">LevelDB</a> database</td></tr>
159
+
160
+ <tr><td>SDBM</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/sdbm/rdoc/SDBM.html">SDBM</a> database</td></tr>
161
+
162
+ <tr><td>TDB</td><td>tdb</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://tdb.samba.org/">TDB</a> database</td></tr>
163
+
164
+ <tr><td>KyotoCabinet</td><td>tokoycabinet</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://fallabs.com/kyotocabinet/">KyotoCabinet</a> database</td></tr>
165
+
166
+ <tr><td>TokyoCabinet</td><td>tokoycabinet</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://fallabs.com/tokyocabinet/">TokyoCabinet</a> database</td></tr>
167
+
168
+ <tr><td>DataMapper</td><td>dm-core, dm-migrations</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://datamapper.org/">DataMapper</a> ORM</td></tr>
169
+
170
+ <tr><td>Cassandra</td><td>cassandra</td><td style="text-align:center;background:#55F">?</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://cassandra.apache.org/">Cassandra</a> distributed database</td></tr>
171
+
172
+ <tr><td>LocalMemCache</td><td>localmemcache</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://localmemcache.rubyforge.org/">LocalMemCache</a> database</td></tr>
173
+
174
+ <tr><td>Couch</td><td>couchrest</td><td style="text-align:center;background:#55F">?</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://couchdb.apache.org/">CouchDB</a> database</td></tr>
175
+
176
+ <tr><td>Fog</td><td>fog</td><td style="text-align:center;background:#55F">?</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://fog.io/">Fog</a> cloud store</td></tr>
177
+
178
+ <tr><td>HBase</td><td>hbase</td><td style="text-align:center;background:#55F">?</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://hbase.apache.org/">HBase</a> database</td></tr>
179
+
180
+ <tr><td>Riak</td><td>riak-client</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td><a href="http://docs.basho.com/">Riak</a> database</td></tr>
181
+
182
+ <tr><th colspan="2">Non persistent stores</th><th colspan="7"></th></tr>
183
+
184
+ <tr><td>MemcachedDalli</td><td>dalli</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database with Dalli library</td></tr>
185
+
186
+ <tr><td>Memcached</td><td>dalli or memcached</td><td style="text-align:center;background:#55F">?</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database</td></tr>
187
+
188
+ <tr><td>MemcachedNative</td><td>memcached</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗<sup>[4]</sup></td><td>Memcached database with native library</td></tr>
189
+
190
+ <tr><td>Cookie</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[6]</sup></td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td>Cookie in memory store</td></tr>
191
+
192
+ <tr><td>LRUHash</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[6]</sup></td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td>LRU memory store</td></tr>
193
+
194
+ <tr><td>Memory</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">(✓)<sup>[6]</sup></td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td>Memory store</td></tr>
195
+
196
+ <tr><td>Null</td><td>-</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td>No database</td></tr>
197
+
198
+ <tr><td>Client</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td>Moneta client adapter</td></tr>
199
+
200
+ <tr><td>RestClient</td><td>-</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#5F5">✓</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#F44">✗</td><td style="text-align:center;background:#55F">?<sup>[5]</sup></td><td>Moneta REST client adapter</td></tr>
201
+
155
202
  </table>
156
203
 
157
204
  * [1]: Make adapters thread-safe by using `Moneta::Lock` or by passing the option `:threadsafe => true` to `Moneta#new`. There is also `Moneta::Pool` which can be used to share a store between multiple threads if the store is multi-process safe. I recommend to add the option `:threadsafe` to ensure thread-safety since for example under JRuby and Rubinius even the basic datastructures are not thread safe due to the lack of a global interpreter lock (GIL). This differs from MRI where some adapters might appear thread safe already but only due to the GIL.
158
205
  * [2]: Share a Moneta store between multiple processes using `Moneta::Shared` (See below).
159
206
  * [3]: Add expiration support by using `Moneta::Expires` or by passing the option `:expires => true` to `Moneta#new`.
160
- * [4]: There are some servers which use the memcached protocol but which are persistent (e.g. [MemcacheDB](http://memcachedb.org/), [Kai](http://sourceforge.net/apps/mediawiki/kai), [IronCache](http://dev.iron.io/cache/reference/memcache/))
207
+ * [4]: There are some servers which use the memcached protocol but which are persistent (e.g. [MemcacheDB](http://memcachedb.org/), [Kai](http://sourceforge.net/apps/mediawiki/kai), [IronCache](http://dev.iron.io/cache/reference/memcache/), [Roma](https://github.com/roma/roma/tree))
161
208
  * [5]: Depends on server
162
209
  * [6]: Store is multi-process safe because it is an in-memory store, values are not shared between multiple processes
163
210
  * [7]: Store is multi-process safe, but not synchronized automatically between multiple processes
164
211
  * [8]: If a store provides atomic increment it can be used with `Moneta::Semaphore`. You can add weak `#increment` using the `Moneta::WeakIncrement` proxy.
165
212
  * [8]: If a store provides atomic creation it can be used with `Moneta::Mutex`. You can add weak `#create` using the `Moneta::WeakCreate` proxy.
166
213
 
214
+ ------
215
+
167
216
  ## Proxies
168
217
 
169
218
  In addition it supports proxies (Similar to [Rack middlewares](http://rack.github.com/)) which
@@ -208,11 +257,13 @@ Special transformers:
208
257
  * Add prefix to keys (`:prefix`)
209
258
  * HMAC to verify values (`:hmac`, useful for `Rack::MonetaCookies`)
210
259
 
260
+ ------
261
+
211
262
  ## Moneta API
212
263
 
213
264
  The Moneta API is purposely extremely similar to the Hash API with a few minor additions.
214
- There are the additional methods `#load`, `#increment`, `#decrement`, `#create` and `#close`. Every method takes also a optional
215
- option hash. In order so support an identical API across stores, Moneta does not support iteration or partial matches.
265
+ Every method takes also a optional option hash. In order so support an identical API across stores,
266
+ Moneta does not support iteration or partial matches.
216
267
 
217
268
  ~~~
218
269
  #initialize(options) options differs per-store, and is used to set up the store.
@@ -248,6 +299,10 @@ option hash. In order so support an identical API across stores, Moneta does not
248
299
  #clear(options = {}) clear all keys in this store.
249
300
 
250
301
  #close close database connection.
302
+
303
+ #features return array of features, e.g. [:create, :expires, :increment]
304
+
305
+ #supports?(feature) returns true if store supports a given feature
251
306
  ~~~
252
307
 
253
308
  ### Creating a Store
@@ -384,7 +439,7 @@ store.create('key', 'other value') # returns false
384
439
  Moneta provides shared/distributed synchronization primitives which are shared database-wide between
385
440
  all clients.
386
441
 
387
- * `Moneta::Mutex`
442
+ `Moneta::Mutex` allows a single thread to enter a critical section.
388
443
 
389
444
  ~~~ ruby
390
445
  mutex = Moneta::Mutex.new(store, 'mutex_key')
@@ -405,7 +460,7 @@ ensure
405
460
  end
406
461
  ~~~
407
462
 
408
- * `Moneta::Semaphore`
463
+ `Moneta::Semaphore` allows `max_concurrent` threads to enter a critical section.
409
464
 
410
465
  ~~~ ruby
411
466
  semaphore = Moneta::Semaphore.new(store, 'semaphore_counter', max_concurrent)
@@ -471,6 +526,8 @@ store['key'] = 'this value will not be compressed'
471
526
  compressed_store['key'] = 'value will be compressed'
472
527
  ~~~
473
528
 
529
+ ------
530
+
474
531
  ## Framework Integration
475
532
 
476
533
  Inspired by [redis-store](https://github.com/jodosha/redis-store) there exist integration classes for [Rails](http://rubyonrails.org/) and [Rack](http://rack.github.com/)/[Rack-Cache](https://github.com/rtomayko/rack-cache). You can also use all the Rack middlewares together with Rails and the [Sinatra](http://sinatrarb.com/) framework. There exist the following integration classes:
@@ -637,6 +694,8 @@ config.cache_store :moneta_store, :store => Moneta.build do
637
694
  end
638
695
  ~~~
639
696
 
697
+ ------
698
+
640
699
  ## Advanced
641
700
 
642
701
  ### Build your own key value server
@@ -684,6 +743,8 @@ add persistence using Moneta as follows:
684
743
  Person.adapter :memory, Moneta.new(:Redis)
685
744
  ~~~
686
745
 
746
+ ------
747
+
687
748
  ## Testing and Benchmarks
688
749
 
689
750
  Testing is done using [Travis-CI](http://travis-ci.org/minad/moneta). Currently we support Ruby 1.8.7 and 1.9.3.
@@ -693,13 +754,19 @@ to compare the speed of the different key value stores for different key/value s
693
754
  Feel free to add your own configurations! The impact of Moneta should be minimal since it is only a thin layer
694
755
  on top of the different stores.
695
756
 
757
+ ------
758
+
696
759
  ## Alternatives
697
760
 
698
761
  * [Horcrux](https://github.com/technoweenie/horcrux): Used at github, supports batch operations but only Memcached backend
699
762
  * [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html): The Rails cache store abstraction
700
- * [Padrino::Cache::Store](http://www.padrinorb.com/api/Padrino/Cache/Store.html): The Padrino cache store abstraction
763
+ * [Padrino::Cache::Store](http://www.padrinorb.com/api/Padrino/Cache/Store.html): The Padrino cache store abstraction. Padrino is currently considering switching to Moneta, see https://github.com/padrino/padrino-framework/pull/1018
701
764
  * [ToyStore](https://github.com/jnunemaker/toystore): ORM mapper for key/value stores
702
765
  * [ToyStore Adapter](https://github.com/jnunemaker/adapter): Adapter to key/value stores used by ToyStore, Moneta can be used directly with the ToyStore Memory adapter
766
+ * [Cache](https://github.com/seamusabshere/cache): Rubygem cache wraps Memcached and Redis
767
+ * [Ramaze::Cache](http://ramaze.net/documentation/Innate/Cache.html): Cache stores of the Ramaze framework with support for LocalMemCache, Memcached, Sequel, Redis, ...
768
+
769
+ ------
703
770
 
704
771
  ## Authors
705
772
 
data/SPEC.md CHANGED
@@ -59,6 +59,14 @@ It MUST return true if the value was created.
59
59
 
60
60
  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.
61
61
 
62
+ ### <code>close</code>
63
+
64
+ Closes the store
65
+
66
+ ### <code>features => Array&lt;Symbol&gt;</code> and <code>supports?(Symbol) => [TrueClass, FalseClass]</code>
67
+
68
+ Feature detection. Adapters MUST return <code>:create</code> and <code>:increment</code> if these methods are supported.
69
+
62
70
  ## Additional Options Hashes
63
71
 
64
72
  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.
data/lib/moneta.rb CHANGED
@@ -39,6 +39,7 @@ module Moneta
39
39
  autoload :GDBM, 'moneta/adapters/gdbm'
40
40
  autoload :HBase, 'moneta/adapters/hbase'
41
41
  autoload :LRUHash, 'moneta/adapters/lruhash'
42
+ autoload :KyotoCabinet, 'moneta/adapters/kyotocabinet'
42
43
  autoload :LevelDB, 'moneta/adapters/leveldb'
43
44
  autoload :LocalMemCache, 'moneta/adapters/localmemcache'
44
45
  autoload :Memcached, 'moneta/adapters/memcached'
@@ -88,7 +89,8 @@ module Moneta
88
89
  #
89
90
  # @api public
90
91
  def self.new(name, options = {})
91
- expires = options.delete(:expires)
92
+ expires = options[:expires]
93
+ options.delete(:expires) unless Integer === expires
92
94
  logger = options.delete(:logger)
93
95
  threadsafe = options.delete(:threadsafe)
94
96
  compress = options.delete(:compress)
@@ -118,17 +120,14 @@ module Moneta
118
120
  when :File
119
121
  # Use escaping
120
122
  transformer[:key] << :escape
121
- when :Cassandra, :Redis, :Mongo, :Memcached, :MemcachedDalli, :MemcachedNative
122
- # Expires already supported
123
- options[:expires] = expires if Integer === expires
124
- expires = false
125
123
  end
124
+ a = Adapters.const_get(name).new(options)
126
125
  build do
127
126
  use :Logger, Hash === logger ? logger : {} if logger
128
- use :Expires, :expires => (Integer === expires ? expires : nil) if expires
127
+ use :Expires, :expires => options[:expires] if !a.supports?(:expires) && expires
129
128
  use :Transformer, transformer
130
129
  use :Lock if threadsafe
131
- adapter name, options
130
+ adapter a
132
131
  end
133
132
  end
134
133
 
@@ -7,6 +7,8 @@ module Moneta
7
7
  class ActiveRecord
8
8
  include Defaults
9
9
 
10
+ supports :create, :increment
11
+
10
12
  def self.tables
11
13
  @tables ||= {}
12
14
  end
@@ -67,6 +67,15 @@ module Moneta
67
67
  nil
68
68
  end
69
69
 
70
+ # (see Default#features)
71
+ def features
72
+ @features ||=
73
+ begin
74
+ write(@socket, [:features])
75
+ read_result.freeze
76
+ end
77
+ end
78
+
70
79
  private
71
80
 
72
81
  def read_result
@@ -8,6 +8,8 @@ module Moneta
8
8
  class DataMapper
9
9
  include Defaults
10
10
 
11
+ supports :create
12
+
11
13
  class Store
12
14
  include ::DataMapper::Resource
13
15
  property :k, Text, :key => true
@@ -9,6 +9,8 @@ module Moneta
9
9
  include Defaults
10
10
  include IncrementSupport
11
11
 
12
+ supports :create
13
+
12
14
  # @param [Hash] options
13
15
  # @option options [String] :dir Directory where files will be stored
14
16
  def initialize(options = {})
@@ -0,0 +1,39 @@
1
+ require 'kyotocabinet'
2
+
3
+ module Moneta
4
+ module Adapters
5
+ # KyotoCabinet backend
6
+ # @api public
7
+ class KyotoCabinet < Memory
8
+ # @param [Hash] options
9
+ # @option options [String] :file Database file
10
+ def initialize(options = {})
11
+ raise ArgumentError, 'Option :file is required' unless options[:file]
12
+ @hash = ::KyotoCabinet::DB.new
13
+ raise @hash.error.to_s unless @hash.open(options[:file],
14
+ ::KyotoCabinet::DB::OWRITER | ::KyotoCabinet::DB::OCREATE)
15
+ end
16
+
17
+ # (see Proxy#key?)
18
+ def key?(key, options = {})
19
+ @hash.check(key) >= 0
20
+ end
21
+
22
+ # (see Proxy#delete)
23
+ def delete(key, options = {})
24
+ @hash.seize(key)
25
+ end
26
+
27
+ # (see Proxy#create)
28
+ def create(key, value, options = {})
29
+ @hash.add(key, value)
30
+ end
31
+
32
+ # (see Proxy#close)
33
+ def close
34
+ @hash.close
35
+ nil
36
+ end
37
+ end
38
+ end
39
+ end
@@ -2,7 +2,7 @@ module Moneta
2
2
  module Adapters
3
3
  # LRUHash backend
4
4
  #
5
- # Based on Hashery::LRUHash but simpler and measures memory usage instead of hash size.
5
+ # Based on Hashery::LRUHash but simpler and measures both memory usage and hash size.
6
6
  #
7
7
  # @api public
8
8
  class LRUHash
@@ -8,6 +8,8 @@ module Moneta
8
8
  include Defaults
9
9
  include ExpiresSupport
10
10
 
11
+ supports :create, :increment
12
+
11
13
  # @param [Hash] options
12
14
  # @option options [String] :server ('127.0.0.1:11211') Memcached server
13
15
  # @option options [Integer] :expires Default expiration time
@@ -46,11 +48,7 @@ module Moneta
46
48
  # FIXME: There is a Dalli bug, load(key) returns a wrong value after increment
47
49
  # therefore we set default = nil and create the counter manually
48
50
  # See https://github.com/mperham/dalli/issues/309
49
- result = if amount >= 0
50
- @cache.incr(key, amount, expires_value(options) || nil, nil)
51
- else
52
- @cache.decr(key, -amount, expires_value(options) || nil, nil)
53
- end
51
+ result = amount >= 0 ? @cache.incr(key, amount, nil, nil) : @cache.decr(key, -amount, nil, nil)
54
52
  if result
55
53
  result
56
54
  elsif create(key, amount.to_s, options)