00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "ArExport.h"
00027 #include "Aria.h"
00028 #include "ArSocket.h"
00029 #include "ArSignalHandler.h"
00030 #include "ArKeyHandler.h"
00031 #include "ArJoyHandler.h"
00032 #ifndef ARINTERFACE
00033 #include "ArModuleLoader.h"
00034 #include "ArRobotJoyHandler.h"
00035 #endif // ARINTERFACE
00036
00037 ArGlobalFunctor1<int> Aria::ourSignalHandlerCB(&Aria::signalHandlerCB);
00038 ArMutex Aria::ourShuttingDownMutex;
00039 bool Aria::ourShuttingDown=false;
00040 bool Aria::ourExiting=false;
00041 std::string Aria::ourDirectory="";
00042 std::list<ArFunctor*> Aria::ourInitCBs;
00043 std::list<ArFunctor*> Aria::ourUninitCBs;
00044 ArKeyHandler *Aria::ourKeyHandler = NULL;
00045 ArJoyHandler *Aria::ourJoyHandler = NULL;
00046 bool Aria::ourInited = false;
00047 bool Aria::ourRunning = false;
00048 ArMutex Aria::ourExitCallbacksMutex;
00049 std::multimap<int, ArFunctor *> Aria::ourExitCallbacks;
00050 bool Aria::ourSigHandleExitNotShutdown = true;
00051 std::multimap<int, ArRetFunctor<bool> *> Aria::ourParseArgCBs;
00052 ArLog::LogLevel Aria::ourParseArgsLogLevel = ArLog::Verbose;
00053 std::multimap<int, ArFunctor *> Aria::ourLogOptionsCBs;
00054
00055 #ifndef ARINTERFACE
00056 std::list<ArRobot*> Aria::ourRobots;
00057 ArConfig Aria::ourConfig;
00058 ArRobotJoyHandler *Aria::ourRobotJoyHandler = NULL;
00059 ArStringInfoGroup Aria::ourInfoGroup;
00060 #endif // ARINTERFACE
00061
00091 AREXPORT void Aria::init(SigHandleMethod method, bool initSockets,
00092 bool sigHandleExitNotShutdown)
00093 {
00094 std::list<ArFunctor*>::iterator iter;
00095 std::string str;
00096 char buf[1024];
00097
00098 if (ourInited == true)
00099 return;
00100
00101 ourRunning = true;
00102 #ifndef WIN32
00103 srand48(time(NULL));
00104 #endif
00105
00106 ArThread::init();
00107
00108 char* overrideSigMethod = getenv("ARIA_SIGHANDLE_METHOD");
00109 if(overrideSigMethod)
00110 {
00111 ArLog::log(ArLog::Terse, "Overriding signal handler method with %s from ARIA_SIGHANDLE_METHOD environment variable.", overrideSigMethod);
00112 if(!strcmp(overrideSigMethod, "NONE"))
00113 method = SIGHANDLE_NONE;
00114 else if(!strcmp(overrideSigMethod, "SINGLE"))
00115 method = SIGHANDLE_SINGLE;
00116 else if(!strcmp(overrideSigMethod, "THREAD"))
00117 method = SIGHANDLE_THREAD;
00118 }
00119
00120 if (method != SIGHANDLE_NONE)
00121 {
00122 ArSignalHandler::addHandlerCB(&ourSignalHandlerCB, ArListPos::LAST);
00123 ArSignalHandler::blockCommon();
00124 ArSignalHandler::handle(ArSignalHandler::SigHUP);
00125 ArSignalHandler::handle(ArSignalHandler::SigINT);
00126 ArSignalHandler::handle(ArSignalHandler::SigQUIT);
00127 ArSignalHandler::handle(ArSignalHandler::SigTERM);
00128 ArSignalHandler::handle(ArSignalHandler::SigPIPE);
00129 if (method == SIGHANDLE_SINGLE)
00130 ArSignalHandler::createHandlerNonThreaded();
00131 else if (method == SIGHANDLE_THREAD)
00132 {
00133 ArSignalHandler::blockCommonThisThread();
00134 ArSignalHandler::createHandlerThreaded();
00135 }
00136 }
00137
00138 if (initSockets)
00139 ArSocket::init();
00140
00141 if (ourDirectory.length() == 0)
00142 {
00143 if (getenv("ARIA") != NULL)
00144 {
00145 setDirectory(getenv("ARIA"));
00146 }
00147 else
00148 {
00149 #ifndef WIN32
00150 ArUtil::getStringFromFile("/etc/Aria", buf, sizeof(buf));
00151 str = buf;
00152 #else // WIN32
00153 if (ArUtil::findFirstStringInRegistry(
00154 "SOFTWARE\\MobileRobots\\Aria",
00155 "Install Directory", buf, 1024))
00156 str = buf;
00157 else
00158 if (ArUtil::findFirstStringInRegistry(
00159 "SOFTWARE\\ActivMedia Robotics\\Aria",
00160 "Install Directory", buf, 1024))
00161 str = buf;
00162 else
00163 str = "";
00164
00165 #endif // WIN32
00166 if (str.length() > 0)
00167 {
00168 setDirectory(str.c_str());
00169 }
00170 else
00171 {
00172 #ifndef ARINTERFACE
00173 ArLog::log(ArLog::Terse, "NonCritical Error: ARIA could not find where it is located.");
00174 #else
00175 ArLog::log(ArLog::Verbose, "NonCritical Error: ARIA could not find where it is located.");
00176 #endif
00177 }
00178 }
00179 }
00180 ourSigHandleExitNotShutdown = sigHandleExitNotShutdown;
00181
00182 ourInited = true;
00183 for (iter=ourInitCBs.begin(); iter != ourInitCBs.end(); ++iter)
00184 (*iter)->invoke();
00185 ArArgumentParser::addDefaultArgumentFile("/etc/Aria.args");
00186 ArArgumentParser::addDefaultArgumentEnv("ARIAARGS");
00187
00188 }
00189
00195 AREXPORT void Aria::uninit()
00196 {
00197 std::list<ArFunctor*>::iterator iter;
00198
00199 for (iter=ourUninitCBs.begin(); iter != ourUninitCBs.end(); ++iter)
00200 (*iter)->invoke();
00201
00202 #ifndef ARINTERFACE
00203 ArModuleLoader::closeAll();
00204 #endif // ARINTERFACE
00205 ArSocket::shutdown();
00206 }
00207
00212 AREXPORT void Aria::addInitCallBack(ArFunctor *cb, ArListPos::Pos position)
00213 {
00214 if (position == ArListPos::FIRST)
00215 ourInitCBs.push_front(cb);
00216 else
00217 ourInitCBs.push_back(cb);
00218 }
00219
00227 AREXPORT void Aria::addUninitCallBack(ArFunctor *cb, ArListPos::Pos position)
00228 {
00229 if (position == ArListPos::FIRST)
00230 ourUninitCBs.push_front(cb);
00231 else
00232 ourUninitCBs.push_back(cb);
00233 }
00234
00241 AREXPORT void Aria::shutdown()
00242 {
00243 bool doExit=false;
00244
00245 ourShuttingDownMutex.lock();
00246 ourRunning = false;
00247 if (ourShuttingDown)
00248 doExit=true;
00249 else
00250 ourShuttingDown=true;
00251 ourShuttingDownMutex.unlock();
00252
00253 if (doExit)
00254 return;
00255
00256 ArThread::stopAll();
00257 ArThread::joinAll();
00258 uninit();
00259 }
00260
00267 AREXPORT void Aria::exit(int exitCode)
00268 {
00269 bool doReturn = false;
00270 ourShuttingDownMutex.lock();
00271 ourRunning = false;
00272 if (ourExiting)
00273 doReturn=true;
00274 else
00275 ourExiting=true;
00276 ourShuttingDownMutex.unlock();
00277
00278 if (doReturn)
00279 return;
00280
00281 callExitCallbacks();
00282 ::exit(exitCode);
00283 }
00284
00285 AREXPORT void Aria::callExitCallbacks(void)
00286 {
00287 ourRunning = false;
00288 std::multimap<int, ArFunctor *>::reverse_iterator it;
00289
00290 ourExitCallbacksMutex.lock();
00291 ArLog::log(ArLog::Verbose, "Aria::exit: Starting exit callbacks");
00292 for (it = ourExitCallbacks.rbegin(); it != ourExitCallbacks.rend(); it++)
00293 {
00294 ArLog::log(ArLog::Verbose,
00295 "Aria::exit: Calling callback at position %d with name '%s'",
00296 (*it).first, (*it).second->getName());
00297 (*it).second->invoke();
00298 }
00299 ArLog::log(ArLog::Verbose, "Aria::exit: Finished exit callbacks");
00300 ourExitCallbacksMutex.unlock();
00301 }
00302
00303 AREXPORT void Aria::addExitCallback(ArFunctor *functor, int position)
00304 {
00305 ourExitCallbacksMutex.lock();
00306 ArLog::log(ArLog::Verbose,
00307 "Aria::addExitCallback: Adding callback at position %d with name '%s'",
00308 position, functor->getName());
00309 ourExitCallbacks.insert(std::pair<int, ArFunctor *>(position, functor));
00310 ourExitCallbacksMutex.unlock();
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00345 AREXPORT void Aria::exitOld(int exitCode)
00346 {
00347 ourRunning = false;
00348 ArThread::cancelAll();
00349 uninit();
00350 ::exit(exitCode);
00351 }
00352
00353 #ifndef ARINTERFACE
00354 AREXPORT void Aria::addRobot(ArRobot *robot)
00355 {
00356 ourRobots.push_back(robot);
00357 }
00358
00359 AREXPORT void Aria::delRobot(ArRobot *robot)
00360 {
00361 ourRobots.remove(robot);
00362 }
00363
00369 AREXPORT ArRobot *Aria::findRobot(char *name)
00370 {
00371 std::string rname;
00372 std::list<ArRobot *>::iterator it;
00373 if (name == NULL)
00374 return NULL;
00375
00376 rname = name;
00377 for (it = ourRobots.begin(); it != ourRobots.end(); it++)
00378 {
00379 if ((*it)->getName() == rname)
00380 return (*it);
00381 }
00382 return NULL;
00383
00384 }
00385
00386 AREXPORT std::list<ArRobot*> * Aria::getRobotList()
00387 {
00388 return(&ourRobots);
00389 }
00390
00391 #endif // ARINTERFACE
00392
00393 AREXPORT void Aria::signalHandlerCB(int sig)
00394 {
00395
00396
00397 if (ourSigHandleExitNotShutdown)
00398 {
00399 ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Exiting.",
00400 ArSignalHandler::nameSignal(sig));
00401 Aria::exit(0);
00402
00403
00404 ::exit(0);
00405 }
00406
00407
00408 ourShuttingDownMutex.lock();
00409 if (!ourRunning)
00410 {
00411 ourShuttingDownMutex.unlock();
00412 return;
00413 }
00414 ourShuttingDownMutex.unlock();
00415
00416
00417 ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Shutting down.",
00418 ArSignalHandler::nameSignal(sig));
00419
00420 #ifndef ARINTERFACE
00421 std::list<ArRobot*>::iterator iter;
00422 if ((sig == ArSignalHandler::SigINT) || (sig == ArSignalHandler::SigHUP) ||
00423 (sig == ArSignalHandler::SigTERM))
00424 {
00425 for (iter=ourRobots.begin(); iter != ourRobots.end(); ++iter)
00426 (*iter)->stopRunning();
00427 }
00428 #endif //ARINTERFACE
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438 shutdown();
00439 }
00440
00449 AREXPORT void Aria::setDirectory(const char *directory)
00450 {
00451 int ind;
00452 if (directory != NULL)
00453 {
00454 ourDirectory = directory;
00455 ind = strlen(directory) - 1;
00456 if (ind < 0)
00457 ind = 0;
00458 if (directory[ind] != '/' && directory[ind] != '\\')
00459 {
00460 #ifdef WIN32
00461 ourDirectory += "\\";
00462 #else // win32
00463 ourDirectory += "/";
00464 #endif // win32
00465 }
00466 #ifndef ARINTERFACE
00467 ourConfig.setBaseDirectory(ourDirectory.c_str());
00468 #endif // ARINTERFACE
00469 }
00470 }
00471
00478 AREXPORT const char *Aria::getDirectory(void)
00479 {
00480 return ourDirectory.c_str();
00481 }
00482
00484 AREXPORT void Aria::setKeyHandler(ArKeyHandler *keyHandler)
00485 {
00486 ourKeyHandler = keyHandler;
00487 }
00488
00490 AREXPORT ArKeyHandler *Aria::getKeyHandler(void)
00491 {
00492 return ourKeyHandler;
00493 }
00494
00496 AREXPORT void Aria::setJoyHandler(ArJoyHandler *joyHandler)
00497 {
00498 ourJoyHandler = joyHandler;
00499 }
00500
00502 AREXPORT ArJoyHandler *Aria::getJoyHandler(void)
00503 {
00504 return ourJoyHandler;
00505 }
00506
00507 #ifndef ARINTERFACE
00508
00509 AREXPORT void Aria::setRobotJoyHandler(ArRobotJoyHandler *robotJoyHandler)
00510 {
00511 ourRobotJoyHandler = robotJoyHandler;
00512 }
00513
00515 AREXPORT ArRobotJoyHandler *Aria::getRobotJoyHandler(void)
00516 {
00517 return ourRobotJoyHandler;
00518 }
00519
00523 AREXPORT ArConfig *Aria::getConfig(void)
00524 {
00525 return &ourConfig;
00526 }
00527
00531 AREXPORT ArStringInfoGroup *Aria::getInfoGroup(void)
00532 {
00533 return &ourInfoGroup;
00534 }
00535
00536 #endif // ARINTERFACE
00537
00543 AREXPORT bool Aria::getRunning(void)
00544 {
00545 return ourRunning;
00546 }
00547
00548 AREXPORT bool Aria::parseArgs(void)
00549 {
00550 std::multimap<int, ArRetFunctor<bool> *>::reverse_iterator it;
00551 ArRetFunctor<bool> *callback;
00552
00553 ArLog::log(ourParseArgsLogLevel, "Aria: Parsing arguments");
00554 for (it = ourParseArgCBs.rbegin(); it != ourParseArgCBs.rend(); it++)
00555 {
00556 callback = (*it).second;
00557 if (callback->getName() != NULL && callback->getName()[0] != '\0')
00558 ArLog::log(ourParseArgsLogLevel,
00559 "Aria: Calling parse arg functor '%s' (%d)",
00560 callback->getName(), (*it).first);
00561 else
00562 ArLog::log(ourParseArgsLogLevel,
00563 "Aria: Calling unnamed parse arg functor (%d)",
00564 (*it).first);
00565
00566 if (!callback->invokeR())
00567 {
00568 return false;
00569 }
00570 }
00571 return true;
00572 }
00573
00574 AREXPORT void Aria::logOptions(void)
00575 {
00576 std::multimap<int, ArFunctor *>::reverse_iterator it;
00577
00578 for (it = ourLogOptionsCBs.rbegin(); it != ourLogOptionsCBs.rend(); it++)
00579 {
00580 (*it).second->invoke();
00581 ArLog::log(ArLog::Terse, "");
00582 ArLog::log(ArLog::Terse, "");
00583 }
00584 }
00585
00586 AREXPORT void Aria::addParseArgsCB(ArRetFunctor<bool> *functor,
00587 int position)
00588 {
00589 ourParseArgCBs.insert(std::pair<int, ArRetFunctor<bool> *>(position,
00590 functor));
00591 }
00592
00593 AREXPORT void Aria::setParseArgLogLevel(ArLog::LogLevel level)
00594 {
00595 ourParseArgsLogLevel = level;
00596 }
00597
00598 AREXPORT void Aria::addLogOptionsCB(ArFunctor *functor, int position)
00599 {
00600 ourLogOptionsCBs.insert(std::pair<int, ArFunctor *>(position, functor));
00601 }
00602
00603