📄 objectclass.cc
字号:
// ----------------------------------------------------------------------------// CERTI - HLA RunTime Infrastructure// Copyright (C) 2002, 2003 ONERA//// This file is part of CERTI-libCERTI//// CERTI-libCERTI is free software ; you can redistribute it and/or// modify it under the terms of the GNU Lesser General Public License// as published by the Free Software Foundation ; either version 2 of// the License, or (at your option) any later version.//// CERTI-libCERTI is distributed in the hope that it will be useful, but// WITHOUT ANY WARRANTY ; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU// Lesser General Public License for more details.//// You should have received a copy of the GNU Lesser General Public// License along with this program ; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307// USA//// $Id: ObjectClass.cc,v 3.21 2004/03/04 20:19:05 breholee Exp $// ----------------------------------------------------------------------------#include <config.h>#include "ObjectClass.hh"#include "ObjectClassAttribute.hh"#include "SocketTCP.hh"#include "PrettyDebug.hh"#include <iostream>#include <assert.h>using std::cout ;using std::endl ;using std::list ;namespace certi {static pdCDebug D("OBJECTCLASS", "(ObjClass) - ");// ----------------------------------------------------------------------------//! To be used only by CRead, it returns the new Attribute's Handle.AttributeHandleObjectClass::addAttribute(ObjectClassAttribute *theAttribute, Boolean is_inherited){ if (theAttribute == NULL) throw RTIinternalError("Tried to add NULL attribute."); theAttribute->setHandle(attributeSet.size() + 1); theAttribute->server = server ; // If the attribute is inherited, it keeps its security level. // If not, it takes the default security level of the class. if (is_inherited != RTI_TRUE) theAttribute->level = LevelID ; attributeSet.push_front(theAttribute); D.Out(pdProtocol, "ObjectClass %u has a new attribute %u.", handle, theAttribute->getHandle()); return theAttribute->getHandle();}// ----------------------------------------------------------------------------//! Add the class' attributes to the 'Child' Class.voidObjectClass::addAttributesToChild(ObjectClass *the_child){ // The Attribute List is read backwards to respect the same attribute order // for the child(Attributes are inserted at the beginning of the list). ObjectClassAttribute *childAttribute = NULL ; list<ObjectClassAttribute *>::reverse_iterator a ; for (a = attributeSet.rbegin(); a != attributeSet.rend(); a++) { assert((*a) != NULL); childAttribute = new ObjectClassAttribute(*a); assert(childAttribute != NULL); D.Out(pdProtocol, "ObjectClass %u adding new attribute %d to child class %u.", handle, (*a)->getHandle(), the_child->getHandle()); the_child->addAttribute(childAttribute); if (childAttribute->getHandle() != (*a)->getHandle()) throw RTIinternalError("Error while copying child's attributes."); }}// ----------------------------------------------------------------------------/*! Take a Broadcast List and continue to send messages. You should take a look at ObjectClassSet::RegisterObject to understand what is going on...*/voidObjectClass::broadcastClassMessage(ObjectClassBroadcastList *ocbList){ // 1. Set ObjectHandle to local class Handle. ocbList->message->objectClass = handle ; // 2. Update message attribute list by removing child's attributes. if ((ocbList->message->type == NetworkMessage::REFLECT_ATTRIBUTE_VALUES) || (ocbList->message->type == NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION)) { int attr = 0 ; while (attr < ocbList->message->handleArraySize) { // If the attribute is not in that class, remove it from // the message. try { getAttributeWithHandle(ocbList->message->handleArray[attr]); attr++ ; } catch (AttributeNotDefined &e) { ocbList->message->removeAttribute(attr); } } } // 3. Add class/attributes subscribers to the list. switch(ocbList->message->type) { case NetworkMessage::DISCOVER_OBJECT: case NetworkMessage::REMOVE_OBJECT: { // For each federate, add it to list if at least one attribute has // been subscribed. FederateHandle federate = 0 ; for (federate = 1 ; federate <= MaxSubscriberHandle ; federate++) { if (isFederateSubscriber(federate)) { ocbList->addFederate(federate); } } } break ; case NetworkMessage::REFLECT_ATTRIBUTE_VALUES: case NetworkMessage::REQUEST_ATTRIBUTE_OWNERSHIP_ASSUMPTION: { // For each class attribute, update the list be adding federates who // subscribed to the attribute. list<ObjectClassAttribute *>::const_iterator a ; for (a = attributeSet.begin(); a != attributeSet.end(); a++) { (*a)->updateBroadcastList(ocbList); } } break ; default: throw RTIinternalError("BroadcastClassMsg: Unknown type."); } // 4. Send pending messages. ocbList->sendPendingMessage(server);}// ----------------------------------------------------------------------------//! sendToFederate.voidObjectClass::sendToFederate(NetworkMessage *msg, FederateHandle theFederate){ // Send the message 'msg' to the Federate which Handle is theFederate. Socket *socket = NULL ; try {#ifdef HLA_USES_UDP socket = server->getSocketLink(theFederate, BEST_EFFORT);#else socket = server->getSocketLink(theFederate);#endif msg->write(socket); } catch (RTIinternalError &e) { D.Out(pdExcept, "Reference to a killed Federate while broadcasting."); } catch (NetworkError &e) { D.Out(pdExcept, "Network error while broadcasting, ignoring."); } // BUG: If except = 0, could use Multicast.}// ----------------------------------------------------------------------------//! sendToOwners.voidObjectClass::sendToOwners(CDiffusion *diffusionList, ObjectHandle theObjectHandle, FederateHandle theFederate, const char *theTag, NetworkMessage::Type type){ int nbAttributes = diffusionList->size ; FederateHandle toFederate ; for (int i = 0 ; i < nbAttributes ; i++) { toFederate = diffusionList->DiffArray[i].federate ; if (toFederate != 0) { NetworkMessage *answer = new NetworkMessage ; answer->type = type ; answer->federation = server->federation(); answer->federate = theFederate ; answer->exception = e_NO_EXCEPTION ; answer->object = theObjectHandle ; strcpy(answer->label, theTag); int index = 0 ; for (int j = i ; j < nbAttributes ; j++) { if (diffusionList->DiffArray[j].federate == toFederate) { D.Out(pdDebug, "handle : %u", diffusionList->DiffArray[j].attribute); diffusionList->DiffArray[j].federate = 0 ; answer->handleArray[index] = diffusionList ->DiffArray[j].attribute ; index++ ; } } answer->handleArraySize = index ; D.Out(pdDebug, "Envoi message type %u ", type); sendToFederate(answer, toFederate); } }}// ----------------------------------------------------------------------------/*! Throw SecurityError if the Federate is not allowed to access the Object Class, and print an Audit message containing reason.*/voidObjectClass::checkFederateAccess(FederateHandle the_federate, const char *reason) throw (SecurityError){ D.Out(pdInit, "Beginning of CheckFederateAccess for the federate %d", the_federate); // BUG: Should at least but a line in Audit if (server == NULL) return ; Boolean result = server->canFederateAccessData(the_federate, LevelID); // BUG: Should use Audit. if (result != RTI_TRUE) { cout << "Object Class " << handle << " : SecurityError for federate " << the_federate << '(' << reason << ")." << endl ; throw SecurityError("Federate should not access Object Class."); }}// ----------------------------------------------------------------------------//! ObjectClass constructor (only one).ObjectClass::ObjectClass() : Father(0), server(NULL), Depth(0), Name(NULL), handle(0), LevelID(PublicLevelID), MaxSubscriberHandle(0){}// ----------------------------------------------------------------------------//! ObjectClass destructor (frees allocated memory).ObjectClass::~ObjectClass(){ if (Name != NULL) { free(Name); Name = NULL ; } // Deleting instances if (!objectSet.empty()) D.Out(pdError, "ObjectClass %d : Instances remaining while exiting...", handle); // while (!objectSet.empty()) { // delete objectSet.front(); // objectSet.pop_front(); // } // Deleting Class Attributes while (!attributeSet.empty()) { delete attributeSet.front(); attributeSet.pop_front(); } // Deleting Sons while (!sonSet.empty()) { sonSet.pop_front(); }}// ----------------------------------------------------------------------------/*! Delete the object instance 'theObjectHandle', and starts to broadcast the RemoveObject message. Return a BroadcastList of Federates, in order to allow our ObjectClassSet to go on with the message broadcasting, by giving the list to our parent class.*/ObjectClassBroadcastList *ObjectClass::deleteInstance(FederateHandle the_federate, ObjectHandle the_object, const char *the_tag) throw (DeletePrivilegeNotHeld, ObjectNotKnown, RTIinternalError){ // 1. Pre-conditions checking(may throw ObjectNotKnown) Object *object = getInstanceWithID(the_object); // Is the Federate really the Object Owner?(Checked only on RTIG) if ((server != 0) && (object->getOwner() != the_federate)) { D.Out(pdExcept, "Delete Object %d: Federate %d not owner.", the_object, the_federate); throw DeletePrivilegeNotHeld(); } // 2. Remove Instance from list. list<Object *>::iterator o ; for (o = objectSet.begin(); o != objectSet.end(); o++) { if ((*o)->getHandle() == the_object) { objectSet.erase(o); // i is dereferenced. break ; } } // 3. Prepare and broadcast message. ObjectClassBroadcastList *ocbList = NULL ; if (server != NULL) { D.Out(pdRegister, "Object %u deleted in class %u, now broadcasting...", the_object, handle); NetworkMessage *answer = new NetworkMessage ; answer->type = NetworkMessage::REMOVE_OBJECT ; answer->federation = server->federation(); answer->federate = the_federate ; answer->exception = e_NO_EXCEPTION ; answer->objectClass = handle ; // Class Handle answer->object = the_object ; strcpy(answer->label, the_tag); ocbList = new ObjectClassBroadcastList(answer, 0); broadcastClassMessage(ocbList); } else { D.Out(pdRegister, "Object %u deleted in class %u, no broadcast to do.", the_object, handle); } // Return the BroadcastList in case it had to be passed to the parent // class. return ocbList ;}// ----------------------------------------------------------------------------//! Print the ObjectClasses tree to the standard output.void ObjectClass::display() const{ cout << " ObjectClass #" << handle << " \"" << Name << "\":" << endl ; // Display inheritance cout << " Parent Class Handle: " << Father << endl ; cout << " Security Level: " << LevelID << endl ; cout << " " << sonSet.size() << " Child(s):" << endl ; list<ObjectClassHandle>::const_iterator s = sonSet.begin(); for (int i = 1 ; s != sonSet.end(); s++, i++) { cout << " Son " << i << " handle: "<< (*s) << endl ; } // Display Attributes cout << " " << attributeSet.size() << " Attribute(s):" << endl ; list<ObjectClassAttribute *>::const_iterator a ; for (a = attributeSet.begin(); a != attributeSet.end(); a++) { (*a)->display(); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -