moneta 0.7.5 → 0.7.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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