# ObjectClass.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: ObjectClass.cc,v 3.64 2008/12/16 07:08:29 approx Exp $
    00023 // ----------------------------------------------------------------------------
    00024
    00025 #include  "Object.hh"
    00026 #include  "ObjectAttribute.hh"
    00027 #include  "ObjectClass.hh"
    00028 #include  "ObjectClassAttribute.hh"
    00029 #include  "ObjectClassSet.hh"
    00030 #include  "ObjectClassBroadcastList.hh"
    00031 #include  "NM_Classes.hh"
    00032
    00033 #include "SocketTCP.hh"
    00034 #include "PrettyDebug.hh"
    00035 #include "helper.hh"
    00036 #include <sstream>
    00037 #include <memory>
    00038
    00039 #ifdef _WIN32
    00040     #include <windows.h>
    00041     #include <algorithm>
    00042     #ifdef max
    00043         #undef max
    00044     #endif
    00045 #else
    00046     #include <iostream>
    00047 #endif
    00048 #include <assert.h>
    00049
    00050 using std::cout ;
    00051 using std::endl ;
    00052 using std::list ;
    00053
    00054 namespace certi {
    00055
    00056 static pdCDebug D("OBJECTCLASS", __FILE__);
    00057 static PrettyDebug G("GENDOC",__FILE__);
    00058
    00059 // ----------------------------------------------------------------------------
    00061 AttributeHandle
    00062 ObjectClass::addAttribute(ObjectClassAttribute *theAttribute,
    00063                           bool is_inherited)
    00064 {
    00065     if (theAttribute == NULL)
    00066         throw RTIinternalError("Tried to add NULL attribute.");
    00067
    00068     theAttribute->setHandle(attributeSet.size() + 1);
    00069     theAttribute->server = server ;
    00070
    00071     // If the attribute is inherited, it keeps its security level.
    00072     // If not, it takes the default security level of the class.
    00073     if (!is_inherited)
    00074         theAttribute->level = securityLevelId ;
    00075
    00076     attributeSet.push_front(theAttribute);
    00077
    00078     D.Out(pdProtocol, "ObjectClass %u has a new attribute %u.",
    00079           handle, theAttribute->getHandle());
    00080
    00081     return theAttribute->getHandle();
    00082 }
    00083
    00084 // ----------------------------------------------------------------------------
    00086 void
    00087 ObjectClass::addInheritedClassAttributes(ObjectClass *the_child)
    00088 {
    00089     // The Attribute List is read backwards to respect the same attribute order
    00090     // for the child(Attributes are inserted at the beginning of the list).
    00091     ObjectClassAttribute *childAttribute = NULL ;
    00092     list<ObjectClassAttribute *>::reverse_iterator a ;
    00093     for (a = attributeSet.rbegin(); a != attributeSet.rend(); a++) {
    00094         assert((*a) != NULL);
    00095
    00096         childAttribute = new ObjectClassAttribute(*a);
    00097         assert(childAttribute != NULL);
    00098
    00099         D.Out(pdProtocol,
    00100               "ObjectClass %u adding new attribute %d to child class %u.",
    00101               handle, (*a)->getHandle(), the_child->getHandle());
    00102
    00103         the_child->addAttribute(childAttribute);
    00104
    00105         if (childAttribute->getHandle() != (*a)->getHandle())
    00106             throw RTIinternalError("Error while copying child's attributes.");
    00107     }
    00108 } /* end of addInheritedClassAttributes */
    00109
    00110 // ----------------------------------------------------------------------------
    00115 void
    00116 ObjectClass::broadcastClassMessage(ObjectClassBroadcastList *ocbList,
    00117                    const Object *source)
    00118 {
    00119     int i, trouve;
    00120     G.Out(pdGendoc,"enter ObjectClass::broadcastClassMessage");
    00121     // 1. Set ObjectHandle to local class Handle.
    00122     ocbList->message->objectClass = handle ;
    00123
    00124     G.Out(pdGendoc,"      ObjectClass::broadcastClassMessage handle=%d",handle);
    00125
    00126     // 2. Update message attribute list by removing child's attributes.
    00127     if ((ocbList->message->getType() == NetworkMessage::REFLECT_ATTRIBUTE_VALUES) ||
    00128         (ocbList->message->getType() == NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION)) {
    00129         int attr = 0 ;
    00130         while (attr < ocbList->message->handleArraySize) {
    00131             // If the attribute is not in that class, remove it from
    00132             // the message.
    00133             try {
    00134                 getAttribute(ocbList->message->handleArray[attr]);
    00135                 attr++ ;
    00136             }
    00137             catch (AttributeNotDefined &e) {
    00138                 ocbList->message->removeAttribute(attr);
    00139             }
    00140         }
    00141     }
    00142
    00143     // 3. Add class/attributes subscribers to the list.
    00144     switch(ocbList->message->getType()) {
    00145       case NetworkMessage::DISCOVER_OBJECT:
    00146       case NetworkMessage::REMOVE_OBJECT: {
    00147           // For each federate, add it to list if at least one attribute has
    00148           // been subscribed.
    00149           FederateHandle federate = 0 ;
    00150           for (federate = 1 ; federate <= maxSubscriberHandle ; federate++) {
    00151               if (isSubscribed(federate) && (federate != ocbList->message->federate)) {
    00152                   ocbList->addFederate(federate);
    00153               }
    00154           }
    00155       } break ;
    00156
    00157       case NetworkMessage::REFLECT_ATTRIBUTE_VALUES: {
    00158           // For each class attribute, update the list be adding federates who
    00159           // subscribed to the attribute.
    00160           list<ObjectClassAttribute *>::const_iterator a ;
    00161           for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00162               // Do not consider attributes that are not updated
    00163               trouve = 0;
    00164               for (i=0 ; i< ocbList->message->handleArraySize ; i++) {
    00165                   if ((*a)->getHandle() == ocbList->message->handleArray[i])
    00166                      trouve = 1;
    00167               }
    00168               if (trouve) {
    00169              ObjectAttribute *attr = source->getAttribute((*a)->getHandle());
    00170                  const RTIRegion *update_region = attr->getRegion();
    00171              D[pdTrace] << "RAV: attr " << (*a)->getHandle()
    00172                 << " / region " << (update_region ? update_region->getHandle() : 0)
    00173                 << std::endl ;
    00174                  (*a)->updateBroadcastList(ocbList, update_region);
    00175               }
    00176           }
    00177       } break ;
    00178
    00179       case NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION: {
    00180           // For each class attribute, update the list be adding federates who
    00181           // subscribed to the attribute.
    00182           list<ObjectClassAttribute *>::const_iterator a ;
    00183           for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00184               (*a)->updateBroadcastList(ocbList);
    00185           }
    00186       } break ;
    00187
    00188       default:
    00189         throw RTIinternalError("BroadcastClassMsg: Unknown type.");
    00190     }
    00191
    00192     // 4. Send pending messages.
    00193     ocbList->sendPendingMessage(server);
    00194     G.Out(pdGendoc,"exit  ObjectClass::broadcastClassMessage");
    00195 }
    00196
    00197 // ----------------------------------------------------------------------------
    00199 void
    00200 ObjectClass::sendToFederate(NetworkMessage *msg, FederateHandle theFederate)
    00201 {
    00202     // Send the message 'msg' to the Federate which Handle is theFederate.
    00203     Socket *socket = NULL ;
    00204     try {
    00205 #ifdef HLA_USES_UDP
    00206         socket = server->getSocketLink(theFederate, BEST_EFFORT);
    00207 #else
    00208         socket = server->getSocketLink(theFederate);
    00209 #endif
    00210         msg->send(socket,NM_msgBufSend);
    00211     }
    00212     catch (RTIinternalError &e) {
    00213         D.Out(pdExcept,
    00214               "Reference to a killed Federate while broadcasting.");
    00215     }
    00216     catch (NetworkError &e) {
    00217         D.Out(pdExcept, "Network error while broadcasting, ignoring.");
    00218     }
    00219     // BUG: If except = 0, could use Multicast.
    00220 }
    00221
    00222 // ----------------------------------------------------------------------------
    00224 void
    00225 ObjectClass::sendToOwners(CDiffusion *diffusionList,
    00226                           ObjectHandle theObjectHandle,
    00227                           FederateHandle theFederate,
    00228                           const char *theTag,
    00229                           NetworkMessage::Type type)
    00230 {
    00231     int nbAttributes = diffusionList->size ;
    00232
    00233     FederateHandle toFederate ;
    00234     for (int i = 0 ; i < nbAttributes ; i++) {
    00235         toFederate = diffusionList->DiffArray[i].federate ;
    00236         if (toFederate != 0) {
    00237             std::auto_ptr<NetworkMessage> answer(NM_Factory::create(type));
    00238             answer->federation = server->federation();
    00239             answer->federate = theFederate ;
    00240             answer->object = theObjectHandle ;
    00241             answer->setLabel(theTag);
    00242             answer->handleArray.resize(nbAttributes) ;
    00243
    00244             int index = 0 ;
    00245             for (int j = i ; j < nbAttributes ; j++) {
    00246                 if (diffusionList->DiffArray[j].federate == toFederate) {
    00247                     D.Out(pdDebug, "handle : %u",
    00248                           diffusionList->DiffArray[j].attribute);
    00249                     diffusionList->DiffArray[j].federate = 0 ;
    00250                     answer->handleArray[index] = diffusionList
    00251                         ->DiffArray[j].attribute ;
    00252                     index++ ;
    00253                 }
    00254             }
    00255             answer->handleArraySize = index ;
    00256             D.Out(pdDebug, "Envoi message type %u ", type);
    00257             sendToFederate(answer.get(), toFederate);
    00258         }
    00259     }
    00260 }
    00261
    00262 // ----------------------------------------------------------------------------
    00266 void
    00267 ObjectClass::checkFederateAccess(FederateHandle the_federate,
    00268                                  const char *reason)
    00269     throw (SecurityError)
    00270 {
    00271     D.Out(pdInit, "Beginning of CheckFederateAccess for the federate %d",
    00272           the_federate);
    00273
    00274     // BUG: Should at least but a line in Audit
    00275     if (server == NULL)
    00276         return ;
    00277
    00278     bool result = server->canFederateAccessData(the_federate, securityLevelId);
    00279
    00280     // BUG: Should use Audit.
    00281     if (!result) {
    00282         cout << "Object Class " << handle << " : SecurityError for federate "
    00283              << the_federate << '(' << reason << ")." << endl ;
    00284         throw SecurityError("Federate should not access Object Class.");
    00285     }
    00286 }
    00287
    00288 // ----------------------------------------------------------------------------
    00289 ObjectClass::ObjectClass(std::string name, ObjectClassHandle handle)
    00290     : Named(name), server(NULL), handle(handle), maxSubscriberHandle(0), securityLevelId(PublicLevelID),
    00291       superClass(0), subClasses(NULL)
    00292 {
    00293     subClasses = new ObjectClassSet(NULL);
    00294 }
    00295
    00296 // ----------------------------------------------------------------------------
    00298 ObjectClass::~ObjectClass()
    00299 {
    00300     // Deleting instances
    00301     if (!objectSet.empty())
    00302         D.Out(pdError,
    00303               "ObjectClass %d : Instances remaining while exiting...", handle);
    00304
    00305     // Deleting Class Attributes
    00306     while (!attributeSet.empty()) {
    00307         delete attributeSet.front();
    00308         attributeSet.pop_front();
    00309     }
    00310     // Deleting subclasses
    00311     if (NULL!=subClasses) {
    00312         delete subClasses;
    00313     }
    00314 } /* end of ObjectClass destructor */
    00315
    00316 // ----------------------------------------------------------------------------
    00317 /* Delete Instance with time.
    00318    Delete the object instance 'theObjectHandle', and starts to
    00319    broadcast the RemoveObject message. Return a BroadcastList of
    00320    Federates, in order to allow our ObjectClassSet to go on with
    00321    the message broadcasting, by giving the list to our parent
    00322    class.
    00323 */
    00324 ObjectClassBroadcastList *
    00325 ObjectClass::deleteInstance(FederateHandle the_federate,
    00326                             ObjectHandle the_object,
    00327                 FederationTime theTime,
    00328                             std::string the_tag)
    00329     throw (DeletePrivilegeNotHeld,
    00330            ObjectNotKnown,
    00331            RTIinternalError)
    00332 {
    00333
    00334     // 1. Pre-conditions checking(may throw ObjectNotKnown)
    00335     Object *object = getInstanceWithID(the_object);
    00336
    00337     // Is the Federate really the Object Owner?(Checked only on RTIG)
    00338     if ((server != 0) && (object->getOwner() != the_federate)) {
    00339         D.Out(pdExcept, "Delete Object %d: Federate %d not owner.",
    00340               the_object, the_federate);
    00341         throw DeletePrivilegeNotHeld("");
    00342     }
    00343
    00344     // 2. Remove Instance from list.
    00345     list<Object *>::iterator o ;
    00346     for (o = objectSet.begin(); o != objectSet.end(); o++) {
    00347         if ((*o)->getHandle() == the_object) {
    00348             objectSet.erase(o); // i is dereferenced.
    00349             break ;
    00350         }
    00351     }
    00352
    00353     // 3. Prepare and broadcast message.
    00354     ObjectClassBroadcastList *ocbList = NULL ;
    00355     if (server != NULL) {
    00356         D.Out(pdRegister,
    00357               "Object %u deleted in class %u, now broadcasting...",
    00358               the_object, handle);
    00359
    00360         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REMOVE_OBJECT);
    00361         answer->federation = server->federation();
    00362         answer->federate = the_federate ;
    00363         answer->exception = e_NO_EXCEPTION ;
    00364         answer->objectClass = handle ; // Class Handle
    00365         answer->object = the_object ;
    00366
    00367     // with time
    00368         answer->setDate(theTime);
    00369         answer->setLabel(the_tag);
    00370
    00371         ocbList = new ObjectClassBroadcastList(answer, 0);
    00372         broadcastClassMessage(ocbList);
    00373     }
    00374     else {
    00375         D.Out(pdRegister,
    00376               "Object %u deleted in class %u, no broadcast to do.",
    00377               the_object, handle);
    00378     }
    00379
    00380     // Return the BroadcastList in case it had to be passed to the parent
    00381     // class.
    00382     return ocbList ;
    00383 }
    00384
    00385 // ----------------------------------------------------------------------------
    00386 /* Delete Instance without time.
    00387    Delete the object instance 'theObjectHandle', and starts to
    00388    broadcast the RemoveObject message. Return a BroadcastList of
    00389    Federates, in order to allow our ObjectClassSet to go on with
    00390    the message broadcasting, by giving the list to our parent
    00391    class.
    00392 */
    00393 ObjectClassBroadcastList *
    00394 ObjectClass::deleteInstance(FederateHandle the_federate,
    00395                             ObjectHandle the_object,
    00396                             std::string the_tag)
    00397     throw (DeletePrivilegeNotHeld,
    00398            ObjectNotKnown,
    00399            RTIinternalError)
    00400 {
    00401     // 1. Pre-conditions checking(may throw ObjectNotKnown)
    00402     Object *object = getInstanceWithID(the_object);
    00403
    00404     // Is the Federate really the Object Owner?(Checked only on RTIG)
    00405     if ((server != 0) && (object->getOwner() != the_federate)) {
    00406         D.Out(pdExcept, "Delete Object %d: Federate %d not owner.",
    00407               the_object, the_federate);
    00408         throw DeletePrivilegeNotHeld("");
    00409     }
    00410
    00411     // 2. Remove Instance from list.
    00412     list<Object *>::iterator o ;
    00413     for (o = objectSet.begin(); o != objectSet.end(); o++) {
    00414         if ((*o)->getHandle() == the_object) {
    00415             objectSet.erase(o); // i is dereferenced.
    00416             break ;
    00417         }
    00418     }
    00419
    00420     // 3. Prepare and broadcast message.
    00421     ObjectClassBroadcastList *ocbList = NULL ;
    00422     if (server != NULL) {
    00423         D.Out(pdRegister,
    00424               "Object %u deleted in class %u, now broadcasting...",
    00425               the_object, handle);
    00426
    00427         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REMOVE_OBJECT);
    00428         answer->federation = server->federation();
    00429         answer->federate = the_federate ;
    00430         answer->objectClass = handle ; // Class Handle
    00431         answer->object = the_object ;
    00432
    00433         // without time
    00434
    00435         answer->setLabel(the_tag);
    00436
    00437         ocbList = new ObjectClassBroadcastList(answer, 0);
    00438         broadcastClassMessage(ocbList);
    00439     }
    00440     else {
    00441         D.Out(pdRegister,
    00442               "Object %u deleted in class %u, no broadcast to do.",
    00443               the_object, handle);
    00444     }
    00445
    00446     // Return the BroadcastList in case it had to be passed to the parent
    00447     // class.
    00448     return ocbList ;
    00449 }
    00450
    00451 // ----------------------------------------------------------------------------
    00453 void ObjectClass::display() const
    00454 {
    00455     cout << " ObjectClass #" << handle << " \"" << name << "\":" << endl ;
    00456
    00457     // Display inheritance
    00458     cout << " Parent Class Handle: " << superClass << endl ;
    00459     cout << " Security Level: " << securityLevelId << endl ;
    00460     cout << " " << subClasses->size() << " Child(s):" << endl ;
    00461     cout << " Subclasses handles:" ;
    00462     ObjectClassSet::const_iterator i ;
    00463     for (i = subClasses->begin(); i != subClasses->end(); ++i) {
    00464         cout << " " << i->second->getHandle() << endl;
    00465     }
    00466
    00467
    00468     // Display Attributes
    00469     cout << " " << attributeSet.size() << " Attribute(s):" << endl ;
    00470     list<ObjectClassAttribute *>::const_iterator a ;
    00471     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00472         (*a)->display();
    00473     }
    00474
    00475     // Display Instances
    00476     cout << " " << objectSet.size() << " Instances(s):" << endl ;
    00477     list<Object *>::const_iterator o ;
    00478     for (o = objectSet.begin(); o != objectSet.end(); o++) {
    00479         (*o)->display();
    00480     }
    00481 }
    00482
    00483 // ----------------------------------------------------------------------------
    00485 AttributeHandle
    00486 ObjectClass::getAttributeHandle(const char *the_name) const
    00487     throw (NameNotFound, RTIinternalError)
    00488 {
    00489     G.Out(pdGendoc,"enter ObjectClass::getAttributeHandle");
    00490
    00491     list<ObjectClassAttribute *>::const_iterator a ;
    00492     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00493         if ((*a)->isNamed(std::string(the_name))) {
    00494             G.Out(pdGendoc,"exit  ObjectClass::getAttributeHandle");
    00495             return (*a)->getHandle();
    00496         }
    00497     }
    00498
    00499     D.Out(pdExcept, "ObjectClass %u: Attribute \"%s\" not defined.",
    00500           handle, the_name);
    00501     G.Out(pdGendoc,"exit  ObjectClass::getAttributeHandle on NameNotFound");
    00502     throw NameNotFound(the_name);
    00503 }
    00504
    00505 // ----------------------------------------------------------------------------
    00507 const char *
    00508 ObjectClass::getAttributeName(AttributeHandle the_handle) const
    00509     throw (AttributeNotDefined,
    00510            RTIinternalError)
    00511 {
    00512     return getAttribute(the_handle)->getCName();
    00513 }
    00514
    00515
    00516 // ----------------------------------------------------------------------------
    00521 ObjectClassAttribute *
    00522 ObjectClass::getAttribute(AttributeHandle the_handle) const
    00523     throw (AttributeNotDefined)
    00524 {
    00525     list<ObjectClassAttribute *>::const_iterator a ;
    00526     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00527         if ((*a)->getHandle() == the_handle)
    00528             return (*a);
    00529     }
    00530
    00531     D.Out(pdExcept, "ObjectClass %d: Attribute %d not defined.",
    00532           handle, the_handle);
    00533
    00534     throw AttributeNotDefined("");
    00535 }
    00536
    00537 // ----------------------------------------------------------------------------
    00539 Object *
    00540 ObjectClass::getInstanceWithID(ObjectHandle the_id) const
    00541     throw (ObjectNotKnown)
    00542 {
    00543     std::stringstream msg;
    00544
    00545     list<Object *>::const_iterator o ;
    00546     for (o = objectSet.begin(); o != objectSet.end(); o++) {
    00547         if ((*o)->getHandle() == the_id)
    00548             return (*o);
    00549     }
    00550
    00551     msg << "Could not find ObjectHandle <" << the_id << "> among <"
    00552            << objectSet.size() << "> objects of ObjectClass "
    00553            << handle;
    00554
    00555     D[pdError] << msg.str().c_str() << std::endl ;
    00556
    00557     throw ObjectNotKnown(msg.str().c_str());
    00558 }
    00559
    00560 // ----------------------------------------------------------------------------
    00562 bool
    00563 ObjectClass::isFederatePublisher(FederateHandle the_federate) const
    00564 {
    00565     D.Out(pdRegister, "attributeSet.size() = %d.", attributeSet.size());
    00566
    00567     list<ObjectClassAttribute *>::const_iterator a ;
    00568     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00569         if ((*a)->isPublishing(the_federate))
    00570             return true ;
    00571     }
    00572     return false ;
    00573 }
    00574
    00575 // ----------------------------------------------------------------------------
    00581 bool
    00582 ObjectClass::isSubscribed(FederateHandle fed) const
    00583 {
    00584     list<ObjectClassAttribute *>::const_iterator a ;
    00585     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00586         if ((*a)->isSubscribed(fed))
    00587             return true ;
    00588     }
    00589     return false ;
    00590 }
    00591
    00592 // ----------------------------------------------------------------------------
    00596 bool
    00597 ObjectClass::isInstanceInClass(ObjectHandle theID)
    00598 {
    00599     try {
    00600         getInstanceWithID(theID);
    00601     }
    00602     catch (ObjectNotKnown &e) {
    00603         return false ;
    00604     }
    00605     return true ;
    00606 }
    00607
    00608 // ----------------------------------------------------------------------------
    00610 ObjectClassBroadcastList *
    00611 ObjectClass::killFederate(FederateHandle the_federate)
    00612     throw ()
    00613 {
    00614     D.Out(pdRegister, "Object Class %d: Killing Federate %d.",
    00615           handle, the_federate);
    00616     std::vector <AttributeHandle> liste_vide ;
    00617     liste_vide.empty();
    00618     try {
    00619         // Does federate is publishing something ? (not important)
    00620         if (isFederatePublisher(the_federate)) {
    00621             publish(the_federate, liste_vide, 0, false);
    00622         }
    00623
    00624         // Does federate subscribed something ?
    00625         // Problem, no removeObject or discover must not be sent to it.
    00626         if (isSubscribed(the_federate)) {
    00627             unsubscribe(the_federate);
    00628         }
    00629     }
    00630     catch (SecurityError &e) {}
    00631
    00632     // Does federate owns instances ?
    00633     list<Object *>::iterator o ;
    00634     for (o = objectSet.begin(); o != objectSet.end(); o++) {
    00635         if ((*o)->getOwner() == the_federate) {
    00636             // Return non-NULL to indicate that :
    00637             // 1- A RemoveObject message should be broadcasted through parent
    00638             // class
    00639             // 2- The federate may own another instance, and this function
    00640             // must be called again.
    00641             // BUG: String \/
    00642             return deleteInstance(the_federate, (*o)->getHandle(), "Killed");
    00643         }
    00644     }
    00645
    00646     D.Out(pdRegister, "Object Class %d:Federate %d killed.",
    00647           handle, the_federate);
    00648
    00649     // Return NULL if the Federate did not own any instance.
    00650     return NULL ;
    00651 }
    00652
    00653 // ----------------------------------------------------------------------------
    00655 void
    00656 ObjectClass::publish(FederateHandle theFederateHandle,
    00657                      std::vector <AttributeHandle> &theAttributeList,
    00658                      UShort theListSize,
    00659                      bool PubOrUnpub)
    00660     throw (AttributeNotDefined,
    00661            RTIinternalError,
    00662            SecurityError)
    00663 {
    00664     D.Out(pdInit, "Beginning of Publish for the federate %d",
    00665           theFederateHandle);
    00666
    00667     // Do all attribute handles exist ? It may throw AttributeNotDefined.
    00668     for (UShort index = 0 ; index < theListSize ; index++)
    00669         getAttribute(theAttributeList[index]);
    00670
    00671     // Check Security Levels
    00672     checkFederateAccess(theFederateHandle, "Publish");
    00673
    00674     // Reset all previous publish information.
    00675     D.Out(pdInit, "ObjectClass %d: Reset publish info of Federate %d.",
    00676           handle, theFederateHandle);
    00677
    00678     list<ObjectClassAttribute *>::const_iterator a ;
    00679     for (a = attributeSet.begin(); a != attributeSet.end(); a++) {
    00680         if ((*a)->isPublishing(theFederateHandle))
    00681             (*a)->unpublish(theFederateHandle);
    00682     }
    00683
    00684     // Publish attributes one by one.
    00685     ObjectClassAttribute * attribute ;
    00686     for (UShort i = 0 ; i < theListSize ; i++) {
    00687         D.Out(pdInit, "ObjectClass %d: Federate %d publishes attribute %d.",
    00688               handle, theFederateHandle, theAttributeList[i]);
    00689         attribute = getAttribute(theAttributeList[i]);
    00690     if (PubOrUnpub)
    00691         attribute->publish(theFederateHandle);
    00692     else
    00693         attribute->unpublish(theFederateHandle);
    00694     }
    00695 }
    00696
    00697 // ----------------------------------------------------------------------------
    00703 ObjectClassBroadcastList *
    00704 ObjectClass::registerObjectInstance(FederateHandle the_federate,
    00705                                     Object *the_object,
    00706                                     ObjectClassHandle classHandle)
    00707     throw (ObjectClassNotPublished,
    00708            ObjectAlreadyRegistered,
    00709            RTIinternalError)
    00710 {
    00711     // Pre-conditions checking
    00712     if (isInstanceInClass(the_object->getHandle())) {
    00713         D.Out(pdExcept, "exception : ObjectAlreadyRegistered.");
    00714         throw ObjectAlreadyRegistered(the_object->getName().c_str());
    00715     }
    00716
    00717     // This condition is only to be checked on the RTIG
    00718     if ((server != NULL) && (!isFederatePublisher(the_federate))) {
    00719         D.Out(pdExcept, "exception : ObjectClassNotPublished.");
    00720         throw ObjectClassNotPublished("");
    00721     }
    00722
    00723     // Ownership management :
    00724     // Copy instance attributes
    00725     // Federate only owns attributes it publishes.
    00726     ObjectAttribute * oa ;
    00727     list<ObjectClassAttribute *>::reverse_iterator a ;
    00728     for (a = attributeSet.rbegin(); a != attributeSet.rend(); a++) {
    00729     oa = new ObjectAttribute((*a)->getHandle(),
    00730                  (*a)->isPublishing(the_federate) ? the_federate : 0,
    00731                  *a);
    00732
    00733         // privilegeToDelete is owned by federate even not published.
    00734         if ((*a)->isNamed("privilegeToDelete")) {
    00735             oa->setOwner(the_federate);
    00736         }
    00737
    00738         the_object->addAttribute(oa);
    00739     }
    00740
    00741     objectSet.push_front(the_object);
    00742     D[pdTrace] << "Added object " << the_object->getHandle() << "/"
    00743            << objectSet.size() << " to class " << handle << std::endl ;
    00744
    00745     // Prepare and Broadcast message for this class
    00746     ObjectClassBroadcastList *ocbList = NULL ;
    00747     if (server != NULL) {
    00748         D.Out(pdRegister,
    00749               "Object %u registered in class %u, now broadcasting...",
    00750               the_object->getHandle(), handle);
    00751
    00752         NM_Discover_Object *answer = new NM_Discover_Object();
    00753         answer->federation  = server->federation();
    00754         answer->federate    = the_federate ;
    00755         answer->exception   = e_NO_EXCEPTION ;
    00756         answer->objectClass = handle ; // Class Handle
    00757         answer->object      = the_object->getHandle();
    00758         answer->setLabel(the_object->getName().c_str());
    00759     // BUG FIXME strange!!
    00760     //answer->setDate(0.0);
    00761
    00762         ocbList = new ObjectClassBroadcastList(answer, 0);
    00763         broadcastClassMessage(ocbList);
    00764     }
    00765     else {
    00766         D.Out(pdRegister,
    00767               "Object %u registered in class %u, no broadcast to do.",
    00768               the_object->getHandle(), handle);
    00769     }
    00770
    00771     // Return the BroadcastList in case it had to be passed to the parent
    00772     // class.
    00773     return ocbList ;
    00774 }
    00775
    00776 // ----------------------------------------------------------------------------
    00786 bool
    00787 ObjectClass::sendDiscoverMessages(FederateHandle federate,
    00788                                   ObjectClassHandle super_handle)
    00789 {
    00790     // If we are in a subclass to which the federate is already subscribed,
    00791     if ((handle != super_handle) && isSubscribed(federate))
    00792         return false ;
    00793
    00794     // Else, send message for each object
    00795     list<Object *>::const_iterator o ;
    00796     for (o = objectSet.begin(); o != objectSet.end(); ++o) {
    00797     if ((*o)->getOwner() != federate) {
    00798         NM_Discover_Object message;
    00799         D.Out(pdInit,
    00800           "Sending DiscoverObj to Federate %d for Object %u in class %u ",
    00801           federate, (*o)->getHandle(), handle, message.getLabel().c_str());
    00802
    00803         message.federation  = server->federation();
    00804         message.federate    = federate ;
    00805         message.exception   = e_NO_EXCEPTION ;
    00806         message.objectClass = super_handle ;
    00807         message.object      = (*o)->getHandle();
    00808         message.setLabel((*o)->getName().c_str());
    00809         //BUG FIXME strange!!
    00810         //message.setDate(0.0);
    00811
    00812         Socket *socket = NULL ;
    00813         try {
    00814         socket = server->getSocketLink(federate);
    00815         message.send(socket,NM_msgBufSend);
    00816         }
    00817         catch (RTIinternalError &e) {
    00818         D.Out(pdExcept,
    00819               "Reference to a killed Federate while sending DO msg.");
    00820         }
    00821         catch (NetworkError &e) {
    00822         D.Out(pdExcept, "Network error while sending DO msg, ignoring.");
    00823         }
    00824         }
    00825     }
    00826
    00827     return true ;
    00828 }
    00829
    00830 // A class' LevelID can only be increased.
    00831 void
    00832 ObjectClass::setSecurityLevelId(SecurityLevelID new_levelID) throw (SecurityError)
    00833 {
    00834     if (!server->dominates(new_levelID, securityLevelId))
    00835         throw SecurityError("Attempt to lower object class level.");
    00836
    00837     securityLevelId = new_levelID ;
    00838 }
    00839
    00840 // ----------------------------------------------------------------------------
    00850 bool
    00851 ObjectClass::subscribe(FederateHandle fed,
    00852         std::vector <AttributeHandle> &attributes,
    00853         int nb_attributes,
    00854         const RTIRegion *region)
    00855 throw (AttributeNotDefined, RTIinternalError, SecurityError)
    00856 {
    00857     checkFederateAccess(fed, "Subscribe");
    00858
    00859     for (int i = 0 ; i < nb_attributes ; ++i) // Check attributes
    00860         getAttribute(attributes[i]);
    00861
    00862     if (nb_attributes > 0)
    00863         maxSubscriberHandle = std::max(fed, maxSubscriberHandle);
    00864
    00865     bool was_subscriber = isSubscribed(fed);
    00866
    00867     // FIXME what does this means?
    00868     unsubscribe(fed, region);
    00869
    00870     D[pdTrace] << "ObjectClass::subscribe" << " : fed " << fed << ", class " << handle
    00871     << ", " << nb_attributes << " attributes, region "
    00872     << (region ? region->getHandle() : 0) << std::endl ;
    00873
    00874     for (int i = 0 ; i < nb_attributes ; ++i) {
    00875         getAttribute(attributes[i])->subscribe(fed, region);
    00876     }
    00877
    00878     return (nb_attributes > 0) && !was_subscriber ;
    00879 } /* end of subscribe */
    00880
    00881 // ----------------------------------------------------------------------------
    00883 ObjectClassBroadcastList *
    00884 ObjectClass::updateAttributeValues(FederateHandle the_federate,
    00885                                    Object *object,
    00886                                    std::vector <AttributeHandle> &the_attributes,
    00887                                    std::vector <AttributeValue_t> &the_values,
    00888                                    int the_size,
    00889                                    FederationTime the_time,
    00890                                    const char *the_tag)
    00891     throw (ObjectNotKnown,
    00892            AttributeNotDefined,
    00893            AttributeNotOwned,
    00894            RTIinternalError,
    00895            InvalidObjectHandle)
    00896 {
    00897     // Ownership management: Test ownership on each attribute before updating.
    00898     ObjectAttribute * oa ;
    00899     for (int i = 0 ; i < the_size ; i++) {
    00900         oa = object->getAttribute(the_attributes[i]);
    00901
    00902         if (oa->getOwner() != the_federate)
    00903             throw AttributeNotOwned("");
    00904     }
    00905
    00906     // Prepare and Broadcast message for this class
    00907     ObjectClassBroadcastList *ocbList = NULL ;
    00908     if (server != NULL) {
    00909         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REFLECT_ATTRIBUTE_VALUES);
    00910         answer->federation = server->federation();
    00911         answer->federate = the_federate ;
    00912         answer->exception = e_NO_EXCEPTION ;
    00913         answer->object = object->getHandle();
    00914         // with time
    00915         answer->setDate(the_time);
    00916         answer->setLabel(the_tag);
    00917         answer->handleArray.resize(the_size) ;
    00918         answer->handleArraySize = the_size ;
    00919         answer->sizeValueArray(the_size) ;
    00920
    00921         for (int i = 0 ; i < the_size ; i++) {
    00922             answer->handleArray[i] = the_attributes[i] ;
    00923             answer->valueArray[i] = the_values[i] ;
    00924         }
    00925
    00926         ocbList = new ObjectClassBroadcastList(answer, attributeSet.size());
    00927
    00928         D.Out(pdProtocol,
    00929               "Object %u updated in class %u, now broadcasting...",
    00930               object->getHandle(), handle);
    00931
    00932         broadcastClassMessage(ocbList, object);
    00933     }
    00934     else {
    00935         D.Out(pdExcept,
    00936               "UpdateAttributeValues should not be called on the RTIA.");
    00937         throw RTIinternalError("UpdateAttributeValues called on the RTIA.");
    00938     }
    00939
    00940     // Return the BroadcastList in case it had to be passed to the parent
    00941     // class.
    00942     return ocbList ;
    00943 }
    00944
    00945 // ----------------------------------------------------------------------------
    00947 ObjectClassBroadcastList *
    00948 ObjectClass::updateAttributeValues(FederateHandle the_federate,
    00949                                    Object *object,
    00950                                    std::vector <AttributeHandle> &the_attributes,
    00951                                    std::vector <AttributeValue_t> &the_values,
    00952                                    int the_size,
    00953                                    const char *the_tag)
    00954     throw (ObjectNotKnown,
    00955            AttributeNotDefined,
    00956            AttributeNotOwned,
    00957            RTIinternalError,
    00958            InvalidObjectHandle)
    00959 {
    00960     // Ownership management: Test ownership on each attribute before updating.
    00961     ObjectAttribute * oa ;
    00962     for (int i = 0 ; i < the_size ; i++) {
    00963         oa = object->getAttribute(the_attributes[i]);
    00964
    00965         if (oa->getOwner() != the_federate)
    00966             throw AttributeNotOwned("");
    00967     }
    00968
    00969     // Prepare and Broadcast message for this class
    00970     ObjectClassBroadcastList *ocbList = NULL ;
    00971     if (server != NULL) {
    00972         NetworkMessage *answer = NM_Factory::create(NetworkMessage::REFLECT_ATTRIBUTE_VALUES) ;
    00973         answer->federation = server->federation();
    00974         answer->federate = the_federate ;
    00975         answer->exception = e_NO_EXCEPTION ;
    00976         answer->object = object->getHandle();
    00977         // without time
    00978
    00979         answer->setLabel(the_tag);
    00980
    00981         answer->handleArraySize = the_size ;
    00982         answer->handleArray.resize(the_size) ;
    00983         answer->sizeValueArray(the_size) ;
    00984
    00985         for (int i = 0 ; i < the_size ; i++) {
    00986             answer->handleArray[i] = the_attributes[i] ;
    00987             answer->valueArray[i] = the_values[i];
    00988         }
    00989
    00990         ocbList = new ObjectClassBroadcastList(answer, attributeSet.size());
    00991
    00992         D.Out(pdProtocol,
    00993               "Object %u updated in class %u, now broadcasting...",
    00994               object->getHandle(), handle);
    00995
    00996         broadcastClassMessage(ocbList, object);
    00997     }
    00998     else {
    00999         D.Out(pdExcept,
    01000               "UpdateAttributeValues should not be called on the RTIA.");
    01001         throw RTIinternalError("UpdateAttributeValues called on the RTIA.");
    01002     }
    01003
    01004     // Return the BroadcastList in case it had to be passed to the parent
    01005     // class.
    01006     return ocbList ;
    01007 }
    01008
    01009 // ----------------------------------------------------------------------------
    01011 ObjectClassBroadcastList * ObjectClass::
    01012 negotiatedAttributeOwnershipDivestiture(FederateHandle theFederateHandle,
    01013                                         ObjectHandle theObjectHandle,
    01014                                         std::vector <AttributeHandle> &theAttributeList,
    01015                                         UShort theListSize,
    01016                                         const char *theTag)
    01017     throw (ObjectNotKnown,
    01018            AttributeNotDefined,
    01019            AttributeNotOwned,
    01020            AttributeAlreadyBeingDivested,
    01021            RTIinternalError)
    01022 {
    01023     // Pre-conditions checking
    01024
    01025     // may throw ObjectNotKnown
    01026     Object *object = getInstanceWithID(theObjectHandle);
    01027
    01028     // Do all attribute handles exist ? It may throw AttributeNotDefined.
    01029     for (int index = 0 ; index < theListSize ; index++)
    01030         getAttribute(theAttributeList[index]);
    01031
    01032     // Does federate owns every attributes.
    01033     // Does federate has called NegotiatedAttributeOwnershipDivestiture.
    01034     D.Out(pdDebug, "NegotiatedDivestiture Demandeur : %u", theFederateHandle);
    01035
    01036     ObjectAttribute * oa ;
    01037     ObjectClassAttribute * oca ;
    01038     for (int i = 0 ; i < theListSize ; i++) {
    01039         oca = getAttribute(theAttributeList[i]);
    01040         oa = object->getAttribute(theAttributeList[i]);
    01041
    01042         D.Out(pdDebug, "Attribute Name : %s", oca->getName().c_str());
    01043         D.Out(pdDebug, "Attribute Handle : %u", oa->getHandle());
    01044         D.Out(pdDebug, "Attribute Owner : %u", oa->getOwner());
    01045         if (oa->getOwner() != theFederateHandle)
    01046             throw AttributeNotOwned("");
    01047         if (oa->beingDivested())
    01048             throw AttributeAlreadyBeingDivested("");
    01049     }
    01050
    01051     int compteur_acquisition = 0 ;
    01052     int compteur_assumption = 0 ;
    01053     int compteur_divestiture = 0 ;
    01054     ObjectClassBroadcastList *List = NULL ;
    01055     FederateHandle NewOwner ;
    01056
    01057     if (server != NULL) {
    01058         NetworkMessage *AnswerAssumption = NM_Factory::create(NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION) ;
    01059         NM_Attribute_Ownership_Divestiture_Notification AnswerDivestiture;
    01060
    01061         AnswerAssumption->handleArraySize = theListSize ;
    01062         AnswerAssumption->handleArray.resize(theListSize) ;
    01063
    01064         // Maximum size
    01065         AnswerDivestiture.handleArray.resize(theListSize) ;
    01066
    01067         CDiffusion diffusionAcquisition;
    01068
    01069         ObjectAttribute * oa ;
    01070         ObjectClassAttribute * oca ;
    01071         for (int i = 0 ; i < theListSize ; i++) {
    01072             oa = object->getAttribute(theAttributeList[i]);
    01073
    01074             if (oa->hasCandidates()) {
    01075                 // An attributeOwnershipAcquisition is on the way
    01076                 // with this attribute.
    01077
    01078                 // Le demandeur le plus recent devient proprietaire
    01079                 NewOwner = oa->getCandidate(1);
    01080
    01081                 oa->setOwner(NewOwner);
    01082
    01083                 // On le supprime de la liste des demandeurs
    01084                 oa->removeCandidate(NewOwner);
    01085
    01086                 // On reinitialise divesting
    01087                 oa->setDivesting(false);
    01088
    01089                 diffusionAcquisition.DiffArray[compteur_acquisition]
    01090                     .federate = NewOwner ;
    01091                 diffusionAcquisition.DiffArray[compteur_acquisition]
    01092                     .attribute = oa->getHandle();
    01093                 compteur_acquisition++ ;
    01094
    01095                 AnswerDivestiture.handleArray[compteur_divestiture]
    01096                     = theAttributeList[i] ;
    01097                 compteur_divestiture++ ;
    01098
    01099                 if (oca->isNamed("privilegeToDelete")) {
    01100                     object->setOwner(NewOwner);
    01101                 }
    01102             }
    01103             else {
    01104                 AnswerAssumption->handleArray[compteur_assumption]
    01105                     = theAttributeList[i] ;
    01106                 oa->setDivesting(true);
    01107                 compteur_assumption++ ;
    01108             }
    01109         }
    01110
    01111         if (compteur_acquisition != 0) {
    01112             diffusionAcquisition.size = compteur_acquisition ;
    01113             sendToOwners(&diffusionAcquisition, theObjectHandle,
    01114                          theFederateHandle, theTag,
    01115                          NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
    01116         }
    01117
    01118         if (compteur_divestiture !=0) {
    01119             AnswerDivestiture.federation = server->federation();
    01120             AnswerDivestiture.federate = theFederateHandle ;
    01121             AnswerDivestiture.object = theObjectHandle ;
    01122             AnswerDivestiture.setLabel(std::string(""));
    01123             AnswerDivestiture.handleArraySize = compteur_divestiture ;
    01124
    01125             sendToFederate(&AnswerDivestiture, theFederateHandle);
    01126         }
    01127
    01128         if (compteur_assumption !=0) {
    01129             AnswerAssumption->federation = server->federation();
    01130             AnswerAssumption->federate = theFederateHandle ;
    01131             AnswerAssumption->exception = e_NO_EXCEPTION ;
    01132             AnswerAssumption->object = theObjectHandle ;
    01133             AnswerAssumption->setLabel(theTag);
    01134             AnswerAssumption->handleArraySize = compteur_assumption ;
    01135
    01136             List = new ObjectClassBroadcastList(AnswerAssumption,
    01137                                                 attributeSet.size());
    01138
    01139             D.Out(pdProtocol,
    01140                   "Object %u divestiture in class %u, now broadcasting...",
    01141                   theObjectHandle, handle);
    01142             broadcastClassMessage(List);
    01143         }
    01144         else
    01145             delete AnswerAssumption ;
    01146     }
    01147     else {
    01148         D.Out(pdExcept,
    01149               "NegotiatedAttributeOwnershipDivestiture should not "
    01150               "be called on the RTIA.");
    01151         throw RTIinternalError("NegotiatedAttributeOwnershipDivestiture "
    01152                                "called on the RTIA.");
    01153     }
    01154
    01155     // Return the BroadcastList in case it had to be passed to the parent
    01156     // class.
    01157     return List ;
    01158 }
    01159
    01160 // ----------------------------------------------------------------------------
    01162 void ObjectClass::
    01163 attributeOwnershipAcquisitionIfAvailable(FederateHandle the_federate,
    01164                                          ObjectHandle the_object,
    01165                                          std::vector <AttributeHandle> &the_attributes,
    01166                                          UShort theListSize)
    01167     throw (ObjectNotKnown,
    01168            ObjectClassNotPublished,
    01169            AttributeNotDefined,
    01170            AttributeNotPublished,
    01171            FederateOwnsAttributes,
    01172            AttributeAlreadyBeingAcquired,
    01173            RTIinternalError)
    01174 {
    01175     //It may throw ObjectNotKnown.
    01176     Object *object = getInstanceWithID(the_object);
    01177
    01178     // Do all attribute handles exist ? It may throw AttributeNotDefined.
    01179     for (int index = 0 ; index < theListSize ; index++) {
    01180         getAttribute(the_attributes[index]);
    01181     }
    01182
    01183     if (server) {
    01184         // Federate must publish the class.
    01185         if (!isFederatePublisher(the_federate)) {
    01186             D.Out(pdExcept, "exception : ObjectClassNotPublished.");
    01187             throw ObjectClassNotPublished("");
    01188         }
    01189
    01190         //rem attributeSet.size()=attributeState.size()
    01191         ObjectAttribute * oa ;
    01192         ObjectClassAttribute * oca ;
    01193         for (int i = 0 ; i < theListSize ; i++) {
    01194             oca = getAttribute(the_attributes[i]);
    01195             oa = object->getAttribute(the_attributes[i]);
    01196
    01197             // The federate has to publish attributes he desire to
    01198             // acquire.
    01199             if (!oca->isPublishing(the_federate) &&
    01200                 (!oca->isNamed("privilegeToDelete")))
    01201                 throw AttributeNotPublished("");
    01202             // Does federate already owns some attributes.
    01203             if (oa->getOwner() == the_federate)
    01204                 throw FederateOwnsAttributes("");
    01205             // Does federate is on the way to acquire something.
    01206             if (oa->isCandidate(the_federate))
    01207                 throw AttributeAlreadyBeingAcquired("");
    01208         }
    01209
    01210         NetworkMessage *Answer_notification = NM_Factory::create(NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
    01211         Answer_notification->federation = server->federation();
    01212         Answer_notification->federate = the_federate ;
    01213         Answer_notification->exception = e_NO_EXCEPTION ;
    01214         Answer_notification->object = the_object ;
    01215         Answer_notification->handleArray.resize(theListSize) ;
    01216
    01217         NetworkMessage *Answer_unavailable = NM_Factory::create(NetworkMessage::ATTRIBUTE_OWNERSHIP_UNAVAILABLE) ;
    01218         Answer_unavailable->federation = server->federation();
    01219         Answer_unavailable->federate = the_federate ;
    01220         Answer_unavailable->exception = e_NO_EXCEPTION ;
    01221         Answer_unavailable->object = the_object ;
    01222         Answer_unavailable->handleArray.resize(theListSize) ;
    01223
    01224         CDiffusion *diffusionDivestiture = new CDiffusion();
    01225
    01226         //
    01227         //Ce service ne doit pas ajouter le federe demandeur a la liste
    01228         //des candidats!!!
    01229         //
    01230         int compteur_unavailable = 0 ;
    01231         int compteur_notification = 0 ;
    01232         int compteur_divestiture = 0 ;
    01233         FederateHandle oldOwner ;
    01234
    01235         for (int i = 0 ; i < theListSize ; i++) {
    01236             oca = getAttribute(the_attributes[i]);
    01237             oa = object->getAttribute(the_attributes[i]);
    01238
    01239             oldOwner = oa->getOwner();
    01240             if ((oldOwner == 0) || (oa->beingDivested())) {
    01241                 //Cet attribut est libre ou offert par son proprietaire
    01242                 //S'il est offert
    01243                 if (oa->beingDivested()) {
    01244                     diffusionDivestiture->DiffArray[compteur_divestiture].federate
    01245                         = oldOwner ;
    01246                     diffusionDivestiture->DiffArray[compteur_divestiture].attribute
    01247                         = oa->getHandle();
    01248                     compteur_divestiture++ ;
    01249                 }
    01250                 //Qu'il soit offert ou libre
    01251                 Answer_notification->handleArray[compteur_notification]
    01252                     = the_attributes[i] ;
    01253                 oa->setOwner(the_federate);
    01254                 oa->setDivesting(false);
    01255                 compteur_notification++ ;
    01256                 //object->Owner reste le champ de reference
    01257                 //pour le privilegeToDelete
    01258                 if (oca->isNamed("privilegeToDelete"))
    01259                     object->setOwner(the_federate);
    01260             }
    01261             else {
    01262                 //Cet attribut n'est pas disponible!!!
    01263                 Answer_unavailable->handleArray[compteur_unavailable]
    01264                     = the_attributes[i] ;
    01265                 oa->addCandidate(the_federate);
    01266                 compteur_unavailable++ ;
    01267             }
    01268         }
    01269
    01270         if (compteur_notification != 0) {
    01271             Answer_notification->handleArraySize = compteur_notification ;
    01272             sendToFederate(Answer_notification, the_federate);
    01273         }
    01274         else
    01275             delete Answer_notification ;
    01276
    01277         D.Out(pdDebug,
    01278               "Debut traitement : send divestiture notification message");
    01279
    01280         if (compteur_divestiture != 0) {
    01281             diffusionDivestiture->size =compteur_divestiture ;
    01282             sendToOwners(diffusionDivestiture, the_object,
    01283                          the_federate, "\0",
    01284                          NetworkMessage::ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION);
    01285         }
    01286         delete diffusionDivestiture ;
    01287
    01288         if (compteur_unavailable != 0) {
    01289             Answer_unavailable->handleArraySize = compteur_unavailable ;
    01290             sendToFederate(Answer_unavailable, the_federate);
    01291         }
    01292         else
    01293             delete Answer_unavailable ;
    01294     }
    01295     else {
    01296         D.Out(pdExcept, "AttributeOwnershipAcquisitionIfAvailable should not "
    01297               "be called on the RTIA.");
    01298         throw RTIinternalError("AttributeOwnershipAcquisitionIfAvailable "
    01299                                "called on the RTIA.");
    01300     }
    01301 }
    01302
    01303 // ----------------------------------------------------------------------------
    01305 ObjectClassBroadcastList * ObjectClass::
    01306 unconditionalAttributeOwnershipDivestiture(FederateHandle theFederateHandle,
    01307                                            ObjectHandle theObjectHandle,
    01308                                            std::vector <AttributeHandle> &theAttributeList,
    01309                                            UShort theListSize)
    01310     throw (ObjectNotKnown,
    01311            AttributeNotDefined,
    01312            AttributeNotOwned,
    01313            RTIinternalError)
    01314 {
    01315     // Pre-conditions checking
    01316
    01317     // may throw ObjectNotKnown
    01318     Object *object = getInstanceWithID(theObjectHandle);
    01319
    01320     // Do all attribute handles exist ? It may throw AttributeNotDefined.
    01321     for (int index = 0 ; index < theListSize ; index++)
    01322         getAttribute(theAttributeList[index]);
    01323
    01324     //Le federe est-il proprietaire de tous les attributs
    01325     ObjectAttribute * oa ;
    01326     for (int i = 0 ; i < theListSize ; i++) {
    01327         oa = object->getAttribute(theAttributeList[i]);
    01328
    01329         if (oa->getOwner() != theFederateHandle)
    01330             throw AttributeNotOwned("");
    01331     }
    01332
    01333     int compteur_assumption = 0 ;
    01334     int compteur_acquisition = 0 ;
    01335     NM_Request_Attribute_Ownership_Assumption *AnswerAssumption = NULL ;
    01336     ObjectClassBroadcastList *List = NULL ;
    01337     FederateHandle NewOwner ;
    01338
    01339     if (server != NULL) {
    01340         AnswerAssumption = new NM_Request_Attribute_Ownership_Assumption();
    01341         AnswerAssumption->handleArraySize = theListSize ;
    01342         AnswerAssumption->handleArray.resize(theListSize) ;
    01343         CDiffusion *diffusionAcquisition = new CDiffusion();
    01344
    01345         ObjectAttribute * oa ;
    01346         ObjectClassAttribute * oca ;
    01347         for (int i = 0 ; i < theListSize ; i++) {
    01348             oca = getAttribute(theAttributeList[i]);
    01349             oa = object->getAttribute(theAttributeList[i]);
    01350
    01351             if (oa->hasCandidates()) {
    01352                 // An attributeOwnershipAcquisition is on the way
    01353                 // on this attribute.
    01354
    01355                 // Le demandeur le plus recent devient proprietaire
    01356                 NewOwner = oa->getCandidate(1);
    01357
    01358                 oa->setOwner(NewOwner);
    01359
    01360                 // We remove it from candidate list.
    01361                 oa->removeCandidate(NewOwner);
    01362
    01363                 // We reinitialize divesting.
    01364                 oa->setDivesting(false);
    01365
    01366                 diffusionAcquisition->DiffArray[compteur_acquisition]
    01367                     .federate = NewOwner ;
    01368                 diffusionAcquisition->DiffArray[compteur_acquisition]
    01369                     .attribute = oa->getHandle();
    01370                 compteur_acquisition++ ;
    01371
    01372                 if (oca->isNamed("privilegeToDelete")) {
    01373                     object->setOwner(NewOwner);
    01374                 }
    01375             }
    01376             else {
    01377                 AnswerAssumption->handleArray[compteur_assumption] =
    01378                     theAttributeList[i] ;
    01379                 oa->setOwner(0);
    01380                 oa->setDivesting(false);
    01381                 compteur_assumption++ ;
    01382             }
    01383         }
    01384
    01385         if (compteur_assumption != 0) {
    01386             AnswerAssumption->federation = server->federation();
    01387             AnswerAssumption->federate = theFederateHandle ;
    01388             AnswerAssumption->exception = e_NO_EXCEPTION ;
    01389             AnswerAssumption->object = theObjectHandle ;
    01390             AnswerAssumption->setLabel(std::string(""));
    01391             AnswerAssumption->handleArraySize = compteur_assumption ;
    01392
    01393             List = new ObjectClassBroadcastList(AnswerAssumption,
    01394                                                 attributeSet.size());
    01395
    01396             D.Out(pdProtocol,
    01397                   "Object %u updated in class %u, now broadcasting...",
    01398                   theObjectHandle, handle);
    01399
    01400             broadcastClassMessage(List);
    01401         }
    01402         else
    01403             delete AnswerAssumption ;
    01404
    01405         if (compteur_acquisition != 0) {
    01406             diffusionAcquisition->size =compteur_acquisition ;
    01407             sendToOwners(diffusionAcquisition, theObjectHandle,
    01408                          theFederateHandle, "\0",
    01409                          NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
    01410         }
    01411         delete diffusionAcquisition ;
    01412     }
    01413     else {
    01414         D.Out(pdExcept, "UnconditionalAttributeOwnershipDivestiture should "
    01415               "not be called on the RTIA.");
    01416         throw RTIinternalError("UnconditionalAttributeOwnershipDivestiture "
    01417                                "called on the RTIA.");
    01418     }
    01419
    01420     // Return the BroadcastList in case it had to be passed to the parent
    01421     // class.
    01422     return List ;
    01423 }
    01424
    01425 // ----------------------------------------------------------------------------
    01427 void
    01428 ObjectClass::attributeOwnershipAcquisition(FederateHandle theFederateHandle,
    01429                                            ObjectHandle theObjectHandle,
    01430                                            std::vector <AttributeHandle> &theAttributeList,
    01431                                            UShort theListSize,
    01432                                            const char *theTag)
    01433     throw (ObjectNotKnown,
    01434            ObjectClassNotPublished,
    01435            AttributeNotDefined,
    01436            AttributeNotPublished,
    01437            FederateOwnsAttributes,
    01438            RTIinternalError)
    01439 {
    01440     //Les v�rifications des conditions doivent �tre faites avant
    01441     //toute modification!!!
    01442
    01443     // Pre-conditions checking
    01444
    01445     // may throw ObjectNotKnown
    01446     Object *object = getInstanceWithID(theObjectHandle);
    01447
    01448     ObjectAttribute * oa ;
    01449     ObjectClassAttribute * oca ;
    01450     for (int i = 0 ; i < theListSize ; i++) {
    01451         // Do all attribute handles exist ? It may throw AttributeNotDefined.
    01452         oca = getAttribute(theAttributeList[i]);
    01453         oa = object->getAttribute(theAttributeList[i]);
    01454
    01455         //Le f�d�r� est-il d�j� propri�taire de certains attributs
    01456         if (oa->getOwner() == theFederateHandle)
    01457             throw FederateOwnsAttributes("");
    01458         //Le f�d�r� publie-t-il les attributs
    01459         if (!oca->isPublishing(theFederateHandle) &&
    01460             (!oca->isNamed("privilegeToDelete")))
    01461             throw AttributeNotPublished("");
    01462     }
    01463
    01464     int compteur_notification = 0 ;
    01465     int compteur_divestiture = 0 ;
    01466     int compteur_release = 0 ;
    01467     FederateHandle oldOwner ;
    01468     if (server != NULL) {
    01469         //Le f�d�r� doit publier la classe
    01470         if (!isFederatePublisher(theFederateHandle)) {
    01471             D.Out(pdExcept, "exception : ObjectClassNotPublished.");
    01472             throw ObjectClassNotPublished("");
    01473         }
    01474
    01475         NetworkMessage *AnswerNotification = NM_Factory::create(NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
    01476
    01477         AnswerNotification->federation = server->federation();
    01478         AnswerNotification->federate = theFederateHandle ;
    01479         AnswerNotification->exception = e_NO_EXCEPTION ;
    01480         AnswerNotification->object = theObjectHandle ;
    01481         AnswerNotification->handleArray.resize(theListSize) ;
    01482
    01483         CDiffusion *diffusionDivestiture = new CDiffusion();
    01484
    01485         CDiffusion *diffusionRelease = new CDiffusion();
    01486
    01487         ObjectAttribute * oa ;
    01488         ObjectClassAttribute * oca ;
    01489         for (int i = 0 ; i < theListSize ; i++) {
    01490             oca = getAttribute(theAttributeList[i]);
    01491             oa = object->getAttribute(theAttributeList[i]);
    01492
    01493             oldOwner = oa->getOwner();
    01494             if ((oldOwner == 0) || (oa->beingDivested())) {
    01495                 //Cet attribut est libre ou offert par son propri�taire s'il est offert
    01496                 if (oa->beingDivested()) {
    01497                     diffusionDivestiture->DiffArray[compteur_divestiture].federate =
    01498                         oldOwner ;
    01499                     diffusionDivestiture->DiffArray[compteur_divestiture].attribute =
    01500                         oa->getHandle();
    01501                     compteur_divestiture++ ;
    01502                 }
    01503                 //Qu'il soit offert ou libre
    01504                 if (oa->isCandidate(theFederateHandle) != 0)
    01505                     oa->removeCandidate(theFederateHandle);
    01506                 AnswerNotification->handleArray[compteur_notification]
    01507                     = theAttributeList[i] ;
    01508                 oa->setOwner(theFederateHandle);
    01509                 oa->setDivesting(false);
    01510                 compteur_notification++ ;
    01511
    01512                 // object->Owner reste le champ de r�f�rence pour
    01513                 // le privilegeToDelete
    01514                 if (oca->isNamed("privilegeToDelete"))
    01515                     object->setOwner(theFederateHandle);
    01516             }
    01517             else {
    01518                 diffusionRelease->DiffArray[compteur_release].federate = oldOwner ;
    01519                 diffusionRelease->DiffArray[compteur_release].attribute =
    01520                     oa->getHandle();
    01521                 compteur_release++ ;
    01522
    01523                 //On l'enl�ve de la liste des demandeurs s'il y �tait
    01524                 oa->removeCandidate(theFederateHandle);
    01525
    01526                 //pour le rajouter en 1ere position
    01527                 oa->addCandidate(theFederateHandle);
    01528             }
    01529         }
    01530
    01531         if (compteur_notification != 0) {
    01532             AnswerNotification->handleArraySize = compteur_notification ;
    01533             sendToFederate(AnswerNotification, theFederateHandle);
    01534         }
    01535         else
    01536             delete AnswerNotification ;
    01537
    01538         if (compteur_divestiture != 0) {
    01539             diffusionDivestiture->size =compteur_divestiture ;
    01540             sendToOwners(diffusionDivestiture, theObjectHandle,
    01541                          theFederateHandle, "\0",
    01542                          NetworkMessage::ATTRIBUTE_OWNERSHIP_DIVESTITURE_NOTIFICATION);
    01543         }
    01544         delete diffusionDivestiture ;
    01545
    01546         if (compteur_release != 0) {
    01547             diffusionRelease->size =compteur_release ;
    01548             sendToOwners(diffusionRelease, theObjectHandle, theFederateHandle,
    01549                          theTag, NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_RELEASE);
    01550         }
    01551         delete diffusionRelease ;
    01552     }
    01553     else {
    01554         D.Out(pdExcept,
    01555               "AttributeOwnershipAcquisition should not be called "
    01556               "on the RTIA.");
    01557         throw RTIinternalError("AttributeOwnershipAcquisition called "
    01558                                "on the RTIA");
    01559     }
    01560 }
    01561
    01562 // ----------------------------------------------------------------------------
    01564 AttributeHandleSet *
    01565 ObjectClass::
    01566 attributeOwnershipReleaseResponse(FederateHandle the_federate,
    01567                                   ObjectHandle the_object,
    01568                                   std::vector <AttributeHandle> &the_attributes,
    01569                                   UShort the_size)
    01570     throw (ObjectNotKnown,
    01571            AttributeNotDefined,
    01572            AttributeNotOwned,
    01573            FederateWasNotAskedToReleaseAttribute,
    01574            RTIinternalError)
    01575 {
    01576     // Pre-conditions checking
    01577
    01578     // may throw ObjectNotKnown
    01579     Object *object = getInstanceWithID(the_object);
    01580
    01581     // Do all attribute handles exist ? It may throw AttributeNotDefined.
    01582     for (int index = 0 ; index < the_size ; index++) {
    01583         getAttribute(the_attributes[index]);
    01584     }
    01585
    01586     //Le f�d�r� est-il propri�taire de tous les attributs
    01587     //Y a-t-il des acqu�reurs pour les attributs
    01588     ObjectAttribute * oa ;
    01589     for (int i = 0 ; i < the_size ; i++) {
    01590         oa = object->getAttribute(the_attributes[i]);
    01591
    01592         if (oa->getOwner() != the_federate) {
    01593             throw AttributeNotOwned("");
    01594         }
    01595         if (!oa->hasCandidates()) {
    01596             throw FederateWasNotAskedToReleaseAttribute("");
    01597         }
    01598     }
    01599
    01600     int compteur_acquisition = 0 ;
    01601     FederateHandle newOwner ;
    01602     AttributeHandleSet *theAttribute ;
    01603     if (server != NULL) {
    01604         CDiffusion *diffusionAcquisition = new CDiffusion();
    01605
    01606         theAttribute = new AttributeHandleSet(the_size);
    01607
    01608         ObjectClassAttribute * oca ;
    01609         for (int i = 0 ; i < the_size ; i++) {
    01610             oca = getAttribute(the_attributes[i]);
    01611             oa = object->getAttribute(the_attributes[i]);
    01612
    01613             //Le demandeur le plus r�cent devient propri�taire
    01614             newOwner = oa->getCandidate(1);
    01615
    01616             oa->setOwner(newOwner);
    01617
    01618             //On le supprime de la liste des demandeurs
    01619             oa->removeCandidate(newOwner);
    01620
    01621             //On r�initialise divesting
    01622             oa->setDivesting(false);
    01623
    01624             diffusionAcquisition->DiffArray[compteur_acquisition].federate = newOwner ;
    01625             diffusionAcquisition->DiffArray[compteur_acquisition].attribute =
    01626                 oa->getHandle();
    01627             compteur_acquisition++ ;
    01628             theAttribute->add(oa->getHandle());
    01629
    01630             D.Out(pdDebug, "Acquisition handle %u compteur %u",
    01631                   the_attributes[i], compteur_acquisition);
    01632
    01633             if (oca->isNamed("privilegeToDelete"))
    01634                 object->setOwner(newOwner);
    01635         }
    01636
    01637         if (compteur_acquisition != 0) {
    01638             diffusionAcquisition->size =compteur_acquisition ;
    01639             sendToOwners(diffusionAcquisition, the_object, the_federate, "\0",
    01640                          NetworkMessage::ATTRIBUTE_OWNERSHIP_ACQUISITION_NOTIFICATION);
    01641         }
    01642         delete diffusionAcquisition ;
    01643     }
    01644     else {
    01645         D.Out(pdExcept, "NegotiatedAttributeOwnershipDivestiture should not "
    01646               "be called on the RTIA.");
    01647         throw RTIinternalError("NegotiatedAttributeOwnershipDivestiture called"
    01648                                " on the RTIA.");
    01649     }
    01650
    01651     return(theAttribute);
    01652 }
    01653
    01654 // ----------------------------------------------------------------------------
    01656 void
    01657 ObjectClass::
    01658 cancelAttributeOwnershipAcquisition(FederateHandle federate_handle,
    01659                                     ObjectHandle object_handle,
    01660                                     std::vector <AttributeHandle> &attribute_list,
    01661                                     UShort list_size)
    01662     throw (ObjectNotKnown,
    01663            AttributeNotDefined,
    01664            AttributeAlreadyOwned,
    01665            AttributeAcquisitionWasNotRequested,
    01666            RTIinternalError)
    01667 {
    01668     // Pre-conditions checking
    01669
    01670     //It may throw ObjectNotKnown.
    01671     Object *object = getInstanceWithID(object_handle);
    01672
    01673     // Do all attribute handles exist ? It may throw AttributeNotDefined.
    01674     for (int index = 0 ; index < list_size ; index++)
    01675         getAttribute(attribute_list[index]);
    01676
    01677     for (int i = 0 ; i < list_size ; i++)
    01678         D.Out(pdDebug, "CancelAcquisition Object %u Attribute %u ",
    01679               object_handle, attribute_list[i]);
    01680
    01681     if (server != NULL) {
    01682         //rem attributeSet.size()=attributeState.size()
    01683         ObjectAttribute * oa ;
    01684         ObjectClassAttribute * oca ;
    01685
    01686         for (int i = 0 ; i < list_size ; i++) {
    01687             oca = getAttribute(attribute_list[i]);
    01688             oa = object->getAttribute(attribute_list[i]);
    01689
    01690             D.Out(pdDebug, "Attribut %u Owner %u", attribute_list[i], oa->getOwner());
    01691             // Does federate is already owning some attributes ?
    01692             if (oa->getOwner() == federate_handle)
    01693                 throw AttributeAlreadyOwned("");
    01694             // Does federate is already doing an acquisition ?
    01695             if (oa->isCandidate(federate_handle) == 0)
    01696                 throw AttributeAcquisitionWasNotRequested("");
    01697         }
    01698
    01699         NetworkMessage *answer_confirmation = NM_Factory::create(NetworkMessage::CONFIRM_ATTRIBUTE_OWNERSHIP_ACQUISITION_CANCELLATION);
    01700         answer_confirmation->federation = server->federation();
    01701         answer_confirmation->federate = federate_handle ;
    01702         answer_confirmation->exception = e_NO_EXCEPTION ;
    01703         answer_confirmation->object = object_handle ;
    01704         answer_confirmation->handleArray.resize(list_size) ;
    01705
    01706         int compteur_confirmation = 0 ;
    01707         for (int i = 0 ; i < list_size ; i++) {
    01708             oa = object->getAttribute(attribute_list[i]);
    01709
    01710             answer_confirmation->handleArray[compteur_confirmation] = attribute_list[i] ;
    01711
    01712             // We remove federate from candidates.
    01713             oa->removeCandidate(federate_handle);
    01714             D.Out(pdDebug, "Adding federate %u to attribute %u object %u",
    01715                   federate_handle, attribute_list[i], object_handle);
    01716             compteur_confirmation++ ;
    01717         }
    01718
    01719         if (compteur_confirmation != 0) {
    01720             answer_confirmation->handleArraySize = compteur_confirmation ;
    01721             sendToFederate(answer_confirmation, federate_handle);
    01722         }
    01723         else
    01724             delete answer_confirmation ;
    01725     }
    01726     else {
    01727         D.Out(pdExcept, "CancelAttributeOwnershipAcquisition should not "
    01728               "be called on the RTIA.");
    01729         throw RTIinternalError("CancelAttributeOwnershipAcquisition called "
    01730                                "on the RTIA.");
    01731     }
    01732 }
    01733
    01734 // ----------------------------------------------------------------------------
    01735 ObjectClassHandle
    01736 ObjectClass::getHandle() const
    01737 {
    01738     return handle ;
    01739 }
    01740
    01741 // ----------------------------------------------------------------------------
    01744 void
    01745 ObjectClass::unsubscribe(FederateHandle fed, const RTIRegion *region)
    01746 {
    01747     D[pdTrace] << "ObjectClass::unsubscribe" << ": fed " << fed << ", region "
    01748            << (region ? region->getHandle() : 0) << std::endl ;
    01749
    01750     list<ObjectClassAttribute *>::iterator i ;
    01751     for (i = attributeSet.begin(); i != attributeSet.end(); ++i) {
    01752     if ((*i)->isSubscribed(fed, region)) {
    01753         (*i)->unsubscribe(fed, region);
    01754     }
    01755     }
    01756 }
    01757
    01758 // ----------------------------------------------------------------------------
    01761 void
    01762 ObjectClass::unsubscribe(FederateHandle fed)
    01763 {
    01764     list<ObjectClassAttribute *>::iterator i ;
    01765     for (i = attributeSet.begin(); i != attributeSet.end(); ++i) {
    01766     if ((*i)->isSubscribed(fed)) {
    01767         (*i)->unsubscribe(fed);
    01768     }
    01769     }
    01770 } /* end of unsubscribe */
    01771
    01772 void
    01773 ObjectClass::addSubClass(ObjectClass *child) {
    01774
    01775     /* build parent-child relationship */
    01776     /* add child as subclass of parent */
    01777     subClasses->addClass(child,NULL);
    01778     /* link child to parent */
    01779     child->superClass = handle;
    01780     /* forward inherited properties to child */
    01781     /* Add Object Class Attribute */
    01782     addInheritedClassAttributes(child);
    01783     /* security server is the same for child */
    01784     child->server = server;
    01785     /* inherit security Level */
    01786     child->setSecurityLevelId(securityLevelId);
    01787
    01788 } /* end of addChild */
    01789
    01790 // ----------------------------------------------------------------------------
    01795 void
    01796 ObjectClass::recursiveDiscovering(FederateHandle federate,
    01797                   ObjectClassHandle subscription)
    01798     throw (ObjectClassNotDefined)
    01799 {
    01800     D[pdInit] << "Recursive Discovering on class " << handle
    01801           << " for Federate " << federate << "." << std::endl ;
    01802
    01803     bool go_deeper = sendDiscoverMessages(federate, subscription);
    01804
    01805     if (go_deeper) {
    01806         ObjectClassSet::const_iterator i ;
    01807         for (i = subClasses->begin(); i != subClasses->end(); ++i) {
    01808             i->second->recursiveDiscovering(federate, subscription);
    01809         }
    01810     }
    01811 }
    01812
    01813 // ----------------------------------------------------------------------------
    01818 // void
    01819 // ObjectClass::apply(Visitor &v)
    01820 // {
    01821 //     bool go_deeper = v.execute(*this);
    01822
    01823 //     if (go_deeper) {
    01824 //         list<ObjectClass *>::const_iterator i ;
    01825 //         for (i = subClasses.begin(); i != subClasses.end(); ++i) {
    01826 //             (*i)->apply(v);
    01827 //         }
    01828 //     }
    01829 // }
    01830
    01831 ObjectClass::AttributeList_t
    01832 ObjectClass::getAttributeList(void) {
    01833         return attributeSet;
    01834 }
    01835
    01836 } // namespace certi
    01837
    01838 // $Id: ObjectClass.cc,v 3.64 2008/12/16 07:08:29 approx Exp $