プロジェクト

全般

プロフィール

Manager.cpp

kawasaki, 2017/11/30 16:55

 
1
// -*- C++ -*-
2
/*!
3
 * @file Manager.h
4
 * @brief RTComponent manager class
5
 * @date $Date: 2008-03-06 06:58:40 $
6
 * @author Noriaki Ando <n-ando@aist.go.jp>
7
 *
8
 * Copyright (C) 2003-2005
9
 *     Task-intelligence Research Group,
10
 *     Intelligent Systems Research Institute,
11
 *     National Institute of
12
 *         Advanced Industrial Science and Technology (AIST), Japan
13
 *     All rights reserved.
14
 *
15
 * $Id: Manager.cpp 3049 2017-09-27 07:13:10Z miyamoto $
16
 *
17
 */
18

    
19

    
20
#include <rtm/Manager.h>
21
#include <rtm/ManagerConfig.h>
22
#include <rtm/ModuleManager.h>
23
#include <rtm/CorbaNaming.h>
24
#include <rtm/NamingManager.h>
25
#include <rtm/RTC.h>
26
#include <rtm/PeriodicExecutionContext.h>
27
#include <rtm/ExtTrigExecutionContext.h>
28
#include <rtm/OpenHRPExecutionContext.h>
29
#include <rtm/PeriodicECSharedComposite.h>
30
#include <rtm/RTCUtil.h>
31
#include <rtm/ManagerServant.h>
32
#include <fstream>
33
#include <iostream>
34
#include <coil/Properties.h>
35
#include <coil/stringutil.h>
36
#include <coil/Signal.h>
37
#include <coil/TimeValue.h>
38
#include <coil/Timer.h>
39
#include <coil/OS.h>
40
#include <rtm/FactoryInit.h>
41
#include <rtm/CORBA_IORUtil.h>
42
#include <rtm/SdoServiceConsumerBase.h>
43
#include <rtm/LocalServiceAdmin.h>
44
#include <rtm/SystemLogger.h>
45
#include <rtm/LogstreamBase.h>
46
#include <rtm/NumberingPolicyBase.h>
47

    
48
#ifdef RTM_OS_VXWORKS
49
#include <rtm/VxWorksRTExecutionContext.h>
50
#ifndef __RTP__
51
#include <rtm/VxWorksInterruptExecutionContext.h>
52
#endif
53
#endif
54

    
55

    
56
#ifdef RTM_OS_LINUX
57
#ifndef _GNU_SOURCE
58
#define _GNU_SOURCE
59
#endif // _GNU_SOURCE
60
#include <pthread.h>
61
#endif // RTM_OS_LINUX
62

    
63
#if defined(minor)
64
#undef minor
65
#endif
66

    
67
//static sig_atomic_t g_mgrActive = true;
68
extern "C" void handler (int)
69
{
70
  ::RTC::Manager::instance().terminate();
71
}
72

    
73
namespace RTC
74
{
75
  Manager* Manager::manager = NULL;
76
  coil::Mutex Manager::mutex;
77

    
78
  Manager::InstanceName::InstanceName(RTObject_impl* comp)
79
    : m_name(comp->getInstanceName())
80
  {}
81
  Manager::InstanceName::InstanceName(const char* name)
82
    : m_name(name)
83
  {}
84
  Manager::InstanceName::InstanceName(const std::string name)
85
    : m_name(name)
86
  {}
87
  bool Manager::InstanceName::operator()(RTObject_impl* comp)
88
  {
89
    return m_name == comp->getInstanceName();
90
  }
91

    
92
  
93
  /*!
94
   * @if jp
95
   * @brief Protected コンストラクタ
96
   * @else
97
   * @brief Protected Constructor
98
   * @endif
99
   */
100
  Manager::Manager()
101
    : m_initProc(0), m_namingManager(0), m_timer(0),
102
      m_logStreamBuf(), rtclog(&m_logStreamBuf),
103
      m_runner(0), m_terminator(0)
104
  {
105
    new coil::SignalAction((coil::SignalHandler) handler, SIGINT);
106
  }
107
  
108
  /*!
109
   * @if jp
110
   * @brief Protected コピーコンストラクタ
111
   * @else
112
   * @brief Protected Copy Constructor
113
   * @endif
114
   */
115
  Manager::Manager(const Manager& manager)
116
    : m_initProc(0), m_namingManager(0), m_timer(0),
117
      m_logStreamBuf(), rtclog(&m_logStreamBuf),
118
      m_runner(0), m_terminator(0)
119
  {
120
    new coil::SignalAction((coil::SignalHandler) handler, SIGINT);
121
  }
122
  
123
  /*!
124
   * @if jp
125
   * @brief マネージャの初期化
126
   * @else
127
   * @brief Initialize manager
128
   * @endif
129
   */
130
  Manager* Manager::init(int argc, char** argv)
131
  {
132
    // DCL for singleton
133
    if (!manager)
134
      {
135
        Guard guard(mutex);
136
        if (!manager)
137
          {
138
            manager = new Manager();
139
            manager->initManager(argc, argv);
140
            manager->initFactories();
141
            manager->initLogger();
142
            manager->initORB();
143
            manager->initNaming();
144
            manager->initExecContext();
145
            manager->initComposite();
146
            manager->initTimer();
147
            manager->initManagerServant();
148
          }
149
      }
150
    return manager;
151
  }
152
  
153
  /*!
154
   * @if jp
155
   * @brief マネージャのインスタンスの取得
156
   * @else
157
   * @brief Get instance of the manager
158
   * @endif
159
   */
160
  Manager& Manager::instance()
161
  {
162
    // DCL for singleton
163
    if (!manager)
164
      {
165
        Guard guard(mutex);
166
        if (!manager)
167
          {
168
            manager = new Manager();
169
            manager->initManager(0, NULL);
170
            manager->initFactories();
171
            manager->initLogger();
172
            manager->initORB();
173
            manager->initNaming();
174
            manager->initExecContext();
175
            manager->initComposite();
176
            manager->initTimer();
177
            manager->initManagerServant();
178
          }
179
      }
180
    return *manager;
181
  }
182
  
183
  /*!
184
   * @if jp
185
   * @brief マネージャ終了処理
186
   * @else
187
   * @brief Terminate Manager
188
   * @endif
189
   */ 
190
  void Manager::terminate()
191
  {
192
    if (m_terminator != NULL)
193
      m_terminator->terminate();
194
  }
195
  
196
  /*!
197
   * @if jp
198
   * @brief マネージャ・シャットダウン
199
   * @else
200
   * @brief Shutdown Manager
201
   * @endif
202
   */
203
  void Manager::shutdown()
204
  {
205
    RTC_TRACE(("Manager::shutdown()"));
206
    m_listeners.manager_.preShutdown();
207
    shutdownComponents();
208
    shutdownNaming();
209
    shutdownORB();
210
    shutdownManager();
211
    // 終了待ち合わせ
212
    if (m_runner != NULL)
213
      {
214
        m_runner->wait();
215
      }
216
    else
217
      {
218
        join();
219
      }
220
    m_listeners.manager_.postShutdown();
221
    shutdownLogger();
222
  }
223
  
224
  /*!
225
   * @if jp
226
   * @brief マネージャ終了処理の待ち合わせ
227
   * @else
228
   * @brief Wait for Manager's termination
229
   * @endif
230
   */ 
231
  void Manager::join()
232
  {
233
    RTC_TRACE(("Manager::wait()"));
234
    {
235
      Guard guard(m_terminate.mutex);
236
      ++m_terminate.waiting;
237
    }
238
    while (1)
239
      {
240
        {
241
          Guard guard(m_terminate.mutex);
242
          if (m_terminate.waiting > 1) break;
243
        }
244
        coil::usleep(100000);
245
      }
246
  }
247
  
248
  /*!
249
   * @if jp
250
   * @brief 初期化プロシージャのセット
251
   * @else
252
   * @brief Set initial procedure
253
   * @endif
254
   */ 
255
  void Manager::setModuleInitProc(ModuleInitProc proc)
256
  {
257
    m_initProc = proc;
258
  }
259
  
260
  /*!
261
   * @if jp
262
   * @brief Managerのアクティブ化
263
   * @else
264
   * @brief Activate the Manager
265
   * @endif
266
   */ 
267
  bool Manager::activateManager()
268
  {
269
    RTC_TRACE(("Manager::activateManager()"));
270
    
271
    try
272
      {
273
        if(CORBA::is_nil(this->thePOAManager()))
274
        {
275
          RTC_ERROR(("Could not get POA manager."));
276
          return false;
277
        }
278
        this->thePOAManager()->activate();
279
        RTC_TRACE(("POA Manager activated."));
280
      }
281
    catch (...)
282
      {
283
        RTC_ERROR(("POA Manager activatatin failed."));
284
        return false;
285
      }
286

    
287
    std::vector<std::string> lsvc;
288
    lsvc = coil::split(m_config["manager.local_service.modules"], ",");
289

    
290
    for (int i(0), len(lsvc.size()); i < len; ++i)
291
      {
292
        size_t begin_pos(lsvc[i].find_first_of('('));
293
        size_t end_pos(lsvc[i].find_first_of(')'));
294
        std::string filename, initfunc;
295
        if (begin_pos != std::string::npos && end_pos != std::string::npos &&
296
            begin_pos < end_pos)
297
          {
298
            initfunc = lsvc[i].substr(begin_pos + 1, end_pos - (begin_pos + 1));
299
            filename = lsvc[i].substr(0, begin_pos);
300
            coil::eraseBothEndsBlank(initfunc);
301
            coil::eraseBothEndsBlank(filename);
302
          }
303
        else
304
          {
305
            initfunc = coil::split(lsvc[i], ".").operator[](0) + "Init";
306
            filename = lsvc[i];
307
          }
308
        if (filename.find_first_of('.') == std::string::npos)
309
          {
310
            if (m_config.findNode("manager.modules.C++.suffixes") != 0)
311
              {
312
                filename += "." + m_config["manager.modules.C++.suffixes"];
313
              }
314
          }
315
        try
316
          {
317
            m_module->load(filename, initfunc);
318
          }
319
        catch (ModuleManager::Error& e)
320
          {
321
            RTC_ERROR(("Module load error: %s", e.reason.c_str()));
322
          }
323
        catch (ModuleManager::SymbolNotFound& e)
324
          {
325
            RTC_ERROR(("Symbol not found: %s", e.name.c_str()));
326
          }
327
        catch (ModuleManager::ModuleNotFound& e)
328
          {
329
            RTC_ERROR(("Module not found: %s", e.name.c_str()));
330
          }
331
        catch (...)
332
          {
333
            RTC_ERROR(("Unknown Exception"));
334
          }
335
      }
336

    
337
    initLocalService();
338

    
339
    std::vector<std::string> mods;
340
    mods = coil::split(m_config["manager.modules.preload"], ",");
341

    
342
    for (int i(0), len(mods.size()); i < len; ++i)
343
      {
344
        size_t begin_pos(mods[i].find_first_of('('));
345
        size_t end_pos(mods[i].find_first_of(')'));
346
        std::string filename, initfunc;
347
        if (begin_pos != std::string::npos && end_pos != std::string::npos &&
348
            begin_pos < end_pos)
349
          {
350
            initfunc = mods[i].substr(begin_pos + 1, end_pos - (begin_pos + 1));
351
            filename = mods[i].substr(0, begin_pos);
352
            coil::eraseBothEndsBlank(initfunc);
353
            coil::eraseBothEndsBlank(filename);
354
          }
355
        else
356
          {
357
            initfunc = coil::split(mods[i], ".").operator[](0) + "Init";
358
            filename = mods[i];
359
          }
360
        if (filename.find_first_of('.') == std::string::npos)
361
          {
362
            std::cout <<  m_config["manager.modules.C++.suffixes"] << std::endl;
363
            if (m_config.findNode("manager.modules.C++.suffixes") != 0)
364
              {
365
                filename += "." + m_config["manager.modules.C++.suffixes"];
366
              }
367
          }
368
        try
369
          {
370
            m_module->load(filename, initfunc);
371
          }
372
        catch (ModuleManager::Error& e)
373
          {
374
            RTC_ERROR(("Module load error: %s", e.reason.c_str()));
375
          }
376
        catch (ModuleManager::SymbolNotFound& e)
377
          {
378
            RTC_ERROR(("Symbol not found: %s", e.name.c_str()));
379
          }
380
        catch (ModuleManager::ModuleNotFound& e)
381
          {
382
            RTC_ERROR(("Module not found: %s", e.name.c_str()));
383
          }
384
        catch (...)
385
          {
386
            RTC_ERROR(("Unknown Exception"));
387
          }
388
      }
389

    
390
    m_config["sdo.service.consumer.available_services"]
391
      = coil::flatten(SdoServiceConsumerFactory::instance().getIdentifiers());
392

    
393

    
394

    
395
    if (m_initProc != NULL)
396
      {
397
        m_initProc(this);
398
      }
399

    
400
    RTC_TRACE(("Components pre-creation: %s",
401
               m_config["manager.components.precreate"].c_str()));
402
    std::vector<std::string> comp;
403
    comp = coil::split(m_config["manager.components.precreate"], ",");
404
    for (int i(0), len(comp.size()); i < len; ++i)
405
      {
406
        this->createComponent(comp[i].c_str());
407
      }
408

    
409
    { // pre-connection
410
      RTC_TRACE(("Connection pre-connection: %s",
411
                 m_config["manager.components.preconnect"].c_str()));
412
      std::vector<std::string> connectors;
413
      connectors = coil::split(m_config["manager.components.preconnect"], ",");
414
      for (int i(0), len(connectors.size()); i < len; ++i)
415
        {
416
          // ConsoleIn.out:Console.in(dataflow_type=push,....)
417
          coil::vstring conn_prop = coil::split(connectors[i], "(");
418
          if (conn_prop.size() == 1)
419
            {
420
              conn_prop.   // default connector profile value
421
                push_back("dataflow_type=push&interface_type=corba_cdr");
422
            } // after this conn_prop.size() >= 2
423
          std::size_t pos = conn_prop[1].find_last_of(")");
424
          if (pos != std::string::npos) { conn_prop[1].erase(pos); }
425

    
426
          coil::vstring comp_ports;
427
          comp_ports = coil::split(conn_prop[0], ":");
428
          if (comp_ports.size() != 2)
429
            {
430
              RTC_ERROR(("Invalid format for pre-connection."));
431
              RTC_ERROR(("Format must be Comp0.port0:Comp1.port1"));
432
              continue;
433
            }
434
          std::string comp0_name = coil::split(comp_ports[0], ".")[0];
435
          std::string comp1_name = coil::split(comp_ports[1], ".")[0];
436
          RTObject_impl* comp0 = getComponent(comp0_name.c_str());
437
          RTObject_impl* comp1 = getComponent(comp1_name.c_str());
438
          if (comp0 == NULL)
439
            { RTC_ERROR(("%s not found.", comp0_name.c_str())); continue; }
440
          if (comp1 == NULL)
441
            { RTC_ERROR(("%s not found.", comp1_name.c_str())); continue; }
442
          std::string port0 = comp_ports[0];
443
          std::string port1 = comp_ports[1];
444
          
445
          PortServiceList_var ports0 = comp0->get_ports();
446
          PortServiceList_var ports1 = comp1->get_ports();
447
          RTC_DEBUG(("%s has %d ports.", comp0_name.c_str(), ports0->length()));
448
          RTC_DEBUG(("%s has %d ports.", comp1_name.c_str(), ports1->length()));
449
          
450
          PortService_var port0_var;
451
          for (size_t p(0); p < ports0->length(); ++p)
452
            {
453
              PortProfile_var pp = ports0[p]->get_port_profile();
454
              std::string s(CORBA::string_dup(pp->name));
455
              if (comp_ports[0] == s)
456
                {
457
                  RTC_DEBUG(("port %s found: ", comp_ports[0].c_str()));
458
                  port0_var = ports0[p];
459
                }
460
            }
461
          PortService_var port1_var;
462
          for (size_t p(0); p < ports1->length(); ++p)
463
            {
464
              PortProfile_var pp = ports1[p]->get_port_profile();
465
              std::string s(CORBA::string_dup(pp->name));
466
              if (port1 == s)
467
                {
468
                  RTC_DEBUG(("port %s found: ", comp_ports[1].c_str()));
469
                  port1_var = ports1[p];
470
                }
471
            }
472
          if (CORBA::is_nil(port0_var))
473
            {
474
              RTC_ERROR(("port0 %s is nil obj", comp_ports[0].c_str()));
475
              continue;
476
            }
477
          if (CORBA::is_nil(port1_var))
478
            {
479
              RTC_ERROR(("port1 %s is nil obj", comp_ports[1].c_str()));
480
              continue;
481
            }
482
          ConnectorProfile conn_prof;
483
          std::string prof_name;
484
          conn_prof.name = CORBA::string_dup(connectors[i].c_str());
485
          conn_prof.connector_id = CORBA::string_dup("");
486
          conn_prof.ports.length(2);
487
          conn_prof.ports[0] = port0_var;
488
          conn_prof.ports[1] = port1_var;
489
          coil::Properties prop;
490
          prop["dataport.dataflow_type"] = "push";
491
          prop["dataport.interface_type"] = "corba_cdr";
492
          coil::vstring opt_props = coil::split(conn_prop[1], "&");
493
          for (size_t o(0); o < opt_props.size(); ++o)
494
            {
495
              coil::vstring temp = coil::split(opt_props[o], "=");
496
              prop["dataport." + temp[0]] = temp[1];
497
            }
498
          NVUtil::copyFromProperties(conn_prof.properties, prop);
499
          if (RTC::RTC_OK != port0_var->connect(conn_prof))
500
            {
501
              RTC_ERROR(("Connection error: %s",
502
                         connectors[i].c_str()));
503
            }
504
        }
505
    } // end of pre-connection
506

    
507
    { // pre-activation
508
      RTC_TRACE(("Components pre-activation: %s",
509
                 m_config["manager.components.preactivation"].c_str()));
510
      std::vector<std::string> comps;
511
      comps = coil::split(m_config["manager.components.preactivation"],
512
                               ",");
513
      for (int i(0), len(comps.size()); i < len; ++i)
514
        {
515
          RTObject_impl* comp = getComponent(comps[i].c_str());
516
          if (comp == NULL)
517
            { RTC_ERROR(("%s not found.", comps[i].c_str())); continue; }
518

    
519
          ExecutionContextList_var ecs = comp->get_owned_contexts();
520
          ecs[CORBA::ULong(0)]->activate_component(comp->getObjRef());
521
        }
522
    } // end of pre-activation
523
    return true;
524
  }
525
  
526
  /*!
527
   * @if jp
528
   * @brief Managerの実行
529
   * @else
530
   * @brief Run the Manager
531
   * @endif
532
   */ 
533
  void Manager::runManager(bool no_block)
534
  {
535
    if (no_block)
536
      {
537
        RTC_TRACE(("Manager::runManager(): non-blocking mode"));
538
        m_runner = new OrbRunner(m_pORB);
539
        m_runner->open(0);
540
      }
541
    else
542
      {
543
        RTC_TRACE(("Manager::runManager(): blocking mode"));
544
        m_pORB->run();
545
        RTC_TRACE(("Manager::runManager(): ORB was terminated"));
546
        join();
547
      }
548
    return;
549
  }
550
  
551
  //============================================================
552
  // Module management
553
  //============================================================
554
  /*!
555
   * @if jp
556
   * @brief モジュールのロード
557
   * @else
558
   * @brief Load module
559
   * @endif
560
   */
561
  ReturnCode_t Manager::load(const std::string& fname,
562
                             const std::string& initfunc)
563
  {
564
    RTC_TRACE(("Manager::load(fname = %s, initfunc = %s)",
565
               fname.c_str(), initfunc.c_str()));
566

    
567
    std::string file_name(fname);
568
    std::string init_func(initfunc);
569
    m_listeners.module_.preLoad(file_name, init_func);
570
    try
571
      {
572
        if (init_func.empty())
573
          {
574
            coil::vstring mod(coil::split(file_name, "."));
575
            init_func = mod[0] + "Init";
576
          }
577
        std::string path(m_module->load(file_name, init_func));
578
        RTC_DEBUG(("module path: %s", path.c_str()));
579
        m_listeners.module_.postLoad(path, init_func);
580
      }
581
    catch(RTC::ModuleManager::NotAllowedOperation& e)
582
      {
583
        RTC_ERROR(("Operation not allowed: %s",
584
                   e.reason.c_str()));
585
        return RTC::PRECONDITION_NOT_MET;
586
      }
587
    catch(RTC::ModuleManager::NotFound& e)
588
      {
589
        RTC_ERROR(("Not found: %s",
590
                   e.name.c_str()));
591
        return RTC::RTC_ERROR;
592
      }
593
    catch(RTC::ModuleManager::InvalidArguments& e)
594
      {
595
        RTC_ERROR(("Invalid argument: %s",
596
                   e.reason.c_str()));
597
        return RTC::BAD_PARAMETER;
598
      }
599
    catch(RTC::ModuleManager::Error& e)
600
      {
601
        RTC_ERROR(("Error: %s", e.reason.c_str()));
602
        return RTC::RTC_ERROR;
603
      }
604
    catch (...)
605
      {
606
        RTC_ERROR(("Unknown error."));
607
        return RTC::RTC_ERROR;
608
      }
609
    return RTC::RTC_OK;
610
  }
611
  
612
  /*!
613
   * @if jp
614
   * @brief モジュールのアンロード
615
   * @else
616
   * @brief Unload module
617
   * @endif
618
   */
619
  void Manager::unload(const char* fname)
620
  {
621
    RTC_TRACE(("Manager::unload()"));
622
    std::string fnamestr(fname);
623
    m_listeners.module_.preUnload(fnamestr);
624
    m_module->unload(fname);
625
    m_listeners.module_.postUnload(fnamestr);
626
    return;
627
  }
628
  
629
  /*!
630
   * @if jp
631
   * @brief 全モジュールのアンロード
632
   * @else
633
   * @brief Unload all modules
634
   * @endif
635
   */ 
636
  void Manager::unloadAll()
637
  {
638
    RTC_TRACE(("Manager::unloadAll()"));
639
    m_module->unloadAll();
640
    return;
641
  }
642
  
643
  /*!
644
   * @if jp
645
   * @brief ロード済みのモジュールリストを取得する
646
   * @else
647
   * @brief Get a list of loaded modules
648
   * @endif
649
   */
650
  std::vector<coil::Properties> Manager::getLoadedModules()
651
  {
652
    RTC_TRACE(("Manager::getLoadedModules()"));
653
    return m_module->getLoadedModules();
654
  }
655
  
656
  /*!
657
   * @if jp
658
   * @brief ロード可能なモジュールリストを取得する
659
   * @else
660
   * @brief Get a list of loadable modules
661
   * @endif
662
   */
663
std::vector<coil::Properties> Manager::getLoadableModules()
664
  {    
665
    RTC_TRACE(("Manager::getLoadableModules()"));
666
    return m_module->getLoadableModules();
667
  }
668
  
669
  //============================================================
670
  // Component factory management
671
  //============================================================
672
  /*!
673
   * @if jp
674
   * @brief RTコンポーネント用ファクトリを登録する
675
   * @else
676
   * @brief Register RT-Component Factory
677
   * @endif
678
   */
679
  bool Manager::registerFactory(coil::Properties& profile,
680
                                RtcNewFunc new_func,
681
                                RtcDeleteFunc delete_func)
682
  {
683
    RTC_TRACE(("Manager::registerFactory(%s)", profile["type_name"].c_str()));
684

    
685
    std::string policy_name =
686
      m_config.getProperty("manager.components.naming_policy", "default");
687
    RTM::NumberingPolicyBase* policy =
688
      RTM::NumberingPolicyFactory::instance().createObject(policy_name);
689
    FactoryBase* factory;
690
    if (policy == NULL)
691
      {
692
        factory = new FactoryCXX(profile, new_func, delete_func);
693
      }
694
    else
695
      {
696
        factory = new FactoryCXX(profile, new_func, delete_func, policy);
697
      }
698
    try
699
      {
700
        bool ret = m_factory.registerObject(factory);
701
        if (!ret) {
702
          delete factory;
703
          return false;
704
        }
705
        return true;
706
      }
707
    catch (...)
708
      {
709
        delete factory;
710
        return false;
711
      }
712
  }
713
  
714
  std::vector<coil::Properties> Manager::getFactoryProfiles()
715
  {
716
    std::vector<FactoryBase*> factories(m_factory.getObjects());
717
    std::vector<coil::Properties> props;
718
    for (int i(0), len(factories.size()); i < len; ++i)
719
      {
720
        props.push_back(factories[i]->profile());
721
      }
722
    return props;
723
  }
724
  
725
  /*!
726
   * @if jp
727
   * @brief ExecutionContext用ファクトリを登録する
728
   * @else
729
   * @brief Register ExecutionContext Factory
730
   * @endif
731
   */
732
  bool Manager::registerECFactory(const char* name,
733
                                  ECNewFunc new_func,
734
                                  ECDeleteFunc delete_func)
735
  {
736
    RTC_TRACE(("Manager::registerECFactory(%s)", name));
737
    try
738
      {    
739
        ECFactoryBase* factory;
740
        factory = new ECFactoryCXX(name, new_func, delete_func);
741
        if(m_ecfactory.registerObject(factory))
742
          {
743
            return true;
744
          }
745
      }
746
    catch (...)
747
      {
748
        return false;
749
      }
750
    return false;
751
  }
752
  
753
  /*!
754
   * @if jp
755
   * @brief ファクトリ全リストを取得する
756
   * @else
757
   * @brief Get the list of all Factories
758
   * @endif
759
   */
760
  std::vector<std::string> Manager::getModulesFactories()
761
  {
762
    RTC_TRACE(("Manager::getModulesFactories()"));
763
    
764
    ModuleFactories m;
765
    return m_factory.for_each(m).modlist;
766
  }
767
  
768
  //============================================================
769
  // Component management
770
  //============================================================
771
  /*!
772
   * @if jp
773
   * @brief RTコンポーネントを生成する
774
   * @else
775
   * @brief Create RT-Components
776
   * @endif
777
   */
778
  RTObject_impl* Manager::createComponent(const char* comp_args)
779
  {
780
    RTC_TRACE(("Manager::createComponent(%s)", comp_args));
781
    std::string argstr(comp_args);
782
    m_listeners.rtclifecycle_.preCreate(argstr);
783
    //------------------------------------------------------------
784
    // extract "comp_type" and "comp_prop" from comp_arg
785
    coil::Properties comp_prop, comp_id;
786
    if (!procComponentArgs(argstr.c_str(), comp_id, comp_prop)) return NULL;
787

    
788
    //------------------------------------------------------------
789
    // Because the format of port-name had been changed from <port_name> 
790
    // to <instance_name>.<port_name>, the following processing was added. 
791
    // (since r1648)
792

    
793
    if (comp_prop.findNode("exported_ports") != 0)
794
      {
795
        coil::vstring exported_ports;
796
        exported_ports = coil::split(comp_prop["exported_ports"], ",");
797

    
798
                                std::string exported_ports_str("");
799
        for (size_t i(0), len(exported_ports.size()); i < len; ++i)
800
          {
801
            coil::vstring keyval(coil::split(exported_ports[i], "."));
802
            if (keyval.size() > 2)
803
              {
804
                exported_ports_str += (keyval[0] + "." + keyval.back());
805
              }
806
            else
807
              {
808
                exported_ports_str += exported_ports[i];
809
              }
810
            
811
            if (i != exported_ports.size() - 1)
812
              {
813
                exported_ports_str += ",";
814
              }
815
          }
816
                                
817
        comp_prop["exported_ports"] = exported_ports_str;
818
        comp_prop["conf.default.exported_ports"] = exported_ports_str;
819
 
820
      }
821
    //------------------------------------------------------------
822

    
823
    //------------------------------------------------------------
824
    // Create Component
825
    FactoryBase* factory(m_factory.find(comp_id));
826
    if (factory == 0)
827
      {
828
        RTC_ERROR(("Factory not found: %s",
829
                   comp_id["implementation_id"].c_str()));
830
        
831
        if (!coil::toBool(m_config["manager.modules.search_auto"], "YES", "NO", true))
832
          {
833
            return 0;
834
          }
835
        // automatic module loading
836
        std::vector<coil::Properties> mp(m_module->getLoadableModules());
837
        RTC_INFO(("%d loadable modules found", mp.size()));
838
        
839
        std::vector<coil::Properties>::iterator it;
840
        it = std::find_if(mp.begin(), mp.end(), ModulePredicate(comp_id));
841
        if (it == mp.end())
842
          {
843
            RTC_ERROR(("No module for %s in loadable modules list",
844
                       comp_id["implementation_id"].c_str()));
845
            return 0;
846
          }
847
        if (it->findNode("module_file_name") == 0)
848
          {
849
            RTC_ERROR(("Hmm...module_file_name key not found."));
850
            return 0;
851
          }
852
        // module loading
853
        RTC_INFO(("Loading module: %s", (*it)["module_file_name"].c_str()))
854
          load((*it)["module_file_name"].c_str(), "");
855
        factory = m_factory.find(comp_id);
856
        if (factory == 0) 
857
          {
858
            RTC_ERROR(("Factory not found for loaded module: %s",
859
                       comp_id["implementation_id"].c_str()));
860
            return 0;
861
          }
862
      }
863

    
864
    coil::Properties prop;
865
    prop = factory->profile();
866

    
867
    const char* inherit_prop[] = {
868
      "config.version",
869
      "openrtm.name",
870
      "openrtm.version",
871
      "os.name",
872
      "os.release",
873
      "os.version",
874
      "os.arch",
875
      "os.hostname",
876
      "corba.endpoint",
877
      "corba.id",
878
      "exec_cxt.periodic.type",
879
      "exec_cxt.periodic.rate",
880
      "exec_cxt.event_driven.type",
881
      "exec_cxt.sync_transition",
882
      "exec_cxt.sync_activation",
883
      "exec_cxt.sync_deactivation",
884
      "exec_cxt.sync_reset",
885
      "exec_cxt.transition_timeout",
886
      "exec_cxt.activation_timeout",
887
      "exec_cxt.deactivation_timeout",
888
      "exec_cxt.reset_timeout",
889
      "exec_cxt.cpu_affinity",
890
      "exec_cxt.priority",
891
      "exec_cxt.stack_size",
892
      "exec_cxt.interrupt",
893
      "logger.enable",
894
      "logger.log_level",
895
      "naming.enable",
896
      "naming.type",
897
      "naming.formats",
898
      ""
899
    };
900

    
901
    for (int i(0); inherit_prop[i][0] != '\0'; ++i)
902
      {
903
        const char* key(inherit_prop[i]);
904
        if (m_config.findNode(key) != NULL)
905
          {
906
            prop[key] = m_config[key];
907
          }
908
      }
909
      
910
    RTObject_impl* comp;
911
    comp = factory->create(this);
912
    if (comp == NULL)
913
      {
914
        RTC_ERROR(("RTC creation failed: %s",
915
                   comp_id["implementation_id"].c_str()));
916
        return NULL;
917
      }
918
    RTC_TRACE(("RTC created: %s", comp_id["implementation_id"].c_str()));
919
    m_listeners.rtclifecycle_.postCreate(comp);
920
    prop << comp_prop;
921

    
922
    //------------------------------------------------------------
923
    // Load configuration file specified in "rtc.conf"
924
    //
925
    // rtc.conf:
926
    //   [category].[type_name].config_file = file_name
927
    //   [category].[instance_name].config_file = file_name
928
    m_listeners.rtclifecycle_.preConfigure(prop);
929
    configureComponent(comp, prop);
930
    m_listeners.rtclifecycle_.postConfigure(prop);
931
    // comp->setProperties(prop);
932
    
933
    //------------------------------------------------------------
934
    // Component initialization
935
    m_listeners.rtclifecycle_.preInitialize();
936
    if (comp->initialize() != RTC::RTC_OK)
937
      {
938
        RTC_TRACE(("RTC initialization failed: %s",
939
                   comp_id["implementation_id"].c_str()));
940
        RTC_TRACE(("%s was finalized", comp_id["implementation_id"].c_str()));
941
        if (comp->exit() != RTC::RTC_OK)
942
          {
943
            RTC_DEBUG(("%s finalization was failed.",
944
                       comp_id["implementation_id"].c_str()));
945
          }
946
        return NULL;
947
      }
948
    RTC_TRACE(("RTC initialization succeeded: %s",
949
               comp_id["implementation_id"].c_str()));
950
    m_listeners.rtclifecycle_.postInitialize();
951
    //------------------------------------------------------------
952
    // Bind component to naming service
953
    registerComponent(comp);
954
    return comp;
955
  }
956
  
957
  /*!
958
   * @if jp
959
   * @brief RTコンポーネントを直接 Manager に登録する
960
   * @else
961
   * @brief Register RT-Component directly without Factory
962
   * @endif
963
   */
964
  bool Manager::registerComponent(RTObject_impl* comp)
965
  {
966
    RTC_TRACE(("Manager::registerComponent(%s)", comp->getInstanceName()));
967
    // ### NamingManager のみで代用可能
968
    m_compManager.registerObject(comp);
969
    
970
    coil::vstring names(comp->getNamingNames());
971
    
972
    m_listeners.naming_.preBind(comp, names);
973
    for (int i(0), len(names.size()); i < len; ++i)
974
      {
975
        RTC_TRACE(("Bind name: %s", names[i].c_str()));
976
        m_namingManager->bindObject(names[i].c_str(), comp);
977
      }
978
    m_listeners.naming_.postBind(comp, names);
979

    
980
    return true;
981
  }
982
  
983
  /*!
984
   * @if jp
985
   * @brief RTコンポーネントの登録を解除する
986
   * @else
987
   * @brief Unregister RT-Components
988
   * @endif
989
   */
990
  bool Manager::unregisterComponent(RTObject_impl* comp)
991
  {
992
    RTC_TRACE(("Manager::unregisterComponent(%s)", comp->getInstanceName()));
993
    // ### NamingManager のみで代用可能
994
    m_compManager.unregisterObject(comp->getInstanceName());
995
    
996
    coil::vstring names(comp->getNamingNames());
997

    
998
    m_listeners.naming_.preUnbind(comp, names);
999
    for (int i(0), len(names.size()); i < len; ++i)
1000
      {
1001
        RTC_TRACE(("Unbind name: %s", names[i].c_str()));
1002
        m_namingManager->unbindObject(names[i].c_str());
1003
      }
1004
    m_listeners.naming_.postUnbind(comp, names);
1005

    
1006
    return true;
1007
  }
1008
  
1009

    
1010
  ExecutionContextBase* Manager::createContext(const char* ec_args)
1011
  {
1012
    RTC_TRACE(("Manager::createContext()"));
1013
    RTC_TRACE(("ExecutionContext type: %s", 
1014
               m_config.getProperty("exec_cxt.periodic.type").c_str()));
1015

    
1016
    std::string ec_id;
1017
    coil::Properties ec_prop;
1018
    if (!procContextArgs(ec_args, ec_id, ec_prop)) return NULL;
1019

    
1020
    ECFactoryBase* factory(m_ecfactory.find(ec_id.c_str()));
1021
    if (factory == NULL)
1022
      {
1023
        RTC_ERROR(("Factory not found: %s", ec_id.c_str()));
1024
        return NULL;
1025
      }
1026

    
1027
    ExecutionContextBase* ec;
1028
    ec = factory->create();
1029
    return ec;
1030
  }
1031
  
1032
  /*!
1033
   * @if jp
1034
   * @brief Manager に登録されているRTコンポーネントを削除する
1035
   * @else
1036
   * @brief Unregister RT-Components that have been registered to Manager
1037
   * @endif
1038
   */
1039
  void Manager::deleteComponent(RTObject_impl* comp)
1040
  {
1041
    RTC_TRACE(("deleteComponent(RTObject*)"));
1042
    // cleanup from manager's table, and naming serivce
1043
    unregisterComponent(comp);
1044

    
1045
    // find factory
1046
    coil::Properties& comp_id(comp->getProperties());
1047
    FactoryBase* factory(m_factory.find(comp_id));
1048
    if (factory == NULL)
1049
      {
1050
        RTC_DEBUG(("Factory not found: %s",
1051
                   comp_id["implementation_id"].c_str()));
1052
        return;
1053
      }
1054
    else
1055
      {
1056
        RTC_DEBUG(("Factory found: %s",
1057
                   comp_id["implementation_id"].c_str()));
1058
        factory->destroy(comp);
1059
      } 
1060
    
1061
    if (coil::toBool(m_config["manager.shutdown_on_nortcs"],
1062
                     "YES", "NO", true) &&
1063
        !coil::toBool(m_config["manager.is_master"], "YES", "NO", false))
1064
      {
1065
        std::vector<RTObject_impl*> comps;
1066
        comps = getComponents();
1067
        if (comps.size() == 0)
1068
          {
1069
            shutdown();
1070
          }
1071
      }
1072
  } 
1073

    
1074
  void Manager::deleteComponent(const char* instance_name)
1075
  {
1076
    RTC_TRACE(("deleteComponent(%s)", instance_name));
1077
    RTObject_impl* comp;
1078
    comp = m_compManager.find(instance_name);
1079
    if (comp == 0)
1080
      {
1081
        RTC_WARN(("RTC %s was not found in manager.", instance_name));
1082
        return;
1083
      }
1084
    deleteComponent(comp);
1085
  }
1086
  
1087
  /*!
1088
   * @if jp
1089
   * @brief Manager に登録されているRTコンポーネントを検索する
1090
   * @else
1091
   * @brief Get RT-Component's pointer
1092
   * @endif
1093
   */
1094
  RTObject_impl* Manager::getComponent(const char* instance_name)
1095
  {
1096
    RTC_TRACE(("Manager::getComponent(%s)", instance_name));
1097
    return m_compManager.find(instance_name);
1098
  }
1099
  
1100
  /*!
1101
   * @if jp
1102
   * @brief Manager に登録されている全RTコンポーネントを取得する
1103
   * @else
1104
   * @brief Get all RT-Components registered in the Manager
1105
   * @endif
1106
   */
1107
  std::vector<RTObject_impl*> Manager::getComponents()
1108
  {
1109
    RTC_TRACE(("Manager::getComponents()"));
1110
    return m_compManager.getObjects();
1111
  }
1112

    
1113
  void Manager::
1114
  addManagerActionListener(RTM::ManagerActionListener* listener,
1115
                           bool autoclean)
1116
  {
1117
    m_listeners.manager_.addListener(listener, autoclean);
1118
  }
1119
  void Manager::
1120
  removeManagerActionListener(RTM::ManagerActionListener* listener)
1121
  {
1122
    m_listeners.manager_.removeListener(listener);
1123
  }
1124
  
1125
  void Manager::
1126
  addModuleActionListener(RTM::ModuleActionListener* listener,
1127
                           bool autoclean)
1128
  {
1129
    m_listeners.module_.addListener(listener, autoclean);
1130
  }
1131
  void Manager::
1132
  removeModuleActionListener(RTM::ModuleActionListener* listener)
1133
  {
1134
    m_listeners.module_.removeListener(listener);
1135
  }
1136

    
1137
  void Manager::
1138
  addRtcLifecycleActionListener(RTM::RtcLifecycleActionListener* listener,
1139
                                bool autoclean)
1140
  {
1141
    m_listeners.rtclifecycle_.addListener(listener, autoclean);
1142
  }
1143
  void Manager::
1144
  removeRtcLifecycleActionListener(RTM::RtcLifecycleActionListener* listener)
1145
  {
1146
    m_listeners.rtclifecycle_.removeListener(listener);
1147
  }
1148
  
1149
  void Manager::
1150
  addNamingActionListener(RTM::NamingActionListener* listener,
1151
                          bool autoclean)
1152
  {
1153
    m_listeners.naming_.addListener(listener, autoclean);
1154
  }
1155

    
1156
  void Manager::
1157
  removeNamingActionListener(RTM::NamingActionListener* listener)
1158
  {
1159
    m_listeners.naming_.removeListener(listener);
1160
  }
1161
  
1162
  void Manager::
1163
  addLocalServiceActionListener(RTM::LocalServiceActionListener* listener,
1164
                                bool autoclean)
1165
  {
1166
    m_listeners.localservice_.addListener(listener, autoclean);
1167
  }
1168

    
1169
  void Manager::
1170
  removeLocalServiceActionListener(RTM::LocalServiceActionListener* listener)
1171
  {
1172
    m_listeners.localservice_.removeListener(listener);
1173
  }
1174

    
1175
  
1176
  //============================================================
1177
  // CORBA 関連
1178
  //============================================================
1179
  /*!
1180
   * @if jp
1181
   * @brief ORB のポインタを取得する (所有権保持)
1182
   * @else
1183
   * @brief Get the pointer to the ORB (ownership retained)
1184
   * @endif
1185
   */
1186
  CORBA::ORB_ptr Manager::theORB()
1187
  {
1188
    RTC_TRACE(("Manager::theORB()"));
1189
    return m_pORB.in();
1190
  }
1191
  /*!
1192
   * @if jp
1193
   * @brief ORB のポインタを取得する (所有権複製)
1194
   * @else
1195
   * @brief Get the pointer to the ORB (ownership duplicated)
1196
   * @endif
1197
   */
1198
  CORBA::ORB_ptr Manager::getORB()
1199
  {
1200
    RTC_TRACE(("Manager::getORB()"));
1201
    return CORBA::ORB::_duplicate(m_pORB);
1202
  }
1203
  
1204
  /*!
1205
   * @if jp
1206
   * @brief Manager が持つ RootPOA のポインタを取得する (所有権保持)
1207
   * @else
1208
   * @brief Get the pointer to the RootPOA (ownership retained)
1209
   * @endif
1210
   */
1211
  PortableServer::POA_ptr Manager::thePOA()
1212
  {
1213
    RTC_TRACE(("Manager::thePOA()"));
1214
    return m_pPOA.in();
1215
  }
1216
#ifdef ORB_IS_OMNIORB
1217
  PortableServer::POA_ptr Manager::theShortCutPOA()
1218
  {
1219
    RTC_TRACE(("Manager::theShortCutPOA()"));
1220
    return m_pShortCutPOA.in();
1221
  }
1222
#endif
1223
  /*!
1224
   * @if jp
1225
   * @brief Manager が持つ RootPOA のポインタを取得する (所有権複製)
1226
   * @else
1227
   * @brief Get the pointer to the RootPOA (ownership duplicated)
1228
   * @endif
1229
   */
1230
  PortableServer::POA_ptr Manager::getPOA()
1231
  {
1232
    RTC_TRACE(("Manager::getPOA()"));
1233
    return PortableServer::POA::_duplicate(m_pPOA);
1234
  }
1235
#ifdef ORB_IS_OMNIORB
1236
  PortableServer::POA_ptr Manager::getShortCutPOA()
1237
  {
1238
    RTC_TRACE(("Manager::getPOA()"));
1239
    return PortableServer::POA::_duplicate(m_pShortCutPOA);
1240
  }
1241
#endif
1242
  
1243
  /*!
1244
   * @if jp
1245
   * @brief Manager が持つ POAManager を取得する (所有権保持)
1246
   * @else
1247
   * @brief Get the pointer to the POAManager (ownership retained)
1248
   * @endif
1249
   */
1250
  PortableServer::POAManager_ptr Manager::thePOAManager()
1251
  {
1252
    RTC_TRACE(("Manager::thePOAManager()"));
1253
    return m_pPOAManager.in();
1254
  }
1255
  
1256
  /*!
1257
   * @if jp
1258
   * @brief Manager が持つ POAManager を取得する (所有権複製)
1259
   * @else
1260
   * @brief Get the pointer to the POAManager (ownership duplicated)
1261
   * @endif
1262
   */
1263
  PortableServer::POAManager_ptr Manager::getPOAManager()
1264
  {
1265
    RTC_TRACE(("Manager::getPOAManager()"));
1266
    return PortableServer::POAManager::_duplicate(m_pPOAManager);
1267
  }
1268
  
1269
  //============================================================
1270
  // Protected functions
1271
  //============================================================
1272
  
1273
  //============================================================
1274
  // Manager initialization and finalization
1275
  //============================================================
1276
  /*!
1277
   * @if jp
1278
   * @brief Manager の内部初期化処理
1279
   * @else
1280
   * @brief Manager internal initialization
1281
   * @endif
1282
   */
1283
  void Manager::initManager(int argc, char** argv)
1284
  {
1285
    // load configurations
1286
    ManagerConfig config(argc, argv);
1287
    config.configure(m_config);
1288
    
1289
    // initialize ModuleManager
1290
    m_module = new ModuleManager(m_config);
1291

    
1292
    // initialize Terminator
1293
    m_terminator = new Terminator(this);
1294
    {
1295
      Guard guard(m_terminate.mutex);
1296
      m_terminate.waiting = 0;
1297
    }
1298
    
1299
    // initialize Timer
1300
    if (coil::toBool(m_config["timer.enable"], "YES", "NO", true))
1301
      {
1302
        coil::TimeValue tm(0, 100000);
1303
        std::string tick(m_config["timer.tick"]);
1304
        if (!tick.empty())
1305
          {
1306
            tm = atof(tick.c_str());
1307
            m_timer = new coil::Timer(tm);
1308
            m_timer->start();
1309
          }
1310
      }
1311

    
1312
    if (coil::toBool(m_config["manager.shutdown_auto"], "YES", "NO", true) &&
1313
        !coil::toBool(m_config["manager.is_master"], "YES", "NO", false))
1314
      {
1315
        coil::TimeValue tm(10, 0);
1316
        if (m_config.findNode("manager.auto_shutdown_duration") != NULL)
1317
          {
1318
            double duration;
1319
            const char* s = m_config["manager.auto_shutdown_duration"].c_str();
1320
            if (coil::stringTo(duration, s))
1321
              {
1322
                tm = duration;
1323
              }
1324
          }
1325
        if (m_timer != NULL)
1326
          {
1327
            m_timer->registerListenerObj(this, 
1328
                                         &Manager::shutdownOnNoRtcs, tm);
1329
          }
1330
      }
1331
    
1332
    {
1333
      coil::TimeValue tm(1, 0); 
1334
      if (m_timer != NULL)
1335
        {
1336
          m_timer->registerListenerObj(this, 
1337
                                       &Manager::cleanupComponents, tm);
1338
        }
1339
    }
1340

    
1341
  }
1342
  
1343
  /*!
1344
   * @if jp
1345
   * @brief Manager の終了処理
1346
   * @else
1347
   * @brief Manager internal finalization
1348
   * @endif
1349
   */
1350
  void Manager::shutdownManager()
1351
  {
1352
    RTC_TRACE(("Manager::shutdownManager()"));
1353
    m_timer->stop();
1354
  }
1355

    
1356
  void  Manager::shutdownOnNoRtcs()
1357
  {
1358
    RTC_TRACE(("Manager::shutdownOnNoRtcs()"));
1359
    if (coil::toBool(m_config["manager.shutdown_on_nortcs"], "YES", "NO", true))
1360
      {
1361
        std::vector<RTObject_impl*> comps(getComponents());
1362
        if (comps.size() == 0)
1363
          {
1364
            shutdown();
1365
          }
1366
      }
1367

    
1368
  }
1369
  
1370
  //============================================================
1371
  // Logger initialization and finalization
1372
  //============================================================
1373
  /*!
1374
   * @if jp
1375
   * @brief File logger 初期化
1376
   * initLoggerから呼ばれる
1377
   * @else
1378
   * @brief File logger initialization
1379
   * This function is called from initLogger.
1380
   * @endif
1381
   */
1382
  void Manager::initLogstreamFile()
1383
  {
1384
    // format logger file name
1385
    m_config["logger.file_name"] = 
1386
      formatString(m_config["logger.file_name"].c_str(), m_config);
1387

    
1388
    std::vector<std::string> logouts =
1389
      coil::split(m_config["logger.file_name"], ",");
1390
    coil::Properties& logprop = m_config.getNode("logger");
1391

    
1392
    for (int i(0), len(logouts.size()); i < len; ++i)
1393
      {
1394
        if (logouts[i].empty()) { continue; }
1395

    
1396
        LogstreamBase* logstream =
1397
          LogstreamFactory::instance().createObject("file");
1398
        if (logstream == NULL)
1399
          {
1400
            std::cerr << "\"file\" logger creation failed" << std::endl;
1401
            continue;
1402
          }
1403
        if (!logstream->init(logprop))
1404
          {
1405
            std::cerr << "\"file\" logger initialization failed" << std::endl;
1406
            LogstreamFactory::instance().deleteObject("file", logstream);
1407
            continue;
1408
          }
1409
        m_logStreamBuf.addStream(logstream->getStreamBuffer());
1410
      }
1411
  }
1412

    
1413
  void Manager::initLogstreamPlugins()
1414
  {
1415
    // loading logstream module
1416
    // create logstream object and attach to the logger
1417
    coil::vstring mods = coil::split(m_config["logger.plugins"], ",");
1418
    for (size_t i(0); i < mods.size(); ++i)
1419
      {
1420
        std::string basename = mods[i].substr(0, mods[i].find('.'));
1421
        basename += "Init";
1422
        try
1423
          {
1424
            m_module->load(mods[i], basename);
1425
          }
1426
        catch (...)
1427
          {
1428
            RTC_WARN(("Logstream plugin module load failed: %s",
1429
                      mods[i].c_str()));
1430
            continue;
1431
          }
1432
      }
1433
  }
1434

    
1435
  void Manager::initLogstreamOthers()
1436
  {
1437
    LogstreamFactory& factory(LogstreamFactory::instance());
1438

    
1439
    coil::Properties pp(m_config.getNode("logger.logstream"));
1440

    
1441
    const std::vector<Properties*>& leaf0 = pp.getLeaf();
1442
    for (size_t i(0); i < leaf0.size(); ++i)
1443
      {
1444
        std::string lstype = leaf0[i]->getName();
1445
        LogstreamBase* logstream = factory.createObject(lstype);
1446
        if (logstream == NULL)
1447
          {
1448
            RTC_WARN(("Logstream %s creation failed.", lstype.c_str()));
1449
            continue;
1450
          }
1451
        RTC_INFO(("Logstream %s created.", lstype.c_str()));
1452
        if (!logstream->init(*leaf0[i]))
1453
          {
1454
            RTC_WARN(("Logstream %s init failed.", lstype.c_str()));
1455
            factory.deleteObject(lstype.c_str(), logstream);
1456
            RTC_WARN(("Logstream %s deleted.", lstype.c_str()));
1457
          }
1458
        RTC_INFO(("Logstream %s added.", lstype.c_str()));
1459
        m_logStreamBuf.addStream(logstream->getStreamBuffer());
1460
      }
1461
  }
1462

    
1463
  /*!
1464
   * @if jp
1465
   * @brief System logger の初期化
1466
   * @else
1467
   * @brief System logger initialization
1468
   * @endif
1469
   */
1470
  bool Manager::initLogger()
1471
  {
1472
    // Enable logger or not
1473
    rtclog.setLevel("SILENT");
1474
    rtclog.setName("manager");
1475
    if (!coil::toBool(m_config["logger.enable"], "YES", "NO", true))
1476
      {
1477
        return true;
1478
      }
1479

    
1480
    // Set date format for log entry header
1481
    rtclog.setDateFormat(m_config["logger.date_format"].c_str());
1482
    rtclog.setClockType(m_config["logger.clock_type"]);
1483
    // Loglevel was set from configuration file.
1484
    rtclog.setLevel(m_config["logger.log_level"].c_str());
1485
    // Log color enable
1486
    coil::toBool(m_config["logger.color_enable"], "YES", "NO", false) ?
1487
      rtclog.enableColor() : rtclog.disableColor();
1488
    // Log stream mutex locking mode
1489
    coil::toBool(m_config["logger.stream_lock"], "enable", "disable", false) ?
1490
      rtclog.enableLock() : rtclog.disableLock();
1491

    
1492
    // File Logstream init
1493
    initLogstreamFile();
1494
    // Load logstream plugin
1495
    initLogstreamPlugins();
1496
    // Initialize other logstreams
1497
    initLogstreamOthers();
1498

    
1499
    RTC_INFO(("%s", m_config["openrtm.version"].c_str()));
1500
    RTC_INFO(("Copyright (C) 2003-2017"));
1501
    RTC_INFO(("  Noriaki Ando"));
1502
    RTC_INFO(("  Intelligent Systems Research Institute, AIST"));
1503
    RTC_INFO(("Manager starting."));
1504
    RTC_INFO(("Starting local logging."));
1505

    
1506
    return true;
1507
  }
1508

    
1509
  /*!
1510
   * @if jp
1511
   * @brief System Logger の終了処理
1512
   * @else
1513
   * @brief System Logger finalization
1514
   * @endif
1515
   */
1516
  void Manager::shutdownLogger()
1517
  {
1518
    RTC_TRACE(("Manager::shutdownLogger()"));
1519
    rtclog.flush();
1520

    
1521
    for (int i(0), len(m_logfiles.size()); i < len; ++i)
1522
      {
1523
        m_logfiles[i]->close();
1524
        //        m_logStreamBuf.removeStream(m_logfiles[i]->rdbuf());
1525
        delete m_logfiles[i];
1526
      }
1527
    if (!m_logfiles.empty())
1528
      {
1529
        m_logfiles.clear();
1530
      }
1531
  }
1532
  
1533
  //============================================================
1534
  // ORB initialization and finalization
1535
  //============================================================
1536
  /*!
1537
   * @if jp
1538
   * @brief CORBA ORB の初期化処理
1539
   * @else
1540
   * @brief CORBA ORB initialization
1541
   * @endif
1542
   */
1543
  bool Manager::initORB()
1544
  {
1545
    RTC_TRACE(("Manager::initORB()"));
1546
    // Initialize ORB
1547
    try
1548
      {
1549
        std::vector<std::string> args(coil::split(createORBOptions(), " "));
1550
        // TAO's ORB_init needs argv[0] as command name.
1551
        args.insert(args.begin(), "manager");
1552
        char** argv = coil::toArgv(args);
1553
        int argc(args.size());
1554
        
1555
#ifdef ORB_IS_ORBEXPRESS
1556
        CORBA::ORB::spawn_flags(VX_SPE_TASK | VX_STDIO);
1557
        CORBA::ORB::stack_size(20000);
1558
        m_pORB = CORBA::ORB_init(argc, argv, "");
1559
        CORBA::Object_var obj =
1560
          m_pORB->resolve_initial_references((char*)"RootPOA");
1561
        m_pPOA = PortableServer::POA::_narrow(obj);
1562
#else
1563
        // ORB initialization
1564
        m_pORB = CORBA::ORB_init(argc, argv);
1565
        // Get the RootPOA
1566
        CORBA::Object_var obj =
1567
          m_pORB->resolve_initial_references((char*)"RootPOA");
1568
        m_pPOA = PortableServer::POA::_narrow(obj);
1569
#endif
1570
        if (CORBA::is_nil(m_pPOA))
1571
          {
1572
            RTC_ERROR(("Could not resolve RootPOA."));
1573
            return false;
1574
          }
1575
        // Get the POAManager
1576
        m_pPOAManager = m_pPOA->the_POAManager();
1577
#ifdef ORB_IS_OMNIORB
1578
        CORBA::PolicyList pl;
1579
        pl.length(1);
1580
#ifdef RTM_OMNIORB_42
1581
        pl[0] = omniPolicy::create_local_shortcut_policy(omniPolicy::LOCAL_CALLS_SHORTCUT);
1582
#else
1583
        CORBA::Any v;
1584
        v <<= omniPolicy::LOCAL_CALLS_SHORTCUT;
1585
        pl[0] = m_pORB->create_policy(omniPolicy::LOCAL_SHORTCUT_POLICY_TYPE, v);
1586
#endif
1587
        m_pShortCutPOA = m_pPOA->create_POA("shortcut", m_pPOAManager, pl);
1588
#endif
1589

    
1590
#ifdef ORB_IS_OMNIORB
1591
        const char* conf = "corba.alternate_iiop_addresses";
1592
        if (m_config.findNode(conf) != NULL)
1593
          {
1594
            coil::vstring addr_list;
1595
            addr_list = coil::split(m_config[conf], ",", true);
1596

    
1597
            for (size_t i(0); i < addr_list.size(); ++i)
1598
              {
1599
                coil::vstring addr_port = coil::split(addr_list[i], ":");
1600
                if (addr_port.size() == 2)
1601
                  {
1602
                    IIOP::Address iiop_addr;
1603
                    iiop_addr.host = addr_port[0].c_str();
1604
                    CORBA::UShort port; 
1605
                    coil::stringTo(port, addr_port[1].c_str());
1606
                    iiop_addr.port = port;
1607
#if defined(RTM_OMNIORB_40) || defined(RTM_OMNIORB_41)
1608
                    omniIOR::add_IIOP_ADDRESS(iiop_addr);
1609
#else
1610
                    omniIOR::add_IIOP_ADDRESS(iiop_addr, 0);
1611
#endif // defined(RTC_OMNIORB_40) and defined(RTC_OMNIORB_41)
1612
                  }
1613
              }
1614
          }
1615
#endif // ORB_IS_OMNIORB
1616
      }
1617
    catch (...)
1618
      {
1619
        RTC_ERROR(("Exception: Caught unknown exception in initORB()." ));
1620
        return false;
1621
      }
1622
    return true;
1623
  }
1624
  
1625
  /*!
1626
   * @if jp
1627
   * @brief ORB のコマンドラインオプション作成
1628
   * @else
1629
   * @brief ORB command option creation
1630
   * @endif
1631
   */
1632
  std::string Manager::createORBOptions()
1633
  {
1634
    std::string opt(m_config["corba.args"]);
1635
    RTC_DEBUG(("corba.args: %s", opt.c_str()));
1636

    
1637
    RTC_DEBUG_STR((m_config));
1638

    
1639
    coil::vstring endpoints;
1640
    createORBEndpoints(endpoints);
1641
    createORBEndpointOption(opt, endpoints);
1642

    
1643
    RTC_PARANOID(("ORB options: %s", opt.c_str()));
1644
    return opt;
1645
  }
1646

    
1647
  void Manager::createORBEndpoints(coil::vstring& endpoints)
1648
  {
1649
    // corba.endpoint is obsolete
1650
    // corba.endpoints with comma separated values are acceptable
1651
    if (m_config.findNode("corba.endpoints") != 0)
1652
      {
1653
        endpoints = coil::split(m_config["corba.endpoints"], ",");
1654
        RTC_DEBUG(("corba.endpoints: %s", m_config["corba.endpoints"].c_str()));
1655
      }
1656

    
1657
    if (m_config.findNode("corba.endpoint") != 0)
1658
      {
1659
        coil::vstring tmp(coil::split(m_config["corba.endpoint"], ","));
1660
        endpoints.insert(endpoints.end(), tmp.begin(), tmp.end());
1661
        RTC_DEBUG(("corba.endpoint: %s", m_config["corba.endpoint"].c_str()));
1662
      }
1663
    // If this process has master manager,
1664
    // master manager's endpoint inserted at the top of endpoints
1665
    RTC_DEBUG(("manager.is_master: %s",
1666
               m_config["manager.is_master"].c_str()));
1667
    if (coil::toBool(m_config["manager.is_master"], "YES", "NO", false))
1668
      {
1669
        std::string mm(m_config.getProperty("corba.master_manager", ":2810"));
1670
        coil::vstring mmm(coil::split(mm, ":"));
1671
        if (mmm.size() == 2)
1672
          {
1673
            endpoints.insert(endpoints.begin(), std::string(":") + mmm[1]);
1674
          }
1675
        else
1676
          {
1677
            endpoints.insert(endpoints.begin(), ":2810");
1678
          }
1679
      }
1680
    coil::vstring tmp(endpoints);
1681
    endpoints = coil::unique_sv(tmp);
1682
  }
1683

    
1684
  void Manager::createORBEndpointOption(std::string& opt,
1685
                                        coil::vstring& endpoints)
1686
  {
1687
    std::string corba(m_config["corba.id"]);
1688
    RTC_DEBUG(("corba.id: %s", corba.c_str()));
1689

    
1690
    for (size_t i(0); i < endpoints.size(); ++i)
1691
      {
1692
        std::string& endpoint(endpoints[i]);
1693
        RTC_DEBUG(("Endpoint is : %s", endpoint.c_str()));
1694
        if (endpoint.find(":") == std::string::npos) { endpoint += ":"; }
1695

    
1696
        if (corba == "omniORB")
1697
          {
1698
            coil::normalize(endpoint);
1699
            if (coil::normalize(endpoint) == "all:")
1700
              {
1701
#ifdef ORB_IS_OMNIORB
1702
#ifdef RTC_CORBA_CXXMAPPING11
1703
                // omniORB 4.1 or later
1704
                opt += " -ORBendPointPublish all(addr)";
1705
#else
1706
                // omniORB 4.0
1707
                opt += " -ORBendPointPublishAllIFs 1";
1708
#endif // RTC_CORBA_CXXMAPPING1
1709
#endif // ORB_IS_OMNIORB
1710
              }
1711
            else
1712
              {
1713
                opt += " -ORBendPoint giop:tcp:" + endpoint;
1714
              }
1715
          }
1716
        else if (corba == "TAO")
1717
          {
1718
            opt += "-ORBEndPoint iiop://" + endpoint;
1719
          }
1720
        else if (corba == "MICO")
1721
          {
1722
            opt += "-ORBIIOPAddr inet:" + endpoint;
1723
          }
1724
      }
1725
  }
1726

    
1727
  
1728
  /*!
1729
   * @if jp
1730
   * @brief ORB の終了処理
1731
   * @else
1732
   * @brief ORB finalization
1733
   * @endif
1734
   */
1735
  void Manager::shutdownORB()
1736
  {
1737
    RTC_TRACE(("Manager::shutdownORB()"));
1738
    if(CORBA::is_nil(m_pORB))
1739
      {
1740
        return;
1741
      }
1742
    try
1743
      {
1744
      while (m_pORB->work_pending())
1745
        {
1746
          RTC_PARANOID(("Pending work still exists."));
1747
          if (m_pORB->work_pending())
1748
            m_pORB->perform_work();
1749
        }
1750
        RTC_DEBUG(("No pending works of ORB. Shutting down POA and ORB."));
1751
      }
1752
    catch(...)
1753
      { 
1754
        RTC_ERROR(("Caught SystemException during perform_work."));
1755
      }
1756
    
1757
    if (!CORBA::is_nil(m_pPOA))
1758
      {
1759
        try
1760
          {
1761
            if (!CORBA::is_nil(m_pPOAManager))
1762
              m_pPOAManager->deactivate(false, true);
1763
            RTC_DEBUG(("POA Manager was deactivated."));
1764
            m_pPOA->destroy(false, true);
1765
            m_pPOA = PortableServer::POA::_nil();
1766
            RTC_DEBUG(("POA was destroid."));
1767
          }
1768
        catch (CORBA::SystemException& ex)
1769
          {
1770
            RTC_ERROR(("Exception cought during root POA destruction"));
1771
#ifndef ORB_IS_RTORB
1772
            RTC_ERROR(("CORBA::SystemException(minor=%d)", ex.minor()));
1773
#endif // ORB_IS_RTORB
1774
          }
1775
        catch (...)
1776
          {
1777
            RTC_ERROR(("Caught unknown exception during POA destruction."));
1778
          }
1779
      }
1780
    
1781
    if (!CORBA::is_nil(m_pORB))
1782
      {
1783
        try
1784
          {
1785
            m_pORB->shutdown(true);
1786
            RTC_DEBUG(("ORB was shutdown."));
1787
            //m_pORB->destroy();
1788
            RTC_DEBUG(("ORB was destroied."));
1789
            m_pORB = CORBA::ORB::_nil();
1790
          }
1791
        catch (CORBA::SystemException& ex)
1792
          {
1793
            RTC_ERROR(("Exception caught during ORB shutdown"));
1794
#ifndef ORB_IS_RTORB
1795
            RTC_ERROR(("CORBA::SystemException(minodor=%d)", ex.minor()));
1796
#endif // ORB_IS_RTORB
1797
          }
1798
        catch (...)
1799
          {
1800
            RTC_ERROR(("Caught unknown exception during ORB shutdown."));
1801
          }
1802
      }
1803
  }
1804
  
1805
  //============================================================
1806
  // Naming initialization and finalization
1807
  //============================================================
1808
  /*!
1809
   * @if jp
1810
   * @brief NamingManager の初期化
1811
   * @else
1812
   * @brief NamingManager initialization
1813
   * @endif
1814
   */
1815
  bool Manager::initNaming()
1816
  {
1817
    RTC_TRACE(("Manager::initNaming()"));
1818
    
1819
    m_namingManager = new NamingManager(this);
1820
    
1821
    // If NameService is disabled, return immediately
1822
    if (!coil::toBool(m_config["naming.enable"], "YES", "NO", true))
1823
      {
1824
        return true;
1825
      }
1826
    
1827
    // NameServer registration for each method and servers
1828
    std::vector<std::string> meth(coil::split(m_config["naming.type"], ","));
1829
    
1830
    for (int i(0), len_i(meth.size()); i < len_i; ++i)
1831
      {
1832
        std::vector<std::string> names;
1833
        names = coil::split(m_config[meth[i] + ".nameservers"], ",");
1834
        
1835
        
1836
        for (int j(0), len_j(names.size()); j < len_j; ++j)
1837
          {
1838
            RTC_TRACE(("Register Naming Server: %s/%s",                \
1839
                       meth[i].c_str(), names[j].c_str()));        
1840
            m_namingManager->registerNameServer(meth[i].c_str(),
1841
                                                names[j].c_str());
1842
          }
1843
      }
1844
    
1845
    // NamingManager Timer update initialization
1846
    if (coil::toBool(m_config["naming.update.enable"], "YES", "NO", true))
1847
      {
1848
        coil::TimeValue tm(10, 0); // default interval = 10sec for safty
1849
        std::string intr(m_config["naming.update.interval"]);
1850
        if (!intr.empty())
1851
          {
1852
            tm = atof(intr.c_str());
1853
          }
1854
        if (m_timer != NULL)
1855
          {
1856
            m_timer->registerListenerObj(m_namingManager, 
1857
                                         &NamingManager::update, tm);
1858
          }
1859
      }
1860
    return true;
1861
  }
1862
  
1863
  /*!
1864
   * @if jp
1865
   * @brief NamingManager の終了処理
1866
   * @else
1867
   * @brief NamingManager finalization
1868
   * @endif
1869
   */
1870
  void Manager::shutdownNaming()
1871
  {
1872
    RTC_TRACE(("Manager::shutdownNaming()"));
1873
    std::vector<RTObject_impl*> comps = getComponents();
1874

    
1875
    for (size_t i(0); i < comps.size(); ++i)
1876
      {
1877
        coil::vstring names = comps[i]->getNamingNames();
1878
        m_listeners.naming_.preUnbind(comps[i], names);
1879
        for (size_t j(0); j < names.size(); ++j)
1880
          {
1881
            m_namingManager->unbindObject(names[j].c_str());
1882
          }
1883
        m_listeners.naming_.postUnbind(comps[i], names);
1884
      }
1885

    
1886
    m_namingManager->unbindAll();
1887
    delete m_namingManager;
1888
  }
1889

    
1890
  /*!
1891
   * @if jp
1892
   * @brief NamingManagerを取得する
1893
   * @else
1894
   * @brief Getting NamingManager
1895
   * @endif
1896
   */
1897
  NamingManager& Manager::getNamingManager()
1898
  {
1899
    return *m_namingManager;
1900
  }
1901

    
1902
  //============================================================
1903
  // Naming initialization and finalization
1904
  //============================================================
1905
  /*!
1906
   * @if jp
1907
   * @brief ExecutionContextManager の初期化
1908
   * @else
1909
   * @brief ExecutionContextManager initialization
1910
   * @endif
1911
   */
1912
  bool Manager::initExecContext()
1913
  {
1914
    RTC_TRACE(("Manager::initExecContext()"));
1915
    PeriodicExecutionContextInit(this);
1916
    ExtTrigExecutionContextInit(this);
1917
    OpenHRPExecutionContextInit(this);
1918
#ifdef RTM_OS_VXWORKS
1919
    VxWorksRTExecutionContextInit(this);
1920
#ifndef __RTP__
1921
    VxWorksInterruptExecutionContextInit(this);
1922
#endif
1923
#endif
1924
    // initialize CPU affinity
1925
#ifdef RTM_OS_LINUX
1926
    initCpuAffinity();
1927
#endif // RTM_OS_LINUX
1928

    
1929
    return true;
1930
  }
1931

    
1932
  bool Manager::initComposite()
1933
  {
1934
    RTC_TRACE(("Manager::initComposite()"));
1935
    PeriodicECSharedCompositeInit(this);
1936

    
1937
    return true;
1938
  }
1939
  
1940
  bool Manager::initFactories()
1941
  {
1942
    RTC_TRACE(("Manager::initFactories()"));
1943
    FactoryInit();
1944
    return true;
1945
  }
1946

    
1947
  void Manager::initCpuAffinity()
1948
  {
1949
    RTC_TRACE(("initCpuAffinity()"));
1950
#ifdef RTM_OS_LINUX
1951
    if (m_config.findNode("manager.cpu_affinity") == 0) { return; }
1952

    
1953
    std::string& affinity(m_config["manager.cpu_affinity"]);
1954
    RTC_DEBUG(("CPU affinity property: %s", affinity.c_str()));
1955

    
1956
    coil::vstring tmp = coil::split(affinity, ",", true);
1957

    
1958
    pid_t pid = getpid();
1959
    cpu_set_t cpu_set; CPU_ZERO(&cpu_set);
1960

    
1961
    for (size_t i(0); i < tmp.size(); ++i)
1962
      {
1963
        int num;
1964
        if (coil::stringTo(num, tmp[i].c_str()))
1965
          {
1966
            CPU_SET(num, &cpu_set);
1967
            RTC_DEBUG(("CPU affinity mask set to %d", num));
1968
          }
1969
      }
1970

    
1971
    int result = sched_setaffinity(pid, sizeof(cpu_set_t), &cpu_set);
1972
    if (result != 0)
1973
      {
1974
        RTC_ERROR(("pthread_getaffinity_np():"
1975
                   "CPU affinity mask setting failed"));
1976
      }
1977
    CPU_ZERO(&cpu_set);
1978
    result = sched_getaffinity(pid, sizeof(cpu_set_t), &cpu_set);
1979
    if (result != 0)
1980
      {
1981
        RTC_ERROR(("pthread_getaffinity_np(): returned error."));
1982
      }
1983
    for (size_t j(0); j < CPU_SETSIZE; ++j)
1984
      {
1985
        if (CPU_ISSET(j, &cpu_set))
1986
          {
1987
            RTC_DEBUG(("Current CPU affinity mask is %d.", j));
1988
          }
1989
      }
1990
#endif // RTM_OS_LINUX
1991
  }
1992
  
1993
  /*!
1994
   * @if jp
1995
   * @brief Timer の初期化
1996
   * @else
1997
   * @brief Timer initialization
1998
   * @endif
1999
   */
2000
  bool Manager::initTimer()
2001
  {
2002
    return true;
2003
  }
2004

    
2005

    
2006
  bool Manager::initManagerServant()
2007
  {
2008
    RTC_TRACE(("Manager::initManagerServant()"));
2009
    if (!coil::toBool(m_config["manager.corba_servant"], "YES", "NO", true))
2010
      {
2011
        return true;
2012
      }
2013
    m_mgrservant = new ::RTM::ManagerServant();
2014
    coil::Properties& prop(m_config.getNode("manager"));
2015
    std::vector<std::string> names(coil::split(prop["naming_formats"], ","));
2016

    
2017
    if (coil::toBool(prop["is_master"], "YES", "NO", true))
2018
      {
2019
        for (int i(0), len(names.size()); i < len; ++i)
2020
          {
2021
            std::string mgr_name(formatString(names[i].c_str(), prop));
2022
            m_namingManager->bindObject(mgr_name.c_str(), m_mgrservant);
2023
          }
2024
      }
2025

    
2026
    std::ifstream otherref(m_config["manager.refstring_path"].c_str());
2027
    if (otherref.fail() != 0)
2028
      {
2029
        otherref.close();
2030
        std::ofstream reffile(m_config["manager.refstring_path"].c_str());
2031
        RTM::Manager_var mgr_v(RTM::Manager::
2032
                               _duplicate(m_mgrservant->getObjRef()));
2033
        CORBA::String_var str_var = m_pORB->object_to_string(mgr_v);
2034
        reffile << str_var;
2035
        reffile.close();
2036
      }
2037
    else
2038
      {
2039
        std::string refstring;
2040
        otherref >> refstring;
2041
        otherref.close();
2042

    
2043
        CORBA::Object_var obj = m_pORB->string_to_object(refstring.c_str());
2044
        RTM::Manager_var mgr = RTM::Manager::_narrow(obj);
2045
        //        if (CORBA::is_nil(mgr)) return false;
2046
        //        mgr->set_child(m_mgrservant->getObjRef());
2047
        //        m_mgrservant->set_owner(mgr);
2048
      }
2049

    
2050
    return true;
2051
  }
2052

    
2053
  /*!
2054
   * @if jp
2055
   * @brief ManagerServantを取得する
2056
   * @else
2057
   * @brief Getting ManagerServant
2058
   * @endif
2059
   */
2060
  RTM::ManagerServant& Manager::getManagerServant()
2061
  {
2062
    return *m_mgrservant;
2063
  }
2064

    
2065
  bool Manager::initLocalService()
2066
  {
2067
    RTC_TRACE(("Manager::initLocalService()"));
2068

    
2069
    RTM::LocalServiceAdmin& admin = RTM::LocalServiceAdmin::instance();
2070
    coil::Properties& prop(m_config.getNode("manager.local_service"));
2071
    admin.init(prop);
2072
    RTC_DEBUG(("LocalServiceAdmin's properties:"));
2073
    RTC_DEBUG_STR((prop));
2074

    
2075
    RTM::LocalServiceProfileList svclist = admin.getServiceProfiles();
2076
    for (size_t i(0); i < svclist.size(); ++i)
2077
      {
2078
        RTC_INFO(("Available local service: %s (%s)",
2079
        svclist[i].name.c_str(), svclist[i].uuid.c_str()));
2080
      }
2081
    return true;
2082
  }
2083

    
2084
  /*!
2085
   * @if jp
2086
   * @brief NamingManager の終了処理
2087
   * @else
2088
   * @brief NamingManager finalization
2089
   * @endif
2090
   */
2091
  void Manager::shutdownComponents()
2092
  {
2093
    RTC_TRACE(("Manager::shutdownComponents()"));
2094
    std::vector<RTObject_impl*> comps;
2095
    comps = m_namingManager->getObjects();
2096
    for (int i(0), len(comps.size()); i < len; ++i)
2097
      {
2098
        try
2099
          {
2100
            comps[i]->exit();
2101
            coil::Properties p(comps[i]->getInstanceName());
2102
            p << comps[i]->getProperties();
2103
            rtclog.lock();
2104
            rtclog.level(::RTC::Logger::RTL_PARANOID) << p;
2105
            rtclog.unlock();
2106
          }
2107
        catch (...)
2108
          {
2109
            ;
2110
          }
2111
      }
2112
    for (CORBA::ULong i(0), len(m_ecs.size()); i < len; ++i)
2113
      {
2114
        try{
2115
      PortableServer::RefCountServantBase* servant;
2116
      servant = dynamic_cast<PortableServer::RefCountServantBase*>(m_ecs[i]);
2117
      if (servant == NULL)
2118
        {
2119
          RTC_ERROR(("Invalid dynamic cast. EC->RefCountServantBase failed."));
2120
          return;
2121
        }
2122
      PortableServer::ObjectId_var oid = m_pPOA->servant_to_id(servant);
2123
          m_pPOA->deactivate_object(oid);
2124
        }
2125
        catch (...)
2126
          {
2127
            ;
2128
          }
2129
      }
2130
    return;
2131
  }
2132
  
2133
  /*!
2134
   * @if jp
2135
   * @brief RTコンポーネントの登録解除
2136
   * @else
2137
   * @brief Unregister RT-Components
2138
   * @endif
2139
   */
2140
  void Manager::cleanupComponent(RTObject_impl* comp)
2141
  {
2142
    RTC_TRACE(("Manager::cleanupComponent()"));
2143
    unregisterComponent(comp);
2144
  }
2145

    
2146
  void Manager::cleanupComponents()
2147
  {
2148
    RTC_VERBOSE(("Manager::cleanupComponents()"));
2149
    Guard guard(m_finalized.mutex);
2150
    RTC_VERBOSE(("%d components are marked as finalized.",
2151
               m_finalized.comps.size()));
2152
    for (size_t i(0); i < m_finalized.comps.size(); ++i)
2153
      {
2154
        deleteComponent(m_finalized.comps[i]);
2155
      }
2156
    m_finalized.comps.clear();
2157
  }
2158

    
2159
  void Manager::notifyFinalized(RTObject_impl* comp)
2160
  {
2161
    RTC_TRACE(("Manager::notifyFinalized()"));
2162
    Guard guard(m_finalized.mutex);
2163
    m_finalized.comps.push_back(comp);
2164
  }
2165
  
2166
  /*!
2167
   * @if jp
2168
   * @brief createComponentの引数を処理する
2169
   * @else
2170
   *
2171
   * @endif
2172
   */
2173
  bool Manager::procComponentArgs(const char* comp_arg,
2174
                                  coil::Properties& comp_id,
2175
                                  coil::Properties& comp_conf)
2176
  {
2177
    std::vector<std::string> id_and_conf(coil::split(comp_arg, "?"));
2178
    // arg should be "id?key0=value0&key1=value1...".
2179
    // id is mandatory, conf is optional
2180
    if (id_and_conf.size() != 1 && id_and_conf.size() != 2)
2181
      {
2182
        RTC_ERROR(("Invalid arguments. Two or more '?' in arg : %s", comp_arg));
2183
        return false;
2184
      }
2185
    if (id_and_conf[0].find(":") == std::string::npos)
2186
      {
2187
        id_and_conf[0].insert(0, "RTC:::");
2188
        id_and_conf[0] += ":";
2189
      }
2190
    std::vector<std::string> id(coil::split(id_and_conf[0], ":"));
2191

    
2192
    // id should be devided into 1 or 5 elements
2193
    // RTC:[vendor]:[category]:impl_id:[version] => 5
2194
    if (id.size() != 5) 
2195
      {
2196
        RTC_ERROR(("Invalid RTC id format.: %s", id_and_conf[0].c_str()));
2197
        return false;
2198
      }
2199

    
2200
    const char* prof[] =
2201
      {
2202
        "RTC", "vendor", "category", "implementation_id", "version"
2203
      };
2204

    
2205
    if (id[0] != prof[0])
2206
      {
2207
        RTC_ERROR(("Invalid id type: %s", id[0].c_str()));
2208
        return false;
2209
      }
2210
    for (int i(1); i < 5; ++i)
2211
      {
2212
        comp_id[prof[i]] = id[i];
2213
        RTC_TRACE(("RTC basic propfile %s: %s", prof[i], id[i].c_str()));
2214
      }
2215

    
2216
    if (id_and_conf.size() == 2)
2217
      {
2218
        std::vector<std::string> conf(coil::split(id_and_conf[1], "&"));
2219
        for (int i(0), len(conf.size()); i < len; ++i)
2220
          {
2221
            if (conf[i].empty()) { continue; }
2222
            std::vector<std::string> keyval(coil::split(conf[i], "="));
2223
            if (keyval.size() != 2) { continue; }
2224
            comp_conf[keyval[0]] = keyval[1];
2225
            RTC_TRACE(("RTC property %s: %s",
2226
                       keyval[0].c_str(), keyval[1].c_str()));
2227
          }
2228
      }
2229
    return true;
2230
  }
2231

    
2232
  bool Manager::procContextArgs(const char* ec_args,
2233
                                std::string& ec_id,
2234
                                coil::Properties& ec_conf)
2235
  {
2236
    std::vector<std::string> id_and_conf(coil::split(ec_args, "?"));
2237
    if (id_and_conf.size() != 1 && id_and_conf.size() != 2)
2238
      {
2239
        RTC_ERROR(("Invalid arguments. Two or more '?' in arg : %s", ec_args));
2240
        return false;
2241
      }
2242
    if (id_and_conf[0].empty())
2243
      {
2244
        RTC_ERROR(("Empty ExecutionContext's name"));
2245
        return false;
2246
      }
2247
    ec_id =id_and_conf[0];
2248
    
2249
    if (id_and_conf.size() == 2)
2250
      {
2251
        std::vector<std::string> conf(coil::split(id_and_conf[1], "&"));
2252
        for (int i(0), len(conf.size()); i < len; ++i)
2253
          {
2254
            std::vector<std::string> k(coil::split(conf[i], "="));
2255
            ec_conf[k[0]] = k[1];
2256
            RTC_TRACE(("EC property %s: %s", k[0].c_str(), k[1].c_str()));
2257
          }
2258
      }
2259
    return true;
2260
  }
2261
  
2262
  /*!
2263
   * @if jp
2264
   * @brief RTコンポーネントのコンフィギュレーション処理
2265
   * @else
2266
   *
2267
   * @endif
2268
   */
2269
  void Manager::configureComponent(RTObject_impl* comp,
2270
                                   const coil::Properties& prop)
2271
  {
2272
    std::string category(comp->getCategory());
2273
    std::string type_name(comp->getTypeName());
2274
    std::string inst_name(comp->getInstanceName());
2275

    
2276
    std::string type_conf(category + "." + type_name + ".config_file");
2277
    std::string name_conf(category + "." + inst_name + ".config_file");
2278
    coil::vstring config_fname;
2279
    coil::Properties type_prop, name_prop;
2280

    
2281
    // Load "category.instance_name.config_file"
2282
    if (!m_config[name_conf].empty())
2283
      {
2284
        std::ifstream conff(m_config[name_conf].c_str());
2285
        if (!conff.fail())
2286
          {
2287
            name_prop.load(conff);
2288
            RTC_INFO(("Component instance conf file: %s loaded.",
2289
                      m_config[name_conf].c_str()));
2290
            RTC_DEBUG_STR((name_prop))
2291
            config_fname.push_back(m_config[name_conf].c_str());
2292
          }
2293
      }
2294
    if (m_config.findNode(category + "." + inst_name) != NULL)
2295
      {
2296
        coil::Properties& temp(m_config.getNode(category + "." + inst_name));
2297
        coil::vstring keys(temp.propertyNames());
2298
        if (!(keys.size() == 1 && keys.back() == "config_file"))
2299
          {
2300
            name_prop << m_config.getNode(category + "." + inst_name);
2301
            RTC_INFO(("Component type conf exists in rtc.conf. Merged."));
2302
            RTC_DEBUG_STR((name_prop));
2303
            if (m_config.findNode("config_file") != NULL)
2304
              {
2305
                config_fname.push_back(m_config["config_file"]);
2306
              }
2307
          }
2308
      }
2309
    if (!m_config[type_conf].empty())
2310
      {
2311
        std::ifstream conff(m_config[type_conf].c_str());
2312
        if (!conff.fail())
2313
          {
2314
            type_prop.load(conff);
2315
            RTC_INFO(("Component type conf file: %s loaded.",
2316
                      m_config[type_conf].c_str()));
2317
            RTC_DEBUG_STR((type_prop));
2318
            config_fname.push_back(m_config[type_conf].c_str());
2319
          }
2320
      }
2321
    if (m_config.findNode(category + "." + type_name) != NULL)
2322
      {
2323
        coil::Properties& temp(m_config.getNode(category + "." + type_name));
2324
        coil::vstring keys(temp.propertyNames());
2325
        if (!(keys.size() == 1 && keys.back() == "config_file"))
2326
          {
2327
            type_prop << m_config.getNode(category + "." + type_name);
2328
            RTC_INFO(("Component type conf exists in rtc.conf. Merged."));
2329
            RTC_DEBUG_STR((type_prop));
2330
            if (m_config.findNode("config_file") != NULL)
2331
              {
2332
                config_fname.push_back(m_config["config_file"]);
2333
              }
2334
          }
2335
      }
2336
    // Merge Properties. type_prop is merged properties
2337
    comp->setProperties(prop);
2338
    type_prop << name_prop;
2339
    type_prop["config_file"] = coil::flatten(coil::unique_sv(config_fname));
2340
    comp->setProperties(type_prop);
2341
    
2342
    //------------------------------------------------------------
2343
    // Format component's name for NameService
2344
    std::string naming_formats;
2345
    coil::Properties& comp_prop(comp->getProperties());
2346
    
2347
    naming_formats += m_config["naming.formats"];
2348
    if (comp_prop.findNode("naming.formats") != 0)
2349
      {
2350
        naming_formats = comp_prop["naming.formats"];
2351
      }
2352
    naming_formats = coil::flatten(coil::unique_sv(coil::split(naming_formats,
2353
                                                               ",")));
2354
    
2355
    std::string naming_names;
2356
    naming_names = formatString(naming_formats.c_str(), comp->getProperties());
2357
    comp->getProperties()["naming.formats"] = naming_formats;
2358
    comp->getProperties()["naming.names"] = naming_names;
2359
  }
2360
  
2361
  /*!
2362
   * @if jp
2363
   * @brief プロパティ情報のマージ
2364
   * @else
2365
   * @brief Merge property information
2366
   * @endif
2367
   */
2368
  bool Manager::mergeProperty(coil::Properties& prop, const char* file_name)
2369
  {
2370
    if (file_name == NULL)
2371
      {
2372
        RTC_ERROR(("Invalid configuration file name."));
2373
        return false;
2374
      }
2375
    if (file_name[0] != '\0')
2376
      {
2377
        std::ifstream conff(file_name);
2378
        if (!conff.fail())
2379
          {
2380
            prop.load(conff);
2381
            conff.close();
2382
            return true;
2383
          }
2384
      }
2385
    return false;
2386
  }
2387
  
2388
  /*!
2389
   * @if jp
2390
   * @brief NamingServer に登録する際の登録情報を組み立てる
2391
   * @else
2392
   * @brief Construct registration information when registering to Naming server
2393
   * @endif
2394
   */
2395
  std::string Manager::formatString(const char* naming_format,
2396
                                    coil::Properties& prop)
2397
  {
2398
    std::string name(naming_format), str("");
2399
    std::string::iterator it, it_end;
2400
    int count(0);
2401
    
2402
    it = name.begin();
2403
    it_end = name.end();
2404
    for ( ; it != it_end; ++it)
2405
      {
2406
        char c(*it);
2407
        if (c == '%')
2408
          {
2409
            ++count;
2410
            if (!(count % 2)) str.push_back((*it));
2411
          }
2412
        else if (c == '$')
2413
          {
2414
            count = 0;
2415
            ++it;
2416
            if (*it == '{' || *it == '(')
2417
              {
2418
                ++it;
2419
                std::string env;
2420
                for ( ; it != it_end && (*it) != '}' && (*it) != ')'; ++it)
2421
                  {
2422
                    env += *it;
2423
                  }
2424
                char* envval = coil::getenv(env.c_str());
2425
                if (envval != NULL) str += envval;
2426
              }
2427
            else
2428
              {
2429
                str.push_back(c);
2430
              }
2431
          }
2432
        else
2433
          {
2434
            if (count > 0 && (count % 2))
2435
              {
2436
                count = 0;
2437
                if      (c == 'n')  str += prop["instance_name"];
2438
                else if (c == 't')  str += prop["type_name"];
2439
                else if (c == 'm')  str += prop["type_name"];
2440
                else if (c == 'v')  str += prop["version"];
2441
                else if (c == 'V')  str += prop["vendor"];
2442
                else if (c == 'c')  str += prop["category"];
2443
                else if (c == 'i')  str += prop["implementation_id"];
2444
                else if (c == 'N')
2445
                  {
2446
                    size_t n = prop["implementation_id"].size();
2447
                    str += prop["instance_name"].substr(n);
2448
                  }
2449
                else if (c == 'h')  str += m_config["os.hostname"];
2450
                else if (c == 'M')  str += m_config["manager.name"];
2451
                else if (c == 'p')  str += m_config["manager.pid"];
2452
                else str.push_back(c);
2453
              }
2454
            else
2455
              {
2456
                count = 0;
2457
                str.push_back(c);
2458
              }
2459
          }
2460
      }
2461
    return str;
2462
  }
2463
  
2464
};