提交 776ea109 编写于 作者: J José Valim

Revert "Merge pull request #6425 from pinetops/resolver_concurrency_fix"

This reverts commit 254c0428, reversing
changes made to 513a0525.
上级 254c0428
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
require "active_support/core_ext/class" require "active_support/core_ext/class"
require "active_support/core_ext/class/attribute_accessors" require "active_support/core_ext/class/attribute_accessors"
require "action_view/template" require "action_view/template"
require "thread"
module ActionView module ActionView
# = Action View Resolver # = Action View Resolver
...@@ -25,64 +24,6 @@ def initialize(name, prefix, partial, virtual) ...@@ -25,64 +24,6 @@ def initialize(name, prefix, partial, virtual)
end end
end end
# Threadsafe template cache
class Cache #:nodoc:
class CacheEntry
attr_accessor :templates
delegate :synchronize, :to => "@mutex"
def initialize
@mutex = Mutex.new
end
end
def initialize
@data = Hash.new { |h1,k1| h1[k1] = Hash.new { |h2,k2|
h2[k2] = Hash.new { |h3,k3| h3[k3] = Hash.new { |h4,k4| h4[k4] = {} } } } }
@mutex = Mutex.new
end
# Cache the templates returned by the block
def cache(key, name, prefix, partial, locals)
cache_entry = nil
# first obtain a lock on the main data structure to create the cache entry
@mutex.synchronize do
cache_entry = @data[key][name][prefix][partial][locals] ||= CacheEntry.new
end
# then to avoid a long lasting global lock, obtain a more granular lock
# on the CacheEntry itself
cache_entry.synchronize do
if Resolver.caching?
# all templates are cached forever the first time they are accessed
cache_entry.templates ||= yield
else
# templates are still cached, but are only returned if they are
# all still current
fresh = yield
mtime = cache_entry.templates && cache_entry.templates.map(&:updated_at).max
newer = !mtime || fresh.empty? || fresh.any? { |t| t.updated_at > mtime }
if newer
cache_entry.templates = fresh
else
cache_entry.templates
end
end
end
end
def clear
@mutex.synchronize do
@data.clear
end
end
end
cattr_accessor :caching cattr_accessor :caching
self.caching = true self.caching = true
...@@ -91,11 +32,12 @@ class << self ...@@ -91,11 +32,12 @@ class << self
end end
def initialize def initialize
@cache = Cache.new @cached = Hash.new { |h1,k1| h1[k1] = Hash.new { |h2,k2|
h2[k2] = Hash.new { |h3,k3| h3[k3] = Hash.new { |h4,k4| h4[k4] = {} } } } }
end end
def clear_cache def clear_cache
@cache.clear @cached.clear
end end
# Normalizes the arguments and passes it on to find_template. # Normalizes the arguments and passes it on to find_template.
...@@ -123,18 +65,27 @@ def build_path(name, prefix, partial) ...@@ -123,18 +65,27 @@ def build_path(name, prefix, partial)
# Handles templates caching. If a key is given and caching is on # Handles templates caching. If a key is given and caching is on
# always check the cache before hitting the resolver. Otherwise, # always check the cache before hitting the resolver. Otherwise,
# it always hits the resolver but if the key is present, check if the # it always hits the resolver but check if the resolver is fresher
# resolver is fresher before returning it. # before returning it.
def cached(key, path_info, details, locals) #:nodoc: def cached(key, path_info, details, locals) #:nodoc:
name, prefix, partial = path_info name, prefix, partial = path_info
locals = locals.map { |x| x.to_s }.sort! locals = locals.map { |x| x.to_s }.sort!
if key if key && caching?
@cache.cache(key, name, prefix, partial, locals) do @cached[key][name][prefix][partial][locals] ||= decorate(yield, path_info, details, locals)
decorate(yield, path_info, details, locals)
end
else else
decorate(yield, path_info, details, locals) fresh = decorate(yield, path_info, details, locals)
return fresh unless key
scope = @cached[key][name][prefix][partial]
cache = scope[locals]
mtime = cache && cache.map(&:updated_at).max
if !mtime || fresh.empty? || fresh.any? { |t| t.updated_at > mtime }
scope[locals] = fresh
else
cache
end
end end
end end
......
...@@ -169,7 +169,7 @@ def teardown ...@@ -169,7 +169,7 @@ def teardown
assert_not_equal template, old_template assert_not_equal template, old_template
end end
test "responds to #prefixes" do test "responds to #prefixes" do
assert_equal [], @lookup_context.prefixes assert_equal [], @lookup_context.prefixes
@lookup_context.prefixes = ["foo"] @lookup_context.prefixes = ["foo"]
...@@ -180,7 +180,7 @@ def teardown ...@@ -180,7 +180,7 @@ def teardown
class LookupContextWithFalseCaching < ActiveSupport::TestCase class LookupContextWithFalseCaching < ActiveSupport::TestCase
def setup def setup
@resolver = ActionView::FixtureResolver.new("test/_foo.erb" => ["Foo", Time.utc(2000)]) @resolver = ActionView::FixtureResolver.new("test/_foo.erb" => ["Foo", Time.utc(2000)])
ActionView::Resolver.stubs(:caching?).returns(false) @resolver.stubs(:caching?).returns(false)
@lookup_context = ActionView::LookupContext.new(@resolver, {}) @lookup_context = ActionView::LookupContext.new(@resolver, {})
end end
...@@ -247,6 +247,6 @@ def setup ...@@ -247,6 +247,6 @@ def setup
@lookup_context.view_paths.find("foo", "parent", true, details) @lookup_context.view_paths.find("foo", "parent", true, details)
end end
assert_match %r{Missing partial parent/foo with .* Searched in:\n \* "/Path/to/views"\n}, e.message assert_match %r{Missing partial parent/foo with .* Searched in:\n \* "/Path/to/views"\n}, e.message
end end
end end
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册