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
00027 #include "ArExport.h"
00028 #include "Aria.h"
00029 #include "ArSocket.h"
00030 #include "ArSignalHandler.h"
00031 #include "ArModuleLoader.h"
00032 #include "ArKeyHandler.h"
00033 #include "ArJoyHandler.h"
00034 #include "ArRobotJoyHandler.h"
00035
00036 ArGlobalFunctor1<int> Aria::ourSignalHandlerCB(&Aria::signalHandlerCB);
00037 std::list<ArRobot*> Aria::ourRobots;
00038 ArMutex Aria::ourShuttingDownMutex;
00039 bool Aria::ourShuttingDown=false;
00040 std::string Aria::ourDirectory="";
00041 std::list<ArFunctor*> Aria::ourInitCBs;
00042 std::list<ArFunctor*> Aria::ourUninitCBs;
00043 ArKeyHandler *Aria::ourKeyHandler = NULL;
00044 ArJoyHandler *Aria::ourJoyHandler = NULL;
00045 ArRobotJoyHandler *Aria::ourRobotJoyHandler = NULL;
00046 bool Aria::ourInited = false;
00047 bool Aria::ourRunning = false;
00048 ArConfig Aria::ourConfig;
00049 ArMutex Aria::ourExitCallbacksMutex;
00050 std::multimap<int, ArFunctor *> Aria::ourExitCallbacks;
00051 bool Aria::ourSigHandleExitNotShutdown = true;
00052
00083 void Aria::init(SigHandleMethod method, bool initSockets,
00084 bool sigHandleExitNotShutdown)
00085 {
00086 std::list<ArFunctor*>::iterator iter;
00087 std::string str;
00088 char buf[1024];
00089
00090 if (ourInited == true)
00091 return;
00092
00093 ourRunning = true;
00094 #ifndef WIN32
00095 srand48(time(NULL));
00096 #endif
00097
00098 ArThread::init();
00099
00100 char* overrideSigMethod = getenv("ARIA_SIGHANDLE_METHOD");
00101 if(overrideSigMethod)
00102 {
00103 ArLog::log(ArLog::Terse, "Overriding signal handler method with %s from ARIA_SIGHANDLE_METHOD environment variable.", overrideSigMethod);
00104 if(!strcmp(overrideSigMethod, "NONE"))
00105 method = SIGHANDLE_NONE;
00106 else if(!strcmp(overrideSigMethod, "SINGLE"))
00107 method = SIGHANDLE_SINGLE;
00108 else if(!strcmp(overrideSigMethod, "THREAD"))
00109 method = SIGHANDLE_THREAD;
00110 }
00111
00112 if (method != SIGHANDLE_NONE)
00113 {
00114 ArSignalHandler::addHandlerCB(&ourSignalHandlerCB, ArListPos::LAST);
00115 ArSignalHandler::blockCommon();
00116 ArSignalHandler::handle(ArSignalHandler::SigHUP);
00117 ArSignalHandler::handle(ArSignalHandler::SigINT);
00118 ArSignalHandler::handle(ArSignalHandler::SigQUIT);
00119 ArSignalHandler::handle(ArSignalHandler::SigTERM);
00120 ArSignalHandler::handle(ArSignalHandler::SigPIPE);
00121 if (method == SIGHANDLE_SINGLE)
00122 ArSignalHandler::createHandlerNonThreaded();
00123 else if (method == SIGHANDLE_THREAD)
00124 {
00125 ArSignalHandler::blockCommonThisThread();
00126 ArSignalHandler::createHandlerThreaded();
00127 }
00128 }
00129
00130 if (initSockets)
00131 ArSocket::init();
00132
00133 if (ourDirectory.length() == 0)
00134 {
00135 if (getenv("ARIA") != NULL)
00136 {
00137 setDirectory(getenv("ARIA"));
00138 }
00139 else
00140 {
00141 #ifndef WIN32
00142 ArUtil::getStringFromFile("/etc/Aria", buf, sizeof(buf));
00143 str = buf;
00144 #else // WIN32
00145 if (ArUtil::findFirstStringInRegistry(
00146 "SOFTWARE\\ActivMedia Robotics\\Aria",
00147 "Install Directory", buf, 1024))
00148 str = buf;
00149 else
00150 str = "";
00151
00152 #endif // WIN32
00153 if (str.length() > 0)
00154 {
00155 setDirectory(str.c_str());
00156 }
00157 else
00158 {
00159 ArLog::log(ArLog::Terse, "NonCritical Error: ARIA could not find where it is located.");
00160 }
00161 }
00162 }
00163 ourSigHandleExitNotShutdown = sigHandleExitNotShutdown;
00164
00165 ourInited = true;
00166 for (iter=ourInitCBs.begin(); iter != ourInitCBs.end(); ++iter)
00167 (*iter)->invoke();
00168 ArArgumentParser::addDefaultArgumentFile("/etc/Aria.args");
00169 ArArgumentParser::addDefaultArgumentEnv("ARIAARGS");
00170
00171 }
00172
00178 void Aria::uninit()
00179 {
00180 std::list<ArFunctor*>::iterator iter;
00181
00182 for (iter=ourUninitCBs.begin(); iter != ourUninitCBs.end(); ++iter)
00183 (*iter)->invoke();
00184
00185 ArModuleLoader::closeAll();
00186 ArSocket::shutdown();
00187 }
00188
00193 void Aria::addInitCallBack(ArFunctor *cb, ArListPos::Pos position)
00194 {
00195 if (position == ArListPos::FIRST)
00196 ourInitCBs.push_front(cb);
00197 else
00198 ourInitCBs.push_back(cb);
00199 }
00200
00208 void Aria::addUninitCallBack(ArFunctor *cb, ArListPos::Pos position)
00209 {
00210 if (position == ArListPos::FIRST)
00211 ourUninitCBs.push_front(cb);
00212 else
00213 ourUninitCBs.push_back(cb);
00214 }
00215
00222 void Aria::shutdown()
00223 {
00224 bool doExit=false;
00225
00226 ourShuttingDownMutex.lock();
00227 ourRunning = false;
00228 if (ourShuttingDown)
00229 doExit=true;
00230 else
00231 ourShuttingDown=true;
00232 ourShuttingDownMutex.unlock();
00233
00234 if (doExit)
00235 return;
00236
00237 ArThread::stopAll();
00238 ArThread::joinAll();
00239 uninit();
00240 }
00241
00248 void Aria::exit(int exitCode)
00249 {
00250 bool doReturn = false;
00251 ourShuttingDownMutex.lock();
00252 ourRunning = false;
00253 if (ourShuttingDown)
00254 doReturn=true;
00255 else
00256 ourShuttingDown=true;
00257 ourShuttingDownMutex.unlock();
00258
00259 if (doReturn)
00260 return;
00261
00262 callExitCallbacks();
00263 ::exit(exitCode);
00264 }
00265
00266 void Aria::callExitCallbacks(void)
00267 {
00268 ourRunning = false;
00269 std::multimap<int, ArFunctor *>::reverse_iterator it;
00270
00271 ourExitCallbacksMutex.lock();
00272 ArLog::log(ArLog::Verbose, "Aria::exit: Starting exit callbacks");
00273 for (it = ourExitCallbacks.rbegin(); it != ourExitCallbacks.rend(); it++)
00274 {
00275 ArLog::log(ArLog::Verbose,
00276 "Aria::exit: Calling callback at position %d with name '%s'",
00277 (*it).first, (*it).second->getName());
00278 (*it).second->invoke();
00279 }
00280 ArLog::log(ArLog::Verbose, "Aria::exit: Finished exit callbacks");
00281 ourExitCallbacksMutex.unlock();
00282 }
00283
00284 void Aria::addExitCallback(ArFunctor *functor, int position)
00285 {
00286 ourExitCallbacksMutex.lock();
00287 ArLog::log(ArLog::Verbose,
00288 "Aria::addExitCallback: Adding callback at position %d with name '%s'",
00289 position, functor->getName());
00290 ourExitCallbacks.insert(std::pair<int, ArFunctor *>(position, functor));
00291 ourExitCallbacksMutex.unlock();
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00326 void Aria::exitOld(int exitCode)
00327 {
00328 ourRunning = false;
00329 ArThread::cancelAll();
00330 uninit();
00331 ::exit(exitCode);
00332 }
00333
00334 void Aria::addRobot(ArRobot *robot)
00335 {
00336 ourRobots.push_back(robot);
00337 }
00338
00339 void Aria::delRobot(ArRobot *robot)
00340 {
00341 ourRobots.remove(robot);
00342 }
00343
00349 ArRobot *Aria::findRobot(char *name)
00350 {
00351 std::string rname;
00352 std::list<ArRobot *>::iterator it;
00353 if (name == NULL)
00354 return NULL;
00355
00356 rname = name;
00357 for (it = ourRobots.begin(); it != ourRobots.end(); it++)
00358 {
00359 if ((*it)->getName() == rname)
00360 return (*it);
00361 }
00362 return NULL;
00363
00364 }
00365
00366 std::list<ArRobot*> * Aria::getRobotList()
00367 {
00368 return(&ourRobots);
00369 }
00370
00371 void Aria::signalHandlerCB(int sig)
00372 {
00373 std::list<ArRobot*>::iterator iter;
00374
00375
00376 if (ourSigHandleExitNotShutdown)
00377 {
00378 ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Exiting.",
00379 ArSignalHandler::nameSignal(sig));
00380 Aria::exit(0);
00381 }
00382
00383
00384 ourShuttingDownMutex.lock();
00385 if (!ourRunning)
00386 {
00387 ourShuttingDownMutex.unlock();
00388 return;
00389 }
00390 ourShuttingDownMutex.unlock();
00391
00392
00393 ArLog::log(ArLog::Normal, "Aria: Received signal '%s'. Shutting down.",
00394 ArSignalHandler::nameSignal(sig));
00395 if ((sig == ArSignalHandler::SigINT) || (sig == ArSignalHandler::SigHUP) ||
00396 (sig == ArSignalHandler::SigTERM))
00397 {
00398 for (iter=ourRobots.begin(); iter != ourRobots.end(); ++iter)
00399 (*iter)->stopRunning();
00400 }
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410 shutdown();
00411 }
00412
00421 void Aria::setDirectory(const char *directory)
00422 {
00423 int ind;
00424 if (directory != NULL)
00425 {
00426 ourDirectory = directory;
00427 ind = strlen(directory) - 1;
00428 if (ind < 0)
00429 ind = 0;
00430 if (directory[ind] != '/' && directory[ind] != '\\')
00431 {
00432 #ifdef WIN32
00433 ourDirectory += "\\";
00434 #else // win32
00435 ourDirectory += "/";
00436 #endif // win32
00437 }
00438 ourConfig.setBaseDirectory(ourDirectory.c_str());
00439 }
00440 }
00441
00448 const char *Aria::getDirectory(void)
00449 {
00450 return ourDirectory.c_str();
00451 }
00452
00454 void Aria::setKeyHandler(ArKeyHandler *keyHandler)
00455 {
00456 ourKeyHandler = keyHandler;
00457 }
00458
00460 ArKeyHandler *Aria::getKeyHandler(void)
00461 {
00462 return ourKeyHandler;
00463 }
00464
00466 void Aria::setJoyHandler(ArJoyHandler *joyHandler)
00467 {
00468 ourJoyHandler = joyHandler;
00469 }
00470
00472 ArJoyHandler *Aria::getJoyHandler(void)
00473 {
00474 return ourJoyHandler;
00475 }
00476
00477
00479 void Aria::setRobotJoyHandler(ArRobotJoyHandler *robotJoyHandler)
00480 {
00481 ourRobotJoyHandler = robotJoyHandler;
00482 }
00483
00485 ArRobotJoyHandler *Aria::getRobotJoyHandler(void)
00486 {
00487 return ourRobotJoyHandler;
00488 }
00489
00495 bool Aria::getRunning(void)
00496 {
00497 return ourRunning;
00498 }
00499
00503 ArConfig *Aria::getConfig(void)
00504 {
00505 return &ourConfig;
00506 }
00507
00508