File indexing completed on 2025-01-05 04:37:19

0001 /*
0002     SPDX-FileCopyrightText: 2005 Joris Guisson <joris.guisson@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 #include "networkthread.h"
0007 #include "socketgroup.h"
0008 #include "socketmonitor.h"
0009 #include <math.h>
0010 #include <util/functions.h>
0011 #include <util/log.h>
0012 
0013 using namespace bt;
0014 
0015 namespace net
0016 {
0017 NetworkThread::NetworkThread(SocketMonitor *sm)
0018     : sm(sm)
0019     , running(false)
0020     , prev_run_time(0)
0021 {
0022     groups.setAutoDelete(true);
0023     groups.insert(0, new SocketGroup(0, 0));
0024 }
0025 
0026 NetworkThread::~NetworkThread()
0027 {
0028 }
0029 
0030 void NetworkThread::run()
0031 {
0032     running = true;
0033     prev_run_time = bt::Now();
0034     while (running)
0035         update();
0036 }
0037 
0038 void NetworkThread::addGroup(Uint32 gid, Uint32 limit, Uint32 assured_rate)
0039 {
0040     // if group already exists, just change the limit
0041     SocketGroup *g = groups.find(gid);
0042     if (g) {
0043         g->setLimit(limit);
0044         g->setAssuredRate(assured_rate);
0045     } else {
0046         g = new SocketGroup(limit, assured_rate);
0047         groups.insert(gid, g);
0048     }
0049 }
0050 
0051 void NetworkThread::removeGroup(Uint32 gid)
0052 {
0053     // make sure the 0 group is never erased
0054     if (gid != 0)
0055         groups.erase(gid);
0056 }
0057 
0058 void NetworkThread::setGroupLimit(Uint32 gid, Uint32 limit)
0059 {
0060     SocketGroup *g = groups.find(gid);
0061     if (g) {
0062         g->setLimit(limit);
0063     }
0064 }
0065 
0066 void NetworkThread::setGroupAssuredRate(Uint32 gid, Uint32 as)
0067 {
0068     SocketGroup *g = groups.find(gid);
0069     if (g) {
0070         g->setAssuredRate(as);
0071     }
0072 }
0073 
0074 Uint32 NetworkThread::doGroupsLimited(Uint32 num_ready, bt::TimeStamp now, Uint32 &allowance)
0075 {
0076     Uint32 num_still_ready = 0;
0077 
0078     // this is one pass over all the groups
0079     bt::PtrMap<Uint32, SocketGroup>::iterator itr = groups.begin();
0080     while (itr != groups.end() && allowance > 0) {
0081         SocketGroup *g = itr->second;
0082         if (g->numSockets() > 0) {
0083             Uint32 group_allowance = (Uint32)ceil(((double)g->numSockets() / num_ready) * allowance);
0084 
0085             // lets not do to much and make sure we don't pass 0 to the socket group (0 is unlimited)
0086             if (group_allowance > allowance || group_allowance == 0)
0087                 group_allowance = allowance;
0088 
0089             Uint32 ga = group_allowance;
0090 
0091             if (!doGroup(g, ga, now))
0092                 g->clear(); // group is done, so clear it
0093             else
0094                 num_still_ready += g->numSockets(); // keep track of the number of sockets which are still ready
0095 
0096             Uint32 done = group_allowance - ga;
0097             if (allowance >= done)
0098                 allowance -= done;
0099             else
0100                 allowance = 0;
0101         }
0102         ++itr;
0103     }
0104 
0105     return num_still_ready > 0;
0106 }
0107 
0108 void NetworkThread::doGroups(Uint32 num_ready, bt::TimeStamp now, bt::Uint32 limit)
0109 {
0110     if (limit == 0) {
0111         // calculate group allowance for each group and check for assured rate groups
0112         bt::PtrMap<Uint32, SocketGroup>::iterator itr = groups.begin();
0113         while (itr != groups.end()) {
0114             SocketGroup *g = itr->second;
0115             g->calcAllowance(now);
0116             if (g->numSockets() > 0 && g->getAssuredAllowance() > 0) {
0117                 // lets make sure that the assured rate is done first
0118                 Uint32 as = g->getAssuredAllowance();
0119                 doGroup(g, as, now);
0120             }
0121             ++itr;
0122         }
0123 
0124         Uint32 allowance = 0;
0125         // do the rest
0126         itr = groups.begin();
0127         while (itr != groups.end()) {
0128             SocketGroup *g = itr->second;
0129             if (g->numSockets() > 0) {
0130                 doGroup(g, allowance, now);
0131                 g->clear();
0132             }
0133             ++itr;
0134         }
0135     } else {
0136         Uint32 allowance = (Uint32)ceil(1.0 * limit * (now - prev_run_time) * 0.001);
0137 
0138         // calculate group allowance for each group
0139         bt::PtrMap<Uint32, SocketGroup>::iterator itr = groups.begin();
0140         while (itr != groups.end()) {
0141             SocketGroup *g = itr->second;
0142             g->calcAllowance(now);
0143             if (g->numSockets() > 0 && g->getAssuredAllowance() > 0) {
0144                 // do assured stuff
0145                 Uint32 as = g->getAssuredAllowance();
0146                 if (as > allowance)
0147                     as = allowance; // make sure we do not do to much
0148 
0149                 Uint32 tmp = as;
0150                 doGroup(g, as, now);
0151                 allowance -= (tmp - as); // subtract from allowance
0152             }
0153             ++itr;
0154         }
0155 
0156         while (allowance > 0 && num_ready > 0) {
0157             // loop until nobody is ready anymore or the allowance is up
0158             num_ready = doGroupsLimited(num_ready, now, allowance);
0159         }
0160 
0161         // make sure all groups are cleared
0162         itr = groups.begin();
0163         while (itr != groups.end()) {
0164             SocketGroup *g = itr->second;
0165             g->clear();
0166             ++itr;
0167         }
0168     }
0169 }
0170 }