PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/wagn/cache.rb

http://github.com/wagn/wagn
Ruby | 176 lines | 171 code | 2 blank | 3 comment | 1 complexity | 4f163db4045687a07f79f80ef87929e5 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1
  1. module Wagn
  2. require 'tempfile'
  3. Tempfile.class_eval do
  4. # overwrite tempfiles implementation of attachment_fu. FIXME: why n is nil?
  5. def make_tmpname(basename, n)
  6. ext = nil
  7. n = 0 if n.nil?
  8. sprintf("%s%d-%d%s", basename.to_s.gsub(/\.\w+$/) { |s| ext = s; '' }, $$, n, ext)
  9. end
  10. end
  11. ActiveSupport::Cache::FileStore.class_eval do
  12. # escape special symbols \*"<>| additionaly to :?.
  13. # All of them not allowed to use in ms windows file system
  14. def real_file_path(name)
  15. name = name.gsub('%','%25').gsub('?','%3F').gsub(':','%3A')
  16. name = name.gsub('\\','%5C').gsub('*','%2A').gsub('"','%22')
  17. name = name.gsub('<','%3C').gsub('>','%3E').gsub('|','%7C')
  18. '%s/%s.cache' % [@cache_path, name ]
  19. end
  20. end
  21. class Cache
  22. class << self
  23. def cache_classes
  24. [Card, Cardtype, Role, User, Revision]
  25. end
  26. def initialize_on_startup
  27. cache_classes.each do |cc|
  28. cc.cache = new :class=>cc, :store=>(Rails.env =~ /^cucumber|test$/ ? nil : Rails.cache)
  29. end
  30. preload_cache_for_tests if preload_cache?
  31. end
  32. def preload_cache?
  33. Rails.env=='cucumber'
  34. end
  35. def preload_cache_for_tests
  36. return unless preload_cache?
  37. set_keys = ['*all','*all plus','basic+*type','html+*type','*cardtype+*type','*sidebar+*self']
  38. set_keys.map{|k| [k,"#{k}+*content", "#{k}+*default", "#{k}+*read", ]}.flatten.each do |key|
  39. Card[key]
  40. end
  41. Role[:auth]; Role[:anon]
  42. @@frozen = Marshal.dump([Card.cache, Role.cache])
  43. end
  44. def system_prefix(klass)
  45. "#{Wagn::Application.config.database_configuration[Rails.env]['database']}/#{klass}"
  46. end
  47. def re_initialize_for_new_request
  48. cache_classes.each do |cc|
  49. if cc.cache
  50. cc.cache.system_prefix = system_prefix(cc)
  51. else
  52. warn "cache nil? #{cc}"
  53. end
  54. end
  55. reset_local unless preload_cache?
  56. end
  57. def reset_for_tests
  58. reset_local
  59. Card.cache, Role.cache = Marshal.load(@@frozen) if preload_cache?
  60. end
  61. def generate_cache_id
  62. ((Time.now.to_f * 100).to_i).to_s + ('a'..'z').to_a[rand(26)] + ('a'..'z').to_a[rand(26)]
  63. end
  64. def expire_card(key)
  65. Card.cache.delete key
  66. end
  67. def reset_global
  68. cache_classes.each{ |cc| cc.cache.reset if cc.cache }
  69. end
  70. private
  71. def reset_local
  72. cache_classes.each{ |cc| cc.cache.reset_local }
  73. end
  74. end
  75. attr_reader :prefix, :store
  76. attr_accessor :local
  77. def initialize(opts={})
  78. #@klass = opts[:class]
  79. @store = opts[:store]
  80. @local = Hash.new
  81. self.system_prefix = opts[:prefix] || self.class.system_prefix(opts[:class])
  82. end
  83. def system_prefix=(system_prefix)
  84. @system_prefix = system_prefix
  85. if @store.nil?
  86. @prefix = system_prefix + self.class.generate_cache_id + "/"
  87. else
  88. @system_prefix += '/' unless @system_prefix[-1] == '/'
  89. @cache_id = @store.fetch(@system_prefix + "cache_id") do
  90. self.class.generate_cache_id
  91. end
  92. @prefix = @system_prefix + @cache_id + "/"
  93. end
  94. end
  95. def read key
  96. return @local[key] unless @store
  97. fetch_local(key) do
  98. @store.read(@prefix + key)
  99. end
  100. end
  101. def write key, value
  102. self.write_local(key, value)
  103. #@store.write(@prefix + key, Marshal.dump(value)) if @store
  104. @store.write(@prefix + key, value) if @store
  105. value
  106. end
  107. def write_local(key, value) @local[key] = value end
  108. def read_local(key) @local[key] end
  109. def fetch key, &block
  110. fetch_local(key) do
  111. if @store
  112. @store.fetch(@prefix + key, &block)
  113. else
  114. block.call
  115. end
  116. end
  117. end
  118. def delete key
  119. @local.delete key
  120. @store.delete(@prefix + key) if @store
  121. end
  122. def dump
  123. p "dumping local...."
  124. @local.each do |k, v|
  125. p "#{k} --> #{v.inspect[0..30]}"
  126. end
  127. end
  128. def reset_local
  129. @local = {}
  130. end
  131. def reset
  132. reset_local
  133. @cache_id = self.class.generate_cache_id
  134. @store.write(@system_prefix + "cache_id", @cache_id) if @store
  135. @prefix = @system_prefix + @cache_id + "/"
  136. end
  137. private
  138. def fetch_local key
  139. if @local.has_key?(key)
  140. @local[key]
  141. else
  142. val = yield
  143. val.reset_mods if val.respond_to?(:reset_mods)
  144. @local[key] = val
  145. end
  146. end
  147. end
  148. end