Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Threadsafety
  • Loading branch information
methodmissing committed Feb 1, 2009
1 parent 3ac1a42 commit da4c45a
Show file tree
Hide file tree
Showing 12 changed files with 114 additions and 68 deletions.
35 changes: 21 additions & 14 deletions lib/scrooge/framework/base.rb
Expand Up @@ -32,6 +32,9 @@ module Framework
autoload :Rails, 'scrooge/framework/rails'

class Base < Scrooge::Base

GUARD = Mutex.new

class NotImplemented < StandardError
end

Expand Down Expand Up @@ -149,7 +152,7 @@ def initialized( &block )
def scopes
ensure_scopes_path do
Dir.entries( scopes_path ).grep(/\d{10}/)
end
end
end

# Return the scopes storage path for the current framework.
Expand Down Expand Up @@ -189,25 +192,29 @@ def scope?( scope )
# could not be found.
#
def from_scope!( scope )
if scope?( scope )
tracker = Scrooge::Tracker::App.new
tracker.marshal_load( YAML.load( IO.read( scope_path( scope.to_s, 'scope.yml' ) ) ) )
tracker
else
raise InvalidScopeSignature
end
GUARD.synchronize do
if scope?( scope )
tracker = Scrooge::Tracker::App.new
tracker.marshal_load( YAML.load( IO.read( scope_path( scope.to_s, 'scope.yml' ) ) ) )
tracker
else
raise InvalidScopeSignature
end
end
end

# Dump the current tracker to the filesystem.
#
def to_scope!
scope = Time.now.to_i
ensure_scope_path( scope ) do
File.open( scope_path( scope, 'scope.yml' ), 'w' ) do |out|
YAML.dump( Scrooge::Base.profile.tracker.marshal_dump, out )
GUARD.synchronize do
scope = Time.now.to_i
ensure_scope_path( scope ) do
File.open( scope_path( scope, 'scope.yml' ), 'w' ) do |out|
YAML.dump( Scrooge::Base.profile.tracker.marshal_dump, out )
end
end
end
scope
scope
end
end

private
Expand Down
26 changes: 16 additions & 10 deletions lib/scrooge/framework/rails.rb
Expand Up @@ -37,11 +37,13 @@ def logger
end

def resource( env )
request = env['action_controller.rescue.request']
Thread.scrooge_resource.controller = request.path_parameters['controller']
Thread.scrooge_resource.action = request.path_parameters['action']
Thread.scrooge_resource.method = request.method
Thread.scrooge_resource.format = request.format.to_s
GUARD.synchronize do
request = env['action_controller.rescue.request']
Thread.scrooge_resource.controller = request.path_parameters['controller']
Thread.scrooge_resource.action = request.path_parameters['action']
Thread.scrooge_resource.method = request.method
Thread.scrooge_resource.format = request.format.to_s
end
end

def read_cache( key )
Expand All @@ -57,15 +59,19 @@ def middleware
end

def install_tracking_middleware
middleware.insert( 0, Scrooge::Middleware::Tracker )
GUARD.synchronize do
middleware.insert( 0, Scrooge::Middleware::Tracker )
end
end

def install_scope_middleware( tracker )
tracker.resources.each do |resource|
resource.middleware.each do |resource_middleware|
middleware.use( resource_middleware )
GUARD.synchronize do
tracker.resources.each do |resource|
resource.middleware.each do |resource_middleware|
middleware.use( resource_middleware )
end
end
end
end
end

def initialized( &block )
Expand Down
7 changes: 3 additions & 4 deletions lib/scrooge/orm/active_record.rb
Expand Up @@ -64,11 +64,10 @@ def scope_to( resource )
end

# Generate scope helpers for a given model and resource.
# We continuously
#
def scope_resource_to_model( resource, model )
method_name = resource_scope_method( resource )
klass = model.model.to_const if model.model.is_a?(String)
klass = model.model.to_const!(false) if model.model.is_a?(String)
unless resource_scope_method?( resource, klass )
klass.instance_eval(<<-EOS, __FILE__, __LINE__)
def #{method_name}(&block)
Expand All @@ -83,14 +82,14 @@ def #{method_name}(&block)
# Returns a lookup key from a given String or AR klass
#
def name( model )
model = model.to_const! if model.is_a?(String)
model = model.to_const!(false) if model.is_a?(String)
model.base_class.to_s
end

# Returns a table name from a given String or AR klass
#
def table_name( model )
model = model.to_const! if model.is_a?(String)
model = model.to_const!(false) if model.is_a?(String)
model.table_name
end

Expand Down
2 changes: 1 addition & 1 deletion lib/scrooge/orm/base.rb
Expand Up @@ -5,7 +5,7 @@ module Orm

class Base < Scrooge::Base

#
#
#
#

Expand Down
4 changes: 4 additions & 0 deletions lib/scrooge/storage/base.rb
Expand Up @@ -10,6 +10,10 @@ class Base < Scrooge::Base
class NotImplemented < StandardError
end

# A Single Mutex for all Storage subclasses as their's only one storage instance.
#
GUARD = Mutex.new

NAMESPACE = 'scrooge_storage'.freeze

class << self
Expand Down
36 changes: 23 additions & 13 deletions lib/scrooge/storage/buffer.rb
Expand Up @@ -2,6 +2,8 @@ module Scrooge
module Storage
module Buffer

GUARD = Mutex.new

attr_accessor :storage_buffer,
:buffered_at

Expand All @@ -10,23 +12,29 @@ def storage_buffer
end

def buffered_at
@buffered_at ||= Time.now.to_i
GUARD.synchronize do
@buffered_at ||= Time.now.to_i
end
end

def read( tracker )
with_read_buffer( tracker ) do
super( tracker )
end
GUARD.synchronize do
with_read_buffer( tracker ) do
super( tracker )
end
end
end

def write( tracker, buffered = true )
if buffered
with_write_buffer( tracker ) do
GUARD.synchronize do
if buffered
with_write_buffer( tracker ) do
super( tracker, buffered )
end
else
super( tracker, buffered )
end
else
super( tracker, buffered )
end
end
end

def buffer?
Expand All @@ -38,18 +46,20 @@ def flush_buffer?
( buffered_at + profile.buffer_threshold ) < Time.now.to_i
else
false
end
end
end

def buffer( tracker )
storage_buffer[tracker.signature] = tracker
end

def flush!
while( !storage_buffer.empty? ) do
write( storage_buffer.shift.last, false )
GUARD.synchronize do
while( !storage_buffer.empty? ) do
write( storage_buffer.shift.last, false )
end
buffered_at = Time.now.to_i
end
buffered_at = Time.now.to_i
end

private
Expand Down
26 changes: 15 additions & 11 deletions lib/scrooge/storage/file_system.rb
Expand Up @@ -7,21 +7,25 @@ def initialize
end

def read( tracker )
begin
File.open( tracker_file( tracker ), 'rb') {|t| Marshal.load(t) }
rescue => exception
profile.framework.logger.error "Scrooge: Could not read storage entry #{tracker.key} (#{exception.to_s})"
end
GUARD.synchronize do
begin
File.open( tracker_file( tracker ), 'rb') {|t| Marshal.load(t) }
rescue => exception
profile.framework.logger.error "Scrooge: Could not read storage entry #{tracker.key} (#{exception.to_s})"
end
end
end

def write( tracker, buffered = true )
begin
ensure_tracker_path( tracker ) do
File.open( tracker_file( tracker ), 'w') {|t| Marshal.dump( tracker, t ) }
GUARD.synchronize do
begin
ensure_tracker_path( tracker ) do
File.open( tracker_file( tracker ), 'w') {|t| Marshal.dump( tracker, t ) }
end
rescue => exception
profile.framework.logger.error "Scrooge: Could not write storage entry #{tracker.key} (#{exception.to_s})"
end
rescue => exception
profile.framework.logger.error "Scrooge: Could not write storage entry #{tracker.key} (#{exception.to_s})"
end
end
end

def tracker_file( tracker )
Expand Down
8 changes: 6 additions & 2 deletions lib/scrooge/storage/memory.rb
Expand Up @@ -9,11 +9,15 @@ def initialize
end

def read( tracker )
@storage[tracker.signature]
GUARD.synchronize do
@storage[tracker.signature]
end
end

def write( tracker, buffered = true )
@storage[tracker.signature] = tracker
GUARD.synchronize do
@storage[tracker.signature] = tracker
end
end

end
Expand Down
14 changes: 9 additions & 5 deletions lib/scrooge/tracker/app.rb
Expand Up @@ -2,6 +2,8 @@ module Scrooge
module Tracker
class App < Scrooge::Tracker::Base

# Application container for various Resources.

GUARD = Monitor.new

attr_accessor :resources
Expand All @@ -10,20 +12,22 @@ def initialize
super()
@resources = Set.new
end


# Add a Resource instance to this tracker.
#
def <<( resource )
GUARD.synchronize do
@resources << setup_resource( resource )
end
end

def marshal_dump
def marshal_dump #:nodoc:
GUARD.synchronize do
{ environment() => dumped_resources() }
end
end

def marshal_load( data )
def marshal_load( data ) #:nodoc:
GUARD.synchronize do
@resources = Set.new( restored_resources( data ) )
end
Expand All @@ -41,7 +45,7 @@ def track( resource )

private

def setup_resource( resource )
def setup_resource( resource ) #:nodoc:
GUARD.synchronize do
resource_for( resource ) || resource
end
Expand All @@ -67,7 +71,7 @@ def dumped_resources #:nodoc:
end
end

def resource_for( resource )
def resource_for( resource ) #:nodoc:
@resources.detect{|r| r.signature == resource.signature }
end

Expand Down
10 changes: 9 additions & 1 deletion lib/scrooge/tracker/base.rb
Expand Up @@ -10,6 +10,8 @@ module Tracker
class Base < Scrooge::Base
include Comparable

# Scrooge Tracker base class.

class NotImplemented < StandardError
end

Expand All @@ -23,14 +25,20 @@ def to_i
@counter
end

# Requires subclasses to implement a custom marshal_dump
#
def marshal_dump
raise NotImplemented
end


# Requires subclasses to implement a custom marshal_load
#
def marshal_load( data )
raise NotImplemented
end

# Compare trackers through their Marshal representations.
#
def ==( tracker )
compare_to( tracker )
end
Expand Down
4 changes: 2 additions & 2 deletions lib/scrooge/tracker/model.rb
Expand Up @@ -21,13 +21,13 @@ def <<( attribute )
end
end

def marshal_dump
def marshal_dump #:nodoc:
GUARD.synchronize do
{ name() => @attributes.to_a }
end
end

def marshal_load( data )
def marshal_load( data ) #:nodoc:
GUARD.synchronize do
@model = data.keys.first
@attributes = Set.new( data[@model] )
Expand Down

0 comments on commit da4c45a

Please sign in to comment.