# 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 $