add configuration PDiffs::Limit-options (FileLimit and SizeLimit) to
authorDavid Kalnischkies <kalnischkies@gmail.com>
Fri, 1 Jan 2010 23:22:31 +0000 (00:22 +0100)
committerDavid Kalnischkies <kalnischkies@gmail.com>
Fri, 1 Jan 2010 23:22:31 +0000 (00:22 +0100)
not download too many or too big patches (Closes: #554349)

apt-pkg/acquire-item.cc
debian/changelog
doc/apt.conf.5.xml
doc/examples/configure-index

index 10e80eb..4f0abbb 100644 (file)
@@ -219,19 +219,19 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)                /*{{{*/
 
    if(TF.Step(Tags) == true)
    {
-      string local_sha1;
       bool found = false;
       DiffInfo d;
       string size;
 
-      string tmp = Tags.FindS("SHA1-Current");
+      string const tmp = Tags.FindS("SHA1-Current");
       std::stringstream ss(tmp);
-      ss >> ServerSha1;
+      ss >> ServerSha1 >> size;
+      unsigned long const ServerSize = atol(size.c_str());
 
       FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
       SHA1Summation SHA1;
       SHA1.AddFD(fd.Fd(), fd.Size());
-      local_sha1 = string(SHA1.Result());
+      string const local_sha1 = SHA1.Result();
 
       if(local_sha1 == ServerSha1) 
       {
@@ -248,20 +248,56 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)                /*{{{*/
            std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
 
         // check the historie and see what patches we need
-        string history = Tags.FindS("SHA1-History");     
+        string const history = Tags.FindS("SHA1-History");
         std::stringstream hist(history);
-        while(hist >> d.sha1 >> size >> d.file) 
+        while(hist >> d.sha1 >> size >> d.file)
         {
-           d.size = atoi(size.c_str());
            // read until the first match is found
+           // from that point on, we probably need all diffs
            if(d.sha1 == local_sha1) 
               found=true;
-           // from that point on, we probably need all diffs
-           if(found) 
+           else if (found == false)
+              continue;
+
+           if(Debug)
+              std::clog << "Need to get diff: " << d.file << std::endl;
+           available_patches.push_back(d);
+        }
+
+        if (available_patches.empty() == false)
+        {
+           // patching with too many files is rather slow compared to a fast download
+           unsigned long const fileLimit = _config->FindI("Acquire::PDiffs::FileLimit", 0);
+           if (fileLimit != 0 && fileLimit < available_patches.size())
+           {
+              if (Debug)
+                 std::clog << "Need " << available_patches.size() << " diffs (Limit is " << fileLimit
+                       << ") so fallback to complete download" << std::endl;
+              return false;
+           }
+
+           // see if the patches are too big
+           found = false; // it was true and it will be true again at the end
+           d = *available_patches.begin();
+           string const firstPatch = d.file;
+           unsigned long patchesSize = 0;
+           std::stringstream patches(Tags.FindS("SHA1-Patches"));
+           while(patches >> d.sha1 >> size >> d.file)
+           {
+              if (firstPatch == d.file)
+                 found = true;
+              else if (found == false)
+                 continue;
+
+              patchesSize += atol(size.c_str());
+           }
+           unsigned long const sizeLimit = ServerSize * _config->FindI("Acquire::PDiffs::SizeLimit", 100);
+           if (sizeLimit > 0 && (sizeLimit/100) < patchesSize)
            {
-              if(Debug)
-                 std::clog << "Need to get diff: " << d.file << std::endl;
-              available_patches.push_back(d);
+              if (Debug)
+                 std::clog << "Need " << patchesSize << " bytes (Limit is " << sizeLimit/100
+                       << ") so fallback to complete download" << std::endl;
+              return false;
            }
         }
       }
@@ -270,7 +306,7 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)          /*{{{*/
       if(found) 
       {
         // queue the diffs
-        string::size_type last_space = Description.rfind(" ");
+        string::size_type const last_space = Description.rfind(" ");
         if(last_space != string::npos)
            Description.erase(last_space, Description.size()-last_space);
         new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
index e368131..1454eed 100644 (file)
@@ -31,6 +31,9 @@ apt (0.7.26) UNRELEASED; urgency=low
     - instruct debiandoc to build files with utf-8 encoding
   * buildlib/tools.m4:
     - fix some warning from the buildtools
+  * apt-pkg/acquire-item.cc:
+    - add configuration PDiffs::Limit-options to not download
+      too many or too big patches (Closes: #554349)
 
  -- Michael Vogt <mvo@debian.org>  Thu, 10 Dec 2009 22:02:38 +0100
 
index 734ae1f..fd50e37 100644 (file)
@@ -221,7 +221,14 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      <varlistentry><term>PDiffs</term>
         <listitem><para>Try to download deltas called <literal>PDiffs</literal> for
         Packages or Sources files instead of downloading whole ones. True
-        by default.</para></listitem>
+        by default.</para>
+        <para>Two sub-options to limit the use of PDiffs are also available:
+        With <literal>FileLimit</literal> can be specified how many PDiff files
+        are downloaded at most to patch a file. <literal>SizeLimit</literal>
+        on the other hand is the maximum precentage of the size of all patches
+        compared to the size of the targeted file. If one of these limits is
+        exceeded the complete file is downloaded instead of the patches.
+        </para></listitem>
      </varlistentry>
 
      <varlistentry><term>Queue-Mode</term>
index 0a20e8f..be461aa 100644 (file)
@@ -176,7 +176,10 @@ Acquire
   Source-Symlinks "true";
 
   PDiffs "true";     // try to get the IndexFile diffs
-  
+  PDiffs::FileLimit "4"; // don't use diffs if we would need more than 4 diffs
+  PDiffs::SizeLimit "50"; // don't use diffs if size of all patches excess
+                         // 50% of the size of the original file
+
   // HTTP method configuration
   http 
   {