[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#146877: [patch] bw-limit



Hi,

attached is a patch that implements bandwith limits for http (adding
support for ftp should be easy). It can be enabled with the 
Acquire::http::DlLimit option and it takes a integer as argument (the
maximum download rate in kb).

thanks,
 Michael

-- 
Linux is not The Answer. Yes is the answer. Linux is The Question. - Neo
--- orig/apt-pkg/acquire.cc
+++ mod/apt-pkg/acquire.cc
@@ -266,6 +266,10 @@
    if (Work.Start() == false)
       return 0;
    
+   /* if a method uses DownloadLimit, we switch to SingleInstance mode */
+   if(_config->FindI("Acquire::"+Access+"::DlLimit",0) > 0)
+      Conf->SingleInstance = true;
+   
    return Conf;
 }
 									/*}}}*/


--- orig/methods/http.cc
+++ mod/methods/http.cc
@@ -58,6 +58,12 @@
 unsigned long TimeOut = 120;
 bool Debug = false;
 
+
+unsigned long CircleBuf::BwReadLimit=0;
+unsigned long CircleBuf::BwTickReadData=0;
+struct timeval CircleBuf::BwReadTick={0,0};
+const unsigned int CircleBuf::BW_HZ=10;
+  
 // CircleBuf::CircleBuf - Circular input buffer				/*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -65,6 +71,8 @@
 {
    Buf = new unsigned char[Size];
    Reset();
+
+   CircleBuf::BwReadLimit = _config->FindI("Acquire::http::DlLimit",0)*1024;
 }
 									/*}}}*/
 // CircleBuf::Reset - Reset to the default state			/*{{{*/
@@ -90,16 +98,45 @@
    is non-blocking.. */
 bool CircleBuf::Read(int Fd)
 {
+   unsigned long BwReadMax;
+
    while (1)
    {
       // Woops, buffer is full
       if (InP - OutP == Size)
 	 return true;
-      
+
+      // what's left to read in this tick
+      BwReadMax = CircleBuf::BwReadLimit/BW_HZ;
+
+      if(CircleBuf::BwReadLimit) {
+	 struct timeval now;
+	 gettimeofday(&now,0);
+
+	 unsigned long d = (now.tv_sec-CircleBuf::BwReadTick.tv_sec)*1000000 +
+	    now.tv_usec-CircleBuf::BwReadTick.tv_usec;
+	 if(d > 1000000/BW_HZ) {
+	    CircleBuf::BwReadTick = now;
+	    CircleBuf::BwTickReadData = 0;
+	 } 
+	 
+	 if(CircleBuf::BwTickReadData >= BwReadMax) {
+	    usleep(1000000/BW_HZ);
+	    return true;
+	 }
+      }
+
       // Write the buffer segment
       int Res;
-      Res = read(Fd,Buf + (InP%Size),LeftRead());
-      
+      if(CircleBuf::BwReadLimit) {
+	 Res = read(Fd,Buf + (InP%Size), 
+		    BwReadMax > LeftRead() ? LeftRead() : BwReadMax);
+      } else
+	 Res = read(Fd,Buf + (InP%Size),LeftRead());
+      
+      if(Res > 0 && BwReadLimit > 0) 
+	 CircleBuf::BwTickReadData += Res;
+    
       if (Res == 0)
 	 return false;
       if (Res < 0)
@@ -989,7 +1026,7 @@
    PipelineDepth = _config->FindI("Acquire::http::Pipeline-Depth",
 				  PipelineDepth);
    Debug = _config->FindB("Debug::Acquire::http",false);
-   
+
    return true;
 }
 									/*}}}*/


--- orig/methods/http.h
+++ mod/methods/http.h
@@ -31,6 +31,11 @@
    unsigned long MaxGet;
    struct timeval Start;
    
+   static unsigned long BwReadLimit;
+   static unsigned long BwTickReadData;
+   static struct timeval BwReadTick;
+   static const unsigned int BW_HZ;
+
    unsigned long LeftRead()
    {
       unsigned long Sz = Size - (InP - OutP);

Reply to: