carioca 0.1 → 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,218 +1,308 @@
1
+ #!/usr/bin/env ruby
2
+ #---
3
+ # Author : Romain GEORGES
4
+ # type : gem component library
5
+ # obj : Carioca Module
6
+ #---
7
+
1
8
  require 'yaml'
2
9
  require 'rubygems'
3
10
  require 'methodic'
4
11
  require 'services'
5
12
  require 'daemons'
13
+ require 'carioca_private'
14
+
6
15
 
16
+
17
+ # module Carioca
18
+ # @author Romain GEORGES <romain@ultragreen.net>
19
+ # @see http://www.ultragreen.net/projects/carioca
20
+ # @version 1.0
21
+ # @note this module is a namespace Carioca
7
22
  module Carioca
8
23
 
9
- module Services
10
- class Registry
24
+
25
+
26
+ # module Services
27
+ # @note this module is a namespace Carioca::Services
28
+ module Services
11
29
 
12
30
 
13
- private_class_method :new
14
- @@inst = nil
15
- def Registry.init(_options = {})
16
- options = Methodic::get_options(_options) do |m|
17
- m.specify_defaults_value :file => './services.registry', :debug => false
18
- m.merge!
19
- end
20
-
21
- @@inst = new(options) if @@inst.nil?
31
+ # class Registry
32
+ # This class provide the Registry manager for Carioca
33
+ # @note this class is a Singleton Class to instanciate do not use new (initializer), but :
34
+ # Carioca::Services::Registry.init options
35
+ # @example Complete usage
36
+ # require 'rubygems'
37
+ # require 'carioca'
38
+ # registry = Carioca::Services::Registry.init
39
+ # registry = Carioca::Services::Registry.init :file => 'myservices.registry'
40
+ # registry = Carioca::Services::Registry.init :file => 'myservices.registry', :debug => true
41
+ class Registry
42
+
43
+ include PrivateMethodsCariocaServicesRegistry
22
44
 
45
+ # for singleton
46
+ private_class_method :new
47
+ private :verify_requires_dependancies
48
+ private :require_service
49
+ private :instanciate_service
50
+ private :kill_service
51
+
23
52
 
24
- return @@inst
53
+ @@inst = nil
25
54
 
26
- end
27
-
28
-
29
- attr_reader :list
30
- attr_reader :loaded_services
31
- attr_reader :debug
55
+ # Singleton constructor for Registry
56
+ # @param [Hash] _options the options, keys are symbols
57
+ # @option _options [String] :file The path of your registry YAML definition (see YAML registry format)
58
+ # @option _options [TrueClass,FalseClass] :debug Boolean activation/deactiviation of the carioca debug mode (log traces)
59
+ # @return [Carioca::Services::Registry] Singleton class instance of Registry
60
+ # @example usage
61
+ # registry = Carioca::Services::Registry.init # or
62
+ # registry = Carioca::Services::Registry.init :file => 'myservices.registry' # or
63
+ # registry = Carioca::Services::Registry.init :file => 'myservices.registry', :debug => true
64
+ def Registry.init(_options = {})
65
+ options = Methodic::get_options(_options) do |m|
66
+ m.specify_defaults_value :file => './services.registry', :debug => false
67
+ m.merge!
68
+ end
69
+ @@inst = new(options) if @@inst.nil?
70
+ return @@inst
71
+ end
72
+
73
+ # @example read
74
+ # registry = Carioca::Services::Registry.init
75
+ # p registry.registry_filename
76
+ # @example write
77
+ # registry = Carioca::Services::Registry.init
78
+ # p registry.registry_filename = '/tmp/test.file'
79
+ # @attr_reader [Hash] list a hash table of all structured registred services definition
80
+ # (come from file and explicitly registered services)
81
+ attr_accessor :registry_filename
82
+
83
+ # @example
84
+ # registry = Carioca::Services::Registry.init
85
+ # p registry.list
86
+ # @attr_reader [Hash] list a hash table of all structured registred services definition
87
+ # (come from file and explicitly registered services)
88
+ attr_reader :list
32
89
 
33
-
34
- def debug=(_value)
90
+ # @example
91
+ # registry = Carioca::Services::Registry.init
92
+ # p registry.loaded_services # you should see the logger service Hash definition
93
+ # @attr_reader [Hash] loaded_services a hash table of all structured loaded services
94
+ attr_reader :loaded_services
95
+
96
+ # @example
97
+ # registry = Carioca::Services::Registry.init
98
+ # p registry.debug
99
+ # @attr_reader [TrueClass,FalseClass] debug a boolean of the current debug status
100
+ attr_reader :debug
101
+
102
+ # writer accessor for debug (interaction with log service)
103
+ # @example
104
+ # registry = Carioca::Services::Registry.init
105
+ # p registry.debug = true
106
+ # @param [TrueClass,FalseClass] _value true or false to activate/deactivate debug mode
107
+ # @note interaction with preloaded service logger
108
+ def debug=(_value)
35
109
  @log.level =(_value)? Logger::DEBUG : Logger::INFO
36
- end
37
-
38
-
39
- def stop_service(_options)
40
- options = Methodic.get_options(_options)
41
- options.specify_class_of :name => String
42
- options.specify_presence_of([:name])
43
- options.validate!
44
- if @loaded_services.include?(options[:name]) then
45
- @loaded_engines[options[:name]].garbage if @loaded_services[options[:name]].respond_to? :garbage
46
- @loaded_services.delete(options[:name])
47
- @log.debug('Carioca') { "Service #{options[:name]} stopped" } if @log
48
- return true
49
- else
50
- @log.debug('Carioca') { "Service #{options[:name]} not loaded" } if @log
51
- return false
52
110
  end
53
111
 
54
- end
55
-
56
- def register_service(_options)
57
- options = Methodic.get_options(_options)
58
- options.specify_classes_of({:name => String, :resource => String, :description => String, :type => Symbol, :init_options => Hash, :service => String })
59
- options.specify_presences_of([:name,:type,:resource,:service])
60
- options.validate!
61
- _name = _options.delete(:name)
62
- @list[_name] = _options
63
- return true
64
- end
65
-
66
- def unregister_service(_options)
67
- options = Methodic.get_options(_options = {})
68
- options.specify_class_of :name => String
69
- options.specify_presence_of :name
70
- options.validate!
71
- raise RegistryError::new("FONDATION : Can't unregistered the logger service" ) if options[:name] == 'logger'
72
- raise RegistryError::new("Can't unregistered a loaded service" ) if @loaded_services.include?(options[:name])
73
- @list.delete(options[:name])
74
- return true
75
- end
76
-
77
- def discover_builtin
78
- Carioca::Services::discover_builtin
79
- end
80
-
81
- def save!
82
- res = false
83
- File.open(@registry_filename, "w") do |f|
84
- res = true if f.write(@list.to_yaml)
112
+
113
+ # stop a service, if loaded and different to logger
114
+ # @param [Hash] _options the options, keys are symbols
115
+ # @option _options [String] :name The name of the service to stop
116
+ # @return [TruaClass,FalseClass] true if service effectivly stopped, false if not, or :name == 'logger'
117
+ # @example usage
118
+ # registry = Carioca::Services::Registry.init
119
+ # registry.start_service :name => 'configuration'
120
+ # registry.stop_service :name => 'configuration'
121
+ # #=> return true
122
+ # registry.stop_service :name => 'configuration'
123
+ # #=> return false
124
+ # registry.stop_service :name => 'logger'
125
+ # #=> return false
126
+ # @note log if debug mode
127
+ def stop_service(_options)
128
+ options = Methodic.get_options(_options)
129
+ options.specify_class_of :name => String
130
+ options.specify_presence_of([:name])
131
+ options.validate!
132
+ if @loaded_services.include?(options[:name]) then
133
+ # prevent logger services killing
134
+ if options[:name] == 'logger' then
135
+ @log.debug('Carioca') { "Service logger can't be unloaded" } if @log
136
+ return false
137
+ end
138
+ # calling private killer
139
+ kill_service options[:name]
140
+ @log.debug('Carioca') { "Service #{options[:name]} stopped" } if @log
141
+ return true
142
+ else
143
+ @log.debug('Carioca') { "Service #{options[:name]} not loaded" } if @log
144
+ return false
145
+ end
146
+
85
147
  end
86
- return res
87
- end
88
-
89
- def start_service(_options)
90
- options = Methodic.get_options(_options)
91
- options.specify_classes_of :name => String, :params => Hash
92
- options.specify_presences_of([:name])
93
- options.validate!
94
- @log.debug('Carioca') { "getting service #{options[:name]}"} if @log
95
- self.restart_service(options) unless @loaded_services.include? options[:name]
96
- return @loaded_services[options[:name]]
97
- end
98
-
99
- alias :get_service :start_service
100
-
101
- def restart_service(_options)
102
- options = Methodic.get_options(_options)
103
- options.specify_classes_of :name => String, :params => Hash
104
- options.specify_presences_of [:name]
105
- options.validate!
106
- self.stop_service :name => options[:name] if @loaded_services.include? options[:name]
107
- if options[:name] =~ /.*_.*/ then
108
- (options[:instance],options[:shortname]) = options[:name].split(/_/)
109
- else
110
- options[:shortname] = options[:name]
148
+
149
+ # register a new service in registry added to @list
150
+ # @param [Hash] _options the options hash, key are :symbols
151
+ # @option _options [String] :name the name of the service (required)
152
+ # @option _options [String] :resource the resource, must be a gem name, a fullpath filename, a builtin service (required)
153
+ # @option _options [Symbol] :type the resource type of the service, must be :gem, :builtin or :file (required)
154
+ # @option _options [String] :service the realname of the service class with namespace (eg. ExternalServices::Dummy )
155
+ # @option _options [String] :description the description of the service (required)
156
+ # @option _options [Hash] :init_options the params of the service, keys are symbols
157
+ # @option _options [Array] :requires the list of [String] services name required to load this service
158
+ # @return [TrueClass,FalseClass] true if service is added
159
+ # @raise ArgumentError when :type is not in [:gem,:file,:builtin]
160
+ def register_service(_options)
161
+ options = Methodic.get_options(_options)
162
+ options.specify_classes_of({:name => String, :resource => String, :description => String, :type => Symbol, :service => String })
163
+ options.specify_presences_of([:name,:type,:resource,:service])
164
+ cond = Proc::new{|option| case option
165
+ when :gem then true
166
+ when :file then true
167
+ when :builtin then true
168
+ else false end }
169
+ options.specify_condition_for :type => cond
170
+ options.validate!
171
+ _name = _options.delete(:name)
172
+ @list[_name] = _options
173
+ return true
111
174
  end
112
- verify_requires_dependancies(options)
113
- require_service(options)
114
- return instanciate_service(options)
115
- end
116
-
117
- def close
118
- @log.debug('Carioca') { "closing Registry ..." }
119
- @loaded_services.keys.each do |service|
120
- next if service == 'logger'
121
- @log.debug('Carioca') { "Stopping service #{service} ..."}
122
- self.stop_service :name => service
175
+
176
+ # unregister a service in registry removed from @list
177
+ # @param [Hash] _options the options hash, key are :symbols
178
+ # @option _options [String] :name the name of the service (required)
179
+ # @raise [RegistryError] if try to unregister logger
180
+ # @raise [registryerror] if try to unregister a loaded service
181
+ # @return [TrueClass,FalseClass]
182
+ def unregister_service(_options = {})
183
+ options = Methodic.get_options(_options)
184
+ options.specify_class_of :name => String
185
+ options.specify_presence_of :name
186
+ options.validate!
187
+ raise RegistryError::new("FONDATION : Can't unregistered the logger service" ) if options[:name] == 'logger'
188
+ raise RegistryError::new("Can't unregistered a loaded service" ) if @loaded_services.include?(options[:name])
189
+ @list.delete(options[:name])
190
+ return true
123
191
  end
124
- @log.debug('Carioca') { "Registry services closed, logger will be closed asynchronously" }
125
- self.stop_service :name => 'logger'
126
- end
127
-
128
-
129
- private
130
- # private initializer
131
- # @param [String] _filename default = '/data/config/service.registry' filename of the service Registry
132
- # @return [Registry] Singleton
133
- def initialize(_options)
134
- @logger_not_in_reg = false
135
- @debug = _options[:debug]
136
- @registry_filename = _options[:file]
137
- @list = Hash::new
138
- load if File::exist?(@registry_filename)
139
- unless @list.include?('logger') then
140
- self.register_service({:name => 'logger',
141
- :service => 'Carioca::Services::InternalLogger',
142
- :resource => 'logger',
143
- :description => "The standard ruby Logger internal wrapper Service",
144
- :type => :builtin,
145
- :init_options => { :target => "/tmp/log.file"}})
146
- @logger_not_in_reg = true
147
- end
148
-
149
- @loaded_services = Hash::new
150
192
 
151
- @log = self.start_service :name => 'logger'
152
- @log.level =(@debug)? Logger::DEBUG : Logger::INFO
153
- @log.debug('Carioca') { "Registry started, service logger preloaded" }
154
- @log.debug('Carioca') { "Logger registered, not in configured registry" } if @logger_not_in_reg
155
- end
156
-
157
- def load
158
- @list = YAML.load_file(@registry_filename)
159
- end
160
-
161
- private
162
-
163
- def verify_requires_dependancies(options)
164
- _name = options[:shortname]
165
- if @list[_name].include?(:requires) then
166
- @list[_name][:requires].each do |service|
167
- unless @loaded_services.include?(service) then
168
- @log.debug('Carioca') { "Registry dependancy found and not loaded : #{service}" }
169
- restart_service :name => service
170
- end
193
+ # overload @list (self.list) by adding/reloading the builtins services definition scanned from Carioca gem
194
+ # alterate @list
195
+ # @example usage
196
+ # registry = Carioca::Services::Registry.init :name => '/tmp/empty.file'
197
+ # registry.discover_builtins
198
+ # registry.save!
199
+ def discover_builtins
200
+ @list.merge! Carioca::Services::discover_builtins
201
+ end
202
+
203
+ # save the registry file in self.registry_filename
204
+ # @return [TruaClass,FalseClass] true if the file is saved
205
+ # @example usage
206
+ # registry = Carioca::Services::Registry.init :file => './empty.file'
207
+ # registry.discover_builtins
208
+ # registry.unregister_service :name => 'configuration'
209
+ # registry.save!
210
+ def save!
211
+ res = false
212
+ File.open(@registry_filename, "w") do |f|
213
+ res = true if f.write(@list.to_yaml)
171
214
  end
172
- end
173
- end
174
-
175
- def require_service(options)
176
- _name = options[:shortname]
177
- sym = ":#{@list[_name][:service].split('::').last}"
178
- case @list[_name][:type]
179
- when :file then
180
- require @list[_name][:resource]
181
- when :builtin then
182
- _file = Carioca::Services::search_builtins _name
183
- if _file then
184
- require _file
215
+ return res
216
+ end
217
+
218
+ # start or get e previously started service in @list
219
+ # @return [Object] the loaded service class instance
220
+ # @param [Hash] _options the params, key are symbols
221
+ # @option _options [String] :name the name of the service
222
+ # @option _options [Hash] :params the params of the service
223
+ # @raise [RegistryError] Config Failed, for unconsistant service definition in @list
224
+ # @example usage
225
+ # registry = Carioca::Services::Registry.init
226
+ # config = registry.start_service :name => 'configuration'
227
+ # proxy = subject.start_service :name => 'debug' , :params => {:service => 'configuration'}
228
+ def start_service(_options)
229
+ options = Methodic.get_options(_options)
230
+ options.specify_classes_of :name => String
231
+ options.specify_presences_of([:name])
232
+ options.validate!
233
+ @log.debug('Carioca') { "getting service #{options[:name]}"} if @log
234
+ self.restart_service(options) unless @loaded_services.include? options[:name]
235
+ return @loaded_services[options[:name]]
236
+ end
237
+ alias :get_service :start_service
238
+
239
+ # start or restart (stop=>start) previously started service in @list
240
+ # @return [Object] the loaded service class instance
241
+ # @param [Hash] _options the params, key are symbols
242
+ # @option _options [String] :name the name of the service
243
+ # @option _options [Hash] :params the params of the service
244
+ # @raise [RegistryError] Config Failed, for unconsistant service definition in @list
245
+ # @example usage
246
+ # registry = Carioca::Services::Registry.init
247
+ # config = registry.restart_service :name => 'configuration'
248
+ # config = registry.restart_service :name => 'configuration' # stop and restart the previous services
249
+ # proxy = subject.restart_service :name => 'debug' , :params => {:service => 'configuration'}
250
+ # @note Registry and services are Singleton
251
+ def restart_service(_options)
252
+ options = Methodic.get_options(_options)
253
+ options.specify_classes_of :name => String
254
+ options.specify_presences_of [:name]
255
+ options.validate!
256
+
257
+ if @loaded_services.include? options[:name] then
258
+ @log.debug('Carioca') { "Restarting service #{options[:name]}"} if @log
259
+ kill_service :name => options[:name]
260
+ end
261
+ if options[:name] =~ /.*_.*/ then
262
+ (options[:shortname],options[:instance]) = options[:name].split(/_/)
185
263
  else
186
- raise RegistryError::new("Config failed")
264
+ options[:shortname] = options[:name]
187
265
  end
188
- when :gem then
189
- eval("require '#{@list[_name][:resource]}'")
190
- else
191
- raise RegistryError::new("Config failed")
266
+ verify_requires_dependancies(options)
267
+ require_service(options)
268
+ return instanciate_service(options)
192
269
  end
193
- end
194
-
195
- def instanciate_service(options)
196
- _name = options[:shortname]
197
- @list[_name][:init_options] = options[:params] unless options[:params].nil?
198
- if @list[_name][:init_options].nil? then
199
- eval("@loaded_services[options[:name]] = #{@list[_name][:service]}::new")
200
- else
201
- eval("@loaded_services[options[:name]] = #{@list[_name][:service]}::new(@list[_name][:init_options])")
270
+
271
+ # close the registry (finalizer)
272
+ # * stop all the services
273
+ # * kill logger
274
+ # * call private kill_service for each
275
+ # @note the garbage method hook is call if defined, for each service
276
+ # @return [TrueClass,FalseClass] true if registry closed successfully
277
+ def close
278
+ @log.debug('Carioca') { "closing Registry ..." }
279
+ @loaded_services.keys.each do |service|
280
+ next if service == 'logger'
281
+ @log.debug('Carioca') { "Stopping service #{service} ..."}
282
+ self.stop_service :name => service
283
+ end
284
+ @log.debug('Carioca') { "Registry services closed, logger will be closed asynchronously" }
285
+ kill_service 'logger'
286
+ return true
202
287
  end
203
- @log.debug('Carioca') { "Service #{options[:name]} started" } if @log
204
- return @loaded_services[options[:name]]
205
- end
206
-
207
-
208
- end
209
- end
210
-
211
-
212
-
213
- end
214
288
 
289
+ # load the registry file from self.registry_filename
290
+ # @return [Hash] @list the list Structure of the loaded registry
291
+ # @example usage
292
+ # registry = Carioca::Services::Registry.init
293
+ # registry.registry_filename = "./an_other.file"
294
+ # registry.load #or
295
+ # registry.reload
296
+ def load
297
+ @list = YAML.load_file(@registry_filename)
298
+ end
299
+ alias :reload :load
300
+
301
+ end # end of Carioca::Services::Registry
302
+ end # end of Carioca:Services
303
+ end # end of Carioca
215
304
 
305
+ # Exception overload class for Carioca
216
306
  class RegistryError < Exception; end
217
307
 
218
308