void AdjustBuildIndex(int childi) { int targetindex = rebuild ? childi+1 : childi; if (targetindex > buildindex) { buildindex = targetindex; for (UserSet::iterator u = users.begin(); u != users.end(); ++u) { (*u)->AdjustBuildIndex(buildindex); } } }
std::string ToString(SerializeFormat format) const { std::ostringstream oss; oss << lastnotify; for (UserSet::const_iterator i = accepting.begin(); i != accepting.end(); ++i) { User* u = *i; // Encode UIDs. oss << "," << (format == FORMAT_USER ? u->nick : u->uuid); } return oss.str(); }
RebuildNode(const std::string &ref, const CurrentStack &currstack) : verref(ref), buildindex(-1), rebuild(false) { if (currstack.size()) { users.insert(currstack.back()); } }
std::priority_queue<ProportionalFair::UserPreference> ProportionalFair::calculateUserPreferences(UserSet activeUsers, bool txStrategy) const { std::map<UserID, ChannelQualityOnOneSubChannel> sinrs; // preference for every user in a priority queue which automatically sorts std::priority_queue<UserPreference> preferences; assure(preferences.size()==0, "preferences.size() must be 0"); for ( UserSet::const_iterator iter = activeUsers.begin(); iter != activeUsers.end(); ++iter) { UserID user = *iter; assure(user.isValid(), "No valid user"); //determines the users SINRs depending on the tx/Rx mode of the strategy if (txStrategy) { sinrs[user] = colleagues.registry->estimateTxSINRAt(user); } else { sinrs[user] = colleagues.registry->estimateRxSINROf(user); } // calculate PhyModeRate for available users wns::Ratio sinr(sinrs[user].carrier / sinrs[user].interference); wns::service::phy::phymode::PhyModeInterfacePtr phyMode = colleagues.registry->getPhyModeMapper()->getBestPhyMode(sinr); assure(phyMode->isValid(),"invalid PhyMode"); // calculate userRate, which is the maximum possible data rate // for one subChannel for the best PhyMode available here float phyModeRate = phyMode->getDataRate(); // rate [b/s] of one subChannel float referenceRate; float pastDataRate = 1.0; // get the past data rate for this user: // iterate over the global past data rates map of all users and // find the past data rate for this user // there is exactly one pastDataRate value per userID int weight = colleagues.registry->getTotalNumberOfUsers(user); for (std::map<UserID, float>::const_iterator iter = pastDataRates.begin(); iter != pastDataRates.end(); ++iter) { if (iter->first/*userID*/ == user) { float dataRate = iter->second; // a RN must get a better share of the bandwidth // here: proportional to its number of users: assure(weight>0, "numberOfUsers(" <<user.getName()<<")=" << weight); dataRate /= static_cast<float>(weight); // dataRate now has the meaning of a weight. pastDataRate = dataRate; } } // for all userIDs in pastDataRates if (pastDataRate < 0.01) pastDataRate = 0.01; // preference is achievable current user rate divided by a history // factor that takes the past throughput of this user into account assure(maxRateOfSubchannel>0.0, "unknown maxRateOfSubchannel"); // goal is either rate (true) or resource (false) fairness if (rateFairness == true) { referenceRate = maxRateOfSubchannel; } else { referenceRate = phyModeRate; } // maxRateOfSubchannel is constant, with range [0..1][bit/s] float resultMaxThroughput = referenceRate / maxRateOfSubchannel; float resultPropFair = referenceRate / pastDataRate; // can be any range if (scalingBetweenMaxTPandPFair <= 0.5) { // variate the preference for each user, so that they differ a little bit (1%) // and the automatic sorting does not always give the same order // (would be a problem for identical preference weights). resultMaxThroughput *= (1 + 0.01*(*preferenceVariationDistribution)()); } float UserPref = (1.0-scalingBetweenMaxTPandPFair) * resultMaxThroughput +scalingBetweenMaxTPandPFair * resultPropFair; MESSAGE_SINGLE(NORMAL, logger, "getPreference("<<user.getName()<<"): weight=" << weight << ", pastDataRate= "<<pastDataRate<<" bit/s, UserPreference= "<<UserPref<<" (resultMaxThroughput="<<resultMaxThroughput<<",resultProportionalFair="<<resultPropFair<<")"); // calculate preferences for users and order them preferences.push(UserPreference(UserPref, user)); } return preferences; }
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; }
void AddUser(const CurrentStack &currstack) { if (currstack.size()) { users.insert(currstack.back()); } }