User Manual, Developers Guide and API Documentation

RRHandler.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 <LTE/controlplane/RRHandler.hpp>
00029 #include <LTE/controlplane/flowmanagement/FlowManager.hpp>
00030 #include <LTE/timing/ResourceSchedulerUT.hpp>
00031 #include <LTE/timing/ResourceSchedulerBS.hpp>
00032 #include <LTE/macg/MACg.hpp>
00033 #include <LTE/rlc/RLCCommand.hpp>
00034 #include <LTE/helper/QoSClasses.hpp>
00035 
00036 #include <DLL/StationManager.hpp>
00037 #include <DLL/Layer2.hpp>
00038 
00039 #include <WNS/StaticFactory.hpp>
00040 #include <WNS/ldk/helper/FakePDU.hpp>
00041 #include <WNS/service/dll/StationTypes.hpp>
00042 
00043 #include <vector>
00044 
00045 #define A2N(a) layer2->getStationManager()->getStationByMAC(a)->getName()
00046 
00047 using namespace lte::controlplane;
00048 
00049 STATIC_FACTORY_REGISTER_WITH_CREATOR(RRHandlerBS,
00050                                      wns::ldk::FunctionalUnit,
00051                                      "lte.controlplane.RRHandler.BS",
00052                                      wns::ldk::FUNConfigCreator);
00053 
00054 STATIC_FACTORY_REGISTER_WITH_CREATOR(RRHandlerUT,
00055                                      wns::ldk::FunctionalUnit,
00056                                      "lte.controlplane.RRHandler.UT",
00057                                      wns::ldk::FUNConfigCreator);
00058 
00059 RRHandler::RRHandler(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) :
00060     wns::ldk::CommandTypeSpecifier<RRCommand>(fun),
00061     wns::ldk::HasReceptor<>(),
00062     wns::ldk::HasConnector<lte::helper::SwitchConnector>(),
00063     wns::ldk::HasDeliverer<>(),
00064     helper::HasModeName(config),
00065     connector(dynamic_cast<lte::helper::SwitchConnector*>(getConnector())),
00066     commandSize(config.get<Bit>("commandSize")),
00067     pcchSize(config.get<Bit>("pcchSize")),
00068     logger(config.get("logger")),
00069     layer2(NULL),
00070     pyco(config),
00071     usesShortcut(config.get<bool>("usesShortcut"))
00072 {
00073     MESSAGE_SINGLE(VERBOSE, logger, "RRHandler::RRHandler()");
00074     rlcReader = NULL;
00075 }
00076 
00077 RRHandler::~RRHandler()
00078 {
00079     MESSAGE_SINGLE(NORMAL, logger, "RRHandler::~RRHandler()");
00080     // cleanup: see derived classes
00081 }
00082 
00083 void
00084 RRHandler::onFUNCreated()
00085 {
00086     wns::ldk::fun::FUN* fun = getFUN();
00087 
00088     layer2 = fun->getLayer<dll::Layer2*>();
00089     associationService = layer2->getControlService<dll::services::control::Association>("ASSOCIATION"+modeBase);
00090 
00091     // get handles to outgoing FUs (for sending the ResourceRequests)
00092     typedef std::list<wns::ldk::IConnectorReceptacle*> FUList;
00093     FUList connectorSet = connector->getFUs();
00094     for (FUList::const_iterator iter = connectorSet.begin();
00095          iter != connectorSet.end();
00096          ++iter)
00097     {
00098         size_t found = (*iter)->getFU()->getName().find("rachDispatcher");
00099         if (found != std::string::npos)
00100             friends.rachDispatcher = (*iter);
00101         found = (*iter)->getFU()->getName().find(pyco.get<std::string>("cpDispatcherName"));
00102         if (found != std::string::npos)
00103             friends.cpDispatcher = (*iter);
00104     }
00105     assure(friends.rachDispatcher, "RRHandler requires a Dispatcher/OpcodeSetter friend with name: "+mode+separator+"rachDispatcher");
00106     assure(friends.cpDispatcher, "RRHandler requires a Dispatcher/OpcodeSetter friend with name: "+mode+separator+pyco.get<std::string>("cpDispatcherName"));
00107 
00108     std::string flowmanagername="FlowManager";
00109 
00110     if (layer2->getStationType() == wns::service::dll::StationTypes::UE()) {
00111         // For UTs, initially activate the RACH as outgoing Data Connection
00112         if (usesShortcut)
00113         {
00114             connector->activate(friends.cpDispatcher);
00115         }
00116         else
00117         {
00118             connector->activate(friends.rachDispatcher);
00119         }
00120         flowmanagername += "UT";
00121     } else { // BS
00122         flowmanagername += "BS";
00123     }
00124     // in the BS we don't activate the connector since we don't send anything
00125 
00126     friends.flowManager = layer2->getControlService<lte::controlplane::flowmanagement::FlowManager>(flowmanagername);
00127     assure(friends.flowManager, "FlowManager not set.");
00128     rlcReader  = fun->getCommandReader("rlc");
00129     // The macg command needs to be manipulated
00130     if (mode == modeBase) {
00131         friends.macg = fun->findFriend<lte::macg::MACg*>("macg");
00132     } else {
00133         // taskID is inherited from HasModeName class
00134         friends.macg = fun->findFriend<lte::macg::MACg*>("macg"+separator+taskID);
00135     }
00136 }
00137 
00138 void
00139 RRHandler::setColleagues(wns::scheduler::RegistryProxyInterface* registry)
00140 {
00141     // only required in BS: RegistryProxy of RS-RX (uplink master). Never for RS-TX.
00142     assure((friends.registry == NULL) || (registry == friends.registry),"failed attempt to overload friends.registry");
00143     friends.registry = registry;
00144     assure(friends.registry != NULL,"friends.registry==NULL");
00145 }
00146 
00147 void
00148 RRHandler::doSendData(const wns::ldk::CompoundPtr&)
00149 {
00150     assure(false, "Should never be called!");
00151 }
00152 
00153 bool
00154 RRHandler::doIsAccepting(const wns::ldk::CompoundPtr& /* compound */) const
00155 {
00156     assure(false,"nobody may downconnect on the MapHandler");
00157     // will never be called since nobody is likely to downconnect on the MapHandler
00158     return false;
00159 } // doIsAccepting
00160 
00161 RRHandlerUT::~RRHandlerUT()
00162 {
00163     // cleanup:
00164     allRelayedRequestedResources.clear();
00165 }
00166 
00167 void
00168 RRHandlerUT::doOnData(const wns::ldk::CompoundPtr&
00169 #ifndef NDEBUG
00170                       compound
00171 #endif
00172     )
00173 {
00174     assure(false, "RRHandlerUT does not expect incoming compounds. This compound's journey:\n"<<compound->dumpJourney());
00175 }
00176 
00177 
00178 void
00179 RRHandlerUT::onFUNCreated()
00180 {
00181     RRHandler::onFUNCreated();
00182 
00183     // The RRHandler needs to listen to the Notification about granted resources
00184     this->startObserving(getFUN()->findFriend<wns::Subject<ResourceGrantNotificationInterface>*>(mode+separator+"mapHandler"));
00185 
00186     // a tx scheduler friend is needed to request queue occupancy levels
00187     rstx = getFUN()->findFriend<lte::timing::ResourceSchedulerUT*>(mode+separator+rsNameSuffix+"TX");
00188 }
00189 
00190 // notified by MapHandler if we got resources granted (indicated in the map)
00191 void
00192 RRHandlerUT::resourcesGranted(bool state)
00193 {
00194     resourceGrantState = state;
00195     if (state == true)
00196     {
00197         MESSAGE_SINGLE(NORMAL, logger, "resourcesGranted(true): choosing cpDispatcher connector");
00198         connector->activate(friends.cpDispatcher);
00199         // activate another signaling of requested resources
00200         this->createRRCompound();
00201     }
00202     else
00203     {
00204         if (usesShortcut)
00205         {
00206             MESSAGE_SINGLE(NORMAL, logger, "resourcesGranted(false), useShortcut(true): choosing cpDispatcher connector");
00207             connector->activate(friends.cpDispatcher);
00208         }
00209         else
00210         {
00211             MESSAGE_SINGLE(NORMAL, logger, "resourcesGranted(false): choosing rachDispatcher connector");
00212             connector->activate(friends.rachDispatcher);
00213         }
00214         // if we are a relay then...
00215         // assure(false,"resourcesGranted(false) must not happen anymore");
00216         // take care that at least one RRCompound is still in the Queue
00217         // and that it will be delivered soon in the future
00223         this->createRRCompound();
00224     }
00225 }
00226 
00227 void
00228 RRHandlerUT::createRRCompound()
00229 {
00230     // We can not send a Request if we don't know where to send it.
00231     if (! associationService->hasAssociation())
00232         return;
00233 
00239     wns::ldk::CompoundPtr requestCompound =
00240         wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool(),
00241                                                      wns::ldk::helper::FakePDUPtr(new wns::ldk::helper::FakePDU())));
00242 
00244     lte::macg::MACgCommand* macgCommand = friends.macg->activateCommand(requestCompound->getCommandPool());
00245     macgCommand->peer.source = layer2->getDLLAddress();
00246     wns::service::dll::UnicastAddress peerAddress =  associationService->getAssociation();
00247     macgCommand->peer.dest = peerAddress;
00248 
00249     lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(requestCompound->getCommandPool()));
00250     rlcCommand->peer.source = layer2->getDLLAddress();
00251     //rlcCommand->peer.destination = ?
00252     if (layer2->getStationType() == wns::service::dll::StationTypes::UE())
00253     {
00254         lte::controlplane::flowmanagement::FlowManager::ControlPlaneFlowIDs controlPlaneFlowIDs =
00255             friends.flowManager->getControlPlaneFlowIDs(peerAddress);
00256         pcchFlowID = controlPlaneFlowIDs[lte::helper::QoSClasses::PCCH()];
00257     }
00258     rlcCommand->peer.flowID = pcchFlowID;
00259     assure(pcchFlowID>0, "PCCH FlowID must be > 0");
00260 
00261     MESSAGE_SINGLE(NORMAL, logger, "createRRCompound() to "<<A2N(peerAddress)<<", PCCH FlowID="<<pcchFlowID);
00262 
00263     // Node pointer of the peer node is needed
00264     wns::scheduler::UserID peer = wns::scheduler::UserID(layer2->getStationManager()->getStationByMAC(peerAddress)->getNode());
00265 
00267     RRCommand* outgoingCommand = this->activateCommand(requestCompound->getCommandPool());
00268 
00269     outgoingCommand->peer.request.user = wns::scheduler::UserID(layer2->getNode());
00270     outgoingCommand->magic.source = macgCommand->peer.source;
00271 
00272     // reserve at least resources for the next UL resource request:
00273     wns::scheduler::QueueStatusContainer totalQueueStatus = rstx->getQueueStatus();// QueueStatusContainer
00274     // reserve UL resources for the PCCH which is generated at the end of this method, but only if we do not use the magic shortcut below:
00275     if (!usesShortcut)
00276     {
00277         wns::scheduler::QueueStatus pcchRequestedResources;
00278         pcchRequestedResources.numOfCompounds = 1;
00279         pcchRequestedResources.numOfBits = pcchSize;
00280         if (totalQueueStatus.knows(pcchFlowID))
00281         {
00282             totalQueueStatus.update(pcchFlowID, pcchRequestedResources);
00283         }
00284         else
00285         {
00286             totalQueueStatus.insert(pcchFlowID, pcchRequestedResources);
00287         }
00288 
00289         assure(totalQueueStatus.size()>0,"totalQueueStatus must contain at least one element for following resource requests");
00290     }
00291     else
00292     { // UT
00293         for(wns::scheduler::QueueStatusContainer::const_iterator iter = totalQueueStatus.begin();
00294             iter != totalQueueStatus.end(); ++iter)
00295         {
00296             wns::service::dll::FlowID flowId = iter->first;
00297 
00298             MESSAGE_SINGLE(NORMAL, logger, "requestedResources[FlowID="<<flowId<<"]="<<iter->second.numOfCompounds<<"pdus, "<<iter->second.numOfBits<<"bits");
00299         }
00300     }
00301 
00302     outgoingCommand->peer.request.allRequestedResources = totalQueueStatus;
00303     outgoingCommand->magic.source = layer2->getDLLAddress();
00304 
00306     if (getConnector()->hasAcceptor(requestCompound))
00307     {
00308         MESSAGE_BEGIN(NORMAL, logger, m, "createRRCompound(): prepared ResourceRequest (");
00309         int bitsWaiting=0, compoundsWaiting=0, numFlows=0;
00310         for(wns::scheduler::QueueStatusContainer::const_iterator iter = totalQueueStatus.begin();
00311             iter != totalQueueStatus.end(); ++iter)
00312         {
00313             bitsWaiting += iter->second.numOfBits;
00314             compoundsWaiting += iter->second.numOfCompounds;
00315             ++numFlows;
00316         }
00317         m << bitsWaiting << " bits, ";
00318         m << compoundsWaiting << " compounds, ";
00319         m << numFlows << " flows)";
00320         assure(compoundsWaiting>0 || usesShortcut,"compounds==0 in forwarded resource request");
00321         MESSAGE_END();
00322         getConnector()->getAcceptor(requestCompound)->sendData(requestCompound);
00323     }
00324     else
00325     {
00326         MESSAGE_SINGLE(NORMAL, logger, "createRRCompound(): Failed to send ResourceRequest Compound to "<< A2N(outgoingCommand->magic.source));
00327         assure(false, "Lower FU is not accepting scheduled ResourceRequest but is supposed to do so");
00328     }
00329 }
00330 
00331 int
00332 RRHandler::getTotalNumberOfUsers(const wns::scheduler::UserID /*user*/) const
00333 {
00334     return 1;
00335 }
00336 
00337 // this method is called for each createFakePDU.
00338 void
00339 RRHandler::calculateSizes(const wns::ldk::CommandPool* commandPool, Bit& commandPoolSize, Bit& dataSize) const
00340 {
00341     getFUN()->calculateSizes(commandPool, commandPoolSize, dataSize, this);
00342     // now we have the size of all previous Commands and of the original Compound
00343 
00344     // add my commandSize. No Data to add.
00345     commandPoolSize += this->commandSize;
00346 }
00347 /***************************************************************************/
00348 RRHandlerBS::RRHandlerBS(wns::ldk::fun::FUN* fun, const wns::pyconfig::View& config) :
00349     RRHandler(fun, config),
00350     wns::Cloneable<RRHandlerBS>(),
00351     firstWakeup(true),
00352     rrStorage(new RequestStorage(logger)),
00353     rnUplinkRRHandler(NULL),
00354     rsrx(NULL),
00355     ulSegmentSize(config.get<int>("ulSegmentSize"))
00356 {
00357 }
00358 
00359 RRHandlerBS::~RRHandlerBS()
00360 {
00361     delete rrStorage; rrStorage=NULL;
00362 }
00363 
00364 void
00365 RRHandlerBS::onFUNCreated()
00366 {
00367     // Do the general stuff
00368     RRHandler::onFUNCreated();
00369 
00370     // The rx scheduler is needed to queue the resource requests
00371     rsrx = getFUN()->findFriend<lte::timing::ResourceSchedulerBS*>(mode+separator+rsNameSuffix+"RX");
00372 
00373     // Register as Observer at the association Info providers
00374     dll::Layer2* layer2 = getFUN()->getLayer<dll::Layer2*>();
00375     dll::Layer2::AssociationInfoContainer ais = layer2->getAssociationInfoProvider(mode);
00376     dll::Layer2::AssociationInfoContainer::const_iterator iter = ais.begin();
00377     //dll::ILayer2::AssociationInfoContainer ais = layer2->getAssociationInfoProvider(mode);
00378     //dll::ILayer2::AssociationInfoContainer::const_iterator iter = ais.begin();
00379     for (; iter != ais.end(); ++iter)
00380         this->dll::services::control::AssociationObserver::startObserving(*iter);
00381 
00382     lte::timing::TimingScheduler* timing = layer2->getManagementService<lte::timing::TimingScheduler>(mode+separator+"Timer");
00383     this->wns::Observer<SuperFrameStartNotificationInterface>::startObserving(timing);
00384 }
00385 
00386 int
00387 RRHandlerBS::getDefaultBitsPerPDU()
00388 {
00389     return ulSegmentSize;
00390 }
00391 
00392 wns::ldk::CompoundPtr
00393 RRHandlerBS::createFakePDU(wns::service::dll::UnicastAddress destinationAddress, wns::scheduler::Bits bits, wns::service::dll::FlowID flowID)
00394 {
00395     MESSAGE_SINGLE(NORMAL, logger, "createFakePDU(flowID="<<flowID<<","<<bits<<"bits)");
00396     wns::ldk::CompoundPtr pdu = wns::ldk::CompoundPtr(new wns::ldk::Compound(getFUN()->createCommandPool(),wns::ldk::helper::FakePDUPtr(new wns::ldk::helper::FakePDU( bits ))));
00397     lte::rlc::RLCCommand* rlcCommand = dynamic_cast<lte::rlc::RLCCommand*>(rlcReader->activateCommand(pdu->getCommandPool()));
00398     rlcCommand->peer.flowID = flowID;
00399     lte::macg::MACgCommand* macgCommand = friends.macg->activateCommand(pdu->getCommandPool());
00400     macgCommand->peer.source = layer2->getDLLAddress();
00401     macgCommand->peer.dest   = destinationAddress;
00402     return pdu;
00403 }
00404 
00405 // only called once at simulation start
00406 void
00407 RRHandlerBS::fakeRelayRRs() const
00408 {
00409     typedef std::vector<wns::service::dll::UnicastAddress> IDList;
00410     // all associated users (RN, UT):
00411     IDList allUsers = associationService->getAssociated();
00412     MESSAGE_SINGLE(NORMAL, logger, "fakeRelayRRs(): "<<allUsers.size()<<" associated users");
00413 
00414     // fake requests for every user and hand them down to the lower layer
00415     for (IDList::iterator iter = allUsers.begin(); iter != allUsers.end(); ++iter)
00416     {
00417         ResourceRequest request;
00418         wns::service::dll::UnicastAddress peerAddress = *iter;
00419         wns::node::Interface* peerUserID = layer2->getStationManager()->getStationByMAC(peerAddress)->getNode();
00420         request.user = wns::scheduler::UserID(layer2->getStationManager()->getStationByMAC(peerAddress)->getNode());
00421         lte::controlplane::flowmanagement::FlowManager::ControlPlaneFlowIDs controlPlaneFlowIDs =
00422             friends.flowManager->getControlPlaneFlowIDs(peerAddress);
00423         wns::service::dll::FlowID pcchFlowID = controlPlaneFlowIDs[lte::helper::QoSClasses::PCCH()];
00424 
00425         wns::scheduler::QueueStatus initialPcchResourceRequest;
00426         initialPcchResourceRequest.numOfBits = pcchSize;
00427         initialPcchResourceRequest.numOfCompounds = 1;
00428         wns::scheduler::QueueStatusContainer rnResourceRequests;
00429         rnResourceRequests.insert(pcchFlowID, initialPcchResourceRequest);
00430         rrStorage->storeRequest(wns::scheduler::UserID(peerUserID),rnResourceRequests);
00431         assure(friends.registry!=NULL,"registry==NULL");
00432         friends.registry->registerCID(pcchFlowID,wns::scheduler::UserID(peerUserID));
00433     } // for all users
00434     MESSAGE_SINGLE(NORMAL, logger, "ResourceRequests="<<rrStorage->printQueueStatus());
00435 } // fakeRelayRRs()
00436 
00437 void
00438 RRHandler::doWakeup()
00439 {} // doWakeup
00440 
00441 void
00442 RRHandlerBS::doWakeup()
00443 {
00444     if (firstWakeup == true)
00445     {
00446         MESSAGE_SINGLE(NORMAL, logger, "doWakeup(): firstWakeup");
00447         fakeRelayRRs();
00448         firstWakeup = false;
00449     }
00450 } // doWakeup
00451 
00452 void
00453 RRHandlerBS::onSuperFrameStart()
00454 {
00455     if (firstWakeup == true)
00456     {
00457         MESSAGE_SINGLE(NORMAL, logger, "onSuperFrameStart(): firstWakeup");
00458         fakeRelayRRs();
00459         firstWakeup = false;
00460     }
00461 }
00462 
00463 // incoming ResourceRequests (from UT/RN to BS task)
00464 void
00465 RRHandlerBS::doOnData(const wns::ldk::CompoundPtr& compound)
00466 {
00470     RRCommand* incomingCommand = getCommand(compound->getCommandPool());
00471     wns::service::dll::UnicastAddress rapAddress  = layer2->getDLLAddress(); // invariant -> member
00472     wns::service::dll::UnicastAddress userAddress = incomingCommand->magic.source; // the requester
00473 
00474     // If the originator of the request is not associated with us, we ignore the request
00475     if (!associationService->hasAssociated(userAddress))
00476         return;
00477 
00478     wns::scheduler::UserID peer = incomingCommand->peer.request.user;
00479 
00480     wns::scheduler::QueueStatusContainer requestedResources = incomingCommand->peer.request.allRequestedResources;
00481     lte::controlplane::flowmanagement::FlowManager::ControlPlaneFlowIDs controlPlaneFlowIDs =
00482         friends.flowManager->getControlPlaneFlowIDs(userAddress);
00483     wns::service::dll::FlowID pcchFlowID = controlPlaneFlowIDs[lte::helper::QoSClasses::PCCH()];
00484     // alternatively we could read the rlc command here: rlcCommand->peer.flowID
00485 
00486     MESSAGE_BEGIN(NORMAL, logger, m, "doOnData(): Received Resource Request from: ");
00487     m << peer.getName();
00488     m << " ("<<A2N(userAddress)<<")";
00489     m << " for "<<requestedResources.size()<<" flows";
00490     m << " (PCCH FlowID="<<pcchFlowID<<")";
00491     MESSAGE_END();
00492 
00493     uint32_t assumedBitsPerPDU = ulSegmentSize;
00494     if (requestedResources.size() > 0)
00495     {
00496         rrStorage->storeRequest(peer,requestedResources);
00497 
00498         wns::node::Interface* peerUserID = layer2->getStationManager()->getStationByMAC(userAddress)->getNode();
00499         for( wns::scheduler::QueueStatusContainer::const_iterator iter = requestedResources.begin(); iter != requestedResources.end(); ++iter)
00500         {
00501             wns::scheduler::ConnectionID flowId = iter->first;
00502             assure(friends.registry!=NULL,"registry==NULL");
00503             friends.registry->registerCID(flowId, wns::scheduler::UserID(peerUserID));
00504             // manipulations in the numbers to adjust for inaccuracies:
00505             int pdus = iter->second.numOfCompounds;
00506             int bits = iter->second.numOfBits;
00507             if (bits<pdus*assumedBitsPerPDU) {
00508                 // adjust bits to be at least a multiple of assumedBitsPerPDU
00509                 MESSAGE_SINGLE(NORMAL, logger, "doOnData(): adjusting flowId="<<flowId<<": "<<iter->second.numOfCompounds<<" pdus, "<<iter->second.numOfBits<<" bits -> "<<pdus*assumedBitsPerPDU<<" bits");
00510                 //iter->second.numOfBits = pdus*assumedBitsPerPDU; // add bits
00511                 wns::scheduler::QueueStatus modifiedQueueStatus = iter->second;
00512                 modifiedQueueStatus.numOfBits = pdus*assumedBitsPerPDU; // add bits
00513                 requestedResources.update(flowId,modifiedQueueStatus);
00514             }
00515         }
00516         MESSAGE_SINGLE(NORMAL, logger, "ResourceRequests("<<peer.getName()<<")="<<rrStorage->printQueueStatus());
00517     }
00518 }
00519 
00520 ResourceShares
00521 RRHandlerBS::getResourceShares(const wns::scheduler::UserSet& users) const
00522 {
00523     return rrStorage->getResourceShares(users);
00524 }
00525 
00526 wns::scheduler::UserSet
00527 RRHandlerBS::getActiveUsers() const
00528 {
00529     wns::scheduler::UserSet result = rrStorage->getActiveUsers();
00530 
00531     MESSAGE_BEGIN(VERBOSE, logger, m, "Active Users are: ");
00532     for (wns::scheduler::UserSet::const_iterator iter = result.begin(); iter != result.end(); ++iter)
00533         m << iter->getName() << ", ";
00534     MESSAGE_END();
00535 
00536     return result;
00537 }
00538 
00539 RequestStorageInterface*
00540 RRHandlerBS::getRRStorage()
00541 {
00542     return rrStorage;
00543 }
00544 
00545 void
00546 RRHandlerBS::reset(const wns::scheduler::UserSet& users)
00547 {
00548     rrStorage->reset(users);
00549 }
00550 
00551 void
00552 RRHandlerBS::onAssociated(wns::service::dll::UnicastAddress userAdr,
00553                           wns::service::dll::UnicastAddress dstAdr)
00554 {
00555 }
00556 
00557 void
00558 RRHandlerBS::onDisassociated(wns::service::dll::UnicastAddress userAdr,
00559                              wns::service::dll::UnicastAddress dstAdr)
00560 {
00561     // If we received forwarded association Info, there's nothing to do
00562     if (layer2->getDLLAddress() != dstAdr)
00563         return;
00564 
00565     wns::scheduler::UserID peer = wns::scheduler::UserID(layer2->getStationManager()->getStationByMAC(userAdr)->getNode());
00566 
00567     // Else remove the disassociating user from the rrStorage
00568     MESSAGE_BEGIN(NORMAL, logger, m, "onDisassociated("<<A2N(userAdr)<<","<<A2N(dstAdr)<<"): removing user ");
00569     m << A2N(userAdr) << " from Resource Request rrStorage (peer="<<peer.getName()<<")";
00570     MESSAGE_END();
00571 
00572     rrStorage->resetUser(peer);
00573 }
00574 
00575 /***************************************************************************/
00576 
00577 RequestStorage::RequestStorage(wns::logger::Logger& _logger)
00578     : logger(_logger)
00579 {
00580     MESSAGE_SINGLE(VERBOSE, logger, "RequestStorage::RequestStorage()");
00581 }
00582 
00583 RequestStorage::~RequestStorage()
00584 {
00585 }
00586 
00587 void
00588 RequestStorage::storeRequest(const wns::scheduler::UserID user, wns::scheduler::QueueStatusContainer& partialQueueStatusContainer)
00589 {
00590     //resetUser(user);
00591     for( wns::scheduler::QueueStatusContainer::const_iterator iter = partialQueueStatusContainer.begin(); iter != partialQueueStatusContainer.end(); ++iter)
00592     {
00593         wns::scheduler::ConnectionID flowId = iter->first;
00594         if (queueStatusContainer.knows(flowId)) {
00595             queueStatusContainer.update(flowId,iter->second);
00596         } else {
00597             queueStatusContainer.insert(flowId,iter->second);
00598         }
00599         if (!connectionUserMapping.knows(flowId)) {
00600             connectionUserMapping.insert(flowId,user);
00601         }
00602     }
00603     // insert user that has requested resources into the set of active users
00604     activeULUsers.insert(user);
00605 }
00606 
00607 void
00608 RequestStorage::resetFlow(const wns::scheduler::ConnectionID flowId)
00609 {
00610     if (queueStatusContainer.knows(flowId)) {
00611         wns::scheduler::QueueStatus emptyQueueStatus; // =0
00612         queueStatusContainer.update(flowId,emptyQueueStatus);
00613     }
00614 }
00615 
00616 void
00617 RequestStorage::resetUser(const wns::scheduler::UserID user)
00618 {
00619     for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter)
00620     {
00621         wns::scheduler::ConnectionID     flowId = iter->first;
00622         wns::scheduler::QueueStatus queueStatus = iter->second;
00623         if (connectionUserMapping.find(flowId) == user) {
00624             queueStatus.numOfCompounds = 0;
00625             queueStatus.numOfBits = 0;
00626             queueStatusContainer.update(flowId,queueStatus);
00627         }
00628     }
00629     // remove user from set of active users
00630     activeULUsers.erase(user);
00631 }
00632 
00633 void
00634 RequestStorage::deleteUser(const wns::scheduler::UserID user)
00635 {
00636     for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); )
00637     {
00638         wns::scheduler::QueueStatusContainer::const_iterator nextIter = iter;
00639         ++nextIter;
00640         wns::scheduler::ConnectionID flowId = iter->first;
00641         if (connectionUserMapping.find(flowId) == user) {
00642             queueStatusContainer.erase(flowId);
00643         }
00644         iter=nextIter;
00645     }
00646     // remove user from set of active users
00647     activeULUsers.erase(user);
00648 }
00649 
00650 void
00651 RequestStorage::reset(const wns::scheduler::UserSet& users)
00652 {
00653     wns::scheduler::QueueStatusContainer tmpQueueStatusContainer = queueStatusContainer;
00654     queueStatusContainer.clear();
00655     for( wns::scheduler::QueueStatusContainer::const_iterator iter = tmpQueueStatusContainer.begin(); iter != tmpQueueStatusContainer.end(); ++iter)
00656     {
00657         wns::scheduler::ConnectionID flowId = iter->first;
00658         wns::scheduler::UserID userID = connectionUserMapping.find(flowId);
00659         if (users.find(userID)==users.end()) // not in list of users to delete
00660             queueStatusContainer.insert(flowId,iter->second);
00661     }
00662     // remove users from set of active users
00663     for (wns::scheduler::UserSet::const_iterator iter = users.begin();
00664          iter != users.end();
00665          ++iter)
00666     {
00667         activeULUsers.erase(*iter);
00668     }
00669 }
00670 
00671 // used only in unitTest:
00672 ResourceShares
00673 RequestStorage::getResourceShares(const wns::scheduler::UserSet& users) const
00674 {
00675     typedef std::map<wns::scheduler::UserID, uint32_t> RequestCounter;
00676     RequestCounter compoundsPerUser;
00677     uint32_t totalCompounds = 0;
00678     for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter)
00679     {
00680         wns::scheduler::ConnectionID flowId = iter->first;
00681         wns::scheduler::UserID userID = connectionUserMapping.find(flowId);
00682         if (users.find(userID) != users.end())
00683         {
00684             wns::scheduler::QueueStatus queueStatus = iter->second;
00685             int compoundsWaiting = queueStatus.numOfCompounds;
00686             totalCompounds += compoundsWaiting;
00687             if ( compoundsPerUser.find(userID) != compoundsPerUser.end() ) // found
00688             {
00689                 compoundsPerUser[userID] += compoundsWaiting;
00690             } else { // new entry
00691                 compoundsPerUser[userID] = compoundsWaiting;
00692             }
00693         } // else: Ignore requests from all users not in the given userset
00694     }
00695 
00696     ResourceShares shares;
00697 
00698     for (RequestCounter::const_iterator iter = compoundsPerUser.begin();
00699          iter != compoundsPerUser.end();
00700          ++iter)
00701     {
00702         wns::scheduler::UserID user = iter->first;
00703         uint32_t compoundsThisUser = iter->second;
00704         shares[user] = double(compoundsThisUser) / double(totalCompounds);
00705     }
00706 
00707     return shares;
00708 }
00709 
00710 std::string
00711 RequestStorage::printQueueStatus() const
00712 {
00713     std::stringstream s;
00714     s << "QueueStatus(";
00715     for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter)
00716     {
00717         wns::scheduler::ConnectionID flowId = iter->first;
00718         s << "flowID="<<flowId<<": p="<<iter->second.numOfCompounds<<", b="<<iter->second.numOfBits<<"; ";
00719     }
00720     s << ")";
00721     return s.str();
00722 }
00723 
00724 wns::scheduler::UserSet
00725 RequestStorage::getActiveUsers() const
00726 {
00727     return activeULUsers;
00728 }
00729 
00730 wns::scheduler::ConnectionSet
00731 RequestStorage::getActiveConnections() const
00732 {
00733     wns::scheduler::ConnectionSet result;
00734     for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter)
00735     {
00736         if (iter->second.numOfCompounds > 0)
00737             result.insert(iter->first);
00738     }
00739     return result;
00740 }
00741 
00742 wns::scheduler::ConnectionSet
00743 RequestStorage::filterActiveConnections(wns::scheduler::ConnectionSet& inputConnectionSet) const
00744 {
00745     wns::scheduler::ConnectionSet result;
00746     for (wns::scheduler::ConnectionSet::const_iterator iter = inputConnectionSet.begin(); iter != inputConnectionSet.end(); ++iter)
00747     {
00748         wns::scheduler::ConnectionID flowId = (*iter);
00749         if (queueStatusContainer.knows(flowId)) {
00750             const wns::scheduler::QueueStatus& queueStatus = queueStatusContainer.find(flowId);
00751             if (queueStatus.numOfCompounds > 0)
00752                 result.insert(flowId);
00753         }
00754     }
00755     return result;
00756 }
00757 
00758 bool
00759 RequestStorage::knowsFlow(wns::scheduler::ConnectionID flowId) const
00760 {
00761     return queueStatusContainer.knows(flowId);
00762 }
00763 
00764 bool
00765 RequestStorage::isEmpty() const
00766 {
00767     for( wns::scheduler::QueueStatusContainer::const_iterator iter = queueStatusContainer.begin(); iter != queueStatusContainer.end(); ++iter)
00768         if (iter->second.numOfCompounds > 0)
00769             return false;
00770     return true;
00771 }
00772 
00773 uint32_t
00774 RequestStorage::numBitsForCid(wns::scheduler::ConnectionID cid) const
00775 {
00776     if (queueStatusContainer.knows(cid))
00777     {
00778         const wns::scheduler::QueueStatus& queueStatus = queueStatusContainer.find(cid);
00779         return queueStatus.numOfBits;
00780     } else {
00781         return 0;
00782     }
00783 }
00784 
00785 uint32_t
00786 RequestStorage::numCompoundsForCid(wns::scheduler::ConnectionID cid) const
00787 {
00788     if (queueStatusContainer.knows(cid))
00789     {
00790         const wns::scheduler::QueueStatus& queueStatus = queueStatusContainer.find(cid);
00791         return queueStatus.numOfCompounds;
00792     } else {
00793         return 0;
00794     }
00795 }
00796 
00797 wns::scheduler::Bits
00798 RequestStorage::decrementRequest(wns::scheduler::ConnectionID cid, wns::scheduler::Bits bits)
00799 {
00800     if (queueStatusContainer.knows(cid))
00801     {
00802         assure(bits>0,"decrementRequest(cid="<<cid<<",bits="<<bits<<") must request bits>0");
00803         wns::scheduler::QueueStatus queueStatus = queueStatusContainer.find(cid);
00804         int queuedPdus = queueStatus.numOfCompounds;
00805         int queuedBits = queueStatus.numOfBits;
00806         MESSAGE_SINGLE(NORMAL, logger, "RequestStorage::decrementRequest(cid="<<cid<<",bits="<<bits<<"): queued: "<<queuedPdus<<" pdus, "<<queuedBits<<" bits");
00807         if ((queuedPdus>0) && (queuedBits>0)) {
00808             queueStatus.numOfCompounds --;
00809             if (queuedBits>=bits) {
00810                 queueStatus.numOfBits -= bits;
00811             } else { // not enough bits in queue
00812                 bits = queuedBits;
00813                 queueStatus.numOfBits = 0;
00814             }
00815             // any remaining bits or compounds?
00816             queuedPdus = queueStatus.numOfCompounds;
00817             queuedBits = queueStatus.numOfBits;
00818             if (((queuedPdus>0) && (queuedBits>0))
00819                 || (queuedPdus==0) && (queuedBits==0)) { // ok
00820             } else if (queuedPdus>0) { // but queuedBits=0
00821                 MESSAGE_SINGLE(NORMAL, logger, "RequestStorage::decrementRequest(cid="<<cid<<"): last "<<bits<<" bits served. Leftover "<<queuedPdus<<" pdus set to zero");
00822                 queueStatus.numOfCompounds = 0;
00823             } else if (queuedBits>0) { // but queuedPdus=0
00824                 MESSAGE_SINGLE(NORMAL, logger, "RequestStorage::decrementRequest(cid="<<cid<<"): "<<bits<<" bits served but zero="<<queuedPdus<<" pdus. Assuming one pdu.");
00825                 queueStatus.numOfCompounds += 1;
00826             }
00827             queueStatusContainer.update(cid,queueStatus);
00828         } else {
00829             assure(false,"decrementRequest(cid="<<cid<<",bits="<<bits<<") for empty RR queue");
00830             return 0;
00831         }
00832     } else {
00833         assure(false,"decrementRequest(cid="<<cid<<",bits="<<bits<<") for unknown cid");
00834         throw wns::Exception("decrementRequest for unknown cid");
00835         return 0;
00836     }
00837     return bits;
00838 }
00839 
00840 wns::scheduler::QueueStatusContainer
00841 RequestStorage::getQueueStatus() const
00842 {
00843     return queueStatusContainer;
00844 }

Generated on Fri May 25 03:32:05 2012 for openWNS by  doxygen 1.5.5