wns::scheduler::MapInfoCollectionPtr ProportionalFair::doStartSubScheduling(SchedulerStatePtr schedulerState, wns::scheduler::SchedulingMapPtr schedulingMap) { MapInfoCollectionPtr mapInfoCollection = MapInfoCollectionPtr(new wns::scheduler::MapInfoCollection); // result datastructure UserSet allUsersInQueue = colleagues.queue->getQueuedUsers(); UserSet activeUsers = colleagues.registry->filterReachable(allUsersInQueue); ConnectionSet ¤tConnections = schedulerState->currentState->activeConnections; MESSAGE_SINGLE(NORMAL, logger, "activeUsers= "<< activeUsers.size()<<" , currentConnections= "<<printConnectionSet(currentConnections)<<" "); if (activeUsers.empty() || currentConnections.empty()) return mapInfoCollection; // nothing to do simTimeType slotLength = schedulingMap->getSlotLength(); bool txStrategy = schedulerState->isTx; std::map<UserID, float> bitsBeforeThisFrame = calculateBitsForConnections(currentConnections); MESSAGE_BEGIN(NORMAL, logger, m, "ProportionalFair"); for (std::map<UserID, float>::const_iterator iter = bitsBeforeThisFrame.begin(); iter != bitsBeforeThisFrame.end(); ++iter) { m << "\n User " << iter->first.getName() << " has " << iter->second; m << " queued bits."; } MESSAGE_END(); std::map<UserID, float> pastDataRates; // make preferences a member, then no return value needed std::priority_queue<UserPreference> preferences = calculateUserPreferences(activeUsers, txStrategy); // returns the connection of the user with the highest preference, i.e. lowest past data rate wns::scheduler::ConnectionID currentConnection = getNextConnection(schedulerState, preferences); //wns::scheduler::UserID user = colleagues.registry->getUserForCid(currentConnection); bool spaceLeft= true; int pduCounter = 0; // static const noCID and then check for (currentConnection != noCID) while(spaceLeft && (currentConnection >= 0)) { // schedule blockSize PDUs for this CID while( colleagues.queue->queueHasPDUs(currentConnection) && spaceLeft) { spaceLeft = scheduleCid(schedulerState,schedulingMap,currentConnection,pduCounter,blockSize,mapInfoCollection); } // while PDUs in queue /*if (!colleagues.queue->queueHasPDUs(currentConnection)) { // exit because of queue empty (most probable case for low traffic) currentConnections.erase(currentConnection); if (currentConnections.empty()) break; // all queues empty }*/ currentConnection = getNextConnection(schedulerState, preferences); // user = colleagues.registry->getUserForCid(currentConnection); MESSAGE_SINGLE(NORMAL, logger, "doStartSubScheduling(): next connection="<<currentConnection); } // while(spaceLeft) MESSAGE_SINGLE(NORMAL, logger, "doStartSubScheduling(): ready: mapInfoCollection of size="<<mapInfoCollection->size()); std::map<UserID, float> bitsAfterThisFrame = calculateBitsForConnections(currentConnections); MESSAGE_BEGIN(NORMAL, logger, m, "ProportionalFair"); for (std::map<UserID, float>::const_iterator iter = bitsAfterThisFrame.begin(); iter != bitsAfterThisFrame.end(); ++iter) { m << "\n User " << iter->first.getName() << " has " << iter->second; m << " queued bits left after this frame."; } MESSAGE_END(); assure(bitsBeforeThisFrame.size() == bitsAfterThisFrame.size(), "bitsBeforeThisFrame and bitsAfterThisFrame do not have the same number of users!"); updatePastDataRates(bitsBeforeThisFrame, bitsAfterThisFrame, slotLength); return mapInfoCollection; }
/** * @brief Return a vector of users but only include those that could get an SINR * that is suitable for transmission when served alone. If we can't even * transmit when the users is grouped alone, there is no point in trying to * group him with users. */ std::vector<UserID> AllPossibleGroupsGrouper::getServableUserVectorFromSet(const UserSet userSet, ModeType mode) { std::map<UserID, wns::CandI> candis; std::vector<UserID> userVector; // convert UserSet to userVector needed for calculateAllPossibleGroups for (UserSet::const_iterator iter = userSet.begin(); iter != userSet.end(); ++iter) { switch(mode) { case tx: { if (beamforming){ std::map<wns::node::Interface*, wns::Power> userNoiseIInterMap; userNoiseIInterMap.clear(); userNoiseIInterMap[iter->getNode()] = colleagues.registry->estimateTxSINRAt(*iter).interference; candis = convertMap(friends.ofdmaProvider->calculateCandIsTx(userNoiseIInterMap, x_friendliness, txPower)); } else{ // no beamforming assure(userSet.size() == 1, "We don't do beamforming, so only one-user groups are supported"); UserID user = *iter; wns::scheduler::ChannelQualityOnOneSubChannel cqi = colleagues.registry->estimateTxSINRAt(user); candis[user] = wns::CandI(cqi.carrier, cqi.interference); } } break; case rx: { if (beamforming){ std::vector<wns::node::Interface*> combination; combination.clear(); combination.push_back(iter->getNode()); candis = convertMap(friends.ofdmaProvider->calculateCandIsRx(combination, colleagues.registry->estimateRxSINROf(*iter).interference)); } else{ // no beamforming assure(userSet.size() == 1, "We don't do beamforming, so only one-user groups are supported"); UserID user = *iter; wns::scheduler::ChannelQualityOnOneSubChannel cqi = colleagues.registry->estimateRxSINROf(user); candis[user] = wns::CandI(cqi.carrier, cqi.interference); } } break; default: assure(0, "Unknown mode"); } wns::Ratio sinr(candis[*iter].C / candis[*iter].I); //if (colleagues.registry->getPhyModeForSIR(candis[*iter].C / candis[*iter].I).second > 0.0001) if (colleagues.phyModeMapper->sinrIsAboveLimit(sinr)) userVector.push_back(*iter); else { MESSAGE_BEGIN(VERBOSE, logger, m, colleagues.registry->getNameForUser(colleagues.registry->getMyUserID())); m << "removing user" << colleagues.registry->getNameForUser(*iter) << " because SINR is not sufficient even for serving the user alone"; MESSAGE_END(); } } return userVector; }