Browse Source

add configuration PDiffs::Limit-options (FileLimit and SizeLimit) to
not download too many or too big patches (Closes: #554349)

David Kalnischkies 16 years ago
parent
commit
02dceb31f7
4 changed files with 64 additions and 15 deletions
  1. 49 13
      apt-pkg/acquire-item.cc
  2. 3 0
      debian/changelog
  3. 8 1
      doc/apt.conf.5.xml
  4. 4 1
      doc/examples/configure-index

+ 49 - 13
apt-pkg/acquire-item.cc

@@ -219,19 +219,19 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
 
 
    if(TF.Step(Tags) == true)
    if(TF.Step(Tags) == true)
    {
    {
-      string local_sha1;
       bool found = false;
       bool found = false;
       DiffInfo d;
       DiffInfo d;
       string size;
       string size;
 
 
-      string tmp = Tags.FindS("SHA1-Current");
+      string const tmp = Tags.FindS("SHA1-Current");
       std::stringstream ss(tmp);
       std::stringstream ss(tmp);
-      ss >> ServerSha1;
+      ss >> ServerSha1 >> size;
+      unsigned long const ServerSize = atol(size.c_str());
 
 
       FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
       FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
       SHA1Summation SHA1;
       SHA1Summation SHA1;
       SHA1.AddFD(fd.Fd(), fd.Size());
       SHA1.AddFD(fd.Fd(), fd.Size());
-      local_sha1 = string(SHA1.Result());
+      string const local_sha1 = SHA1.Result();
 
 
       if(local_sha1 == ServerSha1) 
       if(local_sha1 == ServerSha1) 
       {
       {
@@ -248,20 +248,56 @@ bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)		/*{{{*/
 	    std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
 	    std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
 
 
 	 // check the historie and see what patches we need
 	 // 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);
 	 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
 	    // read until the first match is found
+	    // from that point on, we probably need all diffs
 	    if(d.sha1 == local_sha1) 
 	    if(d.sha1 == local_sha1) 
 	       found=true;
 	       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) 
       if(found) 
       {
       {
 	 // queue the diffs
 	 // queue the diffs
-	 string::size_type last_space = Description.rfind(" ");
+	 string::size_type const last_space = Description.rfind(" ");
 	 if(last_space != string::npos)
 	 if(last_space != string::npos)
 	    Description.erase(last_space, Description.size()-last_space);
 	    Description.erase(last_space, Description.size()-last_space);
 	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
 	 new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,

+ 3 - 0
debian/changelog

@@ -31,6 +31,9 @@ apt (0.7.26) UNRELEASED; urgency=low
     - instruct debiandoc to build files with utf-8 encoding
     - instruct debiandoc to build files with utf-8 encoding
   * buildlib/tools.m4:
   * buildlib/tools.m4:
     - fix some warning from the buildtools
     - 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
  -- Michael Vogt <mvo@debian.org>  Thu, 10 Dec 2009 22:02:38 +0100
 
 

+ 8 - 1
doc/apt.conf.5.xml

@@ -221,7 +221,14 @@ DPkg::Pre-Install-Pkgs {"/usr/sbin/dpkg-preconfigure --apt";};
      <varlistentry><term>PDiffs</term>
      <varlistentry><term>PDiffs</term>
 	 <listitem><para>Try to download deltas called <literal>PDiffs</literal> for
 	 <listitem><para>Try to download deltas called <literal>PDiffs</literal> for
 	 Packages or Sources files instead of downloading whole ones. True
 	 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>
 
 
      <varlistentry><term>Queue-Mode</term>
      <varlistentry><term>Queue-Mode</term>

+ 4 - 1
doc/examples/configure-index

@@ -176,7 +176,10 @@ Acquire
   Source-Symlinks "true";
   Source-Symlinks "true";
 
 
   PDiffs "true";     // try to get the IndexFile diffs
   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 method configuration
   http 
   http 
   {
   {