Mixe for Privacy and Anonymity in the Internet
CAStatusManager.cpp
Go to the documentation of this file.
00001 /*
00002 Copyright (c) The JAP-Team, JonDos GmbH
00003 
00004 All rights reserved.
00005 
00006 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice,
00010        this list of conditions and the following disclaimer in the documentation and/or
00011        other materials provided with the distribution.
00012     * Neither the name of the University of Technology Dresden, Germany, nor the name of
00013        the JonDos GmbH, nor the names of their contributors may be used to endorse or
00014        promote products derived from this software without specific prior written permission.
00015 
00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00017 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00018 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00019 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
00020 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00021 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00022 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00023 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00024 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00025 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027 */
00028 
00029 #include "CAStatusManager.hpp"
00030 
00031 #ifdef SERVER_MONITORING
00032 
00033 #include "CAMsg.hpp"
00034 #include "CAMutex.hpp"
00035 #include "CAUtil.hpp"
00036 #include "xml/DOM_Output.hpp"
00037 #include "CALibProxytest.hpp"
00038 #include "monitoringDefs.h"
00039 
00046 CAStatusManager *CAStatusManager::ms_pStatusManager = NULL;
00047 state_t ***CAStatusManager::ms_pAllStates = NULL;
00048 event_t ***CAStatusManager::ms_pAllEvents = NULL;
00049 
00050 void CAStatusManager::init()
00051 {
00052   if(ms_pAllEvents == NULL)
00053   {
00054     initEvents();
00055   }
00056   if(ms_pAllStates == NULL)
00057   {
00058     initStates();
00059   }
00060   if(ms_pStatusManager == NULL)
00061   {
00062     ms_pStatusManager = new CAStatusManager();
00063   }
00064 }
00065 
00066 void CAStatusManager::cleanup()
00067 {
00068 #ifdef DEBUG
00069   CAMsg::printMsg(LOG_DEBUG,
00070         "CAStatusManager: doing cleanup\n");
00071 #endif
00072   /*if(ms_pStatusManager->m_pStatusSocket != NULL)
00073   {
00074     if(!(ms_pStatusManager->m_pStatusSocket->isClosed()))
00075     {
00076       ms_pStatusManager->m_pStatusSocket->close();
00077     }
00078   }*/
00079 
00080   if(ms_pStatusManager != NULL)
00081   {
00082     delete ms_pStatusManager;
00083     ms_pStatusManager = NULL;
00084   }
00085   if(ms_pAllStates != NULL)
00086   {
00087     deleteStates();
00088   }
00089   if(ms_pAllEvents != NULL)
00090   {
00091     deleteEvents();
00092   }
00093 }
00094 
00095 SINT32 CAStatusManager::fireEvent(event_type_t e_type, enum status_type s_type)
00096 {
00097   if(ms_pStatusManager != NULL)
00098   {
00099     return ms_pStatusManager->transition(e_type, s_type);
00100   }
00101   else
00102   {
00103     CAMsg::printMsg(LOG_CRIT,
00104         "StatusManager: cannot handle event %d/%d "
00105         "because there is no StatusManager deployed\n",
00106         s_type, e_type);
00107     return E_UNKNOWN;
00108   }
00109 }
00110 
00111 CAStatusManager::CAStatusManager()
00112 {
00113   int i = 0, ret = 0;
00114   m_pCurrentStates = NULL;
00115   m_pCurrentStatesInfo = NULL;
00116   m_pStatusLock = NULL;
00117   m_pStatusSocket = NULL;
00118   m_pListenAddr = NULL;
00119   m_pMonitoringThread = NULL;
00120   m_pPreparedStatusMessage = NULL;
00121   m_bTryListen = false;
00122 
00123   m_pCurrentStates = new state_t*[NR_STATUS_TYPES];
00124 
00125   for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00126   {
00127     m_pCurrentStates[i] =
00128         ms_pAllStates[i][ENTRY_STATE];
00129 #ifdef DEBUG
00130     CAMsg::printMsg(LOG_DEBUG, "Init state: %s - %s\n", STATUS_NAMES[i],
00131             m_pCurrentStates[i]->st_description);
00132 #endif
00133   }
00134 
00135   m_pStatusLock = new CAMutex();
00136   m_pStatusSocket = new CASocket();
00137   ret = initSocket();
00138   if( (ret == E_SUCCESS))
00139   {
00140     m_pMonitoringThread = new CAThread((UINT8*)"Monitoring Thread");
00141     m_pMonitoringThread->setMainLoop(serveMonitoringRequests);
00142     m_pMonitoringThread->start(this);
00143   }
00144   else
00145   {
00146     CAMsg::printMsg(LOG_ERR,
00147           "StatusManager: an error occured while initializing the"
00148           " server monitoring socket\n");
00149   }
00150   initStatusMessage();
00151   /* pass entry state staus information to the DOM structure */
00152   for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00153   {
00154     setDOMElementValue(
00155         (m_pCurrentStatesInfo[i]).dsi_stateType,
00156         (UINT32)(m_pCurrentStates[i])->st_type);
00157     setDOMElementValue(
00158         (m_pCurrentStatesInfo[i]).dsi_stateDesc,
00159         (UINT8*)(m_pCurrentStates[i])->st_description);
00160     setDOMElementValue(
00161         (m_pCurrentStatesInfo[i]).dsi_stateLevel,
00162         (UINT8*)(STATUS_LEVEL_NAMES[(m_pCurrentStates[i])->st_stateLevel]));
00163   }
00164 }
00165 
00166 CAStatusManager::~CAStatusManager()
00167 {
00168   int i = 0;
00169   if(m_pMonitoringThread != NULL)
00170   {
00171     if(m_pStatusSocket != NULL)
00172     {
00173       if( !(m_pStatusSocket->isClosed()) )
00174       {
00175         m_pStatusSocket->close();
00176       }
00177     }
00178 
00179     delete m_pMonitoringThread;
00180 #ifdef DEBUG
00181     CAMsg::printMsg(LOG_DEBUG,
00182         "CAStatusManager: The monitoring thread is no more.\n");
00183 #endif
00184     m_pMonitoringThread = NULL;
00185   }
00186   if(m_pStatusLock != NULL)
00187   {
00188     delete m_pStatusLock;
00189     m_pStatusLock = NULL;
00190   }
00191   if(m_pCurrentStates != NULL)
00192   {
00193     for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00194     {
00195       m_pCurrentStates[i] = NULL;
00196     }
00197     delete[] m_pCurrentStates;
00198     m_pCurrentStates = NULL;
00199   }
00200   if(m_pStatusSocket != NULL)
00201   {
00202     delete m_pStatusSocket;
00203     m_pStatusSocket = NULL;
00204   }
00205   if(m_pListenAddr != NULL)
00206   {
00207     delete m_pListenAddr;
00208     m_pListenAddr = NULL;
00209   }
00210   if(m_pPreparedStatusMessage != NULL)
00211   {
00212     m_pPreparedStatusMessage->release();
00213     m_pPreparedStatusMessage = NULL;
00214   }
00215 }
00216 SINT32 CAStatusManager::initSocket()
00217 {
00218   SINT32 ret = E_UNKNOWN;
00219   int errnum = 0;
00220 
00221   if(m_pStatusSocket == NULL)
00222   {
00223     m_pStatusSocket = new CASocket();
00224   }
00225 
00226   if( !(m_pStatusSocket->isClosed()) )
00227   {
00228     CAMsg::printMsg(LOG_ERR,
00229         "StatusManager: server monitoring socket already connected.\n");
00230     return E_UNKNOWN;
00231   }
00232 
00233   ret = m_pStatusSocket->create();
00234   if(ret != E_SUCCESS)
00235   {
00236     CAMsg::printMsg(LOG_ERR,
00237         "StatusManager: could not create server monitoring socket.\n");
00238     return ret;
00239   }
00240   m_pStatusSocket->setReuseAddr(true);
00241   /* listen to default server address, if nothing is specified:
00242    * localhost:8080
00243    */
00244   char *hostname = "localhost";
00245   UINT16 port = MONITORING_SERVER_PORT;
00246   bool userdefined = false;
00247 
00248   if(CALibProxytest::getOptions()->getMonitoringListenerHost()!= NULL)
00249   {
00250     hostname = CALibProxytest::getOptions()->getMonitoringListenerHost();
00251     userdefined = true;
00252   }
00253   if(CALibProxytest::getOptions()->getMonitoringListenerPort()!= 0xFFFF)
00254   {
00255     port = CALibProxytest::getOptions()->getMonitoringListenerPort();
00256     userdefined = true;
00257   }
00258 
00259   m_pListenAddr = new CASocketAddrINet();
00260   ret = m_pListenAddr->setAddr((UINT8 *) hostname, port);
00261   if(ret != E_SUCCESS)
00262   {
00263     if(ret == E_UNKNOWN_HOST)
00264     {
00265       CAMsg::printMsg(LOG_ERR,
00266             "StatusManager: could not initialize specified listener interface:"
00267             " invalid host %s\n", hostname);
00268       if(userdefined)
00269       {
00270         hostname = "localhost";
00271         CAMsg::printMsg(LOG_ERR,
00272             "StatusManager: trying %s.\n", hostname);
00273 
00274         ret = m_pListenAddr->setAddr((UINT8 *) hostname, port);
00275         if(ret != E_SUCCESS)
00276         {
00277           CAMsg::printMsg(LOG_ERR,
00278                 "StatusManager: setting up listener interface %s:%d for "
00279                 "server monitoring failed\n",
00280                 hostname, port);
00281           return ret;
00282         }
00283       }
00284     }
00285     else
00286     {
00287       CAMsg::printMsg(LOG_ERR,
00288             "StatusManager: setting up listener interface %s:%d for "
00289             "server monitoring failed\n",
00290             hostname, port);
00291       return ret;
00292     }
00293   }
00294   ret = m_pStatusSocket->listen(*m_pListenAddr);
00295 
00296   if(ret != E_SUCCESS)
00297   {
00298     if(ret != E_UNKNOWN)
00299     {
00300       errnum = GET_NET_ERROR;
00301       CAMsg::printMsg(LOG_ERR,
00302           "StatusManager: not able to init server socket %s:%d "
00303           "for server monitoring. %s failed because: %s\n",
00304           hostname, port,
00305           ((ret == E_SOCKET_BIND) ? "Bind" : "Listen"),
00306            GET_NET_ERROR_STR(errnum));
00307     }
00308     return ret;
00309   }
00310 #ifdef DEBUG
00311   CAMsg::printMsg(LOG_DEBUG,
00312         "StatusManager: listen to monitoring socket on %s:%d\n",
00313           hostname, port);
00314 #endif
00315   return E_SUCCESS;
00316 }
00317 
00318 SINT32 CAStatusManager::transition(event_type_t e_type, status_type_t s_type)
00319 {
00320   transition_t transitionToNextState = st_ignore;
00321   state_t *prev = NULL;
00322 
00323   if( (m_pStatusLock == NULL) ||
00324     (m_pCurrentStates == NULL) )
00325   {
00326     CAMsg::printMsg(LOG_CRIT,
00327         "StatusManager: fatal error\n");
00328     return E_UNKNOWN;
00329   }
00330   if((s_type >= NR_STATUS_TYPES) || (s_type < FIRST_STATUS))
00331   {
00332     CAMsg::printMsg(LOG_ERR,
00333         "StatusManager: received event for an invalid status type: %d\n", s_type);
00334     return E_INVALID;
00335   }
00336   if((e_type >= EVENT_COUNT[s_type]) || (e_type < FIRST_EVENT))
00337   {
00338     CAMsg::printMsg(LOG_ERR,
00339         "StatusManager: received an invalid event: %d\n", e_type);
00340     return E_INVALID;
00341   }
00342 
00343   /* We process incoming events synchronously, so the calling thread
00344    * should perform state transition very quickly to avoid long blocking
00345    * of other calling threads
00346    */
00347   m_pStatusLock->lock();
00348   if(m_pCurrentStates[s_type]->st_transitions == NULL)
00349   {
00350     m_pStatusLock->unlock();
00351     CAMsg::printMsg(LOG_CRIT,
00352             "StatusManager: current state is corrupt\n");
00353     return E_UNKNOWN;
00354   }
00355   transitionToNextState = m_pCurrentStates[s_type]->st_transitions[e_type];
00356   if(transitionToNextState >= STATE_COUNT[s_type])
00357   {
00358     m_pStatusLock->unlock();
00359     CAMsg::printMsg(LOG_ERR,
00360             "StatusManager: transition to invalid state %d\n", transitionToNextState);
00361     return E_INVALID;
00362   }
00363   if(transitionToNextState != st_ignore)
00364   {
00365     prev = m_pCurrentStates[s_type];
00366     m_pCurrentStates[s_type] = ms_pAllStates[s_type][transitionToNextState];
00367     m_pCurrentStates[s_type]->st_prev = prev;
00368     m_pCurrentStates[s_type]->st_cause = ms_pAllEvents[s_type][e_type];
00369 
00370     /* setting the xml elements of the info message won't be too expensive */
00371     setDOMElementValue(
00372         (m_pCurrentStatesInfo[s_type]).dsi_stateType,
00373         (UINT32)(m_pCurrentStates[s_type])->st_type);
00374     setDOMElementValue(
00375         (m_pCurrentStatesInfo[s_type]).dsi_stateDesc,
00376         (UINT8*)(m_pCurrentStates[s_type])->st_description);
00377     setDOMElementValue(
00378         (m_pCurrentStatesInfo[s_type]).dsi_stateLevel,
00379         (UINT8*)(STATUS_LEVEL_NAMES[(m_pCurrentStates[s_type])->st_stateLevel]));
00380 #ifdef DEBUG
00381     CAMsg::printMsg(LOG_DEBUG,
00382         "StatusManager: status %s: "
00383         "transition from state %d (%s) "
00384         "to state %d (%s) caused by event %d (%s)\n",
00385         STATUS_NAMES[s_type],
00386         prev->st_type, prev->st_description,
00387         m_pCurrentStates[s_type]->st_type, m_pCurrentStates[s_type]->st_description,
00388         e_type, (ms_pAllEvents[s_type][e_type])->ev_description);
00389 #endif
00390   }
00391   m_pStatusLock->unlock();
00392   return E_SUCCESS;
00393 }
00394 
00395 /* prepares (once) a DOM template for all status messages */
00396 SINT32 CAStatusManager::initStatusMessage()
00397 {
00398   int i = 0;
00399   m_pPreparedStatusMessage = createDOMDocument();
00400   m_pCurrentStatesInfo = new dom_state_info[NR_STATUS_TYPES];
00401   DOMElement *elemRoot = createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATUS_MESSAGE_NAME);
00402   DOMElement *status_dom_element = NULL;
00403 
00404   for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00405   {
00406     status_dom_element =
00407       createDOMElement(m_pPreparedStatusMessage, STATUS_NAMES[i]);
00408     (m_pCurrentStatesInfo[i]).dsi_stateType =
00409       createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATE_NAME);
00410 #ifdef DEBUG
00411     setDOMElementValue((m_pCurrentStatesInfo[i]).dsi_stateType, (UINT8*)"Statenumber");
00412 #endif
00413     (m_pCurrentStatesInfo[i]).dsi_stateLevel =
00414       createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATE_LEVEL_NAME);
00415 #ifdef DEBUG
00416     setDOMElementValue((m_pCurrentStatesInfo[i]).dsi_stateLevel, (UINT8*)"OK or Critcal or something");
00417 #endif
00418     (m_pCurrentStatesInfo[i]).dsi_stateDesc =
00419       createDOMElement(m_pPreparedStatusMessage, DOM_ELEMENT_STATE_DESCRIPTION_NAME);
00420 #ifdef DEBUG
00421     setDOMElementValue((m_pCurrentStatesInfo[i]).dsi_stateDesc, (UINT8*)"Description of the state");
00422 #endif
00423     status_dom_element->appendChild((m_pCurrentStatesInfo[i]).dsi_stateType);
00424     status_dom_element->appendChild((m_pCurrentStatesInfo[i]).dsi_stateLevel);
00425     status_dom_element->appendChild((m_pCurrentStatesInfo[i]).dsi_stateDesc);
00426     elemRoot->appendChild(status_dom_element);
00427   }
00428   m_pPreparedStatusMessage->appendChild(elemRoot);
00429 #ifdef DEBUG
00430   UINT32 debuglen = XML_STATUS_MESSAGE_MAX_SIZE - 1;
00431   UINT8 debugout[XML_STATUS_MESSAGE_MAX_SIZE];
00432   memset(debugout, 0, (sizeof(UINT8)*XML_STATUS_MESSAGE_MAX_SIZE));
00433   DOM_Output::dumpToMem(m_pPreparedStatusMessage,debugout,&debuglen);
00434   CAMsg::printMsg(LOG_DEBUG, "the status message template looks like this: %s \n",debugout);
00435 #endif
00436   return E_SUCCESS;
00437 }
00438 
00439 THREAD_RETURN serveMonitoringRequests(void* param)
00440 {
00441   CASocket monitoringRequestSocket;
00442   int ret = 0;
00443   CAStatusManager *statusManager = (CAStatusManager*) param;
00444 
00445   if(statusManager == NULL)
00446   {
00447     CAMsg::printMsg(LOG_CRIT,
00448         "Monitoring Thread: fatal error, exiting.\n");
00449     THREAD_RETURN_ERROR;
00450   }
00451 
00452   for(;EVER;)
00453   {
00454 
00455     if(statusManager->m_pStatusSocket != NULL)
00456     {
00457       if(statusManager->m_pStatusSocket->isClosed())
00458       {
00459         CAMsg::printMsg(LOG_INFO,
00460               "Monitoring Thread: server socket closed, leaving loop.\n");
00461         THREAD_RETURN_SUCCESS;
00462       }
00463     }
00464     else
00465     {
00466       CAMsg::printMsg(LOG_ERR,
00467             "Monitoring Thread: server socket disposed, leaving loop.\n");
00468       THREAD_RETURN_ERROR;
00469     }
00470 
00471     if(statusManager->m_pStatusSocket->accept(monitoringRequestSocket) == E_SUCCESS)
00472     {
00473       UINT32 xmlStatusMessageLength = XML_STATUS_MESSAGE_MAX_SIZE - 1;
00474       char xmlStatusMessage[XML_STATUS_MESSAGE_MAX_SIZE];
00475       memset(xmlStatusMessage, 0, (sizeof(char)*XML_STATUS_MESSAGE_MAX_SIZE));
00476       statusManager->m_pStatusLock->lock();
00477       DOM_Output::dumpToMem(
00478           statusManager->m_pPreparedStatusMessage,
00479           (UINT8*)xmlStatusMessage,
00480           &xmlStatusMessageLength);
00481       statusManager->m_pStatusLock->unlock();
00482 
00483       char http_prefix[HTTP_ANSWER_PREFIX_MAX_LENGTH];
00484       memset(http_prefix, 0, (sizeof(char)*HTTP_ANSWER_PREFIX_MAX_LENGTH));
00485       snprintf(http_prefix, HTTP_ANSWER_PREFIX_MAX_LENGTH,
00486           HTTP_ANSWER_PREFIX_FORMAT, xmlStatusMessageLength);
00487       size_t http_prefix_length = strlen(http_prefix);
00488 
00489       char statusMessageResponse[http_prefix_length+xmlStatusMessageLength+1];
00490       strncpy(statusMessageResponse, http_prefix, http_prefix_length);
00491       strncpy((statusMessageResponse+http_prefix_length), xmlStatusMessage, xmlStatusMessageLength);
00492       statusMessageResponse[xmlStatusMessageLength+http_prefix_length]=0;
00493 
00494 #ifdef DEBUG
00495       CAMsg::printMsg(LOG_DEBUG, "the status message looks like this: %s \n",statusMessageResponse);
00496 #endif
00497 
00498       if(monitoringRequestSocket.send((UINT8*)statusMessageResponse,
00499                       (http_prefix_length+xmlStatusMessageLength)) < 0)
00500       {
00501         CAMsg::printMsg(LOG_ERR,
00502             "StatusManager: error: could not send status message.\n");
00503       }
00504       monitoringRequestSocket.close();
00505     }
00506     else
00507     {
00508       SINT32 errnum = GET_NET_ERROR;
00509       CAMsg::printMsg(LOG_ERR,
00510           "StatusManager: error: could not process monitoring request: %s\n", GET_NET_ERROR_STR(errnum));
00511       switch (errnum)
00512       {
00513         //case ECONNABORTED:
00514         case EBADF:
00515         case EINVAL:
00516           THREAD_RETURN_ERROR;
00517       }
00518     }
00519   }
00520 }
00521 
00522 void CAStatusManager::initStates()
00523 {
00524   int i = 0, j = 0;
00525   ms_pAllStates = new state_t**[NR_STATUS_TYPES];
00526 
00527   for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00528   {
00529     ms_pAllStates[i] =
00530       new state_t*[STATE_COUNT[i]];
00531 
00532     for(j = ENTRY_STATE; j < STATE_COUNT[i]; j++)
00533     {
00534       ms_pAllStates[i][j] = new state_t;
00535       /* only state identifier are set, transitions and state description
00536        * must be set via macro
00537        **/
00538       ms_pAllStates[i][j]->st_type = (state_type_t) j;
00539       ms_pAllStates[i][j]->st_statusType = (status_type_t) i;
00540     }
00541   }
00542   FINISH_STATE_DEFINITIONS(ms_pAllStates);
00543 
00544 }
00545 
00546 void CAStatusManager::deleteStates()
00547 {
00548   int i = 0, j = 0;
00549 
00550   for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00551   {
00552     for(j = ENTRY_STATE; j < STATE_COUNT[i]; j++)
00553     {
00554       if(ms_pAllStates[i][j] != NULL)
00555       {
00556         if(ms_pAllStates[i][j]->st_transitions != NULL)
00557         {
00558           delete[] ms_pAllStates[i][j]->st_transitions;
00559           ms_pAllStates[i][j]->st_transitions = NULL;
00560         }
00561         delete ms_pAllStates[i][j];
00562         ms_pAllStates[i][j] = NULL;
00563       }
00564     }
00565     delete[] ms_pAllStates[i];
00566     ms_pAllStates[i] = NULL;
00567   }
00568   delete[] ms_pAllStates;
00569   ms_pAllStates = NULL;
00570 }
00571 
00572 void CAStatusManager::initEvents()
00573 {
00574   int i = 0, j = 0;
00575   ms_pAllEvents = new event_t**[NR_STATUS_TYPES];
00576 
00577   for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00578   {
00579     ms_pAllEvents[i] = new event_t*[EVENT_COUNT[i]];
00580     for(j = FIRST_EVENT; j < EVENT_COUNT[i]; j++)
00581     {
00582       ms_pAllEvents[i][j] = new event_t;
00583       ms_pAllEvents[i][j]->ev_type = (event_type_t) j;
00584       ms_pAllEvents[i][j]->ev_statusType = (status_type_t) i;
00585     }
00586   }
00587   FINISH_EVENT_DEFINITIONS(ms_pAllEvents);
00588 }
00589 
00590 void CAStatusManager::deleteEvents()
00591 {
00592   int i = 0, j = 0;
00593 
00594   for(i = FIRST_STATUS; i < NR_STATUS_TYPES; i++)
00595   {
00596     for(j = FIRST_EVENT; j < EVENT_COUNT[i]; j++)
00597     {
00598       delete ms_pAllEvents[i][j];
00599       ms_pAllEvents[i][j] = NULL;
00600     }
00601     delete[] ms_pAllEvents[i];
00602     ms_pAllEvents[i] = NULL;
00603   }
00604   delete[] ms_pAllEvents;
00605   ms_pAllEvents = NULL;
00606 }
00607 
00608 transition_t *defineTransitions(status_type_t s_type, SINT32 transitionCount, ...)
00609 {
00610   int i = 0;
00611   va_list ap;
00612   transition_t *transitions = NULL;
00613   event_type_t specifiedEventTypes[transitionCount];
00614   transition_t specifiedTransitions[transitionCount];
00615 
00616   /* read in the specified events with the corresponding transitions */
00617   va_start(ap, transitionCount);
00618   for(i = 0; i < transitionCount; i++)
00619   {
00620     specifiedEventTypes[i] = (event_type_t) va_arg(ap, int);
00621     specifiedTransitions[i] = (transition_t) va_arg(ap, int);
00622   }
00623   va_end(ap);
00624 
00625   if((s_type >= NR_STATUS_TYPES) || (s_type < FIRST_STATUS))
00626   {
00627     /* invalid status type specified */
00628     return NULL;
00629   }
00630   if(transitionCount > (EVENT_COUNT[s_type]))
00631   {
00632     /* more transitions specified than events defined*/
00633     return NULL;
00634   }
00635 
00636   transitions = new transition_t[(EVENT_COUNT[s_type])];
00637   memset(transitions, st_ignore, (sizeof(transition_t)*(EVENT_COUNT[s_type])));
00638   for(i = 0; i < transitionCount; i++)
00639   {
00640     if((specifiedEventTypes[i] >= EVENT_COUNT[s_type]) ||
00641       (specifiedEventTypes[i] < 0))
00642     {
00643       /* specified event is invalid */
00644       CAMsg::printMsg(LOG_WARNING,
00645             "StatusManager: definition of an invalid state transition (invalid event %d).\n",
00646             specifiedEventTypes[i]);
00647       continue;
00648     }
00649     if((specifiedTransitions[i] >= STATE_COUNT[s_type]) ||
00650       (specifiedTransitions[i] < st_ignore))
00651     {
00652       /* corresponding transition to event is not valid */
00653       CAMsg::printMsg(LOG_WARNING,
00654             "StatusManager: definition of an invalid state transition (invalid state %d).\n",
00655             specifiedTransitions[i]);
00656       continue;
00657     }
00658     transitions[specifiedEventTypes[i]] = specifiedTransitions[i];
00659   }
00660 
00661   return transitions;
00662 
00663 }
00664 #endif