In oroGen, a deployment is a Unix process that holds a certain number of task contexts. This Roby task represents the unix process itself. Once it gets instanciated, the associated task contexts can be accessed with #task
The Orocos::Generation::StaticDeployment that represents this deployment.
The set of ports for which logging has already been set up, as a set of [task_name, port_name] pairs
The underlying Orocos::Process instance
A name => Orocos::TaskContext instance mapping of all the task contexts running on this deployment
# File lib/orocos/roby/deployment.rb, line 34 def all_deployments; @@all_deployments end
Creates a subclass of Deployment that
represents the deployment specified by deployment_spec.
deployment_spec is an instance of
Orogen::Generation::Deployment
# File lib/orocos/roby/deployment.rb, line 400 def self.define_from_orogen(deployment_spec) klass = Class.new(Deployment) klass.instance_variable_set :@name, "Orocos::RobyPlugin::Deployments::#{deployment_spec.name.camelcase(:upper)}" klass.instance_variable_set :@orogen_spec, deployment_spec Orocos::RobyPlugin::Deployments.const_set(deployment_spec.name.camelcase(:upper), klass) klass end
Returns the name of this particular deployment instance
# File lib/orocos/roby/deployment.rb, line 48 def self.deployment_name orogen_spec.name end
# File lib/orocos/roby/deployment.rb, line 105 def self.instanciate(engine, arguments = Hash.new) task = new(arguments) task.robot = engine.robot task end
# File lib/orocos/roby/deployment.rb, line 22 def initialize(arguments = Hash.new) opts, task_arguments = Kernel.filter_options arguments, :log => true task_arguments[:log] = opts[:log] @logged_ports = Set.new super(task_arguments) end
# File lib/orocos/roby/deployment.rb, line 43 def self.short_name name.gsub("Orocos::RobyPlugin::", "") end
An array of Orocos::Generation::TaskDeployment instances that represent the tasks available in this deployment. Associated plan objects can be instanciated with #task
# File lib/orocos/roby/deployment.rb, line 95 def self.tasks orogen_spec.task_activities end
Removes any connection that points to tasks that were in this process, and that are therefore dead because of the process termination
# File lib/orocos/roby/deployment.rb, line 291 def cleanup_dead_connections return if !task_handles # task_handles is only initialized when ready is reached ... # so can be nil here all_tasks = task_handles.values.to_value_set all_tasks.each do |task| task.each_parent_vertex(ActualDataFlow) do |parent_task| if parent_task.process next if !parent_task.process.running? roby_task = Deployment.all_deployments[parent_task.process] next if roby_task.finishing? || roby_task.finished? end mappings = parent_task[task, ActualDataFlow] mappings.each do |(source_port, sink_port), policy| if policy[:pull] # we have to disconnect explicitely begin parent_task.port(source_port).disconnect_from(task.port(sink_port, false)) rescue Exception => e Orocos::RobyPlugin.warn "error while disconnecting #{parent_task}:#{source_port} from #{task}:#{sink_port} after #{task} died (#{e.message}). Assuming that both tasks are already dead." end end end end task.each_child_vertex(ActualDataFlow) do |child_task| if child_task.process next if !child_task.process.running? roby_task = Deployment.all_deployments[child_task.process] next if roby_task.finishing? || roby_task.finished? end mappings = task[child_task, ActualDataFlow] mappings.each do |(source_port, sink_port), policy| begin child_task.port(sink_port).disconnect_all rescue Exception => e Orocos::RobyPlugin.warn "error while disconnecting #{task}:#{source_port} from #{child_task}:#{sink_port} after #{task} died (#{e.message}). Assuming that both tasks are already dead." end end end ActualDataFlow.remove(task) RequiredDataFlow.remove(task) end end
Called when the process is finished.
result is the Process::Status object describing how this
process finished.
# File lib/orocos/roby/deployment.rb, line 264 def dead!(result) if !result emit :failed elsif history.find(&:terminal?) # Do nothing. A terminal event already happened, so we don't # need to tell what kind of end this is for the system emit :stop elsif result.success? emit :success elsif result.signaled? emit :signaled, result else emit :failed, result end Deployment.all_deployments.delete(orogen_deployment) orogen_spec.task_activities.each do |act| TaskContext.configured.delete(act.name) end each_parent_object(Roby::TaskStructure::ExecutionAgent) do |task| task.orogen_task = nil end end
The name of the executable, i.e. the name of the deployment as given in the oroGen file
This is a shortcut for deployment.model.deployment_name
# File lib/orocos/roby/deployment.rb, line 60 def deployment_name orogen_spec.name end
Internal helper to set the #orogen_task and
# File lib/orocos/roby/deployment.rb, line 144 def initialize_running_task(name, task) task.orogen_task = task_handles[name] task.orogen_task.process = orogen_deployment if Conf.orocos.conf_log_enabled? task.orogen_task.log_all_configuration(Orocos.configuration_log) end # Override the base model with the new one. The new model # may have been specialized, for instance to handle dynamic # slave creation # task.orogen_task.instance_variable_set(:@model, task.model.orogen_spec) end
# File lib/orocos/roby/deployment.rb, line 111 def instanciate_all_tasks orogen_spec.task_activities.map do |act| task(act.name) end end
# File lib/orocos/roby/deployment.rb, line 248 def log_dir host = self.arguments['on'] ||= 'localhost' process_server, log_dir = Orocos::RobyPlugin.process_servers[host] log_dir end
Returns true if the orocos/roby plugin configuration requires
port to be logged
# File lib/orocos/roby/deployment.rb, line 340 def log_port?(port) result = !Roby::State.orocos.port_excluded_from_log?(self, Roby.app.orocos_tasks[port.task.name], port) if !result Robot.info "not logging #{port.task.name}:#{port.name}" end result end
The name of the machine this deployment is running on, i.e. the name given to the :on argument.
# File lib/orocos/roby/deployment.rb, line 256 def machine arguments[:on] || 'localhost' end
Returns true if self and task are running on the
same process server
# File lib/orocos/roby/deployment.rb, line 101 def on_same_server?(task) task == self || machine == task.machine end
The Orocos::Generation::StaticDeployment object describing this deployment. This is a shortcut for deployment.model.orogen_spec
# File lib/orocos/roby/deployment.rb, line 54 def orogen_spec; self.class.orogen_spec end
The PID of this process
# File lib/orocos/roby/deployment.rb, line 39 def pid @pid ||= orogen_deployment.pid end
Event emitted when the deployment is up and running
# File lib/orocos/roby/deployment.rb, line 79 event :ready
# File lib/orocos/roby/deployment.rb, line 369 def ready_to_die! @ready_to_die = true end
Event emitted whenever the deployment finishes because of a UNIX signal. The event context is the Process::Status instance that describes the termination
It is forwarded to failed_event
# File lib/orocos/roby/deployment.rb, line 89 event :signaled
Starts the process and emits the start event immediately. The :ready event will be emitted when the deployment is up and running.
# File lib/orocos/roby/deployment.rb, line 162 event :start do |context| host = self.arguments['on'] ||= 'localhost' RobyPlugin.info { "starting deployment #{model.deployment_name} on #{host}" } process_server, log_dir = Orocos::RobyPlugin.process_servers[host] if !process_server raise ArgumentError, "cannot find the process server for #{host}" end options = Hash.new # Checking for options which apply in a multi-robot context, # e.g. such as prefixing and service_discovery (distributed # nameservice # # multirobot: # use_prefixing: true # exclude_from_prefixing: # - SIMULATION # - .*TEST.* # service_discovery: # - domain: _rimres._tcp # - publish: # - .*CORE.* if multirobot = Roby.app.options["multirobot"] # Use prefixing of components in order to allow # multiple robots to use the same set of deployments, # since tasks will be renamed using th given prefix # (robot_name) # e.g. with prefix enabled: # ./scripts/run robot_0 robottype # the prefix 'robot_0_' will be used if multirobot.key?("use_prefixing") exclude = false # Exclude deployments from prefixing that match one of the given # regular expressions (matching on complete deployment_name) if prefix_black_list = multirobot["exclude_from_prefixing"] prefix_black_list.each do |pattern| begin exclude = exclude || deployment_name =~ Regexp.new('^' + pattern + '$') rescue RegexpError => e Robot.error "Regular expression in configuration of multirobot with errors: #{e}" end end end if !exclude Robot.info "Deployment #{deployment_name} is started with prefix #{Roby.app.robot_name}" args = { :prefix => "#{Roby.app.robot_name}_" } options.merge!(args) else Robot.info "Deployment #{deployment_name} is started without prefix #{Roby.app.robot_name}" end end # Check whether the deployment should be started with # service discovery options, in order to be published within # the distributed nameservice if multirobot.key?("service_discovery") service_discovery = multirobot['service_discovery'] sd_domains = service_discovery["domain"] publish = false if publish_white_list = service_discovery['publish'] publish_white_list.each do |pattern| begin publish = publish || deployment_name =~ Regexp.new('^' + pattern + '$') rescue RegexpError => e Robot.error "Regular expression in configuration of multirobot with errors: #{e}" end end end if publish args = { 'sd-domain' => sd_domains } options.merge!(args) end end end @orogen_deployment = process_server.start(model.deployment_name, :working_directory => log_dir, :output => "%m-%p.txt", :wait => false, :cmdline_args => options) Deployment.all_deployments[@orogen_deployment] = self emit :start end
Stops all tasks that are running on top of this deployment, and kill the deployment
# File lib/orocos/roby/deployment.rb, line 380 event :stop do |context| begin if task_handles task_handles.each_value do |t| if t.rtt_state == :STOPPED t.cleanup end end end ready_to_die! orogen_deployment.kill(false) rescue CORBA::ComError # Assume that the process is killed as it is not reachable end end
Returns an task instance that represents the given task in this deployment.
# File lib/orocos/roby/deployment.rb, line 119 def task(name, model = nil) activity = orogen_spec.task_activities.find { |act| name == act.name } if !activity raise ArgumentError, "no task called #{name} in #{self.class.deployment_name}" end activity_model = Roby.app.orocos_tasks[activity.context.name] if model if !(model <= activity_model) raise ArgumentError, "incompatible explicit selection #{model} for the model of #{name} in #{self}" end else model = activity_model end plan.add(task = model.new(:orocos_name => activity.name)) task.robot = robot task.executed_by self task.orogen_spec = activity if ready? initialize_running_task(name, task) end task end