csd 0.0.15 → 0.0.16

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 (256) hide show
  1. data/.gitignore +1 -0
  2. data/COPYING +367 -0
  3. data/Rakefile +10 -10
  4. data/VERSION +1 -1
  5. data/bin/ai +19 -0
  6. data/csd.gemspec +257 -35
  7. data/lib/active_support.rb +75 -0
  8. data/lib/active_support/all.rb +3 -0
  9. data/lib/active_support/backtrace_cleaner.rb +94 -0
  10. data/lib/active_support/base64.rb +42 -0
  11. data/lib/active_support/basic_object.rb +21 -0
  12. data/lib/active_support/benchmarkable.rb +60 -0
  13. data/lib/active_support/buffered_logger.rb +132 -0
  14. data/lib/active_support/builder.rb +6 -0
  15. data/lib/active_support/cache.rb +626 -0
  16. data/lib/active_support/cache/compressed_mem_cache_store.rb +13 -0
  17. data/lib/active_support/cache/file_store.rb +188 -0
  18. data/lib/active_support/cache/mem_cache_store.rb +191 -0
  19. data/lib/active_support/cache/memory_store.rb +159 -0
  20. data/lib/active_support/cache/strategy/local_cache.rb +164 -0
  21. data/lib/active_support/cache/synchronized_memory_store.rb +11 -0
  22. data/lib/active_support/callbacks.rb +600 -0
  23. data/lib/active_support/concern.rb +29 -0
  24. data/lib/active_support/configurable.rb +36 -0
  25. data/lib/active_support/core_ext.rb +3 -0
  26. data/lib/active_support/core_ext/array.rb +7 -0
  27. data/lib/active_support/core_ext/array/access.rb +46 -0
  28. data/lib/active_support/core_ext/array/conversions.rb +164 -0
  29. data/lib/active_support/core_ext/array/extract_options.rb +29 -0
  30. data/lib/active_support/core_ext/array/grouping.rb +100 -0
  31. data/lib/active_support/core_ext/array/random_access.rb +20 -0
  32. data/lib/active_support/core_ext/array/uniq_by.rb +17 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +22 -0
  34. data/lib/active_support/core_ext/benchmark.rb +7 -0
  35. data/lib/active_support/core_ext/big_decimal.rb +1 -0
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +27 -0
  37. data/lib/active_support/core_ext/cgi.rb +1 -0
  38. data/lib/active_support/core_ext/cgi/escape_skipping_slashes.rb +19 -0
  39. data/lib/active_support/core_ext/class.rb +4 -0
  40. data/lib/active_support/core_ext/class/attribute.rb +67 -0
  41. data/lib/active_support/core_ext/class/attribute_accessors.rb +63 -0
  42. data/lib/active_support/core_ext/class/delegating_attributes.rb +44 -0
  43. data/lib/active_support/core_ext/class/inheritable_attributes.rb +232 -0
  44. data/lib/active_support/core_ext/class/subclasses.rb +55 -0
  45. data/lib/active_support/core_ext/date/acts_like.rb +8 -0
  46. data/lib/active_support/core_ext/date/calculations.rb +240 -0
  47. data/lib/active_support/core_ext/date/conversions.rb +99 -0
  48. data/lib/active_support/core_ext/date/freeze.rb +31 -0
  49. data/lib/active_support/core_ext/date_time/acts_like.rb +13 -0
  50. data/lib/active_support/core_ext/date_time/calculations.rb +113 -0
  51. data/lib/active_support/core_ext/date_time/conversions.rb +102 -0
  52. data/lib/active_support/core_ext/date_time/zones.rb +17 -0
  53. data/lib/active_support/core_ext/enumerable.rb +119 -0
  54. data/lib/active_support/core_ext/exception.rb +3 -0
  55. data/lib/active_support/core_ext/file.rb +2 -0
  56. data/lib/active_support/core_ext/file/atomic.rb +41 -0
  57. data/lib/active_support/core_ext/file/path.rb +5 -0
  58. data/lib/active_support/core_ext/float.rb +1 -0
  59. data/lib/active_support/core_ext/float/rounding.rb +19 -0
  60. data/lib/active_support/core_ext/hash.rb +8 -0
  61. data/lib/active_support/core_ext/hash/conversions.rb +150 -0
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +16 -0
  63. data/lib/active_support/core_ext/hash/diff.rb +13 -0
  64. data/lib/active_support/core_ext/hash/except.rb +24 -0
  65. data/lib/active_support/core_ext/hash/indifferent_access.rb +14 -0
  66. data/lib/active_support/core_ext/hash/keys.rb +45 -0
  67. data/lib/active_support/core_ext/hash/reverse_merge.rb +28 -0
  68. data/lib/active_support/core_ext/hash/slice.rb +38 -0
  69. data/lib/active_support/core_ext/integer.rb +3 -0
  70. data/lib/active_support/core_ext/integer/inflections.rb +14 -0
  71. data/lib/active_support/core_ext/integer/multiple.rb +6 -0
  72. data/lib/active_support/core_ext/integer/time.rb +39 -0
  73. data/lib/active_support/core_ext/kernel.rb +5 -0
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +11 -0
  75. data/lib/active_support/core_ext/kernel/debugger.rb +16 -0
  76. data/lib/active_support/core_ext/kernel/reporting.rb +62 -0
  77. data/lib/active_support/core_ext/kernel/requires.rb +26 -0
  78. data/lib/active_support/core_ext/kernel/singleton_class.rb +13 -0
  79. data/lib/active_support/core_ext/load_error.rb +23 -0
  80. data/lib/active_support/core_ext/logger.rb +146 -0
  81. data/lib/active_support/core_ext/module.rb +12 -0
  82. data/lib/active_support/core_ext/module/aliasing.rb +70 -0
  83. data/lib/active_support/core_ext/module/anonymous.rb +24 -0
  84. data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
  85. data/lib/active_support/core_ext/module/attr_internal.rb +32 -0
  86. data/lib/active_support/core_ext/module/attribute_accessors.rb +66 -0
  87. data/lib/active_support/core_ext/module/delegation.rb +146 -0
  88. data/lib/active_support/core_ext/module/deprecation.rb +9 -0
  89. data/lib/active_support/core_ext/module/introspection.rb +88 -0
  90. data/lib/active_support/core_ext/module/method_names.rb +14 -0
  91. data/lib/active_support/core_ext/module/reachable.rb +10 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +6 -0
  93. data/lib/active_support/core_ext/module/synchronization.rb +42 -0
  94. data/lib/active_support/core_ext/name_error.rb +18 -0
  95. data/lib/active_support/core_ext/numeric.rb +2 -0
  96. data/lib/active_support/core_ext/numeric/bytes.rb +44 -0
  97. data/lib/active_support/core_ext/numeric/time.rb +77 -0
  98. data/lib/active_support/core_ext/object.rb +14 -0
  99. data/lib/active_support/core_ext/object/acts_like.rb +10 -0
  100. data/lib/active_support/core_ext/object/blank.rb +76 -0
  101. data/lib/active_support/core_ext/object/conversions.rb +4 -0
  102. data/lib/active_support/core_ext/object/duplicable.rb +65 -0
  103. data/lib/active_support/core_ext/object/extending.rb +11 -0
  104. data/lib/active_support/core_ext/object/instance_variables.rb +67 -0
  105. data/lib/active_support/core_ext/object/misc.rb +2 -0
  106. data/lib/active_support/core_ext/object/returning.rb +42 -0
  107. data/lib/active_support/core_ext/object/to_param.rb +49 -0
  108. data/lib/active_support/core_ext/object/to_query.rb +27 -0
  109. data/lib/active_support/core_ext/object/try.rb +36 -0
  110. data/lib/active_support/core_ext/object/with_options.rb +26 -0
  111. data/lib/active_support/core_ext/proc.rb +14 -0
  112. data/lib/active_support/core_ext/process.rb +1 -0
  113. data/lib/active_support/core_ext/process/daemon.rb +23 -0
  114. data/lib/active_support/core_ext/range.rb +4 -0
  115. data/lib/active_support/core_ext/range/blockless_step.rb +29 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +21 -0
  117. data/lib/active_support/core_ext/range/include_range.rb +21 -0
  118. data/lib/active_support/core_ext/range/overlaps.rb +8 -0
  119. data/lib/active_support/core_ext/regexp.rb +5 -0
  120. data/lib/active_support/core_ext/rexml.rb +46 -0
  121. data/lib/active_support/core_ext/string.rb +12 -0
  122. data/lib/active_support/core_ext/string/access.rb +99 -0
  123. data/lib/active_support/core_ext/string/behavior.rb +7 -0
  124. data/lib/active_support/core_ext/string/conversions.rb +61 -0
  125. data/lib/active_support/core_ext/string/encoding.rb +11 -0
  126. data/lib/active_support/core_ext/string/exclude.rb +6 -0
  127. data/lib/active_support/core_ext/string/filters.rb +49 -0
  128. data/lib/active_support/core_ext/string/inflections.rb +149 -0
  129. data/lib/active_support/core_ext/string/interpolation.rb +2 -0
  130. data/lib/active_support/core_ext/string/multibyte.rb +72 -0
  131. data/lib/active_support/core_ext/string/output_safety.rb +109 -0
  132. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -0
  133. data/lib/active_support/core_ext/string/xchar.rb +18 -0
  134. data/lib/active_support/core_ext/time/acts_like.rb +8 -0
  135. data/lib/active_support/core_ext/time/calculations.rb +282 -0
  136. data/lib/active_support/core_ext/time/conversions.rb +85 -0
  137. data/lib/active_support/core_ext/time/marshal.rb +56 -0
  138. data/lib/active_support/core_ext/time/publicize_conversion_methods.rb +10 -0
  139. data/lib/active_support/core_ext/time/zones.rb +78 -0
  140. data/lib/active_support/core_ext/uri.rb +22 -0
  141. data/lib/active_support/dependencies.rb +628 -0
  142. data/lib/active_support/dependencies/autoload.rb +50 -0
  143. data/lib/active_support/deprecation.rb +18 -0
  144. data/lib/active_support/deprecation/behaviors.rb +38 -0
  145. data/lib/active_support/deprecation/method_wrappers.rb +29 -0
  146. data/lib/active_support/deprecation/proxy_wrappers.rb +74 -0
  147. data/lib/active_support/deprecation/reporting.rb +56 -0
  148. data/lib/active_support/duration.rb +105 -0
  149. data/lib/active_support/gzip.rb +25 -0
  150. data/lib/active_support/hash_with_indifferent_access.rb +145 -0
  151. data/lib/active_support/i18n.rb +8 -0
  152. data/lib/active_support/inflections.rb +56 -0
  153. data/lib/active_support/inflector.rb +7 -0
  154. data/lib/active_support/inflector/inflections.rb +211 -0
  155. data/lib/active_support/inflector/methods.rb +141 -0
  156. data/lib/active_support/inflector/transliterate.rb +97 -0
  157. data/lib/active_support/json.rb +2 -0
  158. data/lib/active_support/json/backends/jsongem.rb +43 -0
  159. data/lib/active_support/json/backends/yajl.rb +40 -0
  160. data/lib/active_support/json/backends/yaml.rb +90 -0
  161. data/lib/active_support/json/decoding.rb +51 -0
  162. data/lib/active_support/json/encoding.rb +254 -0
  163. data/lib/active_support/json/variable.rb +11 -0
  164. data/lib/active_support/lazy_load_hooks.rb +27 -0
  165. data/lib/active_support/locale/en.yml +36 -0
  166. data/lib/active_support/memoizable.rb +103 -0
  167. data/lib/active_support/message_encryptor.rb +71 -0
  168. data/lib/active_support/message_verifier.rb +62 -0
  169. data/lib/active_support/multibyte.rb +44 -0
  170. data/lib/active_support/multibyte/chars.rb +480 -0
  171. data/lib/active_support/multibyte/exceptions.rb +8 -0
  172. data/lib/active_support/multibyte/unicode.rb +393 -0
  173. data/lib/active_support/multibyte/utils.rb +60 -0
  174. data/lib/active_support/notifications.rb +81 -0
  175. data/lib/active_support/notifications/fanout.rb +93 -0
  176. data/lib/active_support/notifications/instrumenter.rb +56 -0
  177. data/lib/active_support/option_merger.rb +25 -0
  178. data/lib/active_support/ordered_hash.rb +158 -0
  179. data/lib/active_support/ordered_options.rb +27 -0
  180. data/lib/active_support/railtie.rb +100 -0
  181. data/lib/active_support/rescuable.rb +114 -0
  182. data/lib/active_support/ruby/shim.rb +22 -0
  183. data/lib/active_support/secure_random.rb +199 -0
  184. data/lib/active_support/string_inquirer.rb +21 -0
  185. data/lib/active_support/test_case.rb +42 -0
  186. data/lib/active_support/testing/assertions.rb +82 -0
  187. data/lib/active_support/testing/declarative.rb +40 -0
  188. data/lib/active_support/testing/default.rb +9 -0
  189. data/lib/active_support/testing/deprecation.rb +55 -0
  190. data/lib/active_support/testing/isolation.rb +154 -0
  191. data/lib/active_support/testing/pending.rb +48 -0
  192. data/lib/active_support/testing/performance.rb +455 -0
  193. data/lib/active_support/testing/setup_and_teardown.rb +111 -0
  194. data/lib/active_support/time.rb +34 -0
  195. data/lib/active_support/time/autoload.rb +5 -0
  196. data/lib/active_support/time_with_zone.rb +341 -0
  197. data/lib/active_support/values/time_zone.rb +377 -0
  198. data/lib/active_support/values/unicode_tables.dat +0 -0
  199. data/lib/active_support/version.rb +10 -0
  200. data/lib/active_support/whiny_nil.rb +60 -0
  201. data/lib/active_support/xml_mini.rb +158 -0
  202. data/lib/active_support/xml_mini/jdom.rb +168 -0
  203. data/lib/active_support/xml_mini/libxml.rb +80 -0
  204. data/lib/active_support/xml_mini/libxmlsax.rb +85 -0
  205. data/lib/active_support/xml_mini/nokogiri.rb +78 -0
  206. data/lib/active_support/xml_mini/nokogirisax.rb +83 -0
  207. data/lib/active_support/xml_mini/rexml.rb +129 -0
  208. data/lib/csd.rb +82 -2
  209. data/lib/csd/application.rb +2 -0
  210. data/lib/csd/application/default.rb +51 -0
  211. data/lib/csd/application/default/base.rb +15 -0
  212. data/lib/csd/application/minisip.rb +25 -0
  213. data/lib/csd/application/minisip/about.yml +14 -0
  214. data/lib/csd/application/minisip/base.rb +161 -0
  215. data/lib/csd/application/minisip/error.rb +11 -0
  216. data/lib/csd/application/minisip/options/common.rb +0 -0
  217. data/lib/csd/application/minisip/options/compile.rb +59 -0
  218. data/lib/csd/{applications → application}/minisip/unix/base.rb +10 -11
  219. data/lib/csd/application/opensips/about.yml +2 -0
  220. data/lib/csd/applications.rb +55 -0
  221. data/lib/csd/commands.rb +88 -65
  222. data/lib/csd/error.rb +31 -0
  223. data/lib/csd/extensions.rb +1 -0
  224. data/lib/{extensions → csd/extensions}/core/array.rb +2 -2
  225. data/lib/csd/extensions/core/dir.rb +46 -0
  226. data/lib/{extensions → csd/extensions}/core/file.rb +2 -2
  227. data/lib/{extensions → csd/extensions}/core/object.rb +2 -2
  228. data/lib/csd/extensions/core/option_parser.rb +33 -0
  229. data/lib/{extensions → csd/extensions}/core/pathname.rb +12 -3
  230. data/lib/{extensions → csd/extensions}/core/string.rb +2 -2
  231. data/lib/{extensions → csd/extensions}/gem/platform.rb +6 -2
  232. data/lib/csd/global_open_struct.rb +18 -0
  233. data/lib/csd/options.rb +124 -95
  234. data/lib/csd/path.rb +31 -0
  235. data/lib/csd/ui.rb +1 -0
  236. data/lib/csd/ui/cli.rb +7 -0
  237. data/lib/csd/ui/ui.rb +46 -0
  238. data/lib/csd/version.rb +9 -0
  239. data/lib/term/ansicolor.rb +102 -0
  240. data/lib/term/ansicolor/.keep +0 -0
  241. data/lib/term/ansicolor/version.rb +10 -0
  242. data/test/functional/test_applications.rb +86 -0
  243. data/test/functional/test_commands.rb +42 -29
  244. data/test/functional/test_options.rb +98 -0
  245. data/test/helper.rb +14 -0
  246. data/test/unit/test_dir.rb +38 -0
  247. data/test/unit/test_pathname.rb +32 -0
  248. metadata +253 -40
  249. data/LICENSE +0 -20
  250. data/bin/csd +0 -8
  251. data/lib/csd/applications/base.rb +0 -33
  252. data/lib/csd/applications/minisip/base.rb +0 -125
  253. data/lib/csd/applications/minisip/init.rb +0 -20
  254. data/lib/csd/init.rb +0 -69
  255. data/lib/csd/path_container.rb +0 -15
  256. data/publish +0 -29
@@ -0,0 +1,13 @@
1
+ module ActiveSupport
2
+ module Cache
3
+ class CompressedMemCacheStore < MemCacheStore
4
+ def initialize(*args)
5
+ ActiveSupport::Deprecation.warn('ActiveSupport::Cache::CompressedMemCacheStore has been deprecated in favor of ActiveSupport::Cache::MemCacheStore(:compress => true).', caller)
6
+ addresses = args.dup
7
+ options = addresses.extract_options!
8
+ args = addresses + [options.merge(:compress => true)]
9
+ super(*args)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,188 @@
1
+ require 'active_support/core_ext/file/atomic'
2
+
3
+ module ActiveSupport
4
+ module Cache
5
+ # A cache store implementation which stores everything on the filesystem.
6
+ #
7
+ # FileStore implements the Strategy::LocalCache strategy which implements
8
+ # an in memory cache inside of a block.
9
+ class FileStore < Store
10
+ attr_reader :cache_path
11
+
12
+ DIR_FORMATTER = "%03X"
13
+ ESCAPE_FILENAME_CHARS = /[^a-z0-9_.-]/i
14
+ UNESCAPE_FILENAME_CHARS = /%[0-9A-F]{2}/
15
+
16
+ def initialize(cache_path, options = nil)
17
+ super(options)
18
+ @cache_path = cache_path
19
+ extend Strategy::LocalCache
20
+ end
21
+
22
+ def clear(options = nil)
23
+ root_dirs = Dir.entries(cache_path).reject{|f| ['.', '..'].include?(f)}
24
+ FileUtils.rm_r(root_dirs.collect{|f| File.join(cache_path, f)})
25
+ end
26
+
27
+ def cleanup(options = nil)
28
+ options = merged_options(options)
29
+ each_key(options) do |key|
30
+ entry = read_entry(key, options)
31
+ delete_entry(key, options) if entry && entry.expired?
32
+ end
33
+ end
34
+
35
+ def increment(name, amount = 1, options = nil)
36
+ file_name = key_file_path(namespaced_key(name, options))
37
+ lock_file(file_name) do
38
+ options = merged_options(options)
39
+ if num = read(name, options)
40
+ num = num.to_i + amount
41
+ write(name, num, options)
42
+ num
43
+ else
44
+ nil
45
+ end
46
+ end
47
+ end
48
+
49
+ def decrement(name, amount = 1, options = nil)
50
+ file_name = key_file_path(namespaced_key(name, options))
51
+ lock_file(file_name) do
52
+ options = merged_options(options)
53
+ if num = read(name, options)
54
+ num = num.to_i - amount
55
+ write(name, num, options)
56
+ num
57
+ else
58
+ nil
59
+ end
60
+ end
61
+ end
62
+
63
+ def delete_matched(matcher, options = nil)
64
+ options = merged_options(options)
65
+ instrument(:delete_matched, matcher.inspect) do
66
+ matcher = key_matcher(matcher, options)
67
+ search_dir(cache_path) do |path|
68
+ key = file_path_key(path)
69
+ delete_entry(key, options) if key.match(matcher)
70
+ end
71
+ end
72
+ end
73
+
74
+ protected
75
+
76
+ def read_entry(key, options)
77
+ file_name = key_file_path(key)
78
+ if File.exist?(file_name)
79
+ entry = File.open(file_name) { |f| Marshal.load(f) }
80
+ if entry && !entry.expired? && !entry.expires_in && !self.options[:expires_in]
81
+ # Check for deprecated use of +:expires_in+ option from versions < 3.0
82
+ deprecated_expires_in = options[:expires_in]
83
+ if deprecated_expires_in
84
+ ActiveSupport::Deprecation.warn('Setting :expires_in on read has been deprecated in favor of setting it on write.', caller)
85
+ if entry.created_at + deprecated_expires_in.to_f <= Time.now.to_f
86
+ delete_entry(key, options)
87
+ entry = nil
88
+ end
89
+ end
90
+ end
91
+ entry
92
+ end
93
+ rescue
94
+ nil
95
+ end
96
+
97
+ def write_entry(key, entry, options)
98
+ file_name = key_file_path(key)
99
+ ensure_cache_path(File.dirname(file_name))
100
+ File.atomic_write(file_name, cache_path) {|f| Marshal.dump(entry, f)}
101
+ true
102
+ end
103
+
104
+ def delete_entry(key, options)
105
+ file_name = key_file_path(key)
106
+ if File.exist?(file_name)
107
+ begin
108
+ File.delete(file_name)
109
+ delete_empty_directories(File.dirname(file_name))
110
+ true
111
+ rescue => e
112
+ # Just in case the error was caused by another process deleting the file first.
113
+ raise e if File.exist?(file_name)
114
+ false
115
+ end
116
+ end
117
+ end
118
+
119
+ private
120
+ # Lock a file for a block so only one process can modify it at a time.
121
+ def lock_file(file_name, &block) # :nodoc:
122
+ if File.exist?(file_name)
123
+ File.open(file_name, 'r') do |f|
124
+ begin
125
+ f.flock File::LOCK_EX
126
+ yield
127
+ ensure
128
+ f.flock File::LOCK_UN
129
+ end
130
+ end
131
+ else
132
+ yield
133
+ end
134
+ end
135
+
136
+ # Translate a key into a file path.
137
+ def key_file_path(key)
138
+ fname = key.to_s.gsub(ESCAPE_FILENAME_CHARS){|match| "%#{match.ord.to_s(16).upcase}"}
139
+ hash = Zlib.adler32(fname)
140
+ hash, dir_1 = hash.divmod(0x1000)
141
+ dir_2 = hash.modulo(0x1000)
142
+ fname_paths = []
143
+ # Make sure file name is < 255 characters so it doesn't exceed file system limits.
144
+ if fname.size <= 255
145
+ fname_paths << fname
146
+ else
147
+ while fname.size <= 255
148
+ fname_path << fname[0, 255]
149
+ fname = fname[255, -1]
150
+ end
151
+ end
152
+ File.join(cache_path, DIR_FORMATTER % dir_1, DIR_FORMATTER % dir_2, *fname_paths)
153
+ end
154
+
155
+ # Translate a file path into a key.
156
+ def file_path_key(path)
157
+ fname = path[cache_path.size, path.size].split(File::SEPARATOR, 4).last
158
+ fname.gsub(UNESCAPE_FILENAME_CHARS){|match| $1.ord.to_s(16)}
159
+ end
160
+
161
+ # Delete empty directories in the cache.
162
+ def delete_empty_directories(dir)
163
+ return if dir == cache_path
164
+ if Dir.entries(dir).reject{|f| ['.', '..'].include?(f)}.empty?
165
+ File.delete(dir) rescue nil
166
+ delete_empty_directories(File.dirname(dir))
167
+ end
168
+ end
169
+
170
+ # Make sure a file path's directories exist.
171
+ def ensure_cache_path(path)
172
+ FileUtils.makedirs(path) unless File.exist?(path)
173
+ end
174
+
175
+ def search_dir(dir, &callback)
176
+ Dir.foreach(dir) do |d|
177
+ next if d == "." || d == ".."
178
+ name = File.join(dir, d)
179
+ if File.directory?(name)
180
+ search_dir(name, &callback)
181
+ else
182
+ callback.call name
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
@@ -0,0 +1,191 @@
1
+ begin
2
+ require 'memcache'
3
+ rescue LoadError => e
4
+ $stderr.puts "You don't have memcache installed in your application. Please add it to your Gemfile and run bundle install"
5
+ raise e
6
+ end
7
+ require 'digest/md5'
8
+
9
+ module ActiveSupport
10
+ module Cache
11
+ # A cache store implementation which stores data in Memcached:
12
+ # http://www.danga.com/memcached/
13
+ #
14
+ # This is currently the most popular cache store for production websites.
15
+ #
16
+ # Special features:
17
+ # - Clustering and load balancing. One can specify multiple memcached servers,
18
+ # and MemCacheStore will load balance between all available servers. If a
19
+ # server goes down, then MemCacheStore will ignore it until it goes back
20
+ # online.
21
+ #
22
+ # MemCacheStore implements the Strategy::LocalCache strategy which implements
23
+ # an in memory cache inside of a block.
24
+ class MemCacheStore < Store
25
+ module Response # :nodoc:
26
+ STORED = "STORED\r\n"
27
+ NOT_STORED = "NOT_STORED\r\n"
28
+ EXISTS = "EXISTS\r\n"
29
+ NOT_FOUND = "NOT_FOUND\r\n"
30
+ DELETED = "DELETED\r\n"
31
+ end
32
+
33
+ ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/
34
+
35
+ def self.build_mem_cache(*addresses)
36
+ addresses = addresses.flatten
37
+ options = addresses.extract_options!
38
+ addresses = ["localhost"] if addresses.empty?
39
+ MemCache.new(addresses, options)
40
+ end
41
+
42
+ # Creates a new MemCacheStore object, with the given memcached server
43
+ # addresses. Each address is either a host name, or a host-with-port string
44
+ # in the form of "host_name:port". For example:
45
+ #
46
+ # ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
47
+ #
48
+ # If no addresses are specified, then MemCacheStore will connect to
49
+ # localhost port 11211 (the default memcached port).
50
+ #
51
+ # Instead of addresses one can pass in a MemCache-like object. For example:
52
+ #
53
+ # require 'memcached' # gem install memcached; uses C bindings to libmemcached
54
+ # ActiveSupport::Cache::MemCacheStore.new(Memcached::Rails.new("localhost:11211"))
55
+ def initialize(*addresses)
56
+ addresses = addresses.flatten
57
+ options = addresses.extract_options!
58
+ super(options)
59
+
60
+ if addresses.first.respond_to?(:get)
61
+ @data = addresses.first
62
+ else
63
+ mem_cache_options = options.dup
64
+ UNIVERSAL_OPTIONS.each{|name| mem_cache_options.delete(name)}
65
+ @data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
66
+ end
67
+
68
+ extend Strategy::LocalCache
69
+ extend LocalCacheWithRaw
70
+ end
71
+
72
+ # Reads multiple keys from the cache using a single call to the
73
+ # servers for all keys. Options can be passed in the last argument.
74
+ def read_multi(*names)
75
+ options = names.extract_options!
76
+ options = merged_options(options)
77
+ keys_to_names = names.inject({}){|map, name| map[escape_key(namespaced_key(name, options))] = name; map}
78
+ raw_values = @data.get_multi(keys_to_names.keys, :raw => true)
79
+ values = {}
80
+ raw_values.each do |key, value|
81
+ entry = deserialize_entry(value)
82
+ values[keys_to_names[key]] = entry.value unless entry.expired?
83
+ end
84
+ values
85
+ end
86
+
87
+ # Increment a cached value. This method uses the memcached incr atomic
88
+ # operator and can only be used on values written with the :raw option.
89
+ # Calling it on a value not stored with :raw will initialize that value
90
+ # to zero.
91
+ def increment(name, amount = 1, options = nil) # :nodoc:
92
+ options = merged_options(options)
93
+ response = instrument(:increment, name, :amount => amount) do
94
+ @data.incr(escape_key(namespaced_key(name, options)), amount)
95
+ end
96
+ response == Response::NOT_FOUND ? nil : response.to_i
97
+ rescue MemCache::MemCacheError
98
+ nil
99
+ end
100
+
101
+ # Decrement a cached value. This method uses the memcached decr atomic
102
+ # operator and can only be used on values written with the :raw option.
103
+ # Calling it on a value not stored with :raw will initialize that value
104
+ # to zero.
105
+ def decrement(name, amount = 1, options = nil) # :nodoc:
106
+ options = merged_options(options)
107
+ response = instrument(:decrement, name, :amount => amount) do
108
+ @data.decr(escape_key(namespaced_key(name, options)), amount)
109
+ end
110
+ response == Response::NOT_FOUND ? nil : response.to_i
111
+ rescue MemCache::MemCacheError
112
+ nil
113
+ end
114
+
115
+ # Clear the entire cache on all memcached servers. This method should
116
+ # be used with care when using a shared cache.
117
+ def clear(options = nil)
118
+ @data.flush_all
119
+ end
120
+
121
+ # Get the statistics from the memcached servers.
122
+ def stats
123
+ @data.stats
124
+ end
125
+
126
+ protected
127
+ # Read an entry from the cache.
128
+ def read_entry(key, options) # :nodoc:
129
+ deserialize_entry(@data.get(escape_key(key), true))
130
+ rescue MemCache::MemCacheError => e
131
+ logger.error("MemCacheError (#{e}): #{e.message}") if logger
132
+ nil
133
+ end
134
+
135
+ # Write an entry to the cache.
136
+ def write_entry(key, entry, options) # :nodoc:
137
+ method = options && options[:unless_exist] ? :add : :set
138
+ value = options[:raw] ? entry.value.to_s : entry
139
+ expires_in = options[:expires_in].to_i
140
+ if expires_in > 0 && !options[:raw]
141
+ # Set the memcache expire a few minutes in the future to support race condition ttls on read
142
+ expires_in += 5.minutes
143
+ end
144
+ response = @data.send(method, escape_key(key), value, expires_in, options[:raw])
145
+ response == Response::STORED
146
+ rescue MemCache::MemCacheError => e
147
+ logger.error("MemCacheError (#{e}): #{e.message}") if logger
148
+ false
149
+ end
150
+
151
+ # Delete an entry from the cache.
152
+ def delete_entry(key, options) # :nodoc:
153
+ response = @data.delete(escape_key(key))
154
+ response == Response::DELETED
155
+ rescue MemCache::MemCacheError => e
156
+ logger.error("MemCacheError (#{e}): #{e.message}") if logger
157
+ false
158
+ end
159
+
160
+ private
161
+ def escape_key(key)
162
+ key = key.to_s.gsub(ESCAPE_KEY_CHARS){|match| "%#{match[0].to_s(16).upcase}"}
163
+ key = "#{key[0, 213]}:md5:#{Digest::MD5.hexdigest(key)}" if key.size > 250
164
+ key
165
+ end
166
+
167
+ def deserialize_entry(raw_value)
168
+ if raw_value
169
+ entry = Marshal.load(raw_value) rescue raw_value
170
+ entry.is_a?(Entry) ? entry : Entry.new(entry)
171
+ else
172
+ nil
173
+ end
174
+ end
175
+
176
+ # Provide support for raw values in the local cache strategy.
177
+ module LocalCacheWithRaw # :nodoc:
178
+ protected
179
+ def write_entry(key, entry, options) # :nodoc:
180
+ retval = super
181
+ if options[:raw] && local_cache && retval
182
+ raw_entry = Entry.new(entry.value.to_s)
183
+ raw_entry.expires_at = entry.expires_at
184
+ local_cache.write_entry(key, raw_entry, options)
185
+ end
186
+ retval
187
+ end
188
+ end
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,159 @@
1
+ require 'monitor'
2
+
3
+ module ActiveSupport
4
+ module Cache
5
+ # A cache store implementation which stores everything into memory in the
6
+ # same process. If you're running multiple Ruby on Rails server processes
7
+ # (which is the case if you're using mongrel_cluster or Phusion Passenger),
8
+ # then this means that your Rails server process instances won't be able
9
+ # to share cache data with each other and this may not be the most
10
+ # appropriate cache for you.
11
+ #
12
+ # This cache has a bounded size specified by the :size options to the
13
+ # initializer (default is 32Mb). When the cache exceeds the alotted size,
14
+ # a cleanup will occur which tries to prune the cache down to three quarters
15
+ # of the maximum size by removing the least recently used entries.
16
+ #
17
+ # MemoryStore is thread-safe.
18
+ class MemoryStore < Store
19
+ def initialize(options = nil)
20
+ options ||= {}
21
+ super(options)
22
+ @data = {}
23
+ @key_access = {}
24
+ @max_size = options[:size] || 32.megabytes
25
+ @max_prune_time = options[:max_prune_time] || 2
26
+ @cache_size = 0
27
+ @monitor = Monitor.new
28
+ @pruning = false
29
+ end
30
+
31
+ def clear(options = nil)
32
+ synchronize do
33
+ @data.clear
34
+ @key_access.clear
35
+ @cache_size = 0
36
+ end
37
+ end
38
+
39
+ def cleanup(options = nil)
40
+ options = merged_options(options)
41
+ instrument(:cleanup, :size => @data.size) do
42
+ keys = synchronize{ @data.keys }
43
+ keys.each do |key|
44
+ entry = @data[key]
45
+ delete_entry(key, options) if entry && entry.expired?
46
+ end
47
+ end
48
+ end
49
+
50
+ # Prune the cache down so the entries fit within the specified memory size by removing
51
+ # the least recently accessed entries.
52
+ def prune(target_size, max_time = nil)
53
+ return if pruning?
54
+ @pruning = true
55
+ begin
56
+ start_time = Time.now
57
+ cleanup
58
+ instrument(:prune, target_size, :from => @cache_size) do
59
+ keys = synchronize{ @key_access.keys.sort{|a,b| @key_access[a].to_f <=> @key_access[b].to_f} }
60
+ keys.each do |key|
61
+ delete_entry(key, options)
62
+ return if @cache_size <= target_size || (max_time && Time.now - start_time > max_time)
63
+ end
64
+ end
65
+ ensure
66
+ @pruning = false
67
+ end
68
+ end
69
+
70
+ # Return true if the cache is currently be pruned to remove older entries.
71
+ def pruning?
72
+ @pruning
73
+ end
74
+
75
+ # Increment an integer value in the cache.
76
+ def increment(name, amount = 1, options = nil)
77
+ synchronize do
78
+ options = merged_options(options)
79
+ if num = read(name, options)
80
+ num = num.to_i + amount
81
+ write(name, num, options)
82
+ num
83
+ else
84
+ nil
85
+ end
86
+ end
87
+ end
88
+
89
+ # Decrement an integer value in the cache.
90
+ def decrement(name, amount = 1, options = nil)
91
+ synchronize do
92
+ options = merged_options(options)
93
+ if num = read(name, options)
94
+ num = num.to_i - amount
95
+ write(name, num, options)
96
+ num
97
+ else
98
+ nil
99
+ end
100
+ end
101
+ end
102
+
103
+ def delete_matched(matcher, options = nil)
104
+ options = merged_options(options)
105
+ instrument(:delete_matched, matcher.inspect) do
106
+ matcher = key_matcher(matcher, options)
107
+ keys = synchronize { @data.keys }
108
+ keys.each do |key|
109
+ delete_entry(key, options) if key.match(matcher)
110
+ end
111
+ end
112
+ end
113
+
114
+ def inspect # :nodoc:
115
+ "<##{self.class.name} entries=#{@data.size}, size=#{@cache_size}, options=#{@options.inspect}>"
116
+ end
117
+
118
+ # Synchronize calls to the cache. This should be called wherever the underlying cache implementation
119
+ # is not thread safe.
120
+ def synchronize(&block) # :nodoc:
121
+ @monitor.synchronize(&block)
122
+ end
123
+
124
+ protected
125
+ def read_entry(key, options) # :nodoc:
126
+ entry = @data[key]
127
+ synchronize do
128
+ if entry
129
+ @key_access[key] = Time.now.to_f
130
+ else
131
+ @key_access.delete(key)
132
+ end
133
+ end
134
+ entry
135
+ end
136
+
137
+ def write_entry(key, entry, options) # :nodoc:
138
+ synchronize do
139
+ old_entry = @data[key]
140
+ @cache_size -= old_entry.size if old_entry
141
+ @cache_size += entry.size
142
+ @key_access[key] = Time.now.to_f
143
+ @data[key] = entry
144
+ prune(@max_size * 0.75, @max_prune_time) if @cache_size > @max_size
145
+ true
146
+ end
147
+ end
148
+
149
+ def delete_entry(key, options) # :nodoc:
150
+ synchronize do
151
+ @key_access.delete(key)
152
+ entry = @data.delete(key)
153
+ @cache_size -= entry.size if entry
154
+ !!entry
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end