User Manual, Developers Guide and API Documentation

CommandProxy.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002  * This file is part of openWNS (open Wireless Network Simulator)
00003  * _____________________________________________________________________________
00004  *
00005  * Copyright (C) 2004-2007
00006  * Chair of Communication Networks (ComNets)
00007  * Kopernikusstr. 5, D-52074 Aachen, Germany
00008  * phone: ++49-241-80-27910,
00009  * fax: ++49-241-80-22242
00010  * email: info@openwns.org
00011  * www: http://www.openwns.org
00012  * _____________________________________________________________________________
00013  *
00014  * openWNS is free software; you can redistribute it and/or modify it under the
00015  * terms of the GNU Lesser General Public License version 2 as published by the
00016  * Free Software Foundation;
00017  *
00018  * openWNS is distributed in the hope that it will be useful, but WITHOUT ANY
00019  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00020  * A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
00021  * details.
00022  *
00023  * You should have received a copy of the GNU Lesser General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  *
00026  ******************************************************************************/
00027 
00028 #include <WNS/ldk/CommandProxy.hpp>
00029 #include <WNS/ldk/CommandReaderInterface.hpp>
00030 #include <WNS/ldk/fun/FUN.hpp>
00031 #include <WNS/ldk/FunctionalUnit.hpp>
00032 #include <WNS/ldk/Command.hpp>
00033 #include <WNS/ldk/Compound.hpp>
00034 #include <WNS/TypeInfo.hpp>
00035 #include <WNS/Exception.hpp>
00036 #include <WNS/simulator/ISimulator.hpp>
00037 
00038 using namespace wns::ldk;
00039 
00040 CommandProxy::CommandIDType CommandProxy::serial = CommandIDType(0);
00041 
00042 CommandProxy::CommandProxy(const wns::pyconfig::View& config) :
00043     logger(config.get("logger"))
00044 {
00045     wns::simulator::getResetSignal()->connect(&wns::ldk::CommandProxy::clearRegistries);
00046 }
00047 
00048 
00049 CommandProxy::~CommandProxy()
00050 {
00051     for (size_t ii = 0; ii < this->commandTypeSpecifiers.size(); ++ii) {
00052         if (this->commandTypeSpecifierCloned.at(ii)) {
00053             delete this->commandTypeSpecifiers.at(ii);
00054         }
00055     }
00056 
00059 } // ~CommandProxy
00060 
00061 
00062 void
00063 CommandProxy::addFunctionalUnit(
00064     const std::string& commandName,
00065     CommandTypeSpecifierInterface* functionalUnit)
00066 {
00067     assure(functionalUnit != NULL, "Not a valid CommandTypeSpecifierInterface.");
00068     assure(functionalUnit->getFUN() != NULL, "CommandTypeSpecifierInterface is not attached to a fun::FUN.");
00069     assure(functionalUnit->getFUN()->getProxy() == this, "CommandProxy mismatch.");
00070 
00071     // Registered FU at a global CommandIDRegistry
00072     if (this->getCommandIDRegistry().knows(commandName))
00073     {
00074         CommandIDType id = this->getCommandIDRegistry().find(commandName);
00075         functionalUnit->setPCIID(id);
00076         if (id < this->commandTypeSpecifierCloned.size())
00077         {
00078             if (this->commandTypeSpecifierCloned.at(id) == true)
00079             {
00080                 // we are re-adding a formerly removed FU, so delete the clone
00081                 delete this->commandTypeSpecifiers.at(id);
00082                 this->commandTypeSpecifierCloned.at(id) = false;
00083                 this->commandTypeSpecifiers.at(id) = functionalUnit;
00084             }
00085         }
00086     }
00087     else
00088     {
00089         this->getCommandIDRegistry().insert(commandName, serial);
00090         functionalUnit->setPCIID(serial);
00091         ++serial;
00092     }
00093 
00094     // if container is too small: resize and set new elements to NULL
00095     if (this->commandTypeSpecifiers.size() <= functionalUnit->getPCIID()) {
00096         size_t oldSize = this->commandTypeSpecifiers.size();
00097         this->commandTypeSpecifiers.resize(functionalUnit->getPCIID()+1);
00098         this->commandTypeSpecifierCloned.resize(functionalUnit->getPCIID()+1);
00099         for(size_t ii = oldSize; ii < this->commandTypeSpecifiers.size(); ++ii) {
00100             this->commandTypeSpecifiers.at(ii) = NULL;
00101             this->commandTypeSpecifierCloned.at(ii) = false;
00102         }
00103     }
00104 
00105     if (this->commandTypeSpecifiers.at(functionalUnit->getPCIID()) == NULL) {
00106         this->commandTypeSpecifiers.at(functionalUnit->getPCIID()) = functionalUnit;
00107         MESSAGE_SINGLE(VERBOSE, logger, "Added FU to commandTypeSpecifiers List, Type is: " << wns::TypeInfo::create(*functionalUnit).toString());
00108     }
00109 
00110     // Keep a global list of CopyCommand Objects to enable
00111     // "partialCopy"
00112     if (! this->getCopyCommandRegistry().knows(functionalUnit->getPCIID()))
00113     {
00114         this->getCopyCommandRegistry().insert(functionalUnit->getPCIID(),
00115                               functionalUnit->getCopyCommandInterface());
00116     }
00117     else
00118     {
00119         // Make sure that the new CommandTypeSpecifier works on the same
00120         // command as the already known one.
00121         CopyCommandInterface* tmp = functionalUnit->getCopyCommandInterface();
00122         assure ( wns::TypeInfo::create(*this->getCopyCommandRegistry().find(functionalUnit->getPCIID()))
00123              ==
00124              wns::TypeInfo::create(*tmp), "forbidden commandName duplication ('"+commandName+"')" );
00125         delete tmp;
00126     }
00127 
00128     // Keep a global list of CommandReader Objects to access commands
00129     if (! this->getCommandReaderRegistry().knows(functionalUnit->getPCIID()))
00130     {
00131         this->getCommandReaderRegistry().insert(functionalUnit->getPCIID(),
00132                             functionalUnit->getCommandReader(this));
00133     }
00134     else
00135     {
00136         // Make sure that the new CommandTypeSpecifier works on the same
00137         // command as the already registered one.
00138         CommandReaderInterface* tmp = functionalUnit->getCommandReader(this);
00139         assure ( wns::TypeInfo::create(*this->getCommandReaderRegistry().find(functionalUnit->getPCIID()))
00140              ==
00141              wns::TypeInfo::create(*tmp),  "forbidden commandName duplication ('"+commandName+"')" );
00142         delete tmp;
00143     }
00144 
00145 } // addFunctionalUnit
00146 
00147 
00148 void
00149 CommandProxy::removeFunctionalUnit(const std::string& commandName)
00150 {
00151     if (!this->getCommandIDRegistry().knows(commandName))
00152     {
00153         wns::Exception e;
00154         e << "Can't remove FU. FU commandName \"" << commandName << "\" unknown.";
00155         throw wns::Exception(e);
00156     }
00157 
00158     CommandIDType id = this->getCommandIDRegistry().find(commandName);
00159 
00160     if (this->commandTypeSpecifiers.at(id) == NULL)
00161     {
00162         wns::Exception e;
00163         e << "Can't remove FU. FU with commandName \"" << commandName
00164           << "\" does not exist in this FUN.";
00165         throw wns::Exception(e);
00166     }
00167 
00168     if (this->commandTypeSpecifierCloned.at(id) == false)
00169     {
00170         CommandTypeSpecifierInterface* ctsi = this->commandTypeSpecifiers.at(id);
00171         assureType(ctsi, FunctionalUnit*);
00172         wns::CloneableInterface* clonedFU = dynamic_cast<FunctionalUnit*>(ctsi)->clone();
00173         assureType(clonedFU, FunctionalUnit*);
00174         this->commandTypeSpecifiers.at(id) = dynamic_cast<FunctionalUnit*>(clonedFU);
00175 
00176         this->commandTypeSpecifierCloned.at(id) = true;
00177     }
00178 }
00179 
00180 
00181 wns::ldk::Command*
00182 CommandProxy::getCommand(
00183     const CommandPool* commandPool,
00184     const CommandTypeSpecifierInterface* kind) const
00185 {
00186     assure(kind != NULL, "Invalid argument.");
00187     return this->getCommand(commandPool, kind->getPCIID());
00188 } // getCommand
00189 
00190 
00191 wns::ldk::Command*
00192 CommandProxy::getCommand(
00193     const CommandPool* commandPool,
00194     CommandIDType n) const
00195 {
00196     assure(commandPool != NULL, "Invalid argument.");
00197     assure(commandPool->knows(n),
00198            "Command (Command ID: " << n << ") not activated in CommandPool. Only activated Commands may be retrieved." <<
00199            "\nThe following commands are in the CommandPool:\n" << commandPool->dumpCommandTypes() <<
00200            "\nThe following commands are registered at the CommandProxy:\n" << dumpCommandIDRegistry());
00201 
00202     Command* command = commandPool->find(n);
00203 
00204     return command;
00205 } // getCommand
00206 
00207 CommandReaderInterface*
00208 CommandProxy::getCommandReader(const std::string& role) const
00209 {
00210     assure(this->getCommandIDRegistry().knows(role), "ID for unknown role="<<role<<" requested. Available="<<dumpCommandIDRegistry());
00211     unsigned long int id = this->getCommandIDRegistry().find(role);
00212     assure(this->getCommandReaderRegistry().knows(id), "CommandReader for unknown ID="<<id<<" requested.");
00213     return this->getCommandReaderRegistry().find(id);
00214 } // getCommandReader
00215 
00216 bool
00217 CommandProxy::commandIsActivated(
00218     const CommandPool* commandPool,
00219     const CommandTypeSpecifierInterface* kind) const
00220 {
00221     assure(kind != NULL, "Invalid argument.");
00222     return this->commandIsActivated(commandPool, kind->getPCIID());
00223 } // commandIsActivated
00224 
00225 
00226 bool
00227 CommandProxy::commandIsActivated(
00228     const CommandPool* commandPool,
00229     const CommandIDType& id) const
00230 {
00231     assure(commandPool != NULL, "Invalid argument.");
00232     return commandPool->knows(id);
00233 }
00234 
00235 
00236 wns::ldk::Command*
00237 CommandProxy::activateCommand(
00238     CommandPool* commandPool,
00239     const CommandTypeSpecifierInterface* kind)
00240 {
00241     assure(commandPool != NULL, "Invalid argument.");
00242     assure(kind != NULL, "Invalid argument.");
00243     assure(!commandPool->knows(kind->getPCIID()),
00244            "Command " << kind->getPCIID()  
00245             << " already added to command pool. Trying to activate an already activated Command.\n"
00246             << dumpCommandIDRegistry());
00247 
00248     Command* command = kind->createCommand();
00249 
00250     commandPool->insert(kind->getPCIID(), command);
00251 
00252 #ifndef NDEBUG
00253     for(CommandPool::PathContainer::const_iterator i = commandPool->path.begin();
00254         i != commandPool->path.end();
00255         ++i)
00256         assure(*i != kind->getPCIID(), "Corrupted path: trying to add a CommandTypeSpecifierInterface twice.");
00257 #endif
00258     commandPool->path.push_back(kind->getPCIID());
00259 
00260     return command;
00261 } // activateCommand
00262 
00263 Command*
00264 CommandProxy::activateCommand(
00265                  CommandPool* commandPool,
00266                  const CommandIDType& id)
00267 {
00268     assure(commandPool != NULL, "Invalid argument.");
00269     assure(id < commandTypeSpecifiers.size(), "Invalid ID");
00270 
00271     return activateCommand(commandPool, commandTypeSpecifiers.at(id));
00272 }
00273 
00274 CommandPool*
00275 CommandProxy::createCommandPool(const fun::FUN* origin) const
00276 {
00277     return new CommandPool(this, origin);
00278 } // createCommandPool
00279 
00280 
00281 const CommandTypeSpecifierInterface*
00282 CommandProxy::getNext(
00283     const CommandPool* commandPool,
00284     const CommandTypeSpecifierInterface* questioner) const
00285 {
00286     if(!questioner)
00287     {
00288         if(commandPool->path.empty())
00289             return NULL;
00290 
00291         return getCommandTypeSpecifier(commandPool->path.back());
00292     }
00293 
00294     CommandPool::PathContainer::const_iterator i;
00295     for(i = commandPool->path.begin();
00296         i != commandPool->path.end();
00297         ++i)
00298     {
00299         if(*i == questioner->getPCIID())
00300             break;
00301     }
00302     assure(i != commandPool->path.end(), "Questioner is not in path. This could mean that you have included a FU on the receiver side but not on the sender side.");
00303 
00304     // delegate up one level.
00305     if(i == commandPool->path.begin())
00306         return NULL;
00307 
00308     --i;
00309 
00310     return this->getCommandTypeSpecifier(*i);
00311 } // getNext
00312 
00313 
00314 CommandPool*
00315 CommandProxy::createReply(
00316     const CommandPool* original,
00317     const CommandTypeSpecifierInterface* questioner) const
00318 {
00319     const CommandTypeSpecifierInterface* next = this->getNext(original, questioner);
00320 
00321     if(!next)
00322         return this->createCommandPool();
00323 
00324     return next->createReply(original);
00325 } // createReplyPCI
00326 
00327 
00328 void
00329 CommandProxy::calculateSizes(
00330     const CommandPool* commandPool,
00331     Bit& commandPoolSize, Bit& dataSize,
00332     const CommandTypeSpecifierInterface* questioner) const
00333 {
00334     const CommandTypeSpecifierInterface* next = this->getNext(commandPool, questioner);
00335 
00336     if(next)
00337     {
00338         // Look at the next command in the chain, if its sizes are already commited we can stop
00339         // the recursion
00340         Command* nextCommand = commandPool->commands.at(next->getPCIID());
00341         if ( nextCommand->sizeCommited() )
00342         {
00343             // End recursion
00344             commandPoolSize = nextCommand->getCommandPoolSize();
00345             dataSize        = nextCommand->getPayloadSize();
00346             MESSAGE_BEGIN(VERBOSE, logger,m,"End of recursion, already commited sizes ");
00347             m << " - commandPoolSize: " << commandPoolSize << " dataSize: " << dataSize;
00348             MESSAGE_END();
00349             return;
00350         }
00351         else
00352         {
00353             // Continue recursion
00354             next->calculateSizes(commandPool, commandPoolSize, dataSize);
00355             MESSAGE_BEGIN(VERBOSE, logger,m,"Sizes after: ");
00356             m << dynamic_cast<const wns::ldk::FunctionalUnit*>(next)->getName()
00357               << " - commandPoolSize: " << commandPoolSize << " dataSize: " << dataSize;
00358             MESSAGE_END();
00359             return;
00360         }
00361     }
00362 
00363     // We have reached the beginning of the activation path, so we start
00364     // calculating with an empty commandPool and the original SDU size for
00365     // the data.
00366     commandPoolSize = 0;
00367     if(commandPool->getSDU())
00368         dataSize = commandPool->getSDU()->getLengthInBits();
00369     else
00370         dataSize = 0;
00371 
00372     MESSAGE_BEGIN(VERBOSE, logger,m,"End of recursion, adding SDU size ");
00373     m << " - commandPoolSize: " << commandPoolSize << " dataSize: " << dataSize;
00374     MESSAGE_END();
00375 } // calculateSizes
00376 
00377 
00378 void
00379 CommandProxy::commitSizes(
00380     CommandPool* commandPool,
00381     const CommandTypeSpecifierInterface* commiter) const
00382 {
00383     const CommandTypeSpecifierInterface* next = this->getNext(commandPool, commiter);
00384 
00385     if(next)
00386     {
00387         Command* nextCommand = commandPool->commands.at(next->getPCIID());
00388 
00389         if ( nextCommand->sizeCommited() )
00390         {
00391             // End of recursion, commit the commiters command Sizes
00392             Command* command = this->commit(commandPool, commiter);
00393 
00394             MESSAGE_BEGIN(VERBOSE, logger,m,"End of recursion - beginning of non-commited Path (");
00395             m << dynamic_cast<const wns::ldk::FunctionalUnit*>(next)->getName() << ")"
00396               << " - commandPoolSize: " << command->getCommandPoolSize()
00397               << " dataSize: " << command->getPayloadSize();
00398             MESSAGE_END();
00399 
00400             return;
00401 
00402         }
00403         else
00404         {
00405             // first continue recursion
00406             next->commitSizes(commandPool);
00407             // then commit my own command
00408             Command* command = this->commit(commandPool, commiter);
00409 
00410             MESSAGE_BEGIN(VERBOSE, logger,m,"Sizes after: ");
00411             m << dynamic_cast<const wns::ldk::FunctionalUnit*>(commiter)->getName()
00412               << " - commandPoolSize: " << command->getCommandPoolSize()
00413               << " dataSize: " << command->getPayloadSize();
00414             MESSAGE_END();
00415             return;
00416         }
00417     }
00418 
00419     // We have reached the beginning of the activation path, so we can
00420     // commit the commiter's command size
00421     Command* command = this->commit(commandPool, commiter);
00422 
00423     MESSAGE_BEGIN(VERBOSE, logger,m,"End of recursion - beginning of activation Path (");
00424     m << dynamic_cast<const wns::ldk::FunctionalUnit*>(commiter)->getName() << ")"
00425       << " - commandPoolSize: " << command->getCommandPoolSize()
00426       << " dataSize: " << command->getPayloadSize();
00427     MESSAGE_END();
00428 } // calculateSizes
00429 
00430 void
00431 CommandProxy::commitSizes(CommandPool* commandPool, const CommandIDType& id) const
00432 {
00433     commitSizes(commandPool, getCommandTypeSpecifier(id));
00434 }
00435 
00436 wns::ldk::Command*
00437 CommandProxy::commit(CommandPool* commandPool,
00438              const CommandTypeSpecifierInterface* commiter) const
00439 {
00440     assure(commandPool != NULL, "No valid commandPool given.");
00441     assure(commiter != NULL, "No commiter set. "
00442                              "Are you using the CommandProxy::commitSizes"
00443                              "directly?. You should use the "
00444                              "CommandTypeSpecifier::commitSizes.");
00445 
00446     Command* command = commiter->getCommand(commandPool);
00447     Bit commandPoolSize = 0;
00448     Bit dataSize = 0;
00449     commiter->calculateSizes(commandPool, commandPoolSize, dataSize);
00450     command->setCommandPoolSize(commandPoolSize);
00451     command->setPayloadSize(dataSize);
00452     command->commit(); // makes the command Read-only
00453     return command;
00454 }
00455 
00456 void
00457 CommandProxy::cleanup(CommandPool* commandPool) const
00458 {
00459     delete commandPool;
00460 } // cleanup
00461 
00462 
00463 void
00464 CommandProxy::copy(CommandPool* dst, const CommandPool* src) const
00465 {
00466     for(CommandPool::PathContainer::const_iterator it = src->path.begin();
00467         it != src->path.end();
00468         ++it)
00469     {
00470         CommandIDType id = *it;
00471         dst->insert(id, this->getCopyCommandRegistry().find(id)->copy(src->find(id)));
00472         dst->path.push_back(id);
00473     }
00474 } // copy
00475 
00476 
00477 void
00478 CommandProxy::partialCopy(
00479     const CommandTypeSpecifierInterface* initiator,
00480     CommandPool* dst, const CommandPool* src) const
00481 {
00482     CommandIDType initiatorID = initiator->getPCIID();
00483 
00484     CommandPool::PathContainer::const_iterator it = src->path.begin();
00485     for(;it != src->path.end();
00486         ++it)
00487     {
00488         CommandIDType id = *it;
00489 
00490         if(id == initiatorID)
00491             break;
00492 
00493         dst->insert(id, this->getCopyCommandRegistry().find(id)->copy(src->find(id)));
00494         dst->path.push_back(id);
00495     }
00496     assure(it != src->path.end(), "partial copy failed, initiator was not found in activation path");
00497 } // partialCopy
00498 
00499 
00500 const CommandTypeSpecifierInterface*
00501 CommandProxy::getCommandTypeSpecifier(CommandIDType id) const
00502 {
00503     if (!this->commandTypeSpecifiers.at(id))
00504     {
00505         //std::stringstream ss;
00506         //ss << id;
00507         //throw wns::Exception("Invalid CommandTypeSpecifier instance with id="+ss.str()+" requested.");
00508         // @todo: find a better way to cope with the lack of information here.
00509         MESSAGE_SINGLE(NORMAL, logger, "WARNING: Invalid CommandTypeSpecifier instance with id="<<(int)id<<" requested.");
00510         return NULL;
00511     }
00512     return this->commandTypeSpecifiers.at(id);
00513 } // getCommandTypeSpecifier
00514 
00515 
00516 CommandProxy::CommandIDRegistry&
00517 CommandProxy::getCommandIDRegistry()
00518 {
00519     static CommandIDRegistry registry;
00520     return registry;
00521 }
00522 
00523 std::string
00524 CommandProxy::dumpCommandIDRegistry()
00525 {
00526     CommandIDRegistry& registry = getCommandIDRegistry();
00527     std::stringstream str;
00528     for(CommandIDRegistry::const_iterator itr = registry.begin();
00529         itr != registry.end();
00530         ++itr)
00531     {
00532         str << "Command ID: " << itr->second << ", Role name: " << itr->first << "\n";
00533     }
00534     return str.str();
00535 }
00536 
00537 CommandProxy::CopyCommandInterfaceRegistry&
00538 CommandProxy::getCopyCommandRegistry()
00539 {
00540     static CopyCommandInterfaceRegistry registry;
00541     return registry;
00542 }
00543 
00544 CommandProxy::CommandReaderRegistry&
00545 CommandProxy::getCommandReaderRegistry()
00546 {
00547     static CommandReaderRegistry registry;
00548     return registry;
00549 }
00550 
00551 void
00552 CommandProxy::clearRegistries()
00553 {
00554     CommandProxy::getCommandIDRegistry().clear();
00555     CommandProxy::getCopyCommandRegistry().clear();
00556     CommandProxy::getCommandReaderRegistry().clear();
00557 }
00558 
00559 #ifndef NDEBUG
00560 size_t
00561 CommandProxy::getCommandObjSize(const CommandIDType& id) const
00562 {
00563     const CommandTypeSpecifierInterface* commandTypeSpecifier
00564         = this->getCommandTypeSpecifier(id);
00565     if (commandTypeSpecifier != NULL) {
00566         return this->getCommandTypeSpecifier(id)->getCommandObjSize();
00567     } else {
00568         return 0;
00569     }
00570 }
00571 #endif
00572 
00573 

Generated on Tue May 22 03:31:37 2012 for openWNS by  doxygen 1.5.5