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