ObjectClassBroadcastList.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-libCERTI
00006 //
00007 // CERTI-libCERTI is free software ; you can redistribute it and/or
00008 // modify it under the terms of the GNU Lesser General Public License
00009 // as published by the Free Software Foundation ; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // CERTI-libCERTI is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY ; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00015 // Lesser General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU Lesser General Public
00018 // License along with this program ; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00020 // USA
00021 //
00022 // $Id: ObjectClassBroadcastList.cc,v 3.25 2008/09/18 14:41:29 gotthardp Exp $
00023 // ----------------------------------------------------------------------------
00024 
00025 
00026 #include <assert.h>
00027 
00028 #include "ObjectClassBroadcastList.hh"
00029 #include "PrettyDebug.hh"
00030 #include "NM_Classes.hh"
00031 
00032 using std::list ;
00033 
00034 namespace certi {
00035 
00036 static pdCDebug D("BROADCAST", __FILE__);
00037 static PrettyDebug G("GENDOC",__FILE__);
00038 
00039 // ----------------------------------------------------------------------------
00042 ObjectBroadcastLine::ObjectBroadcastLine(FederateHandle theFederate,
00043                                          ObjectBroadcastLine::State init_state)
00044 {
00045     Federate = theFederate ;
00046     for (AttributeHandle i = 0 ; i <= MAX_STATE_SIZE ; i++)
00047         state[i] = init_state ;
00048 }
00049 
00050 // ============================================================================
00051 
00052 // ----------------------------------------------------------------------------
00057 NetworkMessage *
00058 ObjectClassBroadcastList::adaptMessage(ObjectBroadcastLine *line)
00059 {
00060     G.Out(pdGendoc,"enter ObjectClassBroadcastList::adaptMessage");
00061     G.Out(pdGendoc,"      message->objectClass=%d",message->objectClass);
00062 
00063     if ((message->getType() != NetworkMessage::REFLECT_ATTRIBUTE_VALUES) &&
00064         (message->getType() != NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION))
00065         throw RTIinternalError("Bad Message type in Broadcast's AdaptMsg.");
00066 
00067     // Copy static informations.
00068     NetworkMessage *reducedMessage = NM_Factory::create(message->getType());    
00069     reducedMessage->exception = message->exception ;
00070     reducedMessage->federation = message->federation ;
00071     reducedMessage->federate = message->federate ;
00072     reducedMessage->object = message->object ;
00073     if (message->isDated()) {
00074         reducedMessage->setDate(message->getDate());
00075     }
00076     if (message->isTagged()) {
00077         reducedMessage->setTag(message->getTag());
00078     }
00079     reducedMessage->objectClass = message->objectClass ;
00080 
00081     if (message->isLabelled()) {
00082         reducedMessage->setLabel(message->getLabel());
00083     }
00084     // Copy attributes that are in the bsWaiting state in Line.
00085     UShort currentSize ;
00086     AttributeHandle currentAttrib ;
00087 
00088     reducedMessage->handleArraySize = 0 ;
00089 
00090     for (UShort i = 0 ; i < message->handleArraySize ; i++) {
00091 
00092         currentAttrib = message->handleArray[i] ;
00093 
00094         if (line->state[currentAttrib] == ObjectBroadcastLine::waiting) {
00095 
00096             // Update number of attributes in ReducedMessage.
00097             currentSize = reducedMessage->handleArraySize ;
00098             reducedMessage->handleArraySize ++ ;
00099             reducedMessage->handleArray.resize(reducedMessage->handleArraySize);
00100             reducedMessage->sizeValueArray(reducedMessage->handleArraySize);
00101 
00102             // Copy Attribute Handle.
00103             reducedMessage->handleArray[currentSize] = currentAttrib ;
00104 
00105             if (message->getType() == NetworkMessage::REFLECT_ATTRIBUTE_VALUES) {
00106                 // Copy Attribute Value.
00107                 reducedMessage->valueArray[currentSize] = message->valueArray[i];
00108             }
00109         }
00110     }
00111     G.Out(pdGendoc,"      reducedMessage->objectClass=%d",reducedMessage->objectClass);
00112     G.Out(pdGendoc,"exit  ObjectClassBroadcastList::adaptMessage");
00113     return reducedMessage ;
00114 }
00115 
00116 // ----------------------------------------------------------------------------
00124 void
00125 ObjectClassBroadcastList::addFederate(FederateHandle theFederate,
00126                                       AttributeHandle theAttribute)
00127 {
00128     if (theAttribute > maxHandle) {
00129         D.Out(pdExcept, "Bad attribute handle: %u > %u.", theAttribute,
00130               maxHandle);
00131         throw RTIinternalError("");
00132     }
00133 
00134     ObjectBroadcastLine *line = getLineWithFederate(theFederate);
00135 
00136     if (line == 0) {
00137         line =
00138             new ObjectBroadcastLine(theFederate, ObjectBroadcastLine::notSub);
00139         lines.push_front(line);
00140         D.Out(pdRegister, "Adding new line in list for Federate %d.",
00141               theFederate);
00142     }
00143 
00144     if (line->state[theAttribute] != ObjectBroadcastLine::sent) {
00145         line->state[theAttribute] = ObjectBroadcastLine::waiting ;
00146         D.Out(pdRegister, "List attribute %d for Federate %d is now "
00147               "ObjectBroadcastLine::waiting.", theAttribute, theFederate);
00148     }
00149     else
00150         D.Out(pdTrace,
00151               "Message already sent to federate %d about attribute %d.",
00152               theFederate, theAttribute);
00153 }
00154 
00155 // ----------------------------------------------------------------------------
00162 ObjectClassBroadcastList::ObjectClassBroadcastList(NetworkMessage *theMsg,
00163                                                    AttributeHandle maxAttHandle)
00164     : maxHandle(maxAttHandle)
00165 {
00166     ObjectBroadcastLine *firstLine = 0 ;
00167 
00168     if (theMsg == 0)
00169         throw RTIinternalError("Null Broadcast Message.");
00170 
00171     message = theMsg ;
00172 
00173     // Add reference of the sender.
00174     if (message->federate != 0) {
00175         firstLine = new ObjectBroadcastLine(message->federate,
00176                                             ObjectBroadcastLine::sent);
00177         lines.push_front(firstLine);
00178     }
00179 }
00180 
00181 // ----------------------------------------------------------------------------
00183 ObjectClassBroadcastList::~ObjectClassBroadcastList()
00184 {
00185     this->clear();
00186 }
00187 
00188 // ----------------------------------------------------------------------------
00190 void
00191 ObjectClassBroadcastList::clear()
00192 {
00193     delete message ;
00194     message = 0 ;
00195 
00196     maxHandle = 0 ;
00197 
00198     while (!lines.empty()) {
00199         delete lines.front();
00200         lines.pop_front();
00201     }
00202 
00203     D.Out(pdTerm, "List is now empty.");
00204 }
00205 
00206 
00207 
00208 ObjectBroadcastLine*
00209 ObjectClassBroadcastList::getLineWithFederate(FederateHandle theFederate)
00210 {
00211     list<ObjectBroadcastLine *>::iterator i ;
00212     for (i = lines.begin(); i != lines.end(); i++) {
00213         if ((*i)->Federate == theFederate)
00214             return (*i);
00215     }
00216 
00217     return 0 ;
00218 }
00219 
00220 // ----------------------------------------------------------------------------
00224 bool
00225 ObjectClassBroadcastList::isWaiting(ObjectBroadcastLine *line)
00226 {
00227     for (unsigned int attrIndex = 1 ; attrIndex <= maxHandle ; attrIndex++) {
00228         if (line->state[attrIndex] == ObjectBroadcastLine::waiting) {
00229             return true ;
00230         }
00231     }
00232 
00233     return false ;
00234 }
00235 
00236 
00237 // --------------------------
00238 // -- SendPendingDOMessage --
00239 // --------------------------
00240 
00241 void
00242 ObjectClassBroadcastList::sendPendingDOMessage(SecurityServer *server)
00243 {
00244     Socket *socket = NULL ;
00245 
00246     // Pour chaque ligne de la liste
00247     list<ObjectBroadcastLine *>::iterator i ;
00248     for (i = lines.begin(); i != lines.end(); ++i) {
00249         // Si le federe attend un message(attribute 0 en attente)
00250         if ((*i)->state[0] == ObjectBroadcastLine::waiting) {
00251 
00252             // 1. Envoyer le message au federe
00253             D.Out(pdProtocol,
00254                   "Broadcasting message to Federate %d.", (*i)->Federate);
00255             try {
00256                 socket = server->getSocketLink((*i)->Federate);
00257                 // socket NULL means federate dead (killed ?)
00258                 if ( socket != NULL )
00259                     message->send(socket,NM_msgBufSend);
00260             }
00261             catch (RTIinternalError &e) {
00262                 D.Out(pdExcept,
00263                       "Reference to a killed Federate while broadcasting.");
00264             }
00265             catch (NetworkError &e) {
00266                 D.Out(pdExcept, "Network error while broadcasting, ignoring.");
00267             }
00268 
00269             // 2. Marquer le federe comme ayant recu le message.
00270             (*i)->state[0] = ObjectBroadcastLine::sent ;
00271         }
00272         else
00273             D.Out(pdProtocol, "No message sent to Federate %d.",
00274                   (*i)->Federate);
00275     }
00276 }
00277 
00278 // ----------------------------------------------------------------------------
00291 void ObjectClassBroadcastList::sendPendingMessage(SecurityServer *server)
00292 {
00293     G.Out(pdGendoc,"enter ObjectClassBroadcastList::sendPendingMessage");
00294     switch (message->getType()) {
00295 
00296       case NetworkMessage::REFLECT_ATTRIBUTE_VALUES:
00297       case NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION:
00298         sendPendingRAVMessage(server);
00299         break ;
00300 
00301       case NetworkMessage::DISCOVER_OBJECT:
00302       case NetworkMessage::REMOVE_OBJECT:
00303         sendPendingDOMessage(server);
00304         break ;
00305 
00306       default:
00307         throw RTIinternalError("Unknown message type to broadcast.");
00308     G.Out(pdGendoc,"exit  ObjectClassBroadcastList::sendPendingMessage");
00309     }
00310 }
00311 
00312 // ---------------------------
00313 // -- SendPendingRAVMessage --
00314 // ---------------------------
00315 
00316 void
00317 ObjectClassBroadcastList::sendPendingRAVMessage(SecurityServer *server)
00318 {
00319     Socket *socket = 0 ;
00320     NetworkMessage *currentMessage = 0 ;
00321 
00322     G.Out(pdGendoc,"enter ObjectClassBroadcastList::sendPendingRAVMessage");
00323     // For each line :
00324     list<ObjectBroadcastLine *>::iterator i ;
00325     for (i = lines.begin(); i != lines.end(); i++) {
00326 
00327         // Si AU MOINS UN des attributs est en ObjectBroadcastLine::waiting
00328         if (isWaiting(*i)) {
00329 
00330             // 1. Est-ce que tous les attributs du message sont en
00331             // ObjectBroadcastLine::waiting ?
00332             bool all_waiting = true ;
00333             for (unsigned int attrIndex = 0 ;
00334                  attrIndex < message->handleArraySize ;
00335                  attrIndex ++) {
00336                 AttributeHandle attrib = message->handleArray[attrIndex] ;
00337                 if ((*i)->state[attrib] != ObjectBroadcastLine::waiting)
00338                     all_waiting = false ;
00339             }
00340 
00341             if (!all_waiting) {
00342                 // NO: Create a new message containing only ObjectBroadcastLine::waiting
00343                 // attributes.
00344                 currentMessage = adaptMessage(*i);
00345                 D.Out(pdProtocol,
00346                       "Broadcasting reduced message to Federate %d.",
00347                       (*i)->Federate);
00348             }
00349             else {
00350                 // YES: Nothing to do.
00351                 currentMessage = message ;
00352                 D.Out(pdProtocol,
00353                       "Broadcasting complete message to Federate %d.",
00354                       (*i)->Federate);
00355             }
00356 
00357             // 2. Send message (or reduced one).
00358             try {
00359 #ifdef HLA_USES_UDP
00360                 socket = server->getSocketLink((*i)->Federate, BEST_EFFORT);
00361 #else
00362                 socket = server->getSocketLink((*i)->Federate);
00363 #endif
00364                 // socket NULL means federate is dead (killed ?)
00365                 if ( socket != NULL )
00366                    {
00367                    G.Out(pdGendoc,"                                 sendPendingRAVMessage=====> write");
00368                    currentMessage->send(socket,NM_msgBufSend);
00369                    }
00370             }
00371             catch (RTIinternalError &e) {
00372                 D.Out(pdExcept,
00373                       "Reference to a killed Federate while broadcasting.");
00374             }
00375             catch (NetworkError &e) {
00376                 D.Out(pdExcept, "Network error while broadcasting, ignoring.");
00377             }
00378 
00379             // 3. marquer les attributs en ObjectBroadcastLine::sent.
00380             for (unsigned int attrIndex = 1 ;
00381                  attrIndex <= maxHandle ;
00382                  attrIndex ++) {
00383                 if ((*i)->state[attrIndex] == ObjectBroadcastLine::waiting) {
00384                     (*i)->state[attrIndex] = ObjectBroadcastLine::sent ;
00385                 }
00386             }
00387 
00388             // 4. Eventuellement effacer la copie du message.
00389             if (currentMessage != message) {
00390                 delete currentMessage ;
00391                 currentMessage = NULL ;
00392             }
00393 
00394         } // Si AU MOINS UN des attributs est en ObjectBroadcastLine::waiting
00395         else
00396             D.Out(pdProtocol, "No message sent to Federate %d.",
00397                   (*i)->Federate);
00398     G.Out(pdGendoc,"exit  ObjectClassBroadcastList::sendPendingRAVMessage");
00399     }
00400 }
00401 
00402 } // namespace certi
00403 
00404 // $Id: ObjectClassBroadcastList.cc,v 3.25 2008/09/18 14:41:29 gotthardp Exp $

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