TimeManagement.cc

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 // CERTI - HLA RunTime Infrastructure
00003 // Copyright (C) 2002-2005  ONERA
00004 //
00005 // This file is part of CERTI
00006 //
00007 // CERTI is free software ; you can redistribute it and/or modify
00008 // it under the terms of the GNU General Public License as published by
00009 // the Free Software Foundation ; either version 2 of the License, or
00010 // (at your option) any later version.
00011 //
00012 // CERTI is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY ; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program ; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00020 //
00021 // $Id: TimeManagement.cc,v 3.48 2009/04/21 13:54:02 siron Exp $
00022 // ----------------------------------------------------------------------------
00023 
00024 #include <config.h>
00025 #include "TimeManagement.hh"
00026 #include "NM_Classes.hh"
00027 #include <float.h>
00028 
00029 namespace certi {
00030 namespace rtia {
00031 
00032 namespace {
00033 
00034 PrettyDebug D("RTIA_TM", __FILE__);
00035 static PrettyDebug G("GENDOC",__FILE__) ;
00036 const double epsilon2 = 1.0e-4 ;
00037 
00038 }
00039 
00040 // ----------------------------------------------------------------------------
00044 void
00045 TimeManagement::advance(bool &msg_restant, TypeException &e)
00046 {
00047     switch(_avancee_en_cours) {
00048       case TAR:
00049       case TARA:
00050         D.Out(pdTrace, "Call to TimeAdvance.");
00051         timeAdvance(msg_restant, e);
00052         break ;
00053       case NER:
00054       case NERA:
00055         D.Out(pdTrace, "Call to NextEventAdvance.");
00056         nextEventAdvance(msg_restant, e);
00057         break ;
00058       default:
00059         D.Out(pdTrace, "Unexpected case in advance: %d.", _avancee_en_cours);
00060                                      // No exception is raised, ca
00061                                      // peut etre un cas ou on a
00062                                      // rien a faire, par exemple en
00063                                      // cas d'attente active pendant
00064                                      // une pause.
00065     }
00066 }
00067 
00068 // ----------------------------------------------------------------------------
00070 TimeManagement::TimeManagement(Communications *GC,
00071                                Queues *GQueues,
00072                                FederationManagement *GF,
00073                                DeclarationManagement *GD,
00074                                ObjectManagement *GO,
00075                                OwnershipManagement *GP)
00076     : LBTS()
00077 {
00078     comm = GC ;
00079     queues = GQueues ;
00080     fm = GF ;
00081     dm = GD ;
00082     om = GO ;
00083     owm = GP ;
00084 
00085     lastNullMessageDate = 0.0 ;
00086 
00087     _avancee_en_cours = PAS_D_AVANCEE ;
00088     _tick_state = NO_TICK;
00089     _asynchronous_delivery = false ;
00090 
00091     _heure_courante = 0.0 ;
00092     _lookahead_courant = 0.0 ;
00093     _est_regulateur = false ;
00094     _est_contraint = false ;
00095 }
00096 
00097 // ----------------------------------------------------------------------------
00099 void TimeManagement::sendNullMessage(FederationTime heure_logique)
00100 {
00101     NM_Message_Null msg ;
00102 
00103     msg.setDate(heure_logique);
00104     heure_logique += _lookahead_courant ;
00105 
00106     if (heure_logique > lastNullMessageDate) {
00107         msg.federation = fm->_numero_federation ;
00108         msg.federate = fm->federate ;
00109         msg.setDate(heure_logique) ; // ? See 6 lines upper !
00110 
00111         comm->sendMessage(&msg);
00112         lastNullMessageDate = heure_logique ;
00113         D.Out(pdDebug, "NULL message sent (Time = %f).", heure_logique.getTime()) ;
00114     }
00115     else {
00116         D.Out(pdExcept, "NULL message not sent (Time = %f, Last = %f).",
00117               heure_logique.getTime(), lastNullMessageDate.getTime());
00118     }
00119 }
00120 
00121 // ----------------------------------------------------------------------------
00123 bool
00124 TimeManagement::executeFederateService(NetworkMessage &msg)
00125 {
00126   G.Out(pdGendoc,"enter TimeManagement::executeFederateService for type %d",msg.getType());
00127   D.Out(pdRequest, "Execute federate service: Type %d.", msg.getType());
00128 
00129     _tick_state = TICK_NEXT;  // indicate the callback was processed
00130 
00131     switch (msg.getType()) {
00132 
00133       case NetworkMessage::FEDERATION_SYNCHRONIZED:
00134         try {
00135             fm->federationSynchronized(msg.getLabel().c_str());
00136         }
00137         catch (RTIinternalError &e) {
00138             cout << "RTIA:RTIinternalError in federationSynchronized." << endl ;
00139             throw e ;
00140         }
00141         break ;
00142 
00143       case NetworkMessage::SYNCHRONIZATION_POINT_REGISTRATION_SUCCEEDED:
00144         try {
00145             fm->synchronizationPointRegistrationSucceeded(msg.getLabel().c_str());
00146         }
00147         catch (RTIinternalError &e) {
00148             cout << "RTIA:RTIinternalError in synchronizationPointRegistration"
00149                 "Succeeded." << endl ;
00150             throw e ;
00151         }
00152         break ;
00153 
00154       case NetworkMessage::ANNOUNCE_SYNCHRONIZATION_POINT:
00155         try {
00156             fm->announceSynchronizationPoint(msg.getLabel().c_str(), msg.getTag().c_str());
00157         }
00158         catch (RTIinternalError &e) {
00159             cout << "RTIA:RTIinternalError in announceSynchronizationPoint." << endl ;
00160             throw e ;
00161         }
00162         break ;
00163 
00164       case NetworkMessage::DISCOVER_OBJECT:
00165         try {
00166             om->discoverObject(msg.object,
00167                                msg.objectClass,
00168                                msg.getLabel().c_str(),
00169                                msg.getDate(),
00170                                msg.eventRetraction,
00171                                msg.exception);
00172 
00173         }
00174         catch (RTIinternalError &e) {
00175             cout << "RTIA:RTIinternalError in discoverObject." << endl ;
00176             throw e ;
00177         }
00178         break ;
00179 
00180       case NetworkMessage::REFLECT_ATTRIBUTE_VALUES:
00181       {
00182           std::vector<AttributeValue_t> ValueArray = msg.getAttribValueArray();
00183 
00184           if (msg.isDated())
00185              om->reflectAttributeValues(msg.object,
00186                                         msg.handleArray,
00187                                         ValueArray,
00188                                         msg.handleArraySize,
00189                                         msg.getDate(),
00190                                         msg.getLabel().c_str(),
00191                                         msg.eventRetraction,
00192                                         msg.exception);
00193           else
00194             om->reflectAttributeValues(msg.object,
00195                                         msg.handleArray,
00196                                         ValueArray,
00197                                         msg.handleArraySize,
00198                                         msg.getLabel().c_str(),
00199                                         msg.exception);
00200           ValueArray.empty();
00201           break ;
00202       }
00203 
00204       case NetworkMessage::PROVIDE_ATTRIBUTE_VALUE_UPDATE:
00205       {
00206       om->provideAttributeValueUpdate(msg.object,
00207                                       msg.handleArray,
00208                                       msg.handleArraySize,
00209                                       msg.exception);
00210       break;
00211       }
00212 
00213 
00214       case NetworkMessage::RECEIVE_INTERACTION:
00215       {
00216           std::vector<ParameterValue_t> ValueArray = msg.getParamValueArray();
00217 
00218           if (msg.isDated())
00219               om->receiveInteraction(msg.interactionClass,
00220                                      msg.handleArray,
00221                                      ValueArray,
00222                                      msg.handleArraySize,
00223                                      msg.getDate(),
00224                                      msg.getLabel().c_str(),
00225                                      msg.eventRetraction,
00226                                      msg.exception);
00227           else
00228               om->receiveInteraction(msg.interactionClass,
00229                                      msg.handleArray,
00230                                      ValueArray,
00231                                      msg.handleArraySize,
00232                                      msg.getLabel().c_str(),
00233                                      msg.exception);
00234           ValueArray.empty();
00235 
00236           break ;
00237       }
00238 
00239       case NetworkMessage::REMOVE_OBJECT:
00240           if (msg.isDated()) {
00241             om->removeObject(msg.object,
00242                              msg.federate,
00243                              msg.getDate(),
00244                              msg.getLabel().c_str(),
00245                              msg.eventRetraction,
00246                              msg.exception);
00247       }
00248       else {
00249             om->removeObject(msg.object,
00250                              msg.federate,
00251                              msg.getLabel().c_str(),
00252                              msg.exception);
00253       }
00254         break ;
00255 
00256       case NetworkMessage::INFORM_ATTRIBUTE_OWNERSHIP:
00257 
00258         D.Out(pdInit, "m_REFLECT_ATTRIBUTE_VALUES Owner %u", msg.federate);
00259 
00260         owm->informAttributeOwnership(msg.object,
00261                                       msg.handleArray[0],
00262                                       msg.federate,
00263                                       msg.exception);
00264         break ;
00265 
00266       case NetworkMessage::ATTRIBUTE_IS_NOT_OWNED:
00267         owm->attributeIsNotOwned(msg.object,
00268                                  msg.handleArray[0],
00269                                  msg.federate,
00270                                  msg.exception);
00271         break ;
00272 
00273       case NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION:
00274           {
00275         owm->requestAttributeOwnershipAssumption(msg.object,
00276                                                  msg.handleArray,
00277                                                  msg.handleArraySize,
00278                                                  msg.federate,
00279                                                  const_cast<char*>(msg.getLabel().c_str()),
00280                                                  msg.exception);
00281         break ;
00282            }
00283 
00284       case NetworkMessage::ATTRIBUTE_OWNERSHIP_UNAVAILABLE:
00285         {
00286         owm->attributeOwnershipUnavailable(msg.object,
00287                                            msg.handleArray,
00288                                            msg.handleArraySize,
00289                                            msg.federate,
00290                                            msg.exception);
00291         break ;
00292         }
00293 
00294       case NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION:
00295         {
00296         owm->attributeOwnershipAcquisitionNotification(msg.object,
00297                                                        msg.handleArray,
00298                                                        msg.handleArraySize,
00299                                                        msg.federate,
00300                                                        msg.exception);
00301         break ;
00302         }
00303 
00304       case NetworkMessage::ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION:
00305         {
00306         owm->attributeOwnershipDivestitureNotification(msg.object,
00307                                                        msg.handleArray,
00308                                                        msg.handleArraySize,
00309                                                        msg.exception);
00310         break ;
00311         }
00312 
00313       case NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_RELEASE:
00314         {
00315         owm->requestAttributeOwnershipRelease(msg.object,
00316                                               msg.handleArray,
00317                                               msg.handleArraySize,
00318                                               const_cast<char*>(msg.getLabel().c_str()),
00319                                               msg.exception);
00320         break ;
00321         }
00322 
00323       case NetworkMessage::CONFIRM_ATTRIBUTE_OWNERSHIP_ACQUISITION_CANCELLATION:
00324         {
00325         owm->confirmAttributeOwnershipAcquisitionCancellation(msg.object,
00326                                                               msg.handleArray,
00327                                                               msg.handleArraySize,
00328                                                               msg.exception);
00329         break ;
00330         }
00331 
00332       case NetworkMessage::INITIATE_FEDERATE_SAVE:
00333         fm->initiateFederateSave(msg.getLabel().c_str());
00334         break ;
00335 
00336       case NetworkMessage::FEDERATION_SAVED:
00337       case NetworkMessage::FEDERATION_NOT_SAVED: {
00338           bool status = (msg.getType() == NetworkMessage::FEDERATION_SAVED) ? true : false ;
00339           fm->federationSavedStatus(status);
00340       }
00341         break ;
00342 
00343       case NetworkMessage::REQUEST_FEDERATION_RESTORE_SUCCEEDED:
00344       case NetworkMessage::REQUEST_FEDERATION_RESTORE_FAILED: {
00345           bool status = (msg.getType() == NetworkMessage::REQUEST_FEDERATION_RESTORE_SUCCEEDED)
00346               ? true : false ;
00347           fm->requestFederationRestoreStatus(status, msg.getLabel().c_str(), msg.getTag().c_str());
00348       }
00349         break ;
00350 
00351       case NetworkMessage::FEDERATION_RESTORE_BEGUN:
00352         fm->federationRestoreBegun();
00353         break ;
00354 
00355       case NetworkMessage::INITIATE_FEDERATE_RESTORE:
00356         fm->initiateFederateRestore(msg.getLabel().c_str(), msg.federate);
00357         break ;
00358 
00359       case NetworkMessage::FEDERATION_RESTORED:
00360       case NetworkMessage::FEDERATION_NOT_RESTORED: {
00361           bool status = (msg.getType() == NetworkMessage::FEDERATION_RESTORED) ? true : false ;
00362           fm->federationRestoredStatus(status);
00363       }
00364         break ;
00365       case NetworkMessage::TIME_REGULATION_ENABLED:
00366         this->timeRegulationEnabled(msg.getDate(), msg.exception);
00367         break;
00368       case NetworkMessage::TIME_CONSTRAINED_ENABLED:
00369         this->timeConstrainedEnabled(msg.getDate(), msg.exception);
00370         break;
00371       case NetworkMessage::START_REGISTRATION_FOR_OBJECT_CLASS:
00372     dm->startRegistrationForObjectClass(msg.objectClass, msg.exception);
00373         break;
00374 
00375       default:
00376     std::stringstream errorMsg;
00377         D.Out(pdExcept, "Unknown message type in executeFederateService.");
00378     errorMsg << "Unknown message <" <<  msg.getName() << " in executeFederateService.";
00379         throw RTIinternalError(errorMsg.str().c_str());
00380     }
00381     G.Out(pdGendoc,"exit  TimeManagement::executeFederateService");
00382     return true ;
00383 }
00384 
00385 // ----------------------------------------------------------------------------
00387 void
00388 TimeManagement::flushQueueRequest(FederationTime heure_logique,
00389                                   TypeException &e)
00390 {
00391     e = e_NO_EXCEPTION ;
00392 
00393     // Verifications
00394     if (_avancee_en_cours != PAS_D_AVANCEE)
00395         e = e_TimeAdvanceAlreadyInProgress ;
00396 
00397     if (heure_logique <= _heure_courante)
00398         e = e_FederationTimeAlreadyPassed ;
00399 
00400     if (e == e_NO_EXCEPTION) {
00401         // BUG: Not implemented.
00402         D.Out(pdExcept, "flushQueueRequest not implemented.");
00403         throw RTIinternalError("flushQueueRequest not implemented.");
00404     }
00405 }
00406 
00407 // ----------------------------------------------------------------------------
00412 void
00413 TimeManagement::nextEventAdvance(bool &msg_restant, TypeException &e)
00414 {
00415     FederationTime dateTSO ;
00416     FederationTime date_min = 0.0 ;
00417     bool TSOPresent ;
00418     bool msg_donne ;
00419     NetworkMessage *msg ;
00420 
00421     G.Out(pdGendoc," enter TimeManagement::nextEventAdvance");
00422     msg_restant = false ;
00423 
00424     if (_est_contraint) {
00425 
00426         // Select lower value between expected time and first TSO message time.
00427         queues->nextTsoDate(TSOPresent, dateTSO);
00428 
00429         if ((TSOPresent) && (dateTSO < date_avancee))
00430             date_min = dateTSO ;
00431         else
00432             date_min = date_avancee ;
00433 
00434         if (date_min < _LBTS) {
00435             // nextEventRequest is done because either a TSO message
00436             // can be delivered or no message with lower value than
00437             // expected time is avail.
00438 
00439             // New expected time is keep (can be first TSO message to deliver).
00440             // This value must not be changed.
00441             date_avancee = date_min ;
00442 
00443             // If federate is regulating, inform other federate we advanced.
00444             if (_est_regulateur)
00445                 sendNullMessage(date_min);
00446 
00447             // Deliver to federate every TSO messages with time
00448             // 'date_min' (1 by 1).
00449             msg = queues->giveTsoMessage(date_min, msg_donne, msg_restant);
00450             if (msg_donne) {
00451                 // Send message back to federate.
00452                 executeFederateService(*msg);
00453                 delete msg ;
00454             }
00455             else {
00456                 // Advance current time up to 'date_min'.
00457                 timeAdvanceGrant(date_min, e);
00458                 _avancee_en_cours = PAS_D_AVANCEE ;
00459             }
00460         }
00461         else { // date_min < _LBTS
00462 
00463             // Federate can't advance up to expected time but up to LBTS. Other
00464             // federates are informed and no TSO message are sent.
00465             if (_est_regulateur)
00466                 sendNullMessage(_LBTS);
00467         }
00468     }
00469 
00470     else { // if federate isn't constrained.
00471 
00472         // In this case, federate can advance freely. Moreover, there must be no
00473         // message in TSO list.
00474         if (_est_regulateur)
00475             sendNullMessage(date_avancee);
00476 
00477         timeAdvanceGrant(date_avancee, e);
00478 
00479         _avancee_en_cours = PAS_D_AVANCEE ;
00480     }
00481 G.Out(pdGendoc," exit  TimeManagement::nextEventAdvance");
00482 }
00483 
00484 // ----------------------------------------------------------------------------
00485 void
00486 TimeManagement::nextEventRequest(FederationTime heure_logique,
00487                                  TypeException &e)
00488 {
00489     e = e_NO_EXCEPTION ;
00490 
00491     // Verifications
00492 
00493     if (_avancee_en_cours != PAS_D_AVANCEE)
00494         e = e_TimeAdvanceAlreadyInProgress ;
00495 
00496     if (heure_logique < _heure_courante)
00497         e = e_FederationTimeAlreadyPassed ;
00498 
00499     if (heure_logique < _heure_courante + _lookahead_courant)
00500        e = e_InvalidFederationTime ;
00501 
00502     if (e == e_NO_EXCEPTION) {
00503 
00504         _type_granted_state = AFTER_TAR_OR_NER ;  // will be
00505 
00506         if (_lookahead_courant == 0.0) {
00507            _lookahead_courant == epsilon2 ;
00508            _type_granted_state = AFTER_TAR_OR_NER_WITH_ZERO_LK ;
00509         }
00510 
00511         _avancee_en_cours = NER ;
00512         date_avancee = heure_logique ;
00513         D.Out(pdTrace, "NextEventRequest accepted.");
00514     }
00515     else {
00516         D.Out(pdExcept, "NextEventRequest refused (exception = %d).", e);
00517     }
00518 }
00519 
00520 // ----------------------------------------------------------------------------
00521 void
00522 TimeManagement::nextEventRequestAvailable(FederationTime heure_logique,
00523                                  TypeException &e)
00524 {
00525     e = e_NO_EXCEPTION ;
00526 
00527     // Verifications
00528 
00529     if (_avancee_en_cours != PAS_D_AVANCEE)
00530         e = e_TimeAdvanceAlreadyInProgress ;
00531 
00532     if (heure_logique < _heure_courante)
00533         e = e_FederationTimeAlreadyPassed ;
00534 
00535     if (heure_logique < _heure_courante + _lookahead_courant)
00536        e = e_InvalidFederationTime ;
00537 
00538     if (e == e_NO_EXCEPTION) {
00539         _type_granted_state = AFTER_TARA_OR_NERA ;  // will be
00540         _avancee_en_cours = NERA ;
00541         date_avancee = heure_logique ;
00542         D.Out(pdTrace, "NextEventRequestAvailable accepted.");
00543     }
00544     else {
00545         D.Out(pdExcept, "NextEventRequestAvailable refused (exception = %d).", e);
00546     }
00547 }
00548 
00549 // ----------------------------------------------------------------------------
00550 FederationTime
00551 TimeManagement::requestFederationTime()
00552 {
00553     return _LBTS ;
00554 }
00555 
00556 // ----------------------------------------------------------------------------
00557 FederationTimeDelta TimeManagement::requestLookahead()
00558 {
00559     return _lookahead_courant ;
00560 }
00561 
00562 // ----------------------------------------------------------------------------
00564 FederationTime
00565 TimeManagement::requestMinNextEventTime()
00566 {
00567     FederationTime dateTSO ;
00568     FederationTime dateMNET ;
00569     bool found ;
00570 
00571     queues->nextTsoDate(found, dateTSO) ;
00572 
00573     if (!found)
00574         dateMNET = _LBTS ;
00575     else
00576         dateMNET = (_LBTS <= dateTSO ? _LBTS : dateTSO) ;
00577 
00578    D.Out(pdRegister, "Minimum Next Event Time : %f.", dateMNET.getTime());
00579 
00580    return dateMNET ;
00581 }
00582 
00583 // ----------------------------------------------------------------------------
00584 void
00585 TimeManagement::setLookahead(FederationTimeDelta lookahead, TypeException &e)
00586 {
00587     e = e_NO_EXCEPTION ;
00588 
00589     // Verifications
00590 
00591     if (lookahead < 0.0)
00592         e = e_InvalidLookahead ;
00593 
00594     if (lookahead == epsilon2) {
00595         cout << "Bad value of lookahead due to a zero lookahead implementation trick" << endl;
00596         e = e_RTIinternalError ;
00597     }
00598 
00599     if (e == e_NO_EXCEPTION) {
00600         _lookahead_courant = lookahead ;
00601 
00602         // On previent les autres en leur envoyant un message nul qui contient
00603         // notre temps local + le Lookahead.
00604         if (_est_regulateur)
00605             sendNullMessage(_heure_courante);
00606 
00607         D.Out(pdRegister, "New Lookahead : %f.", _lookahead_courant.getTime());
00608     }
00609 }
00610 
00611 // ----------------------------------------------------------------------------
00612 void
00613 TimeManagement::setTimeConstrained(bool etat, TypeException &e)
00614 {
00615     NM_Set_Time_Constrained msg ;
00616 
00617     e = e_NO_EXCEPTION ;
00618 
00619     // Verifications
00620 
00621     if (_est_contraint == etat)
00622         e = e_RTIinternalError ;
00623 
00624     if (_avancee_en_cours != PAS_D_AVANCEE)
00625         e = e_RTIinternalError ;
00626 
00627     if (e == e_NO_EXCEPTION) {
00628         _est_contraint = etat ;
00629 
00630         msg.federation = fm->_numero_federation ;
00631         msg.federate = fm->federate ;
00632         if (etat) {
00633             msg.constrainedOn();
00634         } else {
00635             msg.constrainedOff();
00636         }
00637 
00638         comm->sendMessage(&msg);
00639 
00640         D.Out(pdRegister,
00641               "Demande de modif de TimeConstrained envoyee(etat=%d, ", etat);
00642     }
00643     else {
00644         D.Out(pdExcept, "SetTimeConstrained refuse(exception = %d).", e);
00645     }
00646 }
00647 
00648 // ----------------------------------------------------------------------------
00649 // Rajouter le time et le lookahead
00650 // Modifier le lookahead courant
00651 void
00652 TimeManagement::setTimeRegulating(bool etat,FederationTime heure_logique,
00653                FederationTimeDelta the_lookahead, TypeException &e)
00654 {
00655     NM_Set_Time_Regulating msg ;
00656 
00657     e = e_NO_EXCEPTION ;
00658 
00659     // Verifications
00660 
00661     if (_est_regulateur == etat) {
00662         e = e_RTIinternalError ;
00663         D.Out(pdRegister,
00664               "erreur e_RTIinternalError : federe deja regulateur");
00665     }
00666 
00667     if (_avancee_en_cours != PAS_D_AVANCEE) {
00668         e = e_RTIinternalError ;
00669         D.Out(pdRegister, "erreur e_RTIinternalError avancee_en_cours");
00670     }
00671 
00672     // Si aucune erreur, prevenir le RTIG et devenir regulateur.
00673     if (e == e_NO_EXCEPTION) {
00674         _est_regulateur = etat ;
00675 
00676         msg.federation = fm->_numero_federation ;
00677         msg.federate = fm->federate ;
00678         if (etat) {
00679             msg.regulatorOn();
00680             D.Out(pdDebug,
00681                   "REGULATOR ON");
00682         } else {
00683             msg.regulatorOff();
00684             D.Out(pdDebug,
00685                   "REGULATOR OFF");
00686         }
00687     // Modifier lookahead courant
00688     _lookahead_courant = the_lookahead;
00689           D.Out(pdDebug,
00690                 "New lookahead = %f",_lookahead_courant.getTime());
00691     // faudrait peut etre remplacer heure courante par le temps en parametre
00692         msg.setDate(_heure_courante + _lookahead_courant);
00693 
00694         comm->sendMessage(&msg);
00695 
00696         D.Out(pdRegister,
00697               "Demande de modif de TimeRegulating emise(etat=%d).", etat);
00698     }
00699     else {
00700         D.Out(pdExcept, "SetTimeRegulating refuse(exception = %d).", e);
00701     }
00702 }
00703 
00704 // ----------------------------------------------------------------------------
00705 void
00706 TimeManagement::timeRegulationEnabled(FederationTime theTime, TypeException &e) {
00707     Message req;
00708 
00709     D.Out(pdDebug,"Sending TIME_REGULATION_ENABLED to Federate");
00710     req.type = Message::TIME_REGULATION_ENABLED;
00711     req.setFederationTime(theTime);
00712     comm->requestFederateService(&req);
00713 }
00714 
00715 // ----------------------------------------------------------------------------
00716 void
00717 TimeManagement::timeConstrainedEnabled(FederationTime theTime, TypeException &e) {
00718     Message req;
00719 
00720     D.Out(pdDebug,"Sending TIME_CONSTRAINED_ENABLED to Federate");
00721     req.type = Message::TIME_CONSTRAINED_ENABLED;
00722     req.setFederationTime(theTime);
00723     comm->requestFederateService(&req);
00724 }
00725 
00726 // ----------------------------------------------------------------------------
00729 bool
00730 TimeManagement::testValidTime(FederationTime theTime)
00731 {
00732    if (_avancee_en_cours == PAS_D_AVANCEE) {
00733       if (_type_granted_state == AFTER_TAR_OR_NER_WITH_ZERO_LK) {
00734          if (theTime <= _heure_courante)
00735             return false;
00736       }
00737       else {  // AFTER_TAR_OR_NER or AFTER_TARA_OR_NARA
00738          if (theTime  < _heure_courante + _lookahead_courant)
00739             return false;
00740       }
00741    }
00742    else {
00743       if (_type_granted_state == AFTER_TAR_OR_NER_WITH_ZERO_LK) {
00744          if (theTime <= date_avancee)
00745             return false;
00746       }
00747       else {  // AFTER_TAR_OR_NER or AFTER_TARA_OR_NARA
00748          if (theTime  < date_avancee + _lookahead_courant)
00749             return false;
00750       }
00751    }
00752    return true;
00753 }
00754 
00755 // ----------------------------------------------------------------------------
00760 bool
00761 TimeManagement::tick(TypeException &e)
00762 {
00763     bool msg_donne = false ;
00764     bool msg_restant = false ;
00765     NetworkMessage *msg = NULL ;
00766 
00767     G.Out(pdGendoc," enter TimeManagement::tick");
00768     // Note: While msg_donne = RTI::RTI_FALSE, msg_restant doesn't matter.
00769 
00770     // 1st try, give a command message. (requestPause, etc.)
00771     msg = queues->giveCommandMessage(msg_donne, msg_restant);
00772 
00773     // 2nd try, give a FIFO message. (discoverObject, etc.)
00774     if (!msg_donne){
00775         if ( _asynchronous_delivery || (_avancee_en_cours != PAS_D_AVANCEE) || (! _est_contraint)) {
00776             D.Out(pdDebug,"FIFO message to be delivered async_deliver=%d, _avancee=%d, constrained=%d",
00777                               _asynchronous_delivery,_avancee_en_cours,_est_contraint);
00778           // to exclude the case not asynchronous_delivery and
00779           // not time advancing for a constrained federate
00780           msg = queues->giveFifoMessage(msg_donne, msg_restant);
00781         } else {
00782           D.Out(pdDebug,"FIFO message skipped async_deliver=%d, _avancee=%d, constrained=%d",
00783                   _asynchronous_delivery,_avancee_en_cours,_est_contraint);
00784         }
00785     }
00786 
00787     // If message exists, send it to federate.
00788     if (msg_donne) {
00789         D.Out(pdDebug, "TickRequest being processed, Message to send.");
00790         try {
00791             executeFederateService(*msg);
00792         }
00793         catch (RTIinternalError &e) {
00794             cout << "RTIA:RTIinternalError thrown in tick (execute)." << endl ;
00795             throw e ;
00796         }
00797     }
00798 
00799     // No message: we try to send TSO messages.
00800     // Messages to be sent depends on asked advance type.
00801     else {
00802         D.Out(pdDebug, "TickRequest being processed, advance called.");
00803         try {
00804             advance(msg_restant, e);
00805         }
00806         catch (RTIinternalError &e) {
00807             cout << "RTIA:RTIinternalError thrown in tick (Advance)." << endl ;
00808             throw e ;
00809         }
00810     }
00811 
00812     delete msg ;
00813 
00814     G.Out(pdGendoc," exit  TimeManagement::tick");
00815     return msg_restant ;
00816 }
00817 
00818 // ----------------------------------------------------------------------------
00823 void
00824 TimeManagement::timeAdvance(bool &msg_restant, TypeException &e)
00825 {
00826     bool msg_donne ;
00827     FederationTime min ;
00828     NetworkMessage *msg ;
00829     G.Out(pdGendoc," enter TimeManagement::timeAdvance");
00830     msg_restant = false ;
00831 
00832     if (_est_contraint) {
00833         // give a TSO message.
00834         if (_LBTS == std::numeric_limits<double>::infinity())
00835            D.Out(pdDebug, "Logical time : %f, LBTS : infini.", date_avancee.getTime());
00836         else
00837            D.Out(pdDebug, "Logical time : %f, LBTS : %lf.", date_avancee.getTime(), _LBTS.getTime());
00838         min = (_LBTS<date_avancee)?(_LBTS):(date_avancee);
00839         msg = queues->giveTsoMessage(min, msg_donne, msg_restant);
00840 
00841         // otherwise
00842         if (!msg_donne) {
00843             // if LBTS allows to give a timeAdvanceGrant.
00844             if (_LBTS == std::numeric_limits<double>::infinity())
00845                D.Out(pdDebug, "Logical time : %f, LBTS : infini, lookahead : %f.",
00846                      date_avancee.getTime(), _lookahead_courant.getTime());
00847             else
00848                D.Out(pdDebug, "Logical time : %15.12f, LBTS : %15.12f, lookahead : %f.",
00849                      date_avancee.getTime(), _LBTS.getTime(), _lookahead_courant.getTime());
00850 
00851             if ((date_avancee < _LBTS) ||
00852                ((date_avancee == _LBTS) && (_avancee_en_cours == TARA))) {
00853                 // send a timeAdvanceGrant to federate.
00854                 timeAdvanceGrant(date_avancee, e);
00855 
00856                 if (e != e_NO_EXCEPTION)
00857                     return ;
00858 
00859                 _avancee_en_cours = PAS_D_AVANCEE ;
00860             }
00861             // otherwise nothing has to be sent to federate (empty tick).
00862         }
00863         else {
00864             executeFederateService(*msg);
00865             delete msg ;
00866         }
00867     }
00868     else {
00869         // if federate is not constrained, send a timeAdvanceGrant to federate.
00870         timeAdvanceGrant(date_avancee, e);
00871         if (e != e_NO_EXCEPTION)
00872             return ;
00873         _avancee_en_cours = PAS_D_AVANCEE ;
00874     }
00875 G.Out(pdGendoc," exit  TimeManagement::timeAdvance");
00876 }
00877 
00878 // ----------------------------------------------------------------------------
00882 void
00883 TimeManagement::timeAdvanceGrant(FederationTime logical_time,
00884                                  TypeException &e)
00885 {
00886     Message req;
00887 
00888     req.type = Message::TIME_ADVANCE_GRANT ;
00889     req.setFederationTime(logical_time);
00890 
00891     D.Out(pdRegister, "timeAdvanceGrant sent to federate (time = %f).",
00892           req.getFederationTime().getTime());
00893 
00894     if (_lookahead_courant == epsilon2)
00895         _lookahead_courant = 0.0 ;
00896 
00897     _tick_state = TICK_NEXT;  // indicate the callback was processed
00898 
00899     comm->requestFederateService(&req);
00900 
00901     _heure_courante = logical_time ;
00902 }
00903 
00904 // ----------------------------------------------------------------------------
00909 void
00910 TimeManagement::timeAdvanceRequest(FederationTime logical_time,
00911                                    TypeException &e)
00912 {
00913     e = e_NO_EXCEPTION ;
00914 
00915     // Verifications
00916 
00917     if (_avancee_en_cours != PAS_D_AVANCEE)
00918         e = e_TimeAdvanceAlreadyInProgress ;
00919 
00920     if (logical_time < _heure_courante)
00921         e = e_FederationTimeAlreadyPassed ;
00922 
00923     if (logical_time < _heure_courante + _lookahead_courant) {
00924 
00925     D.Out(pdDebug,"InvalidFederation time lkahead=%f, current=%f, requested=%f",
00926                 _lookahead_courant.getTime(),_heure_courante.getTime(),logical_time.getTime());
00927        e = e_InvalidFederationTime ;
00928     }
00929 
00930     if (e == e_NO_EXCEPTION) {
00931 
00932         _type_granted_state = AFTER_TAR_OR_NER ;  // will be
00933 
00934         if (_lookahead_courant == 0.0) {
00935            _lookahead_courant = epsilon2 ;
00936            _type_granted_state = AFTER_TAR_OR_NER_WITH_ZERO_LK ;
00937         }
00938 
00939         if (_est_regulateur)
00940             sendNullMessage(logical_time);
00941 
00942         _avancee_en_cours = TAR ;
00943         date_avancee = logical_time ;
00944 
00945         D.Out(pdTrace, "timeAdvanceRequest accepted (asked time=%f).",
00946               date_avancee.getTime());
00947     }
00948     else {
00949         D.Out(pdExcept, "timeAdvanceRequest refused (exception = %d).", e);
00950     }
00951 }
00952 
00953 
00954 void
00955 TimeManagement::timeAdvanceRequestAvailable(FederationTime logical_time,
00956                                    TypeException &e)
00957 {
00958     e = e_NO_EXCEPTION ;
00959 
00960     // Verifications
00961 
00962     if (_avancee_en_cours != PAS_D_AVANCEE)
00963         e = e_TimeAdvanceAlreadyInProgress ;
00964 
00965     if (logical_time < _heure_courante)
00966         e = e_FederationTimeAlreadyPassed ;
00967 
00968     if (logical_time < _heure_courante + _lookahead_courant)
00969        e = e_InvalidFederationTime ;
00970 
00971     if (e == e_NO_EXCEPTION) {
00972 
00973         _type_granted_state = AFTER_TARA_OR_NERA ;  // will be
00974 
00975         if (_est_regulateur)
00976             sendNullMessage(logical_time);
00977 
00978         _avancee_en_cours = TARA ;
00979         date_avancee = logical_time ;
00980 
00981         D.Out(pdTrace, "timeAdvanceRequestAvailable accepted (asked time=%f).",
00982               date_avancee.getTime());
00983     }
00984     else {
00985         D.Out(pdExcept, "timeAdvanceRequestAvailable refused (exception = %d).", e);
00986     }
00987 }
00988 
00989 
00990 }} // namespaces
00991 
00992 // $Id: TimeManagement.cc,v 3.48 2009/04/21 13:54:02 siron Exp $

Generated on Thu Apr 30 15:53:50 2009 for CERTIDeveloperDocumentation by doxygen 1.5.5