bestmike007/log4rails

View on GitHub
lib/log4r/repository.rb

Summary

Maintainability
A
1 hr
Test Coverage
# :nodoc:
# Version:: $Id$
#
# Using Thread.exclusive seems to be more efficient than using
# a class wide instance of Sync.synchronize in ruby 1.8.6 - Colby
#
# Using Sync.synchronize, 5000 iterations:
# real    3m55.493s user    3m45.557s sys    0m3.478s
#
# Using Thread.exclusive, 5000 iterations:
# real    2m35.859s user    2m33.951s sys    0m1.224s
#

require 'monitor'
require "singleton"

module Log4r
  class Logger

    # The repository stores a Hash of loggers keyed to their fullnames and
    # provides a few functions to reduce the code bloat in log4r/logger.rb.
    # This class is supposed to be transparent to end users, hence it is
    # a class within Logger. If anyone knows how to make this private,
    # let me know.

    class Repository # :nodoc:
      extend MonitorMixin
      include Singleton
      attr_reader :loggers

      def initialize
        @loggers = Hash.new
      end
      
      class << self

        def [](fullname)
          synchronize do
            instance.loggers[fullname]
          end # exclusive
        end
  
        def []=(fullname, logger)
          synchronize do
            instance.loggers[fullname] = logger
          end # exclusive
        end
  
        # Retrieves all children of a parent
        def all_children(parent)
          # children have the parent name + delimiter in their fullname
          daddy = parent.name + Log4r::Log4rConfig::LoggerPathDelimiter
          synchronize do
            for fullname, logger in instance.loggers
              yield logger if parent.is_root? || fullname =~ /#{daddy}/
            end
          end # exclusive
        end
  
        # when new loggers are introduced, they may get inserted into
        # an existing inheritance tree. this method
        # updates the children of a logger to link their new parent
        def reassign_any_children(parent)
          synchronize do
            for _, logger in instance.loggers
              next if logger.is_root?
              logger.parent = parent if logger.path =~ /^#{parent.fullname}$/
            end
          end # exclusive
        end
  
        # looks for the first defined logger in a child's path 
        # or nil if none found (which will then be rootlogger)
        def find_ancestor(path)
          arr = path.split Log4rConfig::LoggerPathDelimiter
          logger = nil
          synchronize do
            while arr.size > 0 do
              logger = Repository[arr.join(Log4rConfig::LoggerPathDelimiter)]
              break unless logger.nil?
              arr.pop
            end
          end # exclusive
          logger
        end
      end
        
    end # class Repository
  end # class Logger
end # Module Log4r