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 }