00001 /* 00002 * This file is part of openMask © INRIA, CNRS, Universite de Rennes 1 1993-2002, thereinafter the Software 00003 * 00004 * The Software has been developped within the Siames Project. 00005 * INRIA, the University of Rennes 1 and CNRS jointly hold intellectual property rights 00006 * 00007 * The Software has been registered with the Agence pour la Protection des 00008 * Programmes (APP) under registration number IDDN.FR.001.510008.00.S.P.2001.000.41200 00009 * 00010 * This file may be distributed under the terms of the Q Public License 00011 * version 1.0 as defined by Trolltech AS of Norway and appearing in the file 00012 * LICENSE.QPL included in the packaging of this file. 00013 * 00014 * Licensees holding valid specific licenses issued by INRIA, CNRS or Université de Rennes 1 00015 * for the software may use this file in accordance with that specific license 00016 * 00017 */ 00018 #ifdef _PVM 00019 #include <unistd.h> 00020 #include <signal.h> 00021 #include <PsPvmController.h> 00022 #include "PsSynchronisationMessage.h" 00023 // Pour une mise en oeuvre PVM 00024 #include <PsnPvmSvm.h> 00025 #include <PsnSvmLink.h> 00026 #include "PsnPvmUnicastMessage.h" 00027 00028 #include <PsObjectDescriptor.h> 00029 #include <PsSimulatedObject.h> 00030 #include <PsDuplicatedObject.h> 00031 #include <PsnProcess.h> 00032 #include <PsnMirrorObjectHandle.h> 00033 #include <PsnPvmReferenceObjectHandle.h> 00034 #include <PsnPvmDuplicatedObjectHandle.h> 00035 #include <unistd.h> 00036 #include <PsnDoubleListElement.h> 00037 #include <PsnDoubleList.h> 00038 #include "PsSystemEventIdentifier.h" 00039 #include "PsMultipleConfigurationParameter.h" 00040 00041 #include "PsPvmException.h" 00042 #include "stdio.h" 00043 #include "pvm3.h" 00044 00045 //------------------------------------------------------------------------ 00046 00047 PsPvmController::PsPvmController (PsObjectDescriptor & initialObjects, 00048 const PsDate & initialDate, 00049 int argc, 00050 char * argv []) 00051 : PsDistributedController (initialObjects, initialDate), 00052 _finishing ( false ) 00053 { 00054 PsDate latence = 0 ; 00055 PsNameToPointerMap<PsnProcess> * processTable = new PsNameToPointerMap<PsnProcess>() ; 00056 00057 PsMultipleConfigurationParameter * schedulingParameters = getSchedulingParametersOfObject( initialObjects ) ; 00058 if ( schedulingParameters != NULL) 00059 { 00060 PsConfigurationParameterDescriptor * param = schedulingParameters->getSubDescriptorByName("Latency") ; 00061 if (param != NULL) 00062 { 00063 latence = atoi (param->getAssociatedString().c_str()) ; 00064 } 00065 param = schedulingParameters->getSubDescriptorByName("Machines") ; 00066 PsMultipleConfigurationParameter * describedMachines = dynamic_cast<PsMultipleConfigurationParameter *>(param); 00067 if (describedMachines != NULL) 00068 { 00069 int numberOfMachines = describedMachines->getNumberOfSubItems () ; 00070 for (int machineNumber = 0 ; 00071 machineNumber != numberOfMachines ; 00072 ++machineNumber ) 00073 { 00074 param = describedMachines->getSubDescriptorByPosition ( machineNumber ) ; 00075 processTable->addObjectWithIndex ( describedMachines->getNameOfSubDescriptor (machineNumber), 00076 new PsnProcess ( describedMachines->getNameOfSubDescriptor (machineNumber), 00077 param->getAssociatedString() ) 00078 ) ; 00079 } 00080 } 00081 } 00082 00083 // virtual member functions aren't initiallised in constructor 00084 // therefore, recreate the correct objectHandle 00085 delete _objectHandle ; 00086 00087 _objectHandle = NULL ; 00088 00089 PsnDuplicatedObjectHandle * localObjectHandle = newPsnDuplicatedObjectHandle( *this ) ; 00090 _objectHandle = localObjectHandle ; 00091 00092 for (PsNameToPointerMap<PsnProcess>::const_iterator i = processTable->begin() ; 00093 i != processTable->end () ; 00094 ++i) 00095 { 00096 localObjectHandle->addProcessOfDuplicate ( (*i).second ) ; 00097 } 00098 00099 00100 _distributedVirtualMachine = new PsnPvmSvm (processTable, latence, argc, argv) ; 00101 00102 _distributedVirtualMachine->init (initialDate ) ; 00103 00104 _processName = _distributedVirtualMachine->getSiteName () ; 00105 00106 setProcessOfDescriptor ( initialObjects, _processName ) ; 00107 00108 cout << "PsPvmController::PsPvmController (...)" 00109 << "of process: " << _distributedVirtualMachine->getSiteName () << endl ; 00110 00111 00112 //rewritten 2001/12/5 by D. Margery 00113 list < PsObjectDescriptor *> * descriptorList = _simulationTree.getDescendants() ; 00114 for (list < PsObjectDescriptor *>::iterator descriptorIterator = descriptorList->begin() ; 00115 descriptorIterator != descriptorList->end() ; 00116 ++ descriptorIterator ) 00117 { 00118 PsFrequency currentFreq = (*descriptorIterator)->getFrequency() ; 00119 PsName currentProcess = (*descriptorIterator)->getProcess() ; 00120 PsnProcess * currentProcessDescriptor = processTable->getObjectOfIndex( currentProcess ) ; 00121 if ( currentProcessDescriptor != NULL ) 00122 // the process could have been removed by the svm 00123 { 00124 if ( currentFreq > currentProcessDescriptor->getMaxFrequencyOfHostedObjects () ) 00125 { 00126 currentProcessDescriptor->setMaxHostedFrequency (currentFreq) ; 00127 } 00128 currentProcessDescriptor->setFrequency ( PsController::lcm(currentFreq, currentProcessDescriptor->getFrequency() ) ) ; 00129 } 00130 } 00131 delete descriptorList ; 00132 00133 //subscribe to system signals to receive notification on what is happening on other controllers 00134 registerForSignalBy(PsSystemEventIdentifier::MaskObjectDestroyed, getName()) ; 00135 00136 } 00137 00138 //------------------------------------------------------------------------------ 00139 00140 PsPvmController::~PsPvmController () 00141 { 00142 // deconnexion de la machine virtuelle 00143 #ifdef _DEBUGEXECPVM 00144 cout << "PsPvmController::~PsPvmController : " << endl; 00145 #endif 00146 _distributedVirtualMachine->disconnectFromDistributedSimulation ( getSimulatedDate () ) ; 00147 delete _distributedVirtualMachine ; 00148 } 00149 00150 00151 //------------------------------------------------------------------------------ 00152 00153 void PsPvmController::run() 00154 { 00155 if ( pvm_parent() != PvmNoParent ) 00156 { 00157 PsDistributedController::run() ; 00158 00159 // the simulation is locally finished, so notify all the controllers before exiting 00160 PsDate lastDate = _date + 2 * _stepPeriod + _distributedVirtualMachine->getSynchronisationLatency() ; 00161 00162 while (_date < lastDate ) 00163 { 00164 #ifdef _DEBUGPVMMESS 00165 cerr<<"PsPvmController::run(): trying a clean exit"<<endl; 00166 #endif 00167 PsnReferenceObjectHandle * objectHandle = dynamic_cast<PsnReferenceObjectHandle *> ( _objectHandle ) ; 00168 00169 assert ( objectHandle != NULL ) ; 00170 00171 //the controller has to process residual system events adressed to itself 00172 objectHandle->processEvents() ; 00173 00174 //send enought empty signals to enable other controllers to finish their job 00175 makeSynchronisationMessage( _referenceObjectsMap ) ; 00176 00177 // send the synchronisation messages 00178 _distributedVirtualMachine->sendCurrentBuffersWithTag (PsnPvmMessage::SynchronisationMessage) ; 00179 00180 //wait a little, to try and get clean exit 00181 sleep(1) ; 00182 00183 // for cleanup, read any arrived messages 00184 _distributedVirtualMachine->processReceivedMessages (*this, PsnPvmMessage::SynchronisationMessage) ; 00185 00186 advanceSimulatedDate() ; 00187 } 00188 } 00189 00190 } 00191 00192 00193 00194 PsnMirrorObjectHandle * PsPvmController::createMirrorObject (PsObjectDescriptor * objectDescription) 00195 { 00196 PsnMirrorObjectHandle * mirror = PsDistributedController::createMirrorObject( objectDescription ) ; 00197 00198 // Register the mirror to the reference object for regular updates of outputs 00199 mirror->registerToReferenceObject () ; 00200 00201 return mirror ; 00202 } 00203 00204 00205 //------------------------------------------------------------------------------ 00206 00207 const PsName & PsPvmController::getProcessName () const 00208 { 00209 return (_distributedVirtualMachine->getSiteName ()) ; 00210 } 00211 00212 //------------------------------------------------------------------------------ 00213 void PsPvmController::advanceSimulatedDate () 00214 { 00215 #ifdef _DEBUGEXECPVM 00216 cerr << "PsPvmController::advanceSimulatedDate () from " <<_date<<endl; 00217 #endif 00218 //send any messages collected during init 00219 if (_date < initialSimulationDate ) 00220 { 00221 _distributedVirtualMachine->sendCurrentBuffersWithTag (PsnPvmMessage::SynchronisationMessage) ; 00222 } 00223 00224 PsDistributedController::advanceSimulatedDate () ; 00225 00226 // prepare buffers to receive any message generate during this simulation step 00227 _distributedVirtualMachine->timestampCurrentSendBuffers (_date) ; 00228 } 00229 00230 00231 void PsPvmController::computeNextSimulationStep () { 00232 #ifdef _DEBUGEXECPVM 00233 cerr << "PsPvmController::computeNextSimulation : computing yet another simulation step for " 00234 <<notreProcessus()<< endl; 00235 #endif 00236 00237 // compute the simulation step 00238 PsDistributedController::computeNextSimulationStep () ; 00239 00240 // compute the synchronisation messages 00241 makeSynchronisationMessage ( _referenceObjectsMap ) ; 00242 00243 // send the synchronisation messages 00244 _distributedVirtualMachine->sendCurrentBuffersWithTag (PsnPvmMessage::SynchronisationMessage) ; 00245 00246 // proceed with a relaxed synchronisation 00247 _distributedVirtualMachine->synchroniseReceiveAndProcessMessages (*this, PsnPvmMessage::SynchronisationMessage) ; 00248 } 00249 00250 //------------------------------------------------------------------------------ 00251 00252 void PsPvmController::makeSynchronisationMessage (PsNameToPointerMap<PsnReferenceObjectHandle> & referenceObjects ) 00253 { 00254 static PsName endMessage ("_OpenMASKEndOfSynchronisationMessage") ; 00255 00256 #ifdef _DEBUGPVMMESS 00257 cerr<<"PsPvmController::makeSynchronisationMessage for "<<referenceObjects.size() <<" objects "<<endl; 00258 #endif 00259 00260 PsNameToPointerMap<PsnReferenceObjectHandle>::iterator pTabRef ; 00261 PsDate dt ; 00262 // ask all referentials to contribute to the synchronisation message 00263 for (pTabRef = referenceObjects.begin () ; 00264 pTabRef != referenceObjects.end () ; 00265 pTabRef ++) 00266 { 00267 #ifdef _DEBUGPVMMESS 00268 cerr<<"PsPvmController::makeSynchronisationMessage for object " <<(*pTabRef).second->getSimulatedObject().getName()<<endl; 00269 #endif 00270 00271 PsnPvmReferenceObjectHandle * pvmObjectHandle = dynamic_cast<PsnPvmReferenceObjectHandle *> ( (*pTabRef).second ) ; 00272 if ( pvmObjectHandle != NULL ) 00273 { 00274 pvmObjectHandle->makeSynchronisationMessage ( _date ) ; 00275 } 00276 else 00277 { 00278 #ifdef _DEBUGPVMMESS 00279 cerr<<"No synchronisation message for "<<(*pTabRef).second->getSimulatedObject().getName()<<endl; 00280 #endif 00281 } 00282 #ifdef _DEBUGPVMMESS 00283 cerr<<"PsPvmController::makeSynchronisationMessage of " <<(*pTabRef).second->getSimulatedObject().getName()<<" done"<<endl; 00284 #endif 00285 } 00286 #ifdef _DEBUGPVMMESS 00287 cerr<<"PsPvmController::makeSynchronisationMessage of done"<<endl; 00288 #endif 00289 } 00290 00291 00292 //------------------------------------------------------------------------------ 00293 00294 void PsPvmController::parseSynchronisationMessage (PsnPvmIncomingMessage * message) 00295 { 00296 00297 PsnReferenceObjectHandle * refer ; // Referentiel de l'objet destinataire 00298 PsnMirrorObjectHandle * miroir ; // Miroir de l'objet destinataire 00299 PsName nomObj ; // Nom du miroir destinataire 00300 bool stillMessagesToParse = true ; 00301 00302 #ifdef _DEBUGPVMMESS 00303 cerr << "PsPvmController::parseSynchronisationMessage at "<<getSimulatedDate()<<":"<< endl ; 00304 #endif 00305 00306 00307 while ( stillMessagesToParse ) 00308 { 00309 // get the message recepient 00310 nomObj.unpack ( *message ) ; 00311 00312 00313 #ifdef _DEBUGPVMMESS 00314 cerr << "PsPvmController::parseSynchronisationMessage: message received for " << nomObj << endl; 00315 #endif 00316 if ( nomObj == PsSynchronisationMessage::endOfSynchronisationFragment ) 00317 // the synchronisation message has been completely parsed 00318 { 00319 stillMessagesToParse = false ; 00320 } 00321 else 00322 { 00323 MirrorObjectsContainerType::iterator i = _mirrorObjectsMap.find ( nomObj ) ; 00324 if (i != _mirrorObjectsMap.end ()) 00325 { 00326 // On lui transmet le message 00327 #ifdef _DEBUGPVMMESS 00328 cout << "PsPvmController::parseSynchronisationMessage: for miror" << endl ; 00329 #endif 00330 miroir = i->second ; 00331 miroir->unpack ( *message ) ; 00332 } 00333 else if (_referenceObjectsMap.find (nomObj) != _referenceObjectsMap.end ()) 00334 { 00335 // On lui transmet le message 00336 #ifdef _DEBUGPVMMESS 00337 cout << "PsPvmController::parseSynchronisationMessage : for referential : " << nomObj <<endl ; 00338 #endif 00339 refer = dynamic_cast<PsnPvmReferenceObjectHandle *>(_referenceObjectsMap.getObjectOfIndex (nomObj) ) ; 00340 if ( refer != NULL ) 00341 { 00342 refer->unpack (*message) ; 00343 } 00344 else 00345 { 00346 dynamic_cast<PsnPvmDuplicatedObjectHandle *>(_referenceObjectsMap.getObjectOfIndex (nomObj) )->unpack ( *message ) ; 00347 } 00348 } 00349 else if (nomObj == "") 00350 { 00351 #ifdef _DEBUGPVMMESS 00352 cout << "PsPvmController::parseSynchronisationMessage :CL : message vide d'abonnement ... pour synchro" << endl ; 00353 #endif 00354 } 00355 else 00356 { 00357 #ifdef _DEBUGPVMMESS 00358 cerr << "PsPvmController::parseSynchronisationMessage: "<< endl ; 00359 cerr << "for unknown object: <" << nomObj << "> (was probably destroyed)" << endl ; 00360 error ("PsPvmController::parseSynchronisationMessage : Objet ni miroir ni referentiel") ; 00361 #endif 00362 //probably a request for an object that was destroyed 00363 int typeMess ; 00364 *message >> typeMess ; 00365 // hope it is a registration for a just destroyed referential, and interprete it 00366 if ( typeMess == Registration ) 00367 { 00368 PsName processName ; 00369 *message >> processName ; 00370 } 00371 else if ( typeMess == EventReceived ) 00372 { 00373 PsEvent * event ; 00374 PsName classToCreate ; 00375 PsEventIdentifier eventId; 00376 PsDate eventDate; 00377 PsName sender, receiver ; 00378 *message >> classToCreate >> eventId>> eventDate>>sender>>receiver ; 00379 event = PsEventCreator::createEvent (classToCreate, eventId, eventDate, sender, receiver ) ; 00380 event->unpack ( *message ) ; 00381 //cerr << "PsPvmController::parseSynchronisationMessage event "<<*event<<" undelivered"<<endl; 00382 delete event ; 00383 } 00384 } 00385 } 00386 } 00387 #ifdef _DEBUGPVMMESS 00388 cerr << "PsPvmController::parseSynchronisationMessage : message parsed"<< endl ; 00389 #endif 00390 } 00391 00392 00393 00394 00395 00396 00397 //------------------------------------------------------------------------------ 00398 00399 void PsPvmController::init () 00400 { 00401 00402 if ( pvm_parent() != PvmNoParent ) 00403 { 00404 //on tente l'initialisation normale : pour chaque init, cette initialisation appelle initObjetReferentiel 00405 #ifdef _DEBUGDISTRIBUTEDINIT 00406 cerr<<"PsPvmController::init preparing the outgoing message buffers "<<endl; 00407 #endif 00408 _distributedVirtualMachine->timestampCurrentSendBuffers ( _date ) ; 00409 00410 // try a classic initialisation 00411 PsController::init () ; 00412 00413 //initialisation shouldn't fail 00414 assert ( tableDesNonInitialises.empty () ) ; 00415 00416 //here, as advanceSimulatedDate has been called to restore the initial simulation date, no need to timestamp messages 00417 00418 #ifdef _DEBUGDISTRIBUTEDINIT 00419 cerr<<"PsPvmController::init : classic initialisation tried"<<endl; 00420 #endif 00421 // send all registrations 00422 _distributedVirtualMachine->sendCurrentBuffersWithTag (PsnPvmMessage::SynchronisationMessage) ; 00423 00424 // broadcast a empty message signalling our initialisation is finished, and wait for all processes 00425 _distributedVirtualMachine->synchronizeOn ( *this, PsnPvmMessage::LocalInitSuccessfull ) ; 00426 00427 00428 //restore state to the supposed state resulting of a call to the ancestor init 00429 _distributedVirtualMachine->timestampCurrentSendBuffers (_date) ; 00430 } 00431 00432 } 00433 00434 //------------------------------------------------------------------------------ 00435 00436 int PsPvmController::getOutputHistorySize(void) { 00437 // Taille d'une file d'une output pour un controleur local 00438 // nbMinor * 4 --> pour guarantir la recuperation d'au plus 4 valeurs dans la file 00439 // 1 ?? surete ?? 00440 int nbrValeurPendantLatence = 1 ;//la latence minimal est un pas de simulation au sens controleur 00441 nbrValeurPendantLatence+=_distributedVirtualMachine->getSynchronisationLatency()/_stepPeriod; 00442 return PsDistributedController::getOutputHistorySize()+nbrValeurPendantLatence; 00443 } 00444 00445 00446 00447 //------------------------------------------------------------------------------ 00448 00449 PsnObjectHandle * 00450 PsPvmController::removeObjectFromDataStructures(const PsName & nom) 00451 { 00452 PsnObjectHandle * result = NULL ; 00453 if (_referenceObjectsMap.find (nom) != _referenceObjectsMap.end ()) 00454 { 00455 result = PsController::removeObjectFromDataStructures(nom); 00456 } 00457 else 00458 { 00459 MirrorObjectsContainerType::iterator i = _mirrorObjectsMap.find (nom) ; 00460 if (i != _mirrorObjectsMap.end ()) 00461 { 00462 PsnMirrorObjectHandle * miroir = i->second ; 00463 _mirrorObjectsMap.erase( i ); 00464 result = miroir; 00465 } 00466 else if (_duplicatedObjectsMap.find (nom) != _duplicatedObjectsMap.end()) 00467 { 00468 //a duplicated object is a referential present in the duplicated objects table 00469 _duplicatedObjectsMap.erase(nom); 00470 } 00471 } 00472 return result ; 00473 } 00474 00475 00476 //------------------------------------------------------------------------------ 00477 00478 PsnMirrorObjectHandle * PsPvmController::newPsnMirrorObjectHandle (PsSimulatedObject & obj) 00479 { 00480 return new PsnMirrorObjectHandle(obj); 00481 } 00482 00483 00484 PsnDuplicatedObjectHandle * PsPvmController::newPsnDuplicatedObjectHandle (PsSimulatedObject & obj) 00485 { 00486 return new PsnPvmDuplicatedObjectHandle( obj, *this ); 00487 } 00488 00489 00490 PsnReferenceObjectHandle * PsPvmController::newPsnReferenceObjectHandle(PsSimulatedObject & object, 00491 PsController & controller, 00492 PsnSignalDispatcher * signalDispatcher) 00493 { 00494 return new PsnPvmReferenceObjectHandle(object, controller, signalDispatcher ); 00495 } 00496 00497 PsnSvm * PsPvmController::getDistributedVirtualMachine () 00498 { 00499 return _distributedVirtualMachine; 00500 } 00501 00502 //------------------------------------------------------------------------------ 00503 00504 00505 void PsPvmController::sendInitialValuesToMirror(PsnPvmIncomingMessage & message) 00506 { 00507 if ( ! _finishing ) 00508 { 00509 // first find out the name of the objects whose initial values are needed 00510 PsName referentialName ; 00511 referentialName.unpack ( message ) ; 00512 00513 cerr<<"Looking for initial values of "<<referentialName<<endl; 00514 00515 //then find the corresponding referential 00516 PsNameToPointerMap<PsnReferenceObjectHandle>::iterator i = _referenceObjectsMap.find ( referentialName ) ; 00517 PsnPvmReferenceObjectHandle * referential = NULL ; 00518 if ( i != _referenceObjectsMap.end() ) 00519 { 00520 referential = dynamic_cast<PsnPvmReferenceObjectHandle *> (i->second) ; 00521 } 00522 else 00523 { 00524 //the referential might have been destroyed: look for it in the list of deleted object handles 00525 list <pair <PsDate, PsnObjectHandle *> >::iterator i = _deletedObjectHandles.begin() ; 00526 while ( i != _deletedObjectHandles.end() ) 00527 { 00528 if ( i->second->getSimulatedObject().getName() == referentialName ) 00529 { 00530 referential = dynamic_cast<PsnPvmReferenceObjectHandle *> ( i->second ); 00531 i = _deletedObjectHandles.end() ; 00532 } 00533 else 00534 { 00535 ++ i ; 00536 } 00537 } 00538 } 00539 assert ( referential != NULL ) ; 00540 00541 //find the name of the requesting process 00542 PsName mirrorProcessName ; 00543 mirrorProcessName.unpack( message ) ; 00544 00545 //then find the link to the corresponding process 00546 PsnSvmLink * process = getDistributedVirtualMachine()->getLinkToProcessNamed ( mirrorProcessName ) ; 00547 00548 assert ( process != NULL ) ; 00549 00550 //build the answer 00551 PsnPvmUnicastMessage * urgentAnswer = new PsnPvmUnicastMessage ( process->getTID() ) ; 00552 00553 urgentAnswer->insertTimeStamp( _date ) ; 00554 00555 referential->packInitialValues ( * urgentAnswer ) ; 00556 00557 PsSynchronisationMessage::endOfSynchronisationFragment.pack ( * urgentAnswer ) ; 00558 00559 // and send it 00560 urgentAnswer->send ( PsnPvmMessage::InitialValuesForMirror ) ; 00561 } 00562 } 00563 00564 00565 void PsPvmController::waitForAnswerToBlockingRequest (PsnPvmMessage::MessageTag tag) 00566 { 00567 if ( ! _finishing ) 00568 // avoid blocking the contyroller while terminating, because other controllers could have exited 00569 { 00570 _distributedVirtualMachine->waitForAnswerToBlockingRequest ( *this, tag ) ; 00571 } 00572 } 00573 00574 void PsPvmController::finish() 00575 { 00576 _finishing = true ; 00577 PsDistributedController::finish() ; 00578 } 00579 00580 PsDate PsPvmController::getPurgeDate () 00581 { 00582 //in the worst case we could reveive message from an object whose simulation date is current date - _latency -stepPeriod ; 00583 // make sure by doubling latency 00584 return PsDistributedController::getPurgeDate() - 2 * _distributedVirtualMachine->getSynchronisationLatency() ; 00585 } 00586 00587 #endif 00588 00589 00590 00591 00592 00593 00594
| Documentation generated on Mon Nov 25 15:25:02 2002 |
Generated with doxygen 1.2.12 by Dimitri van Heesch , 1997-2001 |