require 'yaml' require 'rubygems' require 'methodic' require 'services' require 'daemons' module Carioca module Services class Registry private_class_method :new @@inst = nil def Registry.init(_options = {}) options = Methodic::get_options(_options) do |m| m.specify_defaults_value :file => './services.registry', :debug => false m.merge! end @@inst = new(options) if @@inst.nil? return @@inst end attr_reader :list attr_reader :loaded_services attr_reader :debug def debug=(_value) @log.level =(_value)? Logger::DEBUG : Logger::INFO end def stop_service(_options) options = Methodic.get_options(_options) options.specify_class_of :name => String options.specify_presence_of([:name]) options.validate! if @loaded_services.include?(options[:name]) then @loaded_engines[options[:name]].garbage if @loaded_services[options[:name]].respond_to? :garbage @loaded_services.delete(options[:name]) @log.debug('Carioca') { "Service #{options[:name]} stopped" } if @log return true else @log.debug('Carioca') { "Service #{options[:name]} not loaded" } if @log return false end end def register_service(_options) options = Methodic.get_options(_options) options.specify_classes_of({:name => String, :resource => String, :description => String, :type => Symbol, :init_options => Hash, :service => String }) options.specify_presences_of([:name,:type,:resource,:service]) options.validate! _name = _options.delete(:name) @list[_name] = _options return true end def unregister_service(_options) options = Methodic.get_options(_options = {}) options.specify_class_of :name => String options.specify_presence_of :name options.validate! raise RegistryError::new("FONDATION : Can't unregistered the logger service" ) if options[:name] == 'logger' raise RegistryError::new("Can't unregistered a loaded service" ) if @loaded_services.include?(options[:name]) @list.delete(options[:name]) return true end def discover_builtin Carioca::Services::discover_builtin end def save! res = false File.open(@registry_filename, "w") do |f| res = true if f.write(@list.to_yaml) end return res end def start_service(_options) options = Methodic.get_options(_options) options.specify_classes_of :name => String, :params => Hash options.specify_presences_of([:name]) options.validate! @log.debug('Carioca') { "getting service #{options[:name]}"} if @log self.restart_service(options) unless @loaded_services.include? options[:name] return @loaded_services[options[:name]] end alias :get_service :start_service def restart_service(_options) options = Methodic.get_options(_options) options.specify_classes_of :name => String, :params => Hash options.specify_presences_of [:name] options.validate! self.stop_service :name => options[:name] if @loaded_services.include? options[:name] if options[:name] =~ /.*_.*/ then (options[:instance],options[:shortname]) = options[:name].split(/_/) else options[:shortname] = options[:name] end verify_requires_dependancies(options) require_service(options) return instanciate_service(options) end def close @log.debug('Carioca') { "closing Registry ..." } @loaded_services.keys.each do |service| next if service == 'logger' @log.debug('Carioca') { "Stopping service #{service} ..."} self.stop_service :name => service end @log.debug('Carioca') { "Registry services closed, logger will be closed asynchronously" } self.stop_service :name => 'logger' end private # private initializer # @param [String] _filename default = '/data/config/service.registry' filename of the service Registry # @return [Registry] Singleton def initialize(_options) @logger_not_in_reg = false @debug = _options[:debug] @registry_filename = _options[:file] @list = Hash::new load if File::exist?(@registry_filename) unless @list.include?('logger') then self.register_service({:name => 'logger', :service => 'Carioca::Services::InternalLogger', :resource => 'logger', :description => "The standard ruby Logger internal wrapper Service", :type => :builtin, :init_options => { :target => "/tmp/log.file"}}) @logger_not_in_reg = true end @loaded_services = Hash::new @log = self.start_service :name => 'logger' @log.level =(@debug)? Logger::DEBUG : Logger::INFO @log.debug('Carioca') { "Registry started, service logger preloaded" } @log.debug('Carioca') { "Logger registered, not in configured registry" } if @logger_not_in_reg end def load @list = YAML.load_file(@registry_filename) end private def verify_requires_dependancies(options) _name = options[:shortname] if @list[_name].include?(:requires) then @list[_name][:requires].each do |service| unless @loaded_services.include?(service) then @log.debug('Carioca') { "Registry dependancy found and not loaded : #{service}" } restart_service :name => service end end end end def require_service(options) _name = options[:shortname] sym = ":#{@list[_name][:service].split('::').last}" case @list[_name][:type] when :file then require @list[_name][:resource] when :builtin then _file = Carioca::Services::search_builtins _name if _file then require _file else raise RegistryError::new("Config failed") end when :gem then eval("require '#{@list[_name][:resource]}'") else raise RegistryError::new("Config failed") end end def instanciate_service(options) _name = options[:shortname] @list[_name][:init_options] = options[:params] unless options[:params].nil? if @list[_name][:init_options].nil? then eval("@loaded_services[options[:name]] = #{@list[_name][:service]}::new") else eval("@loaded_services[options[:name]] = #{@list[_name][:service]}::new(@list[_name][:init_options])") end @log.debug('Carioca') { "Service #{options[:name]} started" } if @log return @loaded_services[options[:name]] end end end end class RegistryError < Exception; end Module.class_eval do def init_registry _options={} options = Methodic.get_options(_options) options.specify_classes_of :with_file => String options.specify_default_value_of :with_file => './services.registry' options.merge options.validate! Carioca::Services::Registry.init options[:with_file] end end