diff --git a/lib/http/cookie_jar/abstract_store.rb b/lib/http/cookie_jar/abstract_store.rb index 6734854..0f45690 100644 --- a/lib/http/cookie_jar/abstract_store.rb +++ b/lib/http/cookie_jar/abstract_store.rb @@ -1,4 +1,8 @@ +require 'monitor' + class HTTP::CookieJar::AbstractStore + include MonitorMixin + class << self @@class_map = {} @@ -31,6 +35,7 @@ class HTTP::CookieJar::AbstractStore private :default_options def initialize(options = nil) + super() # MonitorMixin options ||= {} @logger = options[:logger] # Initializes each instance variable of the same name as option @@ -65,7 +70,13 @@ class HTTP::CookieJar::AbstractStore # If (and only if) the +uri+ option is given, last access time of # each cookie is updated to the current time. def each(uri = nil, &block) - raise + if uri + raise + else + synchronize { + raise + } + end self end include Enumerable diff --git a/lib/http/cookie_jar/hash_store.rb b/lib/http/cookie_jar/hash_store.rb index ccd6a55..4332986 100644 --- a/lib/http/cookie_jar/hash_store.rb +++ b/lib/http/cookie_jar/hash_store.rb @@ -81,15 +81,17 @@ class HTTP::CookieJar } } else - @jar.each { |domain, paths| - paths.each { |path, hash| - hash.delete_if { |name, cookie| - if cookie.expired?(now) - true - else - yield cookie - false - end + synchronize { + @jar.each { |domain, paths| + paths.each { |path, hash| + hash.delete_if { |name, cookie| + if cookie.expired?(now) + true + else + yield cookie + false + end + } } } } @@ -109,45 +111,51 @@ class HTTP::CookieJar def cleanup(session = false) now = Time.now all_cookies = [] - @jar.each { |domain, paths| - domain_cookies = [] - paths.each { |path, hash| - hash.delete_if { |name, cookie| - if cookie.expired?(now) || (session && cookie.session?) - true - else - domain_cookies << cookie - false - end + synchronize { + break if @gc_index == 0 + + @jar.each { |domain, paths| + domain_cookies = [] + + paths.each { |path, hash| + hash.delete_if { |name, cookie| + if cookie.expired?(now) || (session && cookie.session?) + true + else + domain_cookies << cookie + false + end + } } + + if (debt = domain_cookies.size - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN) > 0 + domain_cookies.sort_by!(&:created_at) + domain_cookies.slice!(0, debt).each { |cookie| + delete(cookie) + } + end + + all_cookies.concat(domain_cookies) } - if (debt = domain_cookies.size - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN) > 0 - domain_cookies.sort_by!(&:created_at) - domain_cookies.slice!(0, debt).each { |cookie| + if (debt = all_cookies.size - HTTP::Cookie::MAX_COOKIES_TOTAL) > 0 + all_cookies.sort_by!(&:created_at) + all_cookies.slice!(0, debt).each { |cookie| delete(cookie) } end - all_cookies.concat(domain_cookies) - } - - if (debt = all_cookies.size - HTTP::Cookie::MAX_COOKIES_TOTAL) > 0 - all_cookies.sort_by!(&:created_at) - all_cookies.slice!(0, debt).each { |cookie| - delete(cookie) + @jar.delete_if { |domain, paths| + paths.delete_if { |path, hash| + hash.empty? + } + paths.empty? } - end - @jar.delete_if { |domain, paths| - paths.delete_if { |path, hash| - hash.empty? - } - paths.empty? + @gc_index = 0 } - - @gc_index = 0 + self end end end diff --git a/lib/http/cookie_jar/mozilla_store.rb b/lib/http/cookie_jar/mozilla_store.rb index a381f33..67e950d 100644 --- a/lib/http/cookie_jar/mozilla_store.rb +++ b/lib/http/cookie_jar/mozilla_store.rb @@ -335,9 +335,6 @@ class HTTP::CookieJar end def cleanup(session = false) - now = Time.now - all_cookies = [] - @st_delete_expired ||= @db.prepare("DELETE FROM moz_cookies WHERE expiry < :expiry") @@ -364,26 +361,31 @@ class HTTP::CookieJar ) SQL - @st_delete_expired.execute({ 'expiry' => now.to_i }) + synchronize { + break if @gc_index == 0 - @st_overusing_domains.execute({ - 'count' => HTTP::Cookie::MAX_COOKIES_PER_DOMAIN - }).each { |row| - domain, count = row['domain'], row['count'] + @st_delete_expired.execute({ 'expiry' => Time.now.to_i }) - @st_delete_per_domain_overuse.execute({ - 'domain' => domain, - 'limit' => count - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN, - }) + @st_overusing_domains.execute({ + 'count' => HTTP::Cookie::MAX_COOKIES_PER_DOMAIN + }).each { |row| + domain, count = row['domain'], row['count'] + + @st_delete_per_domain_overuse.execute({ + 'domain' => domain, + 'limit' => count - HTTP::Cookie::MAX_COOKIES_PER_DOMAIN, + }) + } + + overrun = count - HTTP::Cookie::MAX_COOKIES_TOTAL + + if overrun > 0 + @st_delete_total_overuse.execute({ 'limit' => overrun }) + end + + @gc_index = 0 } - - overrun = count - HTTP::Cookie::MAX_COOKIES_TOTAL - - if overrun > 0 - @st_delete_total_overuse.execute({ 'limit' => overrun }) - end - - @gc_index = 0 + self end end end