deltas: Don't try to rollsum/bsdiff .xz files
authorColin Walters <walters@verbum.org>
Tue, 7 Nov 2017 22:52:12 +0000 (17:52 -0500)
committerAtomic Bot <atomic-devel@projectatomic.io>
Thu, 9 Nov 2017 03:10:49 +0000 (03:10 +0000)
Fedora switched to 'xz' compress kernel modules, and recently
[RHEL7 did too](https://bugzilla.redhat.com/show_bug.cgi?id=1367496).
This compression defeats bsdiff.

While we have a "rollsum-able" test, we don't have a "bsdiff-able" test as it'd
be very expensive (we'd have to bsdiff, then apply it and compare the result).

Let's do the tactical quick fix here and just not try to delta files ending in
`.xz.`. This avoids us using bsdiff pointlessly for over 4000 files, which is
quite a notable speed increase for generating deltas.

Closes: #1333
Approved by: jlebon

src/libostree/ostree-repo-static-delta-compilation-analysis.c

index f3e69af9bb3560fe4cc0b2c09dddc4f16a25f3a8..d96604e59cfc4800f407b9a873103836aff31fa1 100644 (file)
@@ -217,6 +217,37 @@ string_array_nonempty_intersection (GPtrArray    *a,
   return FALSE;
 }
 
+static gboolean
+sizename_is_delta_candidate (OstreeDeltaContentSizeNames *sizename)
+{
+  /* Don't build candidates for the empty object */
+  if (sizename->size == 0)
+    return FALSE;
+
+  /* Look for known non-delta-able files (currently just compression like xz) */
+  for (guint i = 0; i < sizename->basenames->len; i++)
+    {
+      const char *name = sizename->basenames->pdata[i];
+      /* We could replace this down the line with g_content_type_guess() or so,
+       * but it's not clear to me that's a major win; we'd still need to
+       * maintain a list of compression formats, and this doesn't require
+       * allocation.
+       * NB: We explicitly don't have .gz here in case someone might be
+       * using --rsyncable for that.
+       */
+      const char *dot = strrchr (name, '.');
+      if (!dot)
+        continue;
+      const char *extension = dot+1;
+      /* Don't add .gz here, see above */
+      if (g_str_equal (extension, "xz") || g_str_equal (extension, "bz2"))
+        return FALSE;
+    }
+
+  /* Let's try it */
+  return TRUE;
+}
+
 /*
  * Build up a map of files with matching basenames and similar size,
  * and use it to find apparently similar objects.
@@ -258,7 +289,7 @@ _ostree_delta_compute_similar_objects (OstreeRepo                 *repo,
                                          &to_sizes,
                                          cancellable, error))
     goto out;
-  
+
   /* Iterate over all newly added objects, find objects which have
    * similar basename and sizes.
    *
@@ -277,8 +308,7 @@ _ostree_delta_compute_similar_objects (OstreeRepo                 *repo,
       const guint64 max_threshold = to_sizenames->size *
         (1.0+similarity_percent_threshold/100.0);
 
-      /* Don't build candidates for the empty object */
-      if (to_sizenames->size == 0)
+      if (!sizename_is_delta_candidate (to_sizenames))
         continue;
 
       for (fuzzy = 0; fuzzy < 2 && !found; fuzzy++)
@@ -286,12 +316,8 @@ _ostree_delta_compute_similar_objects (OstreeRepo                 *repo,
           for (j = lower; j < upper; j++)
             {
               OstreeDeltaContentSizeNames *from_sizenames = from_sizes->pdata[j];
-
-              /* Don't build candidates for the empty object */
-              if (from_sizenames->size == 0)
-                {
-                  continue;
-                }
+              if (!sizename_is_delta_candidate (from_sizenames))
+                continue;
 
               if (from_sizenames->size < min_threshold)
                 {