carioca 0.1 → 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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