From c53dff179d371c4ab5384b7e0a844938872f6056 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 13 Aug 2013 12:26:54 +0300 Subject: [PATCH] bmaptools: put __init__ first It is just a common convention to put __init__ at the very beginning of the class. And let's also put then the __del__ function to be the second. So this patch does not do any functional modifications, just re-structuring. Change-Id: I2ebdd8c4c54cf5bf3f9be21d7520b42865305dab Signed-off-by: Artem Bityutskiy --- bmaptools/BmapCopy.py | 256 ++++++++++++++++++++++++------------------------ bmaptools/BmapCreate.py | 54 +++++----- bmaptools/Fiemap.py | 20 ++-- bmaptools/TransRead.py | 86 ++++++++-------- 4 files changed, 208 insertions(+), 208 deletions(-) diff --git a/bmaptools/BmapCopy.py b/bmaptools/BmapCopy.py index a025cb5..622fd49 100644 --- a/bmaptools/BmapCopy.py +++ b/bmaptools/BmapCopy.py @@ -117,6 +117,85 @@ class BmapCopy: instance. """ + def __init__(self, image, dest, bmap=None, image_size=None, logger=None): + """ + The class constructor. The parameters are: + image - file-like object of the image which should be copied, + should only support 'read()' and 'seek()' methods, + and only seeking forward has to be supported. + dest - file object of the destination file to copy the image + to. + bmap - file object of the bmap file to use for copying. + image_size - size of the image in bytes. + logger - the logger object to use for printing messages. + """ + + self._logger = logger + if self._logger is None: + self._logger = logging.getLogger(__name__) + + self._xml = None + + self._dest_fsync_watermark = None + self._batch_blocks = None + self._batch_queue = None + self._batch_bytes = 1024 * 1024 + self._batch_queue_len = 2 + + self.bmap_version = None + self.bmap_version_major = None + self.bmap_version_minor = None + self.block_size = None + self.blocks_cnt = None + self.mapped_cnt = None + self.image_size = None + self.image_size_human = None + self.mapped_size = None + self.mapped_size_human = None + self.mapped_percent = None + + self._f_bmap = None + self._f_bmap_path = None + + self._progress_started = None + self._progress_index = None + self._progress_time = None + self._progress_file = None + self._progress_format = None + self.set_progress_indicator(None, None) + + self._f_image = image + self._image_path = image.name + + self._f_dest = dest + self._dest_path = dest.name + st_data = os.fstat(self._f_dest.fileno()) + self._dest_is_regfile = stat.S_ISREG(st_data.st_mode) + + # Special quirk for /dev/null which does not support fsync() + if stat.S_ISCHR(st_data.st_mode) and \ + os.major(st_data.st_rdev) == 1 and \ + os.minor(st_data.st_rdev) == 3: + self._dest_supports_fsync = False + else: + self._dest_supports_fsync = True + + if bmap: + self._f_bmap = bmap + self._bmap_path = bmap.name + self._parse_bmap() + else: + # There is no bmap. Initialize user-visible attributes to something + # sensible with an assumption that we just have all blocks mapped. + self.bmap_version = 0 + self.block_size = 4096 + self.mapped_percent = 100 + + if image_size: + self._set_image_size(image_size) + + self._batch_blocks = self._batch_bytes / self.block_size + def set_progress_indicator(self, file_obj, format_string): """ Setup the progress indicator which shows how much data has been copied @@ -226,85 +305,6 @@ class BmapCopy: # Bmap file checksum appeard in format 1.3 self._verify_bmap_checksum() - def __init__(self, image, dest, bmap=None, image_size=None, logger=None): - """ - The class constructor. The parameters are: - image - file-like object of the image which should be copied, - should only support 'read()' and 'seek()' methods, - and only seeking forward has to be supported. - dest - file object of the destination file to copy the image - to. - bmap - file object of the bmap file to use for copying. - image_size - size of the image in bytes. - logger - the logger object to use for printing messages. - """ - - self._logger = logger - if self._logger is None: - self._logger = logging.getLogger(__name__) - - self._xml = None - - self._dest_fsync_watermark = None - self._batch_blocks = None - self._batch_queue = None - self._batch_bytes = 1024 * 1024 - self._batch_queue_len = 2 - - self.bmap_version = None - self.bmap_version_major = None - self.bmap_version_minor = None - self.block_size = None - self.blocks_cnt = None - self.mapped_cnt = None - self.image_size = None - self.image_size_human = None - self.mapped_size = None - self.mapped_size_human = None - self.mapped_percent = None - - self._f_bmap = None - self._f_bmap_path = None - - self._progress_started = None - self._progress_index = None - self._progress_time = None - self._progress_file = None - self._progress_format = None - self.set_progress_indicator(None, None) - - self._f_image = image - self._image_path = image.name - - self._f_dest = dest - self._dest_path = dest.name - st_data = os.fstat(self._f_dest.fileno()) - self._dest_is_regfile = stat.S_ISREG(st_data.st_mode) - - # Special quirk for /dev/null which does not support fsync() - if stat.S_ISCHR(st_data.st_mode) and \ - os.major(st_data.st_rdev) == 1 and \ - os.minor(st_data.st_rdev) == 3: - self._dest_supports_fsync = False - else: - self._dest_supports_fsync = True - - if bmap: - self._f_bmap = bmap - self._bmap_path = bmap.name - self._parse_bmap() - else: - # There is no bmap. Initialize user-visible attributes to something - # sensible with an assumption that we just have all blocks mapped. - self.bmap_version = 0 - self.block_size = 4096 - self.mapped_percent = 100 - - if image_size: - self._set_image_size(image_size) - - self._batch_blocks = self._batch_bytes / self.block_size - def _update_progress(self, blocks_written): """ Print the progress indicator if the mapped area size is known and if @@ -584,6 +584,55 @@ class BmapBdevCopy(BmapCopy): scheduler. """ + def __init__(self, image, dest, bmap=None, image_size=None, logger=None): + """ + The same as the constructor of the 'BmapCopy' base class, but adds + useful guard-checks specific to block devices. + """ + + # Call the base class constructor first + BmapCopy.__init__(self, image, dest, bmap, image_size, logger=logger) + + self._batch_bytes = 1024 * 1024 + self._batch_blocks = self._batch_bytes / self.block_size + self._batch_queue_len = 6 + self._dest_fsync_watermark = (6 * 1024 * 1024) / self.block_size + + self._sysfs_base = None + self._sysfs_scheduler_path = None + self._sysfs_max_ratio_path = None + self._old_scheduler_value = None + self._old_max_ratio_value = None + + # If the image size is known, check that it fits the block device + if self.image_size: + try: + bdev_size = os.lseek(self._f_dest.fileno(), 0, os.SEEK_END) + os.lseek(self._f_dest.fileno(), 0, os.SEEK_SET) + except OSError as err: + raise Error("cannot seed block device '%s': %s " + % (self._dest_path, err.strerror)) + + if bdev_size < self.image_size: + raise Error("the image file '%s' has size %s and it will not " + "fit the block device '%s' which has %s capacity" + % (self._image_path, self.image_size_human, + self._dest_path, human_size(bdev_size))) + + # Construct the path to the sysfs directory of our block device + st_rdev = os.fstat(self._f_dest.fileno()).st_rdev + self._sysfs_base = "/sys/dev/block/%s:%s/" \ + % (os.major(st_rdev), os.minor(st_rdev)) + + # Check if the 'queue' sub-directory exists. If yes, then our block + # device is entire disk. Otherwise, it is a partition, in which case we + # need to go one level up in the sysfs hierarchy. + if not os.path.exists(self._sysfs_base + "queue"): + self._sysfs_base = self._sysfs_base + "../" + + self._sysfs_scheduler_path = self._sysfs_base + "queue/scheduler" + self._sysfs_max_ratio_path = self._sysfs_base + "bdi/max_ratio" + def _tune_block_device(self): """ Tune the block device for better performance: @@ -673,52 +722,3 @@ class BmapBdevCopy(BmapCopy): raise finally: self._restore_bdev_settings() - - def __init__(self, image, dest, bmap=None, image_size=None, logger=None): - """ - The same as the constructor of the 'BmapCopy' base class, but adds - useful guard-checks specific to block devices. - """ - - # Call the base class constructor first - BmapCopy.__init__(self, image, dest, bmap, image_size, logger=logger) - - self._batch_bytes = 1024 * 1024 - self._batch_blocks = self._batch_bytes / self.block_size - self._batch_queue_len = 6 - self._dest_fsync_watermark = (6 * 1024 * 1024) / self.block_size - - self._sysfs_base = None - self._sysfs_scheduler_path = None - self._sysfs_max_ratio_path = None - self._old_scheduler_value = None - self._old_max_ratio_value = None - - # If the image size is known, check that it fits the block device - if self.image_size: - try: - bdev_size = os.lseek(self._f_dest.fileno(), 0, os.SEEK_END) - os.lseek(self._f_dest.fileno(), 0, os.SEEK_SET) - except OSError as err: - raise Error("cannot seed block device '%s': %s " - % (self._dest_path, err.strerror)) - - if bdev_size < self.image_size: - raise Error("the image file '%s' has size %s and it will not " - "fit the block device '%s' which has %s capacity" - % (self._image_path, self.image_size_human, - self._dest_path, human_size(bdev_size))) - - # Construct the path to the sysfs directory of our block device - st_rdev = os.fstat(self._f_dest.fileno()).st_rdev - self._sysfs_base = "/sys/dev/block/%s:%s/" \ - % (os.major(st_rdev), os.minor(st_rdev)) - - # Check if the 'queue' sub-directory exists. If yes, then our block - # device is entire disk. Otherwise, it is a partition, in which case we - # need to go one level up in the sysfs hierarchy. - if not os.path.exists(self._sysfs_base + "queue"): - self._sysfs_base = self._sysfs_base + "../" - - self._sysfs_scheduler_path = self._sysfs_base + "queue/scheduler" - self._sysfs_max_ratio_path = self._sysfs_base + "bdi/max_ratio" diff --git a/bmaptools/BmapCreate.py b/bmaptools/BmapCreate.py index cb45bc8..b96224a 100644 --- a/bmaptools/BmapCreate.py +++ b/bmaptools/BmapCreate.py @@ -106,26 +106,6 @@ class BmapCreate: the FIEMAP ioctl to generate the bmap. """ - def _open_image_file(self): - """Open the image file.""" - try: - self._f_image = open(self._image_path, 'rb') - except IOError as err: - raise Error("cannot open image file '%s': %s" - % (self._image_path, err)) - - self._f_image_needs_close = True - - def _open_bmap_file(self): - """Open the bmap file.""" - try: - self._f_bmap = open(self._bmap_path, 'w+') - except IOError as err: - raise Error("cannot open bmap file '%s': %s" - % (self._bmap_path, err)) - - self._f_bmap_needs_close = True - def __init__(self, image, bmap): """ Initialize a class instance: @@ -176,6 +156,33 @@ class BmapCreate: self.block_size = self.fiemap.block_size self.blocks_cnt = self.fiemap.blocks_cnt + def __del__(self): + """The class destructor which closes the opened files.""" + if self._f_image_needs_close: + self._f_image.close() + if self._f_bmap_needs_close: + self._f_bmap.close() + + def _open_image_file(self): + """Open the image file.""" + try: + self._f_image = open(self._image_path, 'rb') + except IOError as err: + raise Error("cannot open image file '%s': %s" + % (self._image_path, err)) + + self._f_image_needs_close = True + + def _open_bmap_file(self): + """Open the bmap file.""" + try: + self._f_bmap = open(self._bmap_path, 'w+') + except IOError as err: + raise Error("cannot open bmap file '%s': %s" + % (self._bmap_path, err)) + + self._f_bmap_needs_close = True + def _bmap_file_start(self): """ A helper function which generates the starting contents of the block @@ -313,10 +320,3 @@ class BmapCreate: % (self._bmap_path, err)) self._f_image.seek(image_pos) - - def __del__(self): - """The class destructor which closes the opened files.""" - if self._f_image_needs_close: - self._f_image.close() - if self._f_bmap_needs_close: - self._f_bmap.close() diff --git a/bmaptools/Fiemap.py b/bmaptools/Fiemap.py index 76857b8..3066f18 100644 --- a/bmaptools/Fiemap.py +++ b/bmaptools/Fiemap.py @@ -59,16 +59,6 @@ class Fiemap: over all mapped blocks and over all holes. """ - def _open_image_file(self): - """Open the image file.""" - try: - self._f_image = open(self._image_path, 'rb') - except IOError as err: - raise Error("cannot open image file '%s': %s" - % (self._image_path, err)) - - self._f_image_needs_close = True - def __init__(self, image, buf_size=DEFAULT_BUFFER_SIZE): """ Initialize a class instance. The 'image' argument is full path to the @@ -134,6 +124,16 @@ class Fiemap: if self._f_image_needs_close: self._f_image.close() + def _open_image_file(self): + """Open the image file.""" + try: + self._f_image = open(self._image_path, 'rb') + except IOError as err: + raise Error("cannot open image file '%s': %s" + % (self._image_path, err)) + + self._f_image_needs_close = True + def _invoke_fiemap(self, block, count): """ Invoke the FIEMAP ioctl for 'count' blocks of the file starting from diff --git a/bmaptools/TransRead.py b/bmaptools/TransRead.py index 870b584..16d9525 100644 --- a/bmaptools/TransRead.py +++ b/bmaptools/TransRead.py @@ -217,6 +217,49 @@ class TransRead: this class are file-like objects which you can read and seek only forward. """ + def __init__(self, filepath, local=False): + """ + Class constructor. The 'filepath' argument is the full path to the file + to read transparently. If 'local' is True, then the file-like object is + guaranteed to be backed by a local file. This means that if the source + file is compressed or an URL, then it will first be copied to a + temporary local file, and then all the subsequent operations will be + done with the local copy. + """ + + self.name = filepath + self.size = None + self.is_compressed = True + self.is_url = False + self._child_process = None + self._file_obj = None + self._transfile_obj = None + self._force_fake_seek = False + self._pos = 0 + + try: + self._file_obj = open(self.name, "rb") + except IOError as err: + if err.errno == errno.ENOENT: + # This is probably an URL + self._open_url(filepath) + else: + raise Error("cannot open file '%s': %s" % (filepath, err)) + + self._open_compressed_file() + + if local: + self._create_local_copy() + + def __del__(self): + """The class destructor which closes opened files.""" + if self._transfile_obj: + self._transfile_obj.close() + if self._file_obj: + self._file_obj.close() + if self._child_process: + self._child_process.wait() + def _open_compressed_file(self): """ Detect file compression type and open it with the corresponding @@ -417,40 +460,6 @@ class TransRead: raise Error("cannot open own temporary file '%s': %s" % (tmp_file_obj.name, err)) - def __init__(self, filepath, local=False): - """ - Class constructor. The 'filepath' argument is the full path to the file - to read transparently. If 'local' is True, then the file-like object is - guaranteed to be backed by a local file. This means that if the source - file is compressed or an URL, then it will first be copied to a - temporary local file, and then all the subsequent operations will be - done with the local copy. - """ - - self.name = filepath - self.size = None - self.is_compressed = True - self.is_url = False - self._child_process = None - self._file_obj = None - self._transfile_obj = None - self._force_fake_seek = False - self._pos = 0 - - try: - self._file_obj = open(self.name, "rb") - except IOError as err: - if err.errno == errno.ENOENT: - # This is probably an URL - self._open_url(filepath) - else: - raise Error("cannot open file '%s': %s" % (filepath, err)) - - self._open_compressed_file() - - if local: - self._create_local_copy() - def read(self, size=-1): """ Read the data from the file or URL and and uncompress it on-the-fly if @@ -465,15 +474,6 @@ class TransRead: return buf - def __del__(self): - """The class destructor which closes opened files.""" - if self._transfile_obj: - self._transfile_obj.close() - if self._file_obj: - self._file_obj.close() - if self._child_process: - self._child_process.wait() - def seek(self, offset, whence=os.SEEK_SET): """The 'seek()' method, similar to the one file objects have.""" if self._force_fake_seek or not hasattr(self._transfile_obj, "seek"): -- 2.7.4