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);
     }
   }
 }
Esempio n. 2
0
	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 &currentConnections = 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());
   }
 }