BmapCreate: enable scalability optimization
authorArtem Bityutskiy <artem.bityutskiy@intel.com>
Mon, 6 May 2013 14:12:25 +0000 (17:12 +0300)
committerArtem Bityutskiy <artem.bityutskiy@intel.com>
Tue, 7 May 2013 08:42:31 +0000 (11:42 +0300)
This patch changes the layout of the bmap file a little bit. Before this
change, we wrote the mapped blocks count at the very end, because we only knew
at the very end.

In BmapCopy we need to know the amount of mapped blocks before we start
copying, and this forces us to read entire bmap file to find out the amount of
mapped blocks. This is not an issue when bmap file is small, but if it gets a
lot bigger, this becomes a lot slower.

In this patch, we change bmap file layout a little bit and now we put the
mapped block cound at the beginning of the bmap file. This makes it possible to
parse it more effeciently. This also makes it more human readable.

Change-Id: Id9466ed4a45678a60506d32abe17845e29b79b59
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
bmaptools/BmapCreate.py

index 34619c6..e85c2e3 100644 (file)
@@ -34,7 +34,7 @@ from bmaptools.BmapHelpers import human_size
 from bmaptools import Fiemap
 
 # The bmap format version we generate
-SUPPORTED_BMAP_VERSION = "1.2"
+SUPPORTED_BMAP_VERSION = "1.3"
 
 _BMAP_START_TEMPLATE = \
 """<?xml version="1.0" ?>
@@ -61,7 +61,7 @@ _BMAP_START_TEMPLATE = \
      in case of minor backward-compatible changes. -->
 
 <bmap version="%s">
-    <!-- Image size in bytes (%s) -->
+    <!-- Image size in bytes: %s -->
     <ImageSize> %u </ImageSize>
 
     <!-- Size of a block in bytes -->
@@ -70,10 +70,6 @@ _BMAP_START_TEMPLATE = \
     <!-- Count of blocks in the image file -->
     <BlocksCount> %u </BlocksCount>
 
-    <!-- The block map which consists of elements which may either be a
-         range of blocks or a single block. The 'sha1' attribute (if present)
-         is the SHA1 checksum of this blocks range. -->
-    <BlockMap>
 """
 
 class Error(Exception):
@@ -131,6 +127,9 @@ class BmapCreate:
         self.mapped_size_human = None
         self.mapped_percent = None
 
+        self._mapped_count_pos1 = None
+        self._mapped_count_pos2 = None
+
         self._f_image_needs_close = False
         self._f_bmap_needs_close = False
 
@@ -163,10 +162,35 @@ class BmapCreate:
         """ A helper function which generates the starting contents of the
         block map file: the header comment, image size, block size, etc. """
 
+        # We do not know the amount of mapped blocks at the moment, so just put
+        # whitespaces instead of real numbers. Assume the longest possible
+        # numbers.
+        mapped_count = ' ' * len(str(self.image_size))
+        mapped_size_human = ' ' * len(self.image_size_human)
+
         xml = _BMAP_START_TEMPLATE \
-               % (SUPPORTED_BMAP_VERSION,
-                  self.image_size_human, self.image_size,
-                  self.block_size, self.blocks_cnt)
+               % (SUPPORTED_BMAP_VERSION, self.image_size_human,
+                  self.image_size, self.block_size, self.blocks_cnt)
+        xml += "    <!-- Count of mapped blocks: "
+
+        self._f_bmap.write(xml)
+        self._mapped_count_pos1 = self._f_bmap.tell()
+
+        # Just put white-spaces instead of real information about mapped blocks
+        xml  = "%s or %.1f    -->\n" % (mapped_size_human, 100.0)
+        xml += "    <MappedBlocksCount> "
+
+        self._f_bmap.write(xml)
+        self._mapped_count_pos2 = self._f_bmap.tell()
+
+        xml  = "%s </MappedBlocksCount>\n\n" % mapped_count
+
+        # pylint: disable=C0301
+        xml += "    <!-- The block map which consists of elements which may either be a\n"
+        xml += "         range of blocks or a single block. The 'sha1' attribute (if present)\n"
+        xml += "         is the SHA1 checksum of this blocks range. -->\n"
+        xml += "    <BlockMap>\n"
+        # pylint: enable=C0301
 
         self._f_bmap.write(xml)
 
@@ -175,15 +199,18 @@ class BmapCreate:
         file: the ending tags and the information about the amount of mapped
         blocks. """
 
-        xml =  "    </BlockMap>\n\n"
-        xml += "    <!-- Count of mapped blocks (%s or %.1f%% mapped) -->\n" \
-               % (self.mapped_size_human, self.mapped_percent)
-        xml += "    <MappedBlocksCount> %u </MappedBlocksCount>\n" \
-               % self.mapped_cnt
+        xml =  "    </BlockMap>\n"
         xml += "</bmap>\n"
 
         self._f_bmap.write(xml)
 
+        self._f_bmap.seek(self._mapped_count_pos1)
+        self._f_bmap.write("%s or %.1f%%" % \
+                           (self.mapped_size_human, self.mapped_percent))
+
+        self._f_bmap.seek(self._mapped_count_pos2)
+        self._f_bmap.write("%u" % self.mapped_cnt)
+
     def _calculate_sha1(self, first, last):
         """ A helper function which calculates SHA1 checksum for the range of
         blocks of the image file: from block 'first' to block 'last'. """