moneta 0.7.5 → 0.7.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (160) hide show
  1. data/CHANGES +6 -0
  2. data/README.md +52 -51
  3. data/Rakefile +1 -3
  4. data/lib/moneta/adapters/daybreak.rb +7 -9
  5. data/lib/moneta/adapters/file.rb +2 -2
  6. data/lib/moneta/adapters/memcached/dalli.rb +1 -0
  7. data/lib/moneta/adapters/memcached/native.rb +1 -0
  8. data/lib/moneta/transformer.rb +4 -4
  9. data/lib/moneta/transformer/config.rb +2 -1
  10. data/lib/moneta/version.rb +1 -1
  11. data/script/benchmarks +52 -44
  12. data/script/generate-specs +238 -49
  13. data/spec/helper.rb +4 -0
  14. data/spec/moneta/adapter_activerecord_spec.rb +5 -0
  15. data/spec/moneta/adapter_cassandra_spec.rb +5 -0
  16. data/spec/moneta/adapter_cassandra_with_default_expires_spec.rb +5 -0
  17. data/spec/moneta/adapter_client_spec.rb +5 -0
  18. data/spec/moneta/adapter_cookie_spec.rb +4 -0
  19. data/spec/moneta/adapter_couch_spec.rb +5 -0
  20. data/spec/moneta/adapter_datamapper_spec.rb +5 -0
  21. data/spec/moneta/adapter_daybreak_spec.rb +4 -0
  22. data/spec/moneta/adapter_dbm_spec.rb +4 -0
  23. data/spec/moneta/adapter_file_spec.rb +5 -0
  24. data/spec/moneta/adapter_fog_spec.rb +5 -0
  25. data/spec/moneta/adapter_gdbm_spec.rb +5 -0
  26. data/spec/moneta/adapter_hbase_spec.rb +5 -0
  27. data/spec/moneta/adapter_leveldb_spec.rb +4 -0
  28. data/spec/moneta/adapter_localmemcache_spec.rb +5 -0
  29. data/spec/moneta/adapter_lruhash_spec.rb +4 -0
  30. data/spec/moneta/adapter_memcached_dalli_spec.rb +5 -0
  31. data/spec/moneta/adapter_memcached_dalli_with_default_expires_spec.rb +5 -0
  32. data/spec/moneta/adapter_memcached_native_spec.rb +5 -0
  33. data/spec/moneta/adapter_memcached_native_with_default_expires_spec.rb +5 -0
  34. data/spec/moneta/adapter_memcached_spec.rb +5 -0
  35. data/spec/moneta/adapter_memcached_with_default_expires_spec.rb +5 -0
  36. data/spec/moneta/adapter_memory_spec.rb +4 -0
  37. data/spec/moneta/adapter_mongo_spec.rb +5 -0
  38. data/spec/moneta/adapter_mongo_with_default_expires_spec.rb +5 -0
  39. data/spec/moneta/adapter_pstore_spec.rb +5 -0
  40. data/spec/moneta/adapter_redis_spec.rb +5 -0
  41. data/spec/moneta/adapter_redis_with_default_expires_spec.rb +5 -0
  42. data/spec/moneta/adapter_restclient_spec.rb +5 -0
  43. data/spec/moneta/adapter_riak_spec.rb +5 -0
  44. data/spec/moneta/adapter_sdbm_spec.rb +4 -0
  45. data/spec/moneta/adapter_sequel_spec.rb +5 -0
  46. data/spec/moneta/adapter_sqlite_spec.rb +5 -0
  47. data/spec/moneta/adapter_tdb_spec.rb +4 -0
  48. data/spec/moneta/adapter_tokyocabinet_bdb_spec.rb +4 -0
  49. data/spec/moneta/adapter_tokyocabinet_hdb_spec.rb +4 -0
  50. data/spec/moneta/adapter_yaml_spec.rb +5 -0
  51. data/spec/moneta/cache_file_memory_spec.rb +5 -0
  52. data/spec/moneta/cache_memory_null_spec.rb +4 -0
  53. data/spec/moneta/expires_file_spec.rb +5 -0
  54. data/spec/moneta/expires_memory_spec.rb +4 -0
  55. data/spec/moneta/expires_memory_with_default_expires_spec.rb +4 -0
  56. data/spec/moneta/lock_spec.rb +4 -0
  57. data/spec/moneta/null_adapter_spec.rb +4 -0
  58. data/spec/moneta/optionmerger_spec.rb +5 -1
  59. data/spec/moneta/pool_spec.rb +5 -0
  60. data/spec/moneta/proxy_expires_memory_spec.rb +4 -0
  61. data/spec/moneta/proxy_redis_spec.rb +5 -0
  62. data/spec/moneta/shared_spec.rb +5 -0
  63. data/spec/moneta/simple_activerecord_spec.rb +6 -1
  64. data/spec/moneta/simple_activerecord_with_expires_spec.rb +6 -1
  65. data/spec/moneta/simple_cassandra_spec.rb +6 -1
  66. data/spec/moneta/simple_client_tcp_spec.rb +6 -1
  67. data/spec/moneta/simple_client_unix_spec.rb +6 -1
  68. data/spec/moneta/simple_couch_spec.rb +6 -1
  69. data/spec/moneta/simple_couch_with_expires_spec.rb +6 -1
  70. data/spec/moneta/simple_datamapper_spec.rb +6 -1
  71. data/spec/moneta/simple_datamapper_with_expires_spec.rb +6 -1
  72. data/spec/moneta/simple_datamapper_with_repository_spec.rb +6 -1
  73. data/spec/moneta/simple_daybreak_spec.rb +5 -1
  74. data/spec/moneta/simple_daybreak_with_expires_spec.rb +5 -1
  75. data/spec/moneta/simple_dbm_spec.rb +5 -1
  76. data/spec/moneta/simple_dbm_with_expires_spec.rb +5 -1
  77. data/spec/moneta/simple_file_spec.rb +6 -1
  78. data/spec/moneta/simple_file_with_expires_spec.rb +6 -1
  79. data/spec/moneta/simple_fog_spec.rb +6 -1
  80. data/spec/moneta/simple_fog_with_expires_spec.rb +6 -1
  81. data/spec/moneta/simple_gdbm_spec.rb +5 -1
  82. data/spec/moneta/simple_gdbm_with_expires_spec.rb +5 -1
  83. data/spec/moneta/simple_hashfile_spec.rb +6 -1
  84. data/spec/moneta/simple_hashfile_with_expires_spec.rb +6 -1
  85. data/spec/moneta/simple_hbase_spec.rb +6 -1
  86. data/spec/moneta/simple_hbase_with_expires_spec.rb +6 -1
  87. data/spec/moneta/simple_leveldb_spec.rb +5 -1
  88. data/spec/moneta/simple_leveldb_with_expires_spec.rb +5 -1
  89. data/spec/moneta/simple_localmemcache_spec.rb +6 -1
  90. data/spec/moneta/simple_localmemcache_with_expires_spec.rb +6 -1
  91. data/spec/moneta/simple_lruhash_spec.rb +5 -1
  92. data/spec/moneta/simple_lruhash_with_expires_spec.rb +5 -1
  93. data/spec/moneta/simple_memcached_dalli_spec.rb +6 -1
  94. data/spec/moneta/simple_memcached_native_spec.rb +6 -1
  95. data/spec/moneta/simple_memcached_spec.rb +6 -1
  96. data/spec/moneta/simple_memory_spec.rb +5 -1
  97. data/spec/moneta/simple_memory_with_compress_spec.rb +5 -1
  98. data/spec/moneta/simple_memory_with_expires_spec.rb +5 -1
  99. data/spec/moneta/simple_memory_with_json_key_serializer_spec.rb +5 -1
  100. data/spec/moneta/simple_memory_with_json_serializer_spec.rb +5 -1
  101. data/spec/moneta/simple_memory_with_json_value_serializer_spec.rb +5 -1
  102. data/spec/moneta/simple_memory_with_prefix_spec.rb +5 -1
  103. data/spec/moneta/simple_memory_with_snappy_compress_spec.rb +5 -1
  104. data/spec/moneta/simple_mongo_spec.rb +6 -1
  105. data/spec/moneta/simple_null_spec.rb +5 -1
  106. data/spec/moneta/simple_pstore_spec.rb +6 -1
  107. data/spec/moneta/simple_pstore_with_expires_spec.rb +6 -1
  108. data/spec/moneta/simple_redis_spec.rb +6 -1
  109. data/spec/moneta/simple_restclient_spec.rb +6 -1
  110. data/spec/moneta/simple_riak_spec.rb +6 -1
  111. data/spec/moneta/simple_riak_with_expires_spec.rb +6 -1
  112. data/spec/moneta/simple_sdbm_spec.rb +5 -1
  113. data/spec/moneta/simple_sdbm_with_expires_spec.rb +5 -1
  114. data/spec/moneta/simple_sequel_spec.rb +6 -1
  115. data/spec/moneta/simple_sequel_with_expires_spec.rb +6 -1
  116. data/spec/moneta/simple_sqlite_spec.rb +6 -1
  117. data/spec/moneta/simple_sqlite_with_expires_spec.rb +6 -1
  118. data/spec/moneta/simple_tdb_spec.rb +5 -1
  119. data/spec/moneta/simple_tdb_with_expires_spec.rb +5 -1
  120. data/spec/moneta/simple_tokyocabinet_spec.rb +5 -1
  121. data/spec/moneta/simple_tokyocabinet_with_expires_spec.rb +5 -1
  122. data/spec/moneta/simple_yaml_spec.rb +6 -1
  123. data/spec/moneta/simple_yaml_with_expires_spec.rb +6 -1
  124. data/spec/moneta/stack_file_memory_spec.rb +5 -0
  125. data/spec/moneta/stack_memory_file_spec.rb +5 -0
  126. data/spec/moneta/transformer_bencode_spec.rb +8 -0
  127. data/spec/moneta/transformer_bert_spec.rb +8 -0
  128. data/spec/moneta/transformer_bson_spec.rb +8 -0
  129. data/spec/moneta/transformer_bzip2_spec.rb +8 -0
  130. data/spec/moneta/transformer_json_spec.rb +8 -0
  131. data/spec/moneta/transformer_key_marshal_spec.rb +8 -0
  132. data/spec/moneta/transformer_key_to_s_spec.rb +72 -0
  133. data/spec/moneta/transformer_key_yaml_spec.rb +8 -0
  134. data/spec/moneta/transformer_lzma_spec.rb +8 -0
  135. data/spec/moneta/transformer_lzo_spec.rb +8 -0
  136. data/spec/moneta/transformer_marshal_base64_spec.rb +8 -0
  137. data/spec/moneta/transformer_marshal_escape_spec.rb +8 -0
  138. data/spec/moneta/transformer_marshal_hmac_spec.rb +8 -0
  139. data/spec/moneta/transformer_marshal_md5_spec.rb +8 -0
  140. data/spec/moneta/transformer_marshal_md5_spread_spec.rb +8 -0
  141. data/spec/moneta/transformer_marshal_prefix_spec.rb +8 -0
  142. data/spec/moneta/transformer_marshal_rmd160_spec.rb +8 -0
  143. data/spec/moneta/transformer_marshal_sha1_spec.rb +8 -0
  144. data/spec/moneta/transformer_marshal_sha256_spec.rb +8 -0
  145. data/spec/moneta/transformer_marshal_sha384_spec.rb +8 -0
  146. data/spec/moneta/transformer_marshal_sha512_spec.rb +8 -0
  147. data/spec/moneta/transformer_marshal_spec.rb +8 -0
  148. data/spec/moneta/transformer_marshal_truncate_spec.rb +8 -0
  149. data/spec/moneta/transformer_marshal_uuencode_spec.rb +8 -0
  150. data/spec/moneta/transformer_msgpack_spec.rb +8 -0
  151. data/spec/moneta/transformer_ox_spec.rb +8 -0
  152. data/spec/moneta/transformer_quicklz_spec.rb +8 -0
  153. data/spec/moneta/transformer_snappy_spec.rb +8 -0
  154. data/spec/moneta/transformer_tnet_spec.rb +8 -0
  155. data/spec/moneta/transformer_value_marshal_spec.rb +8 -0
  156. data/spec/moneta/transformer_value_yaml_spec.rb +8 -0
  157. data/spec/moneta/transformer_yaml_spec.rb +8 -0
  158. data/spec/moneta/transformer_zlib_spec.rb +8 -0
  159. data/spec/monetaspecs.rb +11 -0
  160. metadata +4 -2
data/CHANGES CHANGED
@@ -1,3 +1,9 @@
1
+ 0.7.6
2
+
3
+ * Adapters::Daybreak: api changed
4
+ * Adapters::File: flock fix for jruby
5
+ * Transformer: add to_s key transformer
6
+
1
7
  0.7.5
2
8
 
3
9
  * OptionsSupport#with: Add support to insert additional proxies
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Moneta: A unified interface for key/value stores
2
2
 
3
- [![Build Status](https://secure.travis-ci.org/minad/moneta.png?branch=master)](http://travis-ci.org/minad/moneta) [![Dependency Status](https://gemnasium.com/minad/moneta.png?travis)](https://gemnasium.com/minad/moneta) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/minad/moneta)
3
+ [![Gem Version](https://badge.fury.io/rb/moneta.png)](http://rubygems.org/gems/moneta) [![Build Status](https://secure.travis-ci.org/minad/moneta.png?branch=master)](http://travis-ci.org/minad/moneta) [![Dependency Status](https://gemnasium.com/minad/moneta.png?travis)](https://gemnasium.com/minad/moneta) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/minad/moneta)
4
4
 
5
5
  Moneta provides a standard interface for interacting with various kinds of key/value stores. A short overview of the features:
6
6
 
@@ -41,38 +41,38 @@ Out of the box, it supports the following backends:
41
41
  * Memory:
42
42
  * In-memory store (`:Memory`)
43
43
  * LRU hash - prefer this over :Memory! (`:LRUHash`)
44
- * LocalMemCache (`:LocalMemCache`)
45
- * Memcached store (`:Memcached`, `:MemcachedNative` and `:MemcachedDalli`)
44
+ * [LocalMemCache](http://localmemcache.rubyforge.org/) (`:LocalMemCache`)
45
+ * [Memcached](http://memcached.org/) store (`:Memcached`, `:MemcachedNative` and `:MemcachedDalli`)
46
46
  * Relational Databases:
47
- * DataMapper (`:DataMapper`)
48
- * ActiveRecord (`:ActiveRecord`)
49
- * Sequel (`:Sequel`)
50
- * Sqlite3 (`:Sqlite`)
47
+ * [DataMapper](http://datamapper.org/) (`:DataMapper`)
48
+ * [ActiveRecord](https://rubygems.org/gems/activerecord) (`:ActiveRecord`)
49
+ * [Sequel](http://sequel.rubyforge.org/) (`:Sequel`)
50
+ * [Sqlite3](http://sqlite.org/) (`:Sqlite`)
51
51
  * Filesystem:
52
- * PStore (`:PStore`)
53
- * YAML store (`:YAML`)
52
+ * [PStore](http://ruby-doc.org/stdlib/libdoc/pstore/rdoc/PStore.html) (`:PStore`)
53
+ * [YAML](http://www.ruby-doc.org/stdlib/libdoc/yaml/rdoc/YAML/Store.html) store (`:YAML`)
54
54
  * Filesystem directory store (`:File`)
55
55
  * Filesystem directory store which spreads files in subdirectories using md5 hash (`:HashFile`)
56
56
  * Key/value databases:
57
- * Berkeley DB (`:DBM`)
58
- * Cassandra (`:Cassandra`)
59
- * Daybreak (`:Daybreak`)
60
- * GDBM (`:GDBM`)
61
- * HBase (`:HBase`)
62
- * LevelDB (`:LevelDB`)
63
- * Redis (`:Redis`)
64
- * Riak (`:Riak`)
65
- * SDBM (`:SDBM`)
66
- * TokyoCabinet (`:TokyoCabinet`)
67
- * Simple Samba database TDB (`:TDB`)
57
+ * [Berkeley DB](http://www.ruby-doc.org/stdlib/libdoc/dbm/rdoc/DBM.html) (`:DBM`)
58
+ * [Cassandra](http://cassandra.apache.org/) (`:Cassandra`)
59
+ * [Daybreak](http://propublica.github.com/daybreak/) (`:Daybreak`)
60
+ * [GDBM](http://www.ruby-doc.org/stdlib/libdoc/gdbm/rdoc/GDBM.html) (`:GDBM`)
61
+ * [HBase](http://hbase.apache.org/) (`:HBase`)
62
+ * [LevelDB](http://code.google.com/p/leveldb/) (`:LevelDB`)
63
+ * [Redis](http://redis.io/) (`:Redis`)
64
+ * [Riak](http://docs.basho.com/) (`:Riak`)
65
+ * [SDBM](http://www.ruby-doc.org/stdlib/libdoc/sdbm/rdoc/SDBM.html) (`:SDBM`)
66
+ * [TokyoCabinet](http://fallabs.com/tokyocabinet/) (`:TokyoCabinet`)
67
+ * [Simple Samba database TDB](http://tdb.samba.org/) (`:TDB`)
68
68
  * Document databases:
69
- * CouchDB (`:Couch`)
70
- * MongoDB (`:Mongo`)
69
+ * [CouchDB](http://couchdb.apache.org/) (`:Couch`)
70
+ * [MongoDB](http://www.mongodb.org/) (`:Mongo`)
71
71
  * Moneta network protocols:
72
72
  * Moneta key/value client (`:Client` works with `Moneta::Server`)
73
73
  * Moneta HTTP/REST client (`:RestClient` works with `Rack::MonetaRest`)
74
74
  * Other
75
- * Fog cloud storage which supports Amazon S3, Rackspace, etc. (`:Fog`)
75
+ * [Fog](http://fog.io/) cloud storage which supports Amazon S3, Rackspace, etc. (`:Fog`)
76
76
  * Storage which doesn't store anything (`:Null`)
77
77
 
78
78
  Some of the backends are not exactly based on key/value stores, e.g. the relational ones. These
@@ -85,46 +85,47 @@ to upgrade to a real key/value store.
85
85
  <table>
86
86
  <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</th><th>Native expires<sup>[3]</sup></th><th>Persistent</th><th>Description</th></tr></thead>
87
87
  <tbody>
88
- <tr><td>ActiveRecord</td><td>activerecord</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>ActiveRecord ORM</td></tr>
89
- <tr><td>Cassandra</td><td>cassandra</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td>Cassandra distributed database</td></tr>
88
+ <tr><td>ActiveRecord</td><td>activerecord</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="https://rubygems.org/gems/activerecord">ActiveRecord</a> ORM</td></tr>
89
+ <tr><td>Cassandra</td><td>cassandra</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td><a href="http://cassandra.apache.org/">Cassandra</a> distributed database</td></tr>
90
90
  <tr><td>Client</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:blue">?<sup>[5]</sup></td><td style="color:blue">?<sup>[5]</sup></td><td style="color:blue">?<sup>[5]</sup></td><td>Moneta client adapter</td></tr>
91
91
  <tr><td>Cookie</td><td>-</td><td style="color:red">✗</td><td style="color:blue">(✓)<sup>[6]</sup></td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td>Cookie in memory store</td></tr>
92
- <tr><td>Couch</td><td>couchrest</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>CouchDB database</td></tr>
93
- <tr><td>DataMapper</td><td>dm-core, dm-migrations</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>DataMapper ORM</td></tr>
94
- <tr><td>Daybreak</td><td>daybreak</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Daybreak ruby key/value store</td></tr>
95
- <tr><td>DBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Berkeley DB</td></tr>
92
+ <tr><td>Couch</td><td>couchrest</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://couchdb.apache.org/">CouchDB</a> database</td></tr>
93
+ <tr><td>DataMapper</td><td>dm-core, dm-migrations</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://datamapper.org/">DataMapper</a> ORM</td></tr>
94
+ <tr><td>Daybreak</td><td>daybreak</td><td style="color:red">✗</td><td style="color:blue">(✓)<sup>[7]</sup></td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Incredibly fast pure-ruby key/value store <a href="http://propublica.github.com/daybreak/">Daybreak</a></td></tr>
95
+ <tr><td>DBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/dbm/rdoc/DBM.html">Berkeley DB</a></td></tr>
96
96
  <tr><td>File</td><td>-</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>File store</td></tr>
97
- <tr><td>Fog</td><td>fog</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Fog cloud store</td></tr>
98
- <tr><td>GDBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>GDBM database</td></tr>
99
- <tr><td>HBase</td><td>hbase</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>HBase database</td></tr>
100
- <tr><td>LevelDB</td><td>leveldb</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>LevelDB database</td></tr>
101
- <tr><td>LocalMemCache</td><td>localmemcache</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>LocalMemCache database</td></tr>
97
+ <tr><td>Fog</td><td>fog</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://fog.io/">Fog</a> cloud store</td></tr>
98
+ <tr><td>GDBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/gdbm/rdoc/GDBM.html">GDBM</a> database</td></tr>
99
+ <tr><td>HBase</td><td>hbase</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://hbase.apache.org/">HBase</a> database</td></tr>
100
+ <tr><td>LevelDB</td><td>leveldb</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://code.google.com/p/leveldb/">LevelDB</a> database</td></tr>
101
+ <tr><td>LocalMemCache</td><td>localmemcache</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://localmemcache.rubyforge.org/">LocalMemCache</a> database</td></tr>
102
102
  <tr><td>LRUHash</td><td>-</td><td style="color:red">✗</td><td style="color:blue">(✓)<sup>[6]</sup></td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td>LRU memory store</td></tr>
103
- <tr><td>Memcached</td><td>dalli or memcached</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td>Memcached database</td></tr>
104
- <tr><td>MemcachedDalli</td><td>dalli</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td>Memcached database</td></tr>
105
- <tr><td>MemcachedNative</td><td>memcached</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td>Memcached database</td></tr>
103
+ <tr><td>Memcached</td><td>dalli or memcached</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database</td></tr>
104
+ <tr><td>MemcachedDalli</td><td>dalli</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td><a href="http://memcached.org/">Memcached</a> database with Dalli library</td></tr>
105
+ <tr><td>MemcachedNative</td><td>memcached</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗<sup>[4]</sup></td><td>Memcached database with native library</td></tr>
106
106
  <tr><td>Memory</td><td>-</td><td style="color:red">✗</td><td style="color:blue">(✓)<sup>[6]</sup></td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td>Memory store</td></tr>
107
- <tr><td>Mongo</td><td>mongo</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td>MongoDB database</td></tr>
107
+ <tr><td>Mongo</td><td>mongo</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td><a href="http://www.mongodb.org/">MongoDB</a> database</td></tr>
108
108
  <tr><td>Null</td><td>-</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:red">✗</td><td>No database</td></tr>
109
- <tr><td>PStore</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>PStore store</td></tr>
110
- <tr><td>Redis</td><td>redis</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td>Redis database</td></tr>
109
+ <tr><td>PStore</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://ruby-doc.org/stdlib/libdoc/pstore/rdoc/PStore.html">PStore</a> store</td></tr>
110
+ <tr><td>Redis</td><td>redis</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td><a href="http://redis.io/">Redis</a> database</td></tr>
111
111
  <tr><td>RestClient</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:blue">?<sup>[5]</sup></td><td>Moneta REST client adapter</td></tr>
112
- <tr><td>Riak</td><td>riak-client</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Riak database</td></tr>
113
- <tr><td>SDBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>SDBM database</td></tr>
114
- <tr><td>Sequel</td><td>sequel</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Sequel ORM</td></tr>
115
- <tr><td>Sqlite</td><td>sqlite3</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>Sqlite3 database</td></tr>
116
- <tr><td>TDB</td><td>tdb</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>TDB database</td></tr>
117
- <tr><td>TokyoCabinet</td><td>tokoycabinet</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>TokyoCabinet database</td></tr>
118
- <tr><td>YAML</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td>YAML store</td></tr>
112
+ <tr><td>Riak</td><td>riak-client</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://docs.basho.com/">Riak</a> database</td></tr>
113
+ <tr><td>SDBM</td><td>-</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/sdbm/rdoc/SDBM.html">SDBM</a> database</td></tr>
114
+ <tr><td>Sequel</td><td>sequel</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://sequel.rubyforge.org/">Sequel</a> ORM</td></tr>
115
+ <tr><td>Sqlite</td><td>sqlite3</td><td style="color:blue">?</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://sqlite.org/">Sqlite3</a> database</td></tr>
116
+ <tr><td>TDB</td><td>tdb</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://tdb.samba.org/">TDB</a> database</td></tr>
117
+ <tr><td>TokyoCabinet</td><td>tokoycabinet</td><td style="color:red">✗</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://fallabs.com/tokyocabinet/">TokyoCabinet</a> database</td></tr>
118
+ <tr><td>YAML</td><td>-</td><td style="color:red">✗</td><td style="color:green">✓</td><td style="color:green">✓</td><td style="color:red">✗</td><td style="color:green">✓</td><td><a href="http://www.ruby-doc.org/stdlib/libdoc/yaml/rdoc/YAML/Store.html">YAML</a> store</td></tr>
119
119
  </tbody>
120
120
  </table>
121
121
 
122
- * [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.
122
+ * [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.
123
123
  * [2]: Share a Moneta store between multiple processes using `Moneta::Shared` (See below).
124
124
  * [3]: Add expiration support by using `Moneta::Expires` or by passing the option `:expires => true` to `Moneta#new`.
125
125
  * [4]: There are some servers which use the memcached protocol but which are persistent (e.g. MemcacheDB, Kai, IronCache, ...)
126
126
  * [5]: Depends on server
127
127
  * [6]: Store is multi-process safe because it is an in-memory store, values are not shared between multiple processes
128
+ * [7]: Store is multi-process safe, but not synchronized automatically between multiple processes
128
129
 
129
130
  ## Proxies
130
131
 
@@ -592,6 +593,6 @@ on top of the different stores.
592
593
 
593
594
  ## Authors
594
595
 
595
- * Daniel Mendler (@minad)
596
- * Hannes Georg (@hannesg)
597
- * Originally by Yehuda Katz (@wycats) and contributors
596
+ * [Daniel Mendler](https://github.com/minad)
597
+ * [Hannes Georg](https://github.com/hannesg)
598
+ * Originally by [Yehuda Katz](https://github.com/wycats) and contributors
data/Rakefile CHANGED
@@ -24,11 +24,9 @@ task :test do
24
24
  # QuickLZ is also not maintained on Github, but on Bitbucket
25
25
  # and I don't know where the issue tracker is.
26
26
  #
27
- # * Daybreak leads to a segfault
28
- #
29
27
  # * Cassandra and Mongo show spurious failures
30
28
  if ENV['TEST_GROUP']
31
- unstable = specs.select {|s| s =~ /quicklz|cassandra|mongo|daybreak/ }
29
+ unstable = specs.select {|s| s =~ /quicklz|cassandra|mongo/ }
32
30
  specs -= unstable
33
31
  end
34
32
 
@@ -5,23 +5,21 @@ module Moneta
5
5
  # Daybreak backend
6
6
  # @api public
7
7
  class Daybreak < Memory
8
- # Disable serialization, we have `Moneta::Transformer` for that
9
- class DB < ::Daybreak::DB
10
- def serialize(value) value; end
11
- def parse(value) value; end
12
- end
13
-
14
8
  # @param [Hash] options
15
9
  # @option options [String] :file Database file
16
10
  def initialize(options = {})
17
11
  raise ArgumentError, 'Option :file is required' unless options[:file]
18
- @hash = DB.new(options[:file])
12
+ @hash = ::Daybreak::DB.new(options[:file], :serializer => ::Daybreak::Serializer::None)
13
+ end
14
+
15
+ # (see Proxy#increment)
16
+ def increment(key, amount = 1, options = {})
17
+ @hash.lock { return super }
19
18
  end
20
19
 
21
20
  # (see Proxy#close)
22
21
  def close
23
- @hash.close!
24
- nil
22
+ @hash.close
25
23
  end
26
24
  end
27
25
  end
@@ -72,10 +72,10 @@ module Moneta
72
72
  return yield unless ::File.exist?(path)
73
73
  ::File.open(path, 'r+') do |f|
74
74
  begin
75
- f.flock ::File::LOCK_EX
75
+ Thread.pass until f.flock(::File::LOCK_EX)
76
76
  yield
77
77
  ensure
78
- f.flock ::File::LOCK_UN
78
+ f.flock(::File::LOCK_UN)
79
79
  end
80
80
  end
81
81
  end
@@ -45,6 +45,7 @@ module Moneta
45
45
  def increment(key, amount = 1, options = {})
46
46
  # FIXME: There is a Dalli bug, load(key) returns a wrong value after increment
47
47
  # therefore we set default = nil and create the counter manually
48
+ # See https://github.com/mperham/dalli/issues/309
48
49
  result = if amount >= 0
49
50
  @cache.incr(key, amount, expires_value(options) || nil, nil)
50
51
  else
@@ -58,6 +58,7 @@ module Moneta
58
58
  @cache.decrement(key, -amount)
59
59
  end
60
60
  # HACK: Throw error if applied to invalid value
61
+ # see https://github.com/evan/memcached/issues/110
61
62
  convert_for_increment((@cache.get(key, false) rescue nil)) if result == 0
62
63
  result
63
64
  rescue ::Memcached::NotFound => ex
@@ -153,9 +153,9 @@ module Moneta
153
153
 
154
154
  # Compile transformer validator regular expression
155
155
  def compile_validator(s)
156
- Regexp.new(s.gsub(/\w+/) do
156
+ Regexp.new('\A' + s.gsub(/\w+/) do
157
157
  '(' + TRANSFORMER.select {|k,v| v.first.to_s == $& }.map {|v| ":#{v.first}" }.join('|') + ')'
158
- end.gsub(/\s+/, '').sub(/\A/, '\A').sub(/\Z/, '\Z'))
158
+ end.gsub(/\s+/, '') + '\Z')
159
159
  end
160
160
 
161
161
  # Returned compiled transformer code string
@@ -173,8 +173,8 @@ module Moneta
173
173
  end
174
174
 
175
175
  def class_name(keys, values)
176
- (keys.empty? ? '' : keys.map(&:to_s).map(&:capitalize).join << 'Key') <<
177
- (values.empty? ? '' : values.map(&:to_s).map(&:capitalize).join << 'Value')
176
+ (keys.empty? ? '' : keys.map(&:to_s).map(&:capitalize).join + 'Key') +
177
+ (values.empty? ? '' : values.map(&:to_s).map(&:capitalize).join + 'Value')
178
178
  end
179
179
  end
180
180
  end
@@ -33,12 +33,13 @@ module Moneta
33
33
  :sha512 => [ :digest, nil, '::Digest::SHA512.hexdigest(%s)', 'digest/sha2' ],
34
34
  :prefix => [ :prefix, nil, '(options[:prefix]||@prefix)+%s' ],
35
35
  :spread => [ :spread, nil, 'Helper.spread(%s)' ],
36
+ :to_s => [ :to_s, nil, '%s.to_s' ],
36
37
  }
37
38
 
38
39
  # Allowed value transformers (Read it like a regular expression!)
39
40
  VALUE_TRANSFORMER = 'serialize? compress? hmac? encode?'
40
41
 
41
42
  # Allowed key transformers (Read it like a regular expression!)
42
- KEY_TRANSFORMER = 'serialize? prefix? ((encode? truncate?) | (digest spread?))?'
43
+ KEY_TRANSFORMER = '(serialize | to_s)? prefix? ((encode? truncate?) | (digest spread?))?'
43
44
  end
44
45
  end
@@ -1,5 +1,5 @@
1
1
  module Moneta
2
2
  # Moneta version number
3
3
  # @api public
4
- VERSION = '0.7.5'
4
+ VERSION = '0.7.6'
5
5
  end
@@ -16,6 +16,15 @@ class Array
16
16
  inject(0, &:+)
17
17
  end
18
18
 
19
+ def mean
20
+ sum / size
21
+ end
22
+
23
+ def stddev
24
+ m = mean
25
+ Math.sqrt(map {|s| (s - m) ** 2 }.mean)
26
+ end
27
+
19
28
  def randomize
20
29
  rest, result = dup, []
21
30
  result << rest.slice!(rand(rest.size)) until result.size == size
@@ -63,68 +72,68 @@ class MonetaBenchmarks
63
72
  :uniform_small => {
64
73
  :runs => 3,
65
74
  :keys => 1000,
66
- :min_key_length => 1,
67
- :max_key_length => 32,
75
+ :min_key_len => 1,
76
+ :max_key_len => 32,
68
77
  :key_dist => :uniform,
69
- :min_val_length => 0,
70
- :max_val_length => 256,
78
+ :min_val_len => 0,
79
+ :max_val_len => 256,
71
80
  :val_dist => :uniform
72
81
  },
73
82
  :uniform_medium => {
74
83
  :runs => 3,
75
- :keys => 100,
76
- :min_key_length => 3,
77
- :max_key_length => 200,
84
+ :keys => 1000,
85
+ :min_key_len => 3,
86
+ :max_key_len => 200,
78
87
  :key_dist => :uniform,
79
- :min_val_length => 0,
80
- :max_val_length => 1024,
88
+ :min_val_len => 0,
89
+ :max_val_len => 1024,
81
90
  :val_dist => :uniform
82
91
  },
83
92
  :uniform_large => {
84
93
  :runs => 3,
85
94
  :keys => 100,
86
- :min_key_length => 3,
87
- :max_key_length => 200,
95
+ :min_key_len => 3,
96
+ :max_key_len => 200,
88
97
  :key_dist => :uniform,
89
- :min_val_length => 0,
90
- :max_val_length => 10240,
98
+ :min_val_len => 0,
99
+ :max_val_len => 10240,
91
100
  :val_dist => :uniform
92
101
  },
93
102
  :normal_small => {
94
103
  :runs => 3,
95
104
  :keys => 1000,
96
- :min_key_length => 1,
97
- :max_key_length => 32,
105
+ :min_key_len => 1,
106
+ :max_key_len => 32,
98
107
  :key_dist => :normal,
99
- :min_val_length => 0,
100
- :max_val_length => 256,
108
+ :min_val_len => 0,
109
+ :max_val_len => 256,
101
110
  :val_dist => :normal
102
111
  },
103
112
  :normal_medium => {
104
113
  :runs => 3,
105
- :keys => 100,
106
- :min_key_length => 3,
107
- :max_key_length => 200,
114
+ :keys => 1000,
115
+ :min_key_len => 3,
116
+ :max_key_len => 200,
108
117
  :key_dist => :normal,
109
- :min_val_length => 0,
110
- :max_val_length => 1024,
118
+ :min_val_len => 0,
119
+ :max_val_len => 1024,
111
120
  :val_dist => :normal
112
121
  },
113
122
  :normal_large => {
114
123
  :runs => 3,
115
124
  :keys => 100,
116
- :min_key_length => 3,
117
- :max_key_length => 200,
125
+ :min_key_len => 3,
126
+ :max_key_len => 200,
118
127
  :key_dist => :normal,
119
- :min_val_length => 0,
120
- :max_val_length => 10240,
128
+ :min_val_len => 0,
129
+ :max_val_len => 10240,
121
130
  :val_dist => :normal
122
131
  },
123
132
  }
124
133
 
125
134
  DICT = 'ABCDEFGHIJKLNOPQRSTUVWXYZabcdefghijklnopqrstuvwxyz123456789'.freeze
126
- HEADER = "\n Minimum Maximum Total Average Ops/s"
127
- SEPARATOR = '=' * 68
135
+ HEADER = "\n Minimum Maximum Total Mean Stddev Ops/s"
136
+ SEPARATOR = '=' * 77
128
137
 
129
138
  module Rand
130
139
  extend self
@@ -240,20 +249,20 @@ class MonetaBenchmarks
240
249
 
241
250
  def generate_data
242
251
  until @data.size == @config[:keys]
243
- key = DICT.random(Rand.send(@config[:key_dist], @config[:min_key_length], @config[:max_key_length]))
244
- @data[key] = DICT.random(Rand.send(@config[:val_dist], @config[:min_val_length], @config[:max_val_length]))
252
+ key = DICT.random(Rand.send(@config[:key_dist], @config[:min_key_len], @config[:max_key_len]))
253
+ @data[key] = DICT.random(Rand.send(@config[:val_dist], @config[:min_val_len], @config[:max_val_len]))
245
254
  end
246
255
 
247
- key_lengths, val_lengths = @data.keys.map(&:size), @data.values.map(&:size)
256
+ key_lens, val_lens = @data.keys.map(&:size), @data.values.map(&:size)
248
257
  @data = @data.to_a
249
258
 
250
- write_histogram("#{DIR}/key.histogram", key_lengths)
251
- write_histogram("#{DIR}/value.histogram", val_lengths)
259
+ write_histogram("#{DIR}/key.histogram", key_lens)
260
+ write_histogram("#{DIR}/value.histogram", val_lens)
252
261
 
253
262
  puts "\n\e[1m\e[34m#{SEPARATOR}\n\e[34mComputing keys and values...\n\e[34m#{SEPARATOR}\e[0m"
254
- puts %{ Minimum Maximum Total Average}
255
- puts 'Key Length % 8d % 8d % 8d % 8d ' % [key_lengths.min, key_lengths.max, key_lengths.sum, key_lengths.sum / @data.size]
256
- puts 'Value Length % 8d % 8d % 8d % 8d ' % [val_lengths.min, val_lengths.max, val_lengths.sum, val_lengths.sum / @data.size]
263
+ puts %{ Minimum Maximum Total Mean Stddev}
264
+ puts 'Key Length % 8d % 8d % 8d % 8d % 8d' % [key_lens.min, key_lens.max, key_lens.sum, key_lens.mean, key_lens.stddev]
265
+ puts 'Value Length % 8d % 8d % 8d % 8d % 8d' % [val_lens.min, val_lens.max, val_lens.sum, val_lens.mean, val_lens.stddev]
257
266
  end
258
267
 
259
268
  def print_config
@@ -266,11 +275,10 @@ class MonetaBenchmarks
266
275
  def print_store_stats(name)
267
276
  puts HEADER
268
277
  [:write, :read, :sum].each do |i|
269
- total = @stats[name][i].sum
270
- ops = (@config[:runs] * @data.size) / total
271
- line = '%-17.17s %-5s % 8d % 8d % 8d % 8d % 8d' %
272
- [name, i, @stats[name][i].min * 1000, @stats[name][i].max * 1000,
273
- total * 1000, total * 1000 / @config[:runs], ops]
278
+ ops = (1000 * @config[:runs] * @data.size) / @stats[name][i].sum
279
+ line = '%-17.17s %-5s % 8d % 8d % 8d % 8d % 8d % 8d' %
280
+ [name, i, @stats[name][i].min, @stats[name][i].max, @stats[name][i].sum,
281
+ @stats[name][i].mean, @stats[name][i].stddev, ops]
274
282
  @summary << [-ops, line << "\n"] if i == :sum
275
283
  puts line
276
284
  end
@@ -320,10 +328,10 @@ class MonetaBenchmarks
320
328
  end
321
329
 
322
330
  if type == 'Measure'
323
- @stats[name][:write] << m1.real
331
+ @stats[name][:write] << m1.real * 1000
324
332
  @stats[name][:error] << error
325
- @stats[name][:read] << m2.real
326
- @stats[name][:sum] << (m1.real + m2.real)
333
+ @stats[name][:read] << m2.real * 1000
334
+ @stats[name][:sum] << (m1.real + m2.real) * 1000
327
335
  end
328
336
  end
329
337
  end