activesupport 2.3.18 → 3.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activesupport might be problematic. Click here for more details.

Files changed (403) hide show
  1. data/CHANGELOG +30 -53
  2. data/lib/active_support.rb +43 -31
  3. data/lib/active_support/all.rb +3 -7
  4. data/lib/active_support/backtrace_cleaner.rb +24 -8
  5. data/lib/active_support/base64.rb +9 -0
  6. data/lib/active_support/benchmarkable.rb +60 -0
  7. data/lib/active_support/buffered_logger.rb +12 -9
  8. data/lib/active_support/cache.rb +75 -55
  9. data/lib/active_support/cache/compressed_mem_cache_store.rb +2 -0
  10. data/lib/active_support/cache/file_store.rb +35 -17
  11. data/lib/active_support/cache/mem_cache_store.rb +29 -20
  12. data/lib/active_support/cache/memory_store.rb +18 -17
  13. data/lib/active_support/cache/strategy/local_cache.rb +9 -1
  14. data/lib/active_support/callbacks.rb +490 -169
  15. data/lib/active_support/concern.rb +29 -0
  16. data/lib/active_support/configurable.rb +35 -0
  17. data/lib/active_support/core_ext.rb +2 -7
  18. data/lib/active_support/core_ext/array.rb +2 -10
  19. data/lib/active_support/core_ext/array/access.rb +39 -46
  20. data/lib/active_support/core_ext/array/conversions.rb +146 -182
  21. data/lib/active_support/core_ext/array/extract_options.rb +12 -18
  22. data/lib/active_support/core_ext/array/grouping.rb +87 -93
  23. data/lib/active_support/core_ext/array/random_access.rb +4 -40
  24. data/lib/active_support/core_ext/array/uniq_by.rb +17 -0
  25. data/lib/active_support/core_ext/array/wrap.rb +22 -0
  26. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  27. data/lib/active_support/core_ext/big_decimal/conversions.rb +27 -0
  28. data/lib/active_support/core_ext/cgi.rb +0 -4
  29. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +16 -20
  30. data/lib/active_support/core_ext/class.rb +0 -2
  31. data/lib/active_support/core_ext/class/attribute.rb +8 -39
  32. data/lib/active_support/core_ext/class/attribute_accessors.rb +31 -35
  33. data/lib/active_support/core_ext/class/delegating_attributes.rb +34 -40
  34. data/lib/active_support/core_ext/class/inheritable_attributes.rb +100 -16
  35. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  36. data/lib/active_support/core_ext/date/calculations.rb +218 -238
  37. data/lib/active_support/core_ext/date/conversions.rb +87 -96
  38. data/lib/active_support/core_ext/date/freeze.rb +31 -0
  39. data/lib/active_support/core_ext/date_time/acts_like.rb +13 -0
  40. data/lib/active_support/core_ext/date_time/calculations.rb +97 -110
  41. data/lib/active_support/core_ext/date_time/conversions.rb +83 -95
  42. data/lib/active_support/core_ext/date_time/zones.rb +17 -0
  43. data/lib/active_support/core_ext/enumerable.rb +14 -15
  44. data/lib/active_support/core_ext/exception.rb +1 -43
  45. data/lib/active_support/core_ext/file.rb +0 -4
  46. data/lib/active_support/core_ext/file/atomic.rb +34 -41
  47. data/lib/active_support/core_ext/float.rb +0 -6
  48. data/lib/active_support/core_ext/float/rounding.rb +15 -20
  49. data/lib/active_support/core_ext/hash.rb +8 -14
  50. data/lib/active_support/core_ext/hash/conversions.rb +236 -236
  51. data/lib/active_support/core_ext/hash/deep_merge.rb +12 -19
  52. data/lib/active_support/core_ext/hash/diff.rb +11 -17
  53. data/lib/active_support/core_ext/hash/except.rb +21 -22
  54. data/lib/active_support/core_ext/hash/indifferent_access.rb +8 -137
  55. data/lib/active_support/core_ext/hash/keys.rb +38 -45
  56. data/lib/active_support/core_ext/hash/reverse_merge.rb +25 -32
  57. data/lib/active_support/core_ext/hash/slice.rb +35 -37
  58. data/lib/active_support/core_ext/integer.rb +1 -7
  59. data/lib/active_support/core_ext/integer/inflections.rb +10 -16
  60. data/lib/active_support/core_ext/integer/multiple.rb +6 -0
  61. data/lib/active_support/core_ext/integer/time.rb +36 -42
  62. data/lib/active_support/core_ext/kernel/reporting.rb +9 -7
  63. data/lib/active_support/core_ext/kernel/requires.rb +3 -1
  64. data/lib/active_support/core_ext/load_error.rb +16 -33
  65. data/lib/active_support/core_ext/logger.rb +3 -2
  66. data/lib/active_support/core_ext/module.rb +3 -16
  67. data/lib/active_support/core_ext/module/aliasing.rb +64 -68
  68. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +1 -1
  69. data/lib/active_support/core_ext/module/attr_internal.rb +4 -4
  70. data/lib/active_support/core_ext/module/attribute_accessors.rb +36 -41
  71. data/lib/active_support/core_ext/module/delegation.rb +1 -1
  72. data/lib/active_support/core_ext/module/deprecation.rb +9 -0
  73. data/lib/active_support/core_ext/module/introspection.rb +77 -79
  74. data/lib/active_support/core_ext/module/loading.rb +2 -0
  75. data/lib/active_support/core_ext/module/synchronization.rb +4 -1
  76. data/lib/active_support/core_ext/name_error.rb +3 -4
  77. data/lib/active_support/core_ext/numeric.rb +1 -8
  78. data/lib/active_support/core_ext/numeric/bytes.rb +35 -41
  79. data/lib/active_support/core_ext/numeric/time.rb +70 -74
  80. data/lib/active_support/core_ext/object.rb +4 -2
  81. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  82. data/lib/active_support/core_ext/object/conversions.rb +4 -15
  83. data/lib/active_support/core_ext/object/duplicable.rb +65 -0
  84. data/lib/active_support/core_ext/object/instance_variables.rb +0 -7
  85. data/lib/active_support/core_ext/object/metaclass.rb +5 -6
  86. data/lib/active_support/core_ext/object/misc.rb +2 -93
  87. data/lib/active_support/core_ext/object/returning.rb +42 -0
  88. data/lib/active_support/core_ext/object/to_param.rb +49 -0
  89. data/lib/active_support/core_ext/object/to_query.rb +27 -0
  90. data/lib/active_support/core_ext/{try.rb → object/try.rb} +4 -4
  91. data/lib/active_support/core_ext/object/with_options.rb +24 -0
  92. data/lib/active_support/core_ext/proc.rb +6 -4
  93. data/lib/active_support/core_ext/process/daemon.rb +17 -19
  94. data/lib/active_support/core_ext/range.rb +2 -9
  95. data/lib/active_support/core_ext/range/blockless_step.rb +24 -27
  96. data/lib/active_support/core_ext/range/conversions.rb +17 -23
  97. data/lib/active_support/core_ext/range/include_range.rb +18 -27
  98. data/lib/active_support/core_ext/range/overlaps.rb +6 -13
  99. data/lib/active_support/core_ext/regexp.rb +5 -0
  100. data/lib/active_support/core_ext/rexml.rb +12 -7
  101. data/lib/active_support/core_ext/string.rb +6 -19
  102. data/lib/active_support/core_ext/string/access.rb +88 -95
  103. data/lib/active_support/core_ext/string/behavior.rb +6 -12
  104. data/lib/active_support/core_ext/string/conversions.rb +19 -21
  105. data/lib/active_support/core_ext/string/exclude.rb +6 -0
  106. data/lib/active_support/core_ext/string/filters.rb +17 -23
  107. data/lib/active_support/core_ext/string/inflections.rb +146 -153
  108. data/lib/active_support/{vendor/i18n-0.4.1/i18n/core_ext/string/interpolate.rb → core_ext/string/interpolation.rb} +8 -15
  109. data/lib/active_support/core_ext/string/multibyte.rb +68 -74
  110. data/lib/active_support/core_ext/string/output_safety.rb +21 -17
  111. data/lib/active_support/core_ext/string/starts_ends_with.rb +3 -32
  112. data/lib/active_support/core_ext/string/xchar.rb +10 -3
  113. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  114. data/lib/active_support/core_ext/time/calculations.rb +276 -308
  115. data/lib/active_support/core_ext/time/conversions.rb +78 -84
  116. data/lib/active_support/core_ext/time/marshal_with_utc_flag.rb +22 -0
  117. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +10 -0
  118. data/lib/active_support/core_ext/time/zones.rb +73 -81
  119. data/lib/active_support/core_ext/uri.rb +2 -1
  120. data/lib/active_support/dependencies.rb +38 -48
  121. data/lib/active_support/dependencies/autoload.rb +49 -0
  122. data/lib/active_support/deprecation.rb +9 -195
  123. data/lib/active_support/deprecation/behaviors.rb +38 -0
  124. data/lib/active_support/deprecation/method_wrappers.rb +29 -0
  125. data/lib/active_support/deprecation/proxy_wrappers.rb +74 -0
  126. data/lib/active_support/deprecation/reporting.rb +55 -0
  127. data/lib/active_support/duration.rb +6 -2
  128. data/lib/active_support/hash_with_indifferent_access.rb +137 -0
  129. data/lib/active_support/i18n.rb +2 -0
  130. data/lib/active_support/inflections.rb +1 -1
  131. data/lib/active_support/inflector.rb +4 -406
  132. data/lib/active_support/inflector/inflections.rb +211 -0
  133. data/lib/active_support/inflector/methods.rb +139 -0
  134. data/lib/active_support/inflector/transliterate.rb +61 -0
  135. data/lib/active_support/json/backends/jsongem.rb +16 -10
  136. data/lib/active_support/json/backends/yaml.rb +72 -2
  137. data/lib/active_support/json/decoding.rb +2 -16
  138. data/lib/active_support/json/encoding.rb +153 -33
  139. data/lib/active_support/json/variable.rb +4 -3
  140. data/lib/active_support/locale/en.yml +1 -4
  141. data/lib/active_support/memoizable.rb +7 -6
  142. data/lib/active_support/message_encryptor.rb +1 -0
  143. data/lib/active_support/message_verifier.rb +12 -29
  144. data/lib/active_support/multibyte.rb +9 -4
  145. data/lib/active_support/multibyte/chars.rb +25 -17
  146. data/lib/active_support/multibyte/unicode_database.rb +5 -5
  147. data/lib/active_support/multibyte/utils.rb +1 -1
  148. data/lib/active_support/notifications.rb +77 -0
  149. data/lib/active_support/notifications/fanout.rb +69 -0
  150. data/lib/active_support/notifications/instrumenter.rb +50 -0
  151. data/lib/active_support/option_merger.rb +2 -0
  152. data/lib/active_support/ordered_hash.rb +33 -37
  153. data/lib/active_support/ordered_options.rb +3 -1
  154. data/lib/active_support/railtie.rb +64 -0
  155. data/lib/active_support/rescuable.rb +11 -6
  156. data/lib/active_support/ruby/shim.rb +19 -0
  157. data/lib/active_support/test_case.rb +8 -1
  158. data/lib/active_support/testing/assertions.rb +2 -14
  159. data/lib/active_support/testing/declarative.rb +31 -12
  160. data/lib/active_support/testing/deprecation.rb +8 -10
  161. data/lib/active_support/testing/isolation.rb +153 -0
  162. data/lib/active_support/testing/pending.rb +48 -0
  163. data/lib/active_support/testing/performance.rb +342 -339
  164. data/lib/active_support/testing/setup_and_teardown.rb +48 -31
  165. data/lib/active_support/time.rb +34 -0
  166. data/lib/active_support/time/autoload.rb +5 -0
  167. data/lib/active_support/time_with_zone.rb +18 -12
  168. data/lib/active_support/values/time_zone.rb +97 -93
  169. data/lib/active_support/version.rb +3 -3
  170. data/lib/active_support/whiny_nil.rb +1 -4
  171. data/lib/active_support/xml_mini.rb +2 -0
  172. data/lib/active_support/xml_mini/jdom.rb +13 -7
  173. data/lib/active_support/xml_mini/libxml.rb +19 -12
  174. data/lib/active_support/xml_mini/libxmlsax.rb +19 -9
  175. data/lib/active_support/xml_mini/nokogiri.rb +18 -12
  176. data/lib/active_support/xml_mini/nokogirisax.rb +15 -6
  177. data/lib/active_support/xml_mini/rexml.rb +24 -9
  178. metadata +94 -244
  179. data/lib/active_support/cache/drb_store.rb +0 -14
  180. data/lib/active_support/core_ext/array/wrapper.rb +0 -24
  181. data/lib/active_support/core_ext/base64.rb +0 -4
  182. data/lib/active_support/core_ext/base64/encoding.rb +0 -16
  183. data/lib/active_support/core_ext/bigdecimal.rb +0 -6
  184. data/lib/active_support/core_ext/bigdecimal/conversions.rb +0 -37
  185. data/lib/active_support/core_ext/blank.rb +0 -2
  186. data/lib/active_support/core_ext/class/removal.rb +0 -50
  187. data/lib/active_support/core_ext/date.rb +0 -10
  188. data/lib/active_support/core_ext/date/behavior.rb +0 -42
  189. data/lib/active_support/core_ext/date_time.rb +0 -12
  190. data/lib/active_support/core_ext/duplicable.rb +0 -43
  191. data/lib/active_support/core_ext/float/time.rb +0 -27
  192. data/lib/active_support/core_ext/integer/even_odd.rb +0 -29
  193. data/lib/active_support/core_ext/kernel/singleton_class.rb +0 -13
  194. data/lib/active_support/core_ext/module/model_naming.rb +0 -25
  195. data/lib/active_support/core_ext/module/remove_method.rb +0 -6
  196. data/lib/active_support/core_ext/numeric/conversions.rb +0 -19
  197. data/lib/active_support/core_ext/object/extending.rb +0 -80
  198. data/lib/active_support/core_ext/object/singleton_class.rb +0 -13
  199. data/lib/active_support/core_ext/pathname.rb +0 -7
  200. data/lib/active_support/core_ext/pathname/clean_within.rb +0 -14
  201. data/lib/active_support/core_ext/string/bytesize.rb +0 -5
  202. data/lib/active_support/core_ext/string/iterators.rb +0 -23
  203. data/lib/active_support/core_ext/symbol.rb +0 -14
  204. data/lib/active_support/core_ext/time.rb +0 -46
  205. data/lib/active_support/core_ext/time/behavior.rb +0 -13
  206. data/lib/active_support/json/backends/okjson.rb +0 -644
  207. data/lib/active_support/json/backends/yajl.rb +0 -40
  208. data/lib/active_support/json/encoders/date.rb +0 -22
  209. data/lib/active_support/json/encoders/date_time.rb +0 -22
  210. data/lib/active_support/json/encoders/enumerable.rb +0 -17
  211. data/lib/active_support/json/encoders/false_class.rb +0 -7
  212. data/lib/active_support/json/encoders/hash.rb +0 -56
  213. data/lib/active_support/json/encoders/nil_class.rb +0 -7
  214. data/lib/active_support/json/encoders/numeric.rb +0 -21
  215. data/lib/active_support/json/encoders/object.rb +0 -10
  216. data/lib/active_support/json/encoders/regexp.rb +0 -9
  217. data/lib/active_support/json/encoders/string.rb +0 -9
  218. data/lib/active_support/json/encoders/symbol.rb +0 -5
  219. data/lib/active_support/json/encoders/time.rb +0 -22
  220. data/lib/active_support/json/encoders/true_class.rb +0 -7
  221. data/lib/active_support/vendor.rb +0 -36
  222. data/lib/active_support/vendor/builder-2.1.2/blankslate.rb +0 -113
  223. data/lib/active_support/vendor/builder-2.1.2/builder.rb +0 -13
  224. data/lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb +0 -20
  225. data/lib/active_support/vendor/builder-2.1.2/builder/css.rb +0 -250
  226. data/lib/active_support/vendor/builder-2.1.2/builder/xchar.rb +0 -115
  227. data/lib/active_support/vendor/builder-2.1.2/builder/xmlbase.rb +0 -139
  228. data/lib/active_support/vendor/builder-2.1.2/builder/xmlevents.rb +0 -63
  229. data/lib/active_support/vendor/builder-2.1.2/builder/xmlmarkup.rb +0 -328
  230. data/lib/active_support/vendor/i18n-0.4.1/i18n.rb +0 -322
  231. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend.rb +0 -20
  232. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/active_record.rb +0 -61
  233. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/active_record/missing.rb +0 -65
  234. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/active_record/store_procs.rb +0 -38
  235. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/active_record/translation.rb +0 -93
  236. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/base.rb +0 -237
  237. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/cache.rb +0 -77
  238. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/cascade.rb +0 -57
  239. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/chain.rb +0 -77
  240. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/cldr.rb +0 -100
  241. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/fallbacks.rb +0 -69
  242. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/flatten.rb +0 -113
  243. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/gettext.rb +0 -75
  244. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/interpolation_compiler.rb +0 -123
  245. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/key_value.rb +0 -102
  246. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/memoize.rb +0 -48
  247. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/metadata.rb +0 -65
  248. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/pluralization.rb +0 -57
  249. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/simple.rb +0 -87
  250. data/lib/active_support/vendor/i18n-0.4.1/i18n/backend/transliterator.rb +0 -98
  251. data/lib/active_support/vendor/i18n-0.4.1/i18n/config.rb +0 -84
  252. data/lib/active_support/vendor/i18n-0.4.1/i18n/core_ext/hash.rb +0 -29
  253. data/lib/active_support/vendor/i18n-0.4.1/i18n/exceptions.rb +0 -61
  254. data/lib/active_support/vendor/i18n-0.4.1/i18n/gettext.rb +0 -27
  255. data/lib/active_support/vendor/i18n-0.4.1/i18n/gettext/helpers.rb +0 -65
  256. data/lib/active_support/vendor/i18n-0.4.1/i18n/gettext/po_parser.rb +0 -329
  257. data/lib/active_support/vendor/i18n-0.4.1/i18n/locale.rb +0 -6
  258. data/lib/active_support/vendor/i18n-0.4.1/i18n/locale/fallbacks.rb +0 -98
  259. data/lib/active_support/vendor/i18n-0.4.1/i18n/locale/tag.rb +0 -28
  260. data/lib/active_support/vendor/i18n-0.4.1/i18n/locale/tag/parents.rb +0 -24
  261. data/lib/active_support/vendor/i18n-0.4.1/i18n/locale/tag/rfc4646.rb +0 -76
  262. data/lib/active_support/vendor/i18n-0.4.1/i18n/locale/tag/simple.rb +0 -41
  263. data/lib/active_support/vendor/i18n-0.4.1/i18n/version.rb +0 -3
  264. data/lib/active_support/vendor/memcache-client-1.7.4/memcache.rb +0 -1107
  265. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo.rb +0 -33
  266. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/data_timezone.rb +0 -47
  267. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/data_timezone_info.rb +0 -228
  268. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Africa/Algiers.rb +0 -55
  269. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Africa/Cairo.rb +0 -219
  270. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Africa/Casablanca.rb +0 -40
  271. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Africa/Harare.rb +0 -18
  272. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Africa/Johannesburg.rb +0 -25
  273. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Africa/Monrovia.rb +0 -22
  274. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Africa/Nairobi.rb +0 -23
  275. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina/Buenos_Aires.rb +0 -166
  276. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Argentina/San_Juan.rb +0 -86
  277. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Bogota.rb +0 -23
  278. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Caracas.rb +0 -23
  279. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Chicago.rb +0 -283
  280. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Chihuahua.rb +0 -136
  281. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Denver.rb +0 -204
  282. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Godthab.rb +0 -161
  283. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Guatemala.rb +0 -27
  284. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Halifax.rb +0 -274
  285. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Indiana/Indianapolis.rb +0 -149
  286. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Juneau.rb +0 -194
  287. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/La_Paz.rb +0 -22
  288. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Lima.rb +0 -35
  289. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Los_Angeles.rb +0 -232
  290. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Mazatlan.rb +0 -139
  291. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Mexico_City.rb +0 -144
  292. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Monterrey.rb +0 -131
  293. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/New_York.rb +0 -282
  294. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Phoenix.rb +0 -30
  295. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Regina.rb +0 -74
  296. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Santiago.rb +0 -205
  297. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Sao_Paulo.rb +0 -171
  298. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/St_Johns.rb +0 -288
  299. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/America/Tijuana.rb +0 -196
  300. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Almaty.rb +0 -67
  301. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Baghdad.rb +0 -73
  302. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Baku.rb +0 -161
  303. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Bangkok.rb +0 -20
  304. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Chongqing.rb +0 -33
  305. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Colombo.rb +0 -30
  306. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Dhaka.rb +0 -27
  307. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Hong_Kong.rb +0 -87
  308. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Irkutsk.rb +0 -165
  309. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Jakarta.rb +0 -30
  310. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Jerusalem.rb +0 -163
  311. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Kabul.rb +0 -20
  312. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Kamchatka.rb +0 -163
  313. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Karachi.rb +0 -30
  314. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Katmandu.rb +0 -20
  315. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Kolkata.rb +0 -25
  316. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Krasnoyarsk.rb +0 -163
  317. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Kuala_Lumpur.rb +0 -31
  318. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Kuwait.rb +0 -18
  319. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Magadan.rb +0 -163
  320. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Muscat.rb +0 -18
  321. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Novosibirsk.rb +0 -164
  322. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Rangoon.rb +0 -24
  323. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Riyadh.rb +0 -18
  324. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Seoul.rb +0 -34
  325. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Shanghai.rb +0 -35
  326. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Singapore.rb +0 -33
  327. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Taipei.rb +0 -59
  328. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Tashkent.rb +0 -47
  329. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Tbilisi.rb +0 -78
  330. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Tehran.rb +0 -121
  331. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Tokyo.rb +0 -30
  332. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Ulaanbaatar.rb +0 -65
  333. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Urumqi.rb +0 -33
  334. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Vladivostok.rb +0 -164
  335. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Yakutsk.rb +0 -163
  336. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Yekaterinburg.rb +0 -165
  337. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Asia/Yerevan.rb +0 -165
  338. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Atlantic/Azores.rb +0 -270
  339. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Atlantic/Cape_Verde.rb +0 -23
  340. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Atlantic/South_Georgia.rb +0 -18
  341. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Australia/Adelaide.rb +0 -187
  342. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Australia/Brisbane.rb +0 -35
  343. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Australia/Darwin.rb +0 -29
  344. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Australia/Hobart.rb +0 -193
  345. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Australia/Melbourne.rb +0 -185
  346. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Australia/Perth.rb +0 -37
  347. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Australia/Sydney.rb +0 -185
  348. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Etc/UTC.rb +0 -16
  349. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Amsterdam.rb +0 -228
  350. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Athens.rb +0 -185
  351. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Belgrade.rb +0 -163
  352. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Berlin.rb +0 -188
  353. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Bratislava.rb +0 -13
  354. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Brussels.rb +0 -232
  355. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Bucharest.rb +0 -181
  356. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Budapest.rb +0 -197
  357. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Copenhagen.rb +0 -179
  358. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Dublin.rb +0 -276
  359. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Helsinki.rb +0 -163
  360. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Istanbul.rb +0 -218
  361. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Kiev.rb +0 -168
  362. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Lisbon.rb +0 -268
  363. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Ljubljana.rb +0 -13
  364. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/London.rb +0 -288
  365. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Madrid.rb +0 -211
  366. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Minsk.rb +0 -170
  367. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Moscow.rb +0 -181
  368. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Paris.rb +0 -232
  369. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Prague.rb +0 -187
  370. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Riga.rb +0 -176
  371. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Rome.rb +0 -215
  372. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Sarajevo.rb +0 -13
  373. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Skopje.rb +0 -13
  374. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Sofia.rb +0 -173
  375. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Stockholm.rb +0 -165
  376. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Tallinn.rb +0 -172
  377. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Vienna.rb +0 -183
  378. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Vilnius.rb +0 -170
  379. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Warsaw.rb +0 -212
  380. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Europe/Zagreb.rb +0 -13
  381. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Auckland.rb +0 -202
  382. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Fiji.rb +0 -23
  383. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Guam.rb +0 -22
  384. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Honolulu.rb +0 -28
  385. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Majuro.rb +0 -20
  386. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Midway.rb +0 -25
  387. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Noumea.rb +0 -25
  388. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Pago_Pago.rb +0 -26
  389. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Port_Moresby.rb +0 -20
  390. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/definitions/Pacific/Tongatapu.rb +0 -27
  391. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/info_timezone.rb +0 -52
  392. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/linked_timezone.rb +0 -51
  393. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/linked_timezone_info.rb +0 -44
  394. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/offset_rationals.rb +0 -98
  395. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/ruby_core_support.rb +0 -56
  396. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/time_or_datetime.rb +0 -292
  397. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/timezone.rb +0 -508
  398. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/timezone_definition.rb +0 -56
  399. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/timezone_info.rb +0 -40
  400. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/timezone_offset_info.rb +0 -94
  401. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/timezone_period.rb +0 -198
  402. data/lib/active_support/vendor/tzinfo-0.3.12/tzinfo/timezone_transition_info.rb +0 -129
  403. data/lib/activesupport.rb +0 -2
@@ -1,24 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module I18n
4
- module Locale
5
- module Tag
6
- module Parents
7
- def parent
8
- @parent ||= begin
9
- segs = to_a.compact
10
- segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil
11
- end
12
- end
13
-
14
- def self_and_parents
15
- @self_and_parents ||= [self] + parents
16
- end
17
-
18
- def parents
19
- @parents ||= ([parent] + (parent ? parent.parents : [])).compact
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,76 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # RFC 4646/47 compliant Locale tag implementation that parses locale tags to
4
- # subtags such as language, script, region, variant etc.
5
- #
6
- # For more information see by http://en.wikipedia.org/wiki/IETF_language_tag
7
- #
8
- # Rfc4646::Parser does not implement grandfathered tags.
9
-
10
- module I18n
11
- module Locale
12
- module Tag
13
- RFC4646_SUBTAGS = [ :language, :script, :region, :variant, :extension, :privateuse, :grandfathered ]
14
- RFC4646_FORMATS = { :language => :downcase, :script => :capitalize, :region => :upcase, :variant => :downcase }
15
-
16
- class Rfc4646 < Struct.new(*RFC4646_SUBTAGS)
17
- class << self
18
- # Parses the given tag and returns a Tag instance if it is valid.
19
- # Returns false if the given tag is not valid according to RFC 4646.
20
- def tag(tag)
21
- matches = parser.match(tag)
22
- new(*matches) if matches
23
- end
24
-
25
- def parser
26
- @@parser ||= Rfc4646::Parser
27
- end
28
-
29
- def parser=(parser)
30
- @@parser = parser
31
- end
32
- end
33
-
34
- include Parents
35
-
36
- RFC4646_FORMATS.each do |name, format|
37
- define_method(name) { self[name].send(format) unless self[name].nil? }
38
- end
39
-
40
- def to_sym
41
- to_s.to_sym
42
- end
43
-
44
- def to_s
45
- @tag ||= to_a.compact.join("-")
46
- end
47
-
48
- def to_a
49
- members.collect { |attr| self.send(attr) }
50
- end
51
-
52
- module Parser
53
- PATTERN = %r{\A(?:
54
- ([a-z]{2,3}(?:(?:-[a-z]{3}){0,3})?|[a-z]{4}|[a-z]{5,8}) # language
55
- (?:-([a-z]{4}))? # script
56
- (?:-([a-z]{2}|\d{3}))? # region
57
- (?:-([0-9a-z]{5,8}|\d[0-9a-z]{3}))* # variant
58
- (?:-([0-9a-wyz](?:-[0-9a-z]{2,8})+))* # extension
59
- (?:-(x(?:-[0-9a-z]{1,8})+))?| # privateuse subtag
60
- (x(?:-[0-9a-z]{1,8})+)| # privateuse tag
61
- /* ([a-z]{1,3}(?:-[0-9a-z]{2,8}){1,2}) */ # grandfathered
62
- )\z}xi
63
-
64
- class << self
65
- def match(tag)
66
- c = PATTERN.match(tag.to_s).captures
67
- c[0..4] << (c[5].nil? ? c[6] : c[5]) << c[7] # TODO c[7] is grandfathered, throw a NotImplemented exception here?
68
- rescue
69
- false
70
- end
71
- end
72
- end
73
- end
74
- end
75
- end
76
- end
@@ -1,41 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # Simple Locale tag implementation that computes subtags by simply splitting
4
- # the locale tag at '-' occurences.
5
- module I18n
6
- module Locale
7
- module Tag
8
- class Simple
9
- class << self
10
- def tag(tag)
11
- new(tag)
12
- end
13
- end
14
-
15
- include Parents
16
-
17
- attr_reader :tag
18
-
19
- def initialize(*tag)
20
- @tag = tag.join('-').to_sym
21
- end
22
-
23
- def subtags
24
- @subtags = tag.to_s.split('-').map { |subtag| subtag.to_s }
25
- end
26
-
27
- def to_sym
28
- tag
29
- end
30
-
31
- def to_s
32
- tag.to_s
33
- end
34
-
35
- def to_a
36
- subtags
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,3 +0,0 @@
1
- module I18n
2
- VERSION = "0.4.1"
3
- end
@@ -1,1107 +0,0 @@
1
- $TESTING = defined?($TESTING) && $TESTING
2
-
3
- require 'socket'
4
- require 'thread'
5
- require 'zlib'
6
- require 'digest/sha1'
7
- require 'net/protocol'
8
-
9
- ##
10
- # A Ruby client library for memcached.
11
- #
12
-
13
- class MemCache
14
-
15
- ##
16
- # The version of MemCache you are using.
17
-
18
- VERSION = '1.7.4'
19
-
20
- ##
21
- # Default options for the cache object.
22
-
23
- DEFAULT_OPTIONS = {
24
- :namespace => nil,
25
- :readonly => false,
26
- :multithread => true,
27
- :failover => true,
28
- :timeout => 0.5,
29
- :logger => nil,
30
- :no_reply => false,
31
- }
32
-
33
- ##
34
- # Default memcached port.
35
-
36
- DEFAULT_PORT = 11211
37
-
38
- ##
39
- # Default memcached server weight.
40
-
41
- DEFAULT_WEIGHT = 1
42
-
43
- ##
44
- # The namespace for this instance
45
-
46
- attr_reader :namespace
47
-
48
- ##
49
- # The multithread setting for this instance
50
-
51
- attr_reader :multithread
52
-
53
- ##
54
- # The servers this client talks to. Play at your own peril.
55
-
56
- attr_reader :servers
57
-
58
- ##
59
- # Socket timeout limit with this client, defaults to 0.5 sec.
60
- # Set to nil to disable timeouts.
61
-
62
- attr_reader :timeout
63
-
64
- ##
65
- # Should the client try to failover to another server if the
66
- # first server is down? Defaults to true.
67
-
68
- attr_reader :failover
69
-
70
- ##
71
- # Log debug/info/warn/error to the given Logger, defaults to nil.
72
-
73
- attr_reader :logger
74
-
75
- ##
76
- # Don't send or look for a reply from the memcached server for write operations.
77
- # Please note this feature only works in memcached 1.2.5 and later. Earlier
78
- # versions will reply with "ERROR".
79
- attr_reader :no_reply
80
-
81
- ##
82
- # Accepts a list of +servers+ and a list of +opts+. +servers+ may be
83
- # omitted. See +servers=+ for acceptable server list arguments.
84
- #
85
- # Valid options for +opts+ are:
86
- #
87
- # [:namespace] Prepends this value to all keys added or retrieved.
88
- # [:readonly] Raises an exception on cache writes when true.
89
- # [:multithread] Wraps cache access in a Mutex for thread safety. Defaults to true.
90
- # [:failover] Should the client try to failover to another server if the
91
- # first server is down? Defaults to true.
92
- # [:timeout] Time to use as the socket read timeout. Defaults to 0.5 sec,
93
- # set to nil to disable timeouts (this is a major performance penalty in Ruby 1.8,
94
- # "gem install SystemTimer' to remove most of the penalty).
95
- # [:logger] Logger to use for info/debug output, defaults to nil
96
- # [:no_reply] Don't bother looking for a reply for write operations (i.e. they
97
- # become 'fire and forget'), memcached 1.2.5 and later only, speeds up
98
- # set/add/delete/incr/decr significantly.
99
- #
100
- # Other options are ignored.
101
-
102
- def initialize(*args)
103
- servers = []
104
- opts = {}
105
-
106
- case args.length
107
- when 0 then # NOP
108
- when 1 then
109
- arg = args.shift
110
- case arg
111
- when Hash then opts = arg
112
- when Array then servers = arg
113
- when String then servers = [arg]
114
- else raise ArgumentError, 'first argument must be Array, Hash or String'
115
- end
116
- when 2 then
117
- servers, opts = args
118
- else
119
- raise ArgumentError, "wrong number of arguments (#{args.length} for 2)"
120
- end
121
-
122
- opts = DEFAULT_OPTIONS.merge opts
123
- @namespace = opts[:namespace]
124
- @readonly = opts[:readonly]
125
- @multithread = opts[:multithread]
126
- @timeout = opts[:timeout]
127
- @failover = opts[:failover]
128
- @logger = opts[:logger]
129
- @no_reply = opts[:no_reply]
130
- @mutex = Mutex.new if @multithread
131
-
132
- logger.info { "memcache-client #{VERSION} #{Array(servers).inspect}" } if logger
133
-
134
- Thread.current[:memcache_client] = self.object_id if !@multithread
135
-
136
- self.servers = servers
137
- end
138
-
139
- ##
140
- # Returns a string representation of the cache object.
141
-
142
- def inspect
143
- "<MemCache: %d servers, ns: %p, ro: %p>" %
144
- [@servers.length, @namespace, @readonly]
145
- end
146
-
147
- ##
148
- # Returns whether there is at least one active server for the object.
149
-
150
- def active?
151
- not @servers.empty?
152
- end
153
-
154
- ##
155
- # Returns whether or not the cache object was created read only.
156
-
157
- def readonly?
158
- @readonly
159
- end
160
-
161
- ##
162
- # Set the servers that the requests will be distributed between. Entries
163
- # can be either strings of the form "hostname:port" or
164
- # "hostname:port:weight" or MemCache::Server objects.
165
- #
166
- def servers=(servers)
167
- # Create the server objects.
168
- @servers = Array(servers).collect do |server|
169
- case server
170
- when String
171
- host, port, weight = server.split ':', 3
172
- port ||= DEFAULT_PORT
173
- weight ||= DEFAULT_WEIGHT
174
- Server.new self, host, port, weight
175
- else
176
- server
177
- end
178
- end
179
-
180
- logger.debug { "Servers now: #{@servers.inspect}" } if logger
181
-
182
- # There's no point in doing this if there's only one server
183
- @continuum = create_continuum_for(@servers) if @servers.size > 1
184
-
185
- @servers
186
- end
187
-
188
- ##
189
- # Decrements the value for +key+ by +amount+ and returns the new value.
190
- # +key+ must already exist. If +key+ is not an integer, it is assumed to be
191
- # 0. +key+ can not be decremented below 0.
192
-
193
- def decr(key, amount = 1)
194
- raise MemCacheError, "Update of readonly cache" if @readonly
195
- with_server(key) do |server, cache_key|
196
- cache_decr server, cache_key, amount
197
- end
198
- rescue TypeError => err
199
- handle_error nil, err
200
- end
201
-
202
- ##
203
- # Retrieves +key+ from memcache. If +raw+ is false, the value will be
204
- # unmarshalled.
205
-
206
- def get(key, raw = false)
207
- with_server(key) do |server, cache_key|
208
- logger.debug { "get #{key} from #{server.inspect}" } if logger
209
- value = cache_get server, cache_key
210
- return nil if value.nil?
211
- value = Marshal.load value unless raw
212
- return value
213
- end
214
- rescue TypeError => err
215
- handle_error nil, err
216
- end
217
-
218
- ##
219
- # Performs a +get+ with the given +key+. If
220
- # the value does not exist and a block was given,
221
- # the block will be called and the result saved via +add+.
222
- #
223
- # If you do not provide a block, using this
224
- # method is the same as using +get+.
225
- #
226
- def fetch(key, expiry = 0, raw = false)
227
- value = get(key, raw)
228
-
229
- if value.nil? && block_given?
230
- value = yield
231
- add(key, value, expiry, raw)
232
- end
233
-
234
- value
235
- end
236
-
237
- ##
238
- # Retrieves multiple values from memcached in parallel, if possible.
239
- #
240
- # The memcached protocol supports the ability to retrieve multiple
241
- # keys in a single request. Pass in an array of keys to this method
242
- # and it will:
243
- #
244
- # 1. map the key to the appropriate memcached server
245
- # 2. send a single request to each server that has one or more key values
246
- #
247
- # Returns a hash of values.
248
- #
249
- # cache["a"] = 1
250
- # cache["b"] = 2
251
- # cache.get_multi "a", "b" # => { "a" => 1, "b" => 2 }
252
- #
253
- # Note that get_multi assumes the values are marshalled.
254
-
255
- def get_multi(*keys)
256
- raise MemCacheError, 'No active servers' unless active?
257
-
258
- keys.flatten!
259
- key_count = keys.length
260
- cache_keys = {}
261
- server_keys = Hash.new { |h,k| h[k] = [] }
262
-
263
- # map keys to servers
264
- keys.each do |key|
265
- server, cache_key = request_setup key
266
- cache_keys[cache_key] = key
267
- server_keys[server] << cache_key
268
- end
269
-
270
- results = {}
271
-
272
- server_keys.each do |server, keys_for_server|
273
- keys_for_server_str = keys_for_server.join ' '
274
- begin
275
- values = cache_get_multi server, keys_for_server_str
276
- values.each do |key, value|
277
- results[cache_keys[key]] = Marshal.load value
278
- end
279
- rescue IndexError => e
280
- # Ignore this server and try the others
281
- logger.warn { "Unable to retrieve #{keys_for_server.size} elements from #{server.inspect}: #{e.message}"} if logger
282
- end
283
- end
284
-
285
- return results
286
- rescue TypeError => err
287
- handle_error nil, err
288
- end
289
-
290
- ##
291
- # Increments the value for +key+ by +amount+ and returns the new value.
292
- # +key+ must already exist. If +key+ is not an integer, it is assumed to be
293
- # 0.
294
-
295
- def incr(key, amount = 1)
296
- raise MemCacheError, "Update of readonly cache" if @readonly
297
- with_server(key) do |server, cache_key|
298
- cache_incr server, cache_key, amount
299
- end
300
- rescue TypeError => err
301
- handle_error nil, err
302
- end
303
-
304
- ##
305
- # Add +key+ to the cache with value +value+ that expires in +expiry+
306
- # seconds. If +raw+ is true, +value+ will not be Marshalled.
307
- #
308
- # Warning: Readers should not call this method in the event of a cache miss;
309
- # see MemCache#add.
310
-
311
- ONE_MB = 1024 * 1024
312
-
313
- def set(key, value, expiry = 0, raw = false)
314
- raise MemCacheError, "Update of readonly cache" if @readonly
315
- with_server(key) do |server, cache_key|
316
-
317
- value = Marshal.dump value unless raw
318
- logger.debug { "set #{key} to #{server.inspect}: #{value.to_s.size}" } if logger
319
-
320
- raise MemCacheError, "Value too large, memcached can only store 1MB of data per key" if value.to_s.size > ONE_MB
321
-
322
- command = "set #{cache_key} 0 #{expiry} #{value.to_s.size}#{noreply}\r\n#{value}\r\n"
323
-
324
- with_socket_management(server) do |socket|
325
- socket.write command
326
- break nil if @no_reply
327
- result = socket.gets
328
- raise_on_error_response! result
329
-
330
- if result.nil?
331
- server.close
332
- raise MemCacheError, "lost connection to #{server.host}:#{server.port}"
333
- end
334
-
335
- result
336
- end
337
- end
338
- end
339
-
340
- ##
341
- # "cas" is a check and set operation which means "store this data but
342
- # only if no one else has updated since I last fetched it." This can
343
- # be used as a form of optimistic locking.
344
- #
345
- # Works in block form like so:
346
- # cache.cas('some-key') do |value|
347
- # value + 1
348
- # end
349
- #
350
- # Returns:
351
- # +nil+ if the value was not found on the memcached server.
352
- # +STORED+ if the value was updated successfully
353
- # +EXISTS+ if the value was updated by someone else since last fetch
354
-
355
- def cas(key, expiry=0, raw=false)
356
- raise MemCacheError, "Update of readonly cache" if @readonly
357
- raise MemCacheError, "A block is required" unless block_given?
358
-
359
- (value, token) = gets(key, raw)
360
- return nil unless value
361
- updated = yield value
362
-
363
- with_server(key) do |server, cache_key|
364
-
365
- value = Marshal.dump updated unless raw
366
- logger.debug { "cas #{key} to #{server.inspect}: #{value.to_s.size}" } if logger
367
- command = "cas #{cache_key} 0 #{expiry} #{value.to_s.size} #{token}#{noreply}\r\n#{value}\r\n"
368
-
369
- with_socket_management(server) do |socket|
370
- socket.write command
371
- break nil if @no_reply
372
- result = socket.gets
373
- raise_on_error_response! result
374
-
375
- if result.nil?
376
- server.close
377
- raise MemCacheError, "lost connection to #{server.host}:#{server.port}"
378
- end
379
-
380
- result
381
- end
382
- end
383
- end
384
-
385
- ##
386
- # Add +key+ to the cache with value +value+ that expires in +expiry+
387
- # seconds, but only if +key+ does not already exist in the cache.
388
- # If +raw+ is true, +value+ will not be Marshalled.
389
- #
390
- # Readers should call this method in the event of a cache miss, not
391
- # MemCache#set.
392
-
393
- def add(key, value, expiry = 0, raw = false)
394
- raise MemCacheError, "Update of readonly cache" if @readonly
395
- with_server(key) do |server, cache_key|
396
- value = Marshal.dump value unless raw
397
- logger.debug { "add #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger
398
- command = "add #{cache_key} 0 #{expiry} #{value.to_s.size}#{noreply}\r\n#{value}\r\n"
399
-
400
- with_socket_management(server) do |socket|
401
- socket.write command
402
- break nil if @no_reply
403
- result = socket.gets
404
- raise_on_error_response! result
405
- result
406
- end
407
- end
408
- end
409
-
410
- ##
411
- # Add +key+ to the cache with value +value+ that expires in +expiry+
412
- # seconds, but only if +key+ already exists in the cache.
413
- # If +raw+ is true, +value+ will not be Marshalled.
414
- def replace(key, value, expiry = 0, raw = false)
415
- raise MemCacheError, "Update of readonly cache" if @readonly
416
- with_server(key) do |server, cache_key|
417
- value = Marshal.dump value unless raw
418
- logger.debug { "replace #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger
419
- command = "replace #{cache_key} 0 #{expiry} #{value.to_s.size}#{noreply}\r\n#{value}\r\n"
420
-
421
- with_socket_management(server) do |socket|
422
- socket.write command
423
- break nil if @no_reply
424
- result = socket.gets
425
- raise_on_error_response! result
426
- result
427
- end
428
- end
429
- end
430
-
431
- ##
432
- # Append - 'add this data to an existing key after existing data'
433
- # Please note the value is always passed to memcached as raw since it
434
- # doesn't make a lot of sense to concatenate marshalled data together.
435
- def append(key, value)
436
- raise MemCacheError, "Update of readonly cache" if @readonly
437
- with_server(key) do |server, cache_key|
438
- logger.debug { "append #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger
439
- command = "append #{cache_key} 0 0 #{value.to_s.size}#{noreply}\r\n#{value}\r\n"
440
-
441
- with_socket_management(server) do |socket|
442
- socket.write command
443
- break nil if @no_reply
444
- result = socket.gets
445
- raise_on_error_response! result
446
- result
447
- end
448
- end
449
- end
450
-
451
- ##
452
- # Prepend - 'add this data to an existing key before existing data'
453
- # Please note the value is always passed to memcached as raw since it
454
- # doesn't make a lot of sense to concatenate marshalled data together.
455
- def prepend(key, value)
456
- raise MemCacheError, "Update of readonly cache" if @readonly
457
- with_server(key) do |server, cache_key|
458
- logger.debug { "prepend #{key} to #{server}: #{value ? value.to_s.size : 'nil'}" } if logger
459
- command = "prepend #{cache_key} 0 0 #{value.to_s.size}#{noreply}\r\n#{value}\r\n"
460
-
461
- with_socket_management(server) do |socket|
462
- socket.write command
463
- break nil if @no_reply
464
- result = socket.gets
465
- raise_on_error_response! result
466
- result
467
- end
468
- end
469
- end
470
-
471
- ##
472
- # Removes +key+ from the cache in +expiry+ seconds.
473
-
474
- def delete(key, expiry = 0)
475
- raise MemCacheError, "Update of readonly cache" if @readonly
476
- with_server(key) do |server, cache_key|
477
- with_socket_management(server) do |socket|
478
- logger.debug { "delete #{cache_key} on #{server}" } if logger
479
- socket.write "delete #{cache_key} #{expiry}#{noreply}\r\n"
480
- break nil if @no_reply
481
- result = socket.gets
482
- raise_on_error_response! result
483
- result
484
- end
485
- end
486
- end
487
-
488
- ##
489
- # Flush the cache from all memcache servers.
490
- # A non-zero value for +delay+ will ensure that the flush
491
- # is propogated slowly through your memcached server farm.
492
- # The Nth server will be flushed N*delay seconds from now,
493
- # asynchronously so this method returns quickly.
494
- # This prevents a huge database spike due to a total
495
- # flush all at once.
496
-
497
- def flush_all(delay=0)
498
- raise MemCacheError, 'No active servers' unless active?
499
- raise MemCacheError, "Update of readonly cache" if @readonly
500
-
501
- begin
502
- delay_time = 0
503
- @servers.each do |server|
504
- with_socket_management(server) do |socket|
505
- logger.debug { "flush_all #{delay_time} on #{server}" } if logger
506
- if delay == 0 # older versions of memcached will fail silently otherwise
507
- socket.write "flush_all#{noreply}\r\n"
508
- else
509
- socket.write "flush_all #{delay_time}#{noreply}\r\n"
510
- end
511
- break nil if @no_reply
512
- result = socket.gets
513
- raise_on_error_response! result
514
- result
515
- end
516
- delay_time += delay
517
- end
518
- rescue IndexError => err
519
- handle_error nil, err
520
- end
521
- end
522
-
523
- ##
524
- # Reset the connection to all memcache servers. This should be called if
525
- # there is a problem with a cache lookup that might have left the connection
526
- # in a corrupted state.
527
-
528
- def reset
529
- @servers.each { |server| server.close }
530
- end
531
-
532
- ##
533
- # Returns statistics for each memcached server. An explanation of the
534
- # statistics can be found in the memcached docs:
535
- #
536
- # http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt
537
- #
538
- # Example:
539
- #
540
- # >> pp CACHE.stats
541
- # {"localhost:11211"=>
542
- # {"bytes"=>4718,
543
- # "pid"=>20188,
544
- # "connection_structures"=>4,
545
- # "time"=>1162278121,
546
- # "pointer_size"=>32,
547
- # "limit_maxbytes"=>67108864,
548
- # "cmd_get"=>14532,
549
- # "version"=>"1.2.0",
550
- # "bytes_written"=>432583,
551
- # "cmd_set"=>32,
552
- # "get_misses"=>0,
553
- # "total_connections"=>19,
554
- # "curr_connections"=>3,
555
- # "curr_items"=>4,
556
- # "uptime"=>1557,
557
- # "get_hits"=>14532,
558
- # "total_items"=>32,
559
- # "rusage_system"=>0.313952,
560
- # "rusage_user"=>0.119981,
561
- # "bytes_read"=>190619}}
562
- # => nil
563
-
564
- def stats
565
- raise MemCacheError, "No active servers" unless active?
566
- server_stats = {}
567
-
568
- @servers.each do |server|
569
- next unless server.alive?
570
-
571
- with_socket_management(server) do |socket|
572
- value = nil
573
- socket.write "stats\r\n"
574
- stats = {}
575
- while line = socket.gets do
576
- raise_on_error_response! line
577
- break if line == "END\r\n"
578
- if line =~ /\ASTAT ([\S]+) ([\w\.\:]+)/ then
579
- name, value = $1, $2
580
- stats[name] = case name
581
- when 'version'
582
- value
583
- when 'rusage_user', 'rusage_system' then
584
- seconds, microseconds = value.split(/:/, 2)
585
- microseconds ||= 0
586
- Float(seconds) + (Float(microseconds) / 1_000_000)
587
- else
588
- if value =~ /\A\d+\Z/ then
589
- value.to_i
590
- else
591
- value
592
- end
593
- end
594
- end
595
- end
596
- server_stats["#{server.host}:#{server.port}"] = stats
597
- end
598
- end
599
-
600
- raise MemCacheError, "No active servers" if server_stats.empty?
601
- server_stats
602
- end
603
-
604
- ##
605
- # Shortcut to get a value from the cache.
606
-
607
- alias [] get
608
-
609
- ##
610
- # Shortcut to save a value in the cache. This method does not set an
611
- # expiration on the entry. Use set to specify an explicit expiry.
612
-
613
- def []=(key, value)
614
- set key, value
615
- end
616
-
617
- protected unless $TESTING
618
-
619
- ##
620
- # Create a key for the cache, incorporating the namespace qualifier if
621
- # requested.
622
-
623
- def make_cache_key(key)
624
- if namespace.nil? then
625
- key
626
- else
627
- "#{@namespace}:#{key}"
628
- end
629
- end
630
-
631
- ##
632
- # Returns an interoperable hash value for +key+. (I think, docs are
633
- # sketchy for down servers).
634
-
635
- def hash_for(key)
636
- Zlib.crc32(key)
637
- end
638
-
639
- ##
640
- # Pick a server to handle the request based on a hash of the key.
641
-
642
- def get_server_for_key(key, options = {})
643
- raise ArgumentError, "illegal character in key #{key.inspect}" if
644
- key =~ /\s/
645
- raise ArgumentError, "key too long #{key.inspect}" if key.length > 250
646
- raise MemCacheError, "No servers available" if @servers.empty?
647
- return @servers.first if @servers.length == 1
648
-
649
- hkey = hash_for(key)
650
-
651
- 20.times do |try|
652
- entryidx = Continuum.binary_search(@continuum, hkey)
653
- server = @continuum[entryidx].server
654
- return server if server.alive?
655
- break unless failover
656
- hkey = hash_for "#{try}#{key}"
657
- end
658
-
659
- raise MemCacheError, "No servers available"
660
- end
661
-
662
- ##
663
- # Performs a raw decr for +cache_key+ from +server+. Returns nil if not
664
- # found.
665
-
666
- def cache_decr(server, cache_key, amount)
667
- with_socket_management(server) do |socket|
668
- socket.write "decr #{cache_key} #{amount}#{noreply}\r\n"
669
- break nil if @no_reply
670
- text = socket.gets
671
- raise_on_error_response! text
672
- return nil if text == "NOT_FOUND\r\n"
673
- return text.to_i
674
- end
675
- end
676
-
677
- ##
678
- # Fetches the raw data for +cache_key+ from +server+. Returns nil on cache
679
- # miss.
680
-
681
- def cache_get(server, cache_key)
682
- with_socket_management(server) do |socket|
683
- socket.write "get #{cache_key}\r\n"
684
- keyline = socket.gets # "VALUE <key> <flags> <bytes>\r\n"
685
-
686
- if keyline.nil? then
687
- server.close
688
- raise MemCacheError, "lost connection to #{server.host}:#{server.port}"
689
- end
690
-
691
- raise_on_error_response! keyline
692
- return nil if keyline == "END\r\n"
693
-
694
- unless keyline =~ /(\d+)\r/ then
695
- server.close
696
- raise MemCacheError, "unexpected response #{keyline.inspect}"
697
- end
698
- value = socket.read $1.to_i
699
- socket.read 2 # "\r\n"
700
- socket.gets # "END\r\n"
701
- return value
702
- end
703
- end
704
-
705
- def gets(key, raw = false)
706
- with_server(key) do |server, cache_key|
707
- logger.debug { "gets #{key} from #{server.inspect}" } if logger
708
- result = with_socket_management(server) do |socket|
709
- socket.write "gets #{cache_key}\r\n"
710
- keyline = socket.gets # "VALUE <key> <flags> <bytes> <cas token>\r\n"
711
-
712
- if keyline.nil? then
713
- server.close
714
- raise MemCacheError, "lost connection to #{server.host}:#{server.port}"
715
- end
716
-
717
- raise_on_error_response! keyline
718
- return nil if keyline == "END\r\n"
719
-
720
- unless keyline =~ /(\d+) (\w+)\r/ then
721
- server.close
722
- raise MemCacheError, "unexpected response #{keyline.inspect}"
723
- end
724
- value = socket.read $1.to_i
725
- socket.read 2 # "\r\n"
726
- socket.gets # "END\r\n"
727
- [value, $2]
728
- end
729
- result[0] = Marshal.load result[0] unless raw
730
- result
731
- end
732
- rescue TypeError => err
733
- handle_error nil, err
734
- end
735
-
736
-
737
- ##
738
- # Fetches +cache_keys+ from +server+ using a multi-get.
739
-
740
- def cache_get_multi(server, cache_keys)
741
- with_socket_management(server) do |socket|
742
- values = {}
743
- socket.write "get #{cache_keys}\r\n"
744
-
745
- while keyline = socket.gets do
746
- return values if keyline == "END\r\n"
747
- raise_on_error_response! keyline
748
-
749
- unless keyline =~ /\AVALUE (.+) (.+) (.+)/ then
750
- server.close
751
- raise MemCacheError, "unexpected response #{keyline.inspect}"
752
- end
753
-
754
- key, data_length = $1, $3
755
- values[$1] = socket.read data_length.to_i
756
- socket.read(2) # "\r\n"
757
- end
758
-
759
- server.close
760
- raise MemCacheError, "lost connection to #{server.host}:#{server.port}" # TODO: retry here too
761
- end
762
- end
763
-
764
- ##
765
- # Performs a raw incr for +cache_key+ from +server+. Returns nil if not
766
- # found.
767
-
768
- def cache_incr(server, cache_key, amount)
769
- with_socket_management(server) do |socket|
770
- socket.write "incr #{cache_key} #{amount}#{noreply}\r\n"
771
- break nil if @no_reply
772
- text = socket.gets
773
- raise_on_error_response! text
774
- return nil if text == "NOT_FOUND\r\n"
775
- return text.to_i
776
- end
777
- end
778
-
779
- ##
780
- # Gets or creates a socket connected to the given server, and yields it
781
- # to the block, wrapped in a mutex synchronization if @multithread is true.
782
- #
783
- # If a socket error (SocketError, SystemCallError, IOError) or protocol error
784
- # (MemCacheError) is raised by the block, closes the socket, attempts to
785
- # connect again, and retries the block (once). If an error is again raised,
786
- # reraises it as MemCacheError.
787
- #
788
- # If unable to connect to the server (or if in the reconnect wait period),
789
- # raises MemCacheError. Note that the socket connect code marks a server
790
- # dead for a timeout period, so retrying does not apply to connection attempt
791
- # failures (but does still apply to unexpectedly lost connections etc.).
792
-
793
- def with_socket_management(server, &block)
794
- check_multithread_status!
795
-
796
- @mutex.lock if @multithread
797
- retried = false
798
-
799
- begin
800
- socket = server.socket
801
-
802
- # Raise an IndexError to show this server is out of whack. If were inside
803
- # a with_server block, we'll catch it and attempt to restart the operation.
804
-
805
- raise IndexError, "No connection to server (#{server.status})" if socket.nil?
806
-
807
- block.call(socket)
808
-
809
- rescue SocketError, Errno::EAGAIN, Timeout::Error => err
810
- logger.warn { "Socket failure: #{err.message}" } if logger
811
- server.mark_dead(err)
812
- handle_error(server, err)
813
-
814
- rescue MemCacheError, SystemCallError, IOError => err
815
- logger.warn { "Generic failure: #{err.class.name}: #{err.message}" } if logger
816
- handle_error(server, err) if retried || socket.nil?
817
- retried = true
818
- retry
819
- end
820
- ensure
821
- @mutex.unlock if @multithread
822
- end
823
-
824
- def with_server(key)
825
- retried = false
826
- begin
827
- server, cache_key = request_setup(key)
828
- yield server, cache_key
829
- rescue IndexError => e
830
- logger.warn { "Server failed: #{e.class.name}: #{e.message}" } if logger
831
- if !retried && @servers.size > 1
832
- logger.info { "Connection to server #{server.inspect} DIED! Retrying operation..." } if logger
833
- retried = true
834
- retry
835
- end
836
- handle_error(nil, e)
837
- end
838
- end
839
-
840
- ##
841
- # Handles +error+ from +server+.
842
-
843
- def handle_error(server, error)
844
- raise error if error.is_a?(MemCacheError)
845
- server.close if server
846
- new_error = MemCacheError.new error.message
847
- new_error.set_backtrace error.backtrace
848
- raise new_error
849
- end
850
-
851
- def noreply
852
- @no_reply ? ' noreply' : ''
853
- end
854
-
855
- ##
856
- # Performs setup for making a request with +key+ from memcached. Returns
857
- # the server to fetch the key from and the complete key to use.
858
-
859
- def request_setup(key)
860
- raise MemCacheError, 'No active servers' unless active?
861
- cache_key = make_cache_key key
862
- server = get_server_for_key cache_key
863
- return server, cache_key
864
- end
865
-
866
- def raise_on_error_response!(response)
867
- if response =~ /\A(?:CLIENT_|SERVER_)?ERROR(.*)/
868
- raise MemCacheError, $1.strip
869
- end
870
- end
871
-
872
- def create_continuum_for(servers)
873
- total_weight = servers.inject(0) { |memo, srv| memo + srv.weight }
874
- continuum = []
875
-
876
- servers.each do |server|
877
- entry_count_for(server, servers.size, total_weight).times do |idx|
878
- hash = Digest::SHA1.hexdigest("#{server.host}:#{server.port}:#{idx}")
879
- value = Integer("0x#{hash[0..7]}")
880
- continuum << Continuum::Entry.new(value, server)
881
- end
882
- end
883
-
884
- continuum.sort { |a, b| a.value <=> b.value }
885
- end
886
-
887
- def entry_count_for(server, total_servers, total_weight)
888
- ((total_servers * Continuum::POINTS_PER_SERVER * server.weight) / Float(total_weight)).floor
889
- end
890
-
891
- def check_multithread_status!
892
- return if @multithread
893
-
894
- if Thread.current[:memcache_client] != self.object_id
895
- raise MemCacheError, <<-EOM
896
- You are accessing this memcache-client instance from multiple threads but have not enabled multithread support.
897
- Normally: MemCache.new(['localhost:11211'], :multithread => true)
898
- In Rails: config.cache_store = [:mem_cache_store, 'localhost:11211', { :multithread => true }]
899
- EOM
900
- end
901
- end
902
-
903
- ##
904
- # This class represents a memcached server instance.
905
-
906
- class Server
907
-
908
- ##
909
- # The amount of time to wait before attempting to re-establish a
910
- # connection with a server that is marked dead.
911
-
912
- RETRY_DELAY = 30.0
913
-
914
- ##
915
- # The host the memcached server is running on.
916
-
917
- attr_reader :host
918
-
919
- ##
920
- # The port the memcached server is listening on.
921
-
922
- attr_reader :port
923
-
924
- ##
925
- # The weight given to the server.
926
-
927
- attr_reader :weight
928
-
929
- ##
930
- # The time of next retry if the connection is dead.
931
-
932
- attr_reader :retry
933
-
934
- ##
935
- # A text status string describing the state of the server.
936
-
937
- attr_reader :status
938
-
939
- attr_reader :logger
940
-
941
- ##
942
- # Create a new MemCache::Server object for the memcached instance
943
- # listening on the given host and port, weighted by the given weight.
944
-
945
- def initialize(memcache, host, port = DEFAULT_PORT, weight = DEFAULT_WEIGHT)
946
- raise ArgumentError, "No host specified" if host.nil? or host.empty?
947
- raise ArgumentError, "No port specified" if port.nil? or port.to_i.zero?
948
-
949
- @host = host
950
- @port = port.to_i
951
- @weight = weight.to_i
952
-
953
- @sock = nil
954
- @retry = nil
955
- @status = 'NOT CONNECTED'
956
- @timeout = memcache.timeout
957
- @logger = memcache.logger
958
- end
959
-
960
- ##
961
- # Return a string representation of the server object.
962
-
963
- def inspect
964
- "<MemCache::Server: %s:%d [%d] (%s)>" % [@host, @port, @weight, @status]
965
- end
966
-
967
- ##
968
- # Check whether the server connection is alive. This will cause the
969
- # socket to attempt to connect if it isn't already connected and or if
970
- # the server was previously marked as down and the retry time has
971
- # been exceeded.
972
-
973
- def alive?
974
- !!socket
975
- end
976
-
977
- ##
978
- # Try to connect to the memcached server targeted by this object.
979
- # Returns the connected socket object on success or nil on failure.
980
-
981
- def socket
982
- return @sock if @sock and not @sock.closed?
983
-
984
- @sock = nil
985
-
986
- # If the host was dead, don't retry for a while.
987
- return if @retry and @retry > Time.now
988
-
989
- # Attempt to connect if not already connected.
990
- begin
991
- @sock = connect_to(@host, @port, @timeout)
992
- @sock.setsockopt Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1
993
- @retry = nil
994
- @status = 'CONNECTED'
995
- rescue SocketError, SystemCallError, IOError => err
996
- logger.warn { "Unable to open socket: #{err.class.name}, #{err.message}" } if logger
997
- mark_dead err
998
- end
999
-
1000
- return @sock
1001
- end
1002
-
1003
- def connect_to(host, port, timeout=nil)
1004
- io = MemCache::BufferedIO.new(TCPSocket.new(host, port))
1005
- io.read_timeout = timeout
1006
- io
1007
- end
1008
-
1009
- ##
1010
- # Close the connection to the memcached server targeted by this
1011
- # object. The server is not considered dead.
1012
-
1013
- def close
1014
- @sock.close if @sock && !@sock.closed?
1015
- @sock = nil
1016
- @retry = nil
1017
- @status = "NOT CONNECTED"
1018
- end
1019
-
1020
- ##
1021
- # Mark the server as dead and close its socket.
1022
-
1023
- def mark_dead(error)
1024
- @sock.close if @sock && !@sock.closed?
1025
- @sock = nil
1026
- @retry = Time.now + RETRY_DELAY
1027
-
1028
- reason = "#{error.class.name}: #{error.message}"
1029
- @status = sprintf "%s:%s DEAD (%s), will retry at %s", @host, @port, reason, @retry
1030
- @logger.info { @status } if @logger
1031
- end
1032
-
1033
- end
1034
-
1035
- ##
1036
- # Base MemCache exception class.
1037
-
1038
- class MemCacheError < RuntimeError; end
1039
-
1040
- class BufferedIO < Net::BufferedIO # :nodoc:
1041
- BUFSIZE = 1024 * 16
1042
-
1043
- # An implementation similar to this is in *trunk* for 1.9. When it
1044
- # gets released, this method can be removed when using 1.9
1045
- def rbuf_fill
1046
- begin
1047
- @rbuf << @io.read_nonblock(BUFSIZE)
1048
- rescue Errno::EWOULDBLOCK
1049
- retry unless @read_timeout
1050
- if IO.select([@io], nil, nil, @read_timeout)
1051
- retry
1052
- else
1053
- raise Timeout::Error, 'IO timeout'
1054
- end
1055
- end
1056
- end
1057
-
1058
- def setsockopt *args
1059
- @io.setsockopt *args
1060
- end
1061
-
1062
- def gets
1063
- readuntil("\n")
1064
- end
1065
- end
1066
-
1067
- end
1068
-
1069
- module Continuum
1070
- POINTS_PER_SERVER = 160 # this is the default in libmemcached
1071
-
1072
- # Find the closest index in Continuum with value <= the given value
1073
- def self.binary_search(ary, value, &block)
1074
- upper = ary.size - 1
1075
- lower = 0
1076
- idx = 0
1077
-
1078
- while(lower <= upper) do
1079
- idx = (lower + upper) / 2
1080
- comp = ary[idx].value <=> value
1081
-
1082
- if comp == 0
1083
- return idx
1084
- elsif comp > 0
1085
- upper = idx - 1
1086
- else
1087
- lower = idx + 1
1088
- end
1089
- end
1090
- return upper
1091
- end
1092
-
1093
- class Entry
1094
- attr_reader :value
1095
- attr_reader :server
1096
-
1097
- def initialize(val, srv)
1098
- @value = val
1099
- @server = srv
1100
- end
1101
-
1102
- def inspect
1103
- "<#{value}, #{server.host}:#{server.port}>"
1104
- end
1105
- end
1106
-
1107
- end