xref: /aosp_15_r20/external/toolchain-utils/crosperf/image_checksummer.py (revision 760c253c1ed00ce9abd48f8546f08516e57485fe)
1# -*- coding: utf-8 -*-
2# Copyright 2011 The ChromiumOS Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Compute image checksum."""
7
8
9import os
10import threading
11
12from cros_utils import logger
13from cros_utils.file_utils import FileUtils
14
15
16class ImageChecksummer(object):
17    """Compute image checksum."""
18
19    class PerImageChecksummer(object):
20        """Compute checksum for an image."""
21
22        def __init__(self, label, log_level):
23            self._lock = threading.Lock()
24            self.label = label
25            self._checksum = None
26            self.log_level = log_level
27
28        def Checksum(self):
29            with self._lock:
30                if not self._checksum:
31                    logger.GetLogger().LogOutput(
32                        "Acquiring checksum for '%s'." % self.label.name
33                    )
34                    self._checksum = None
35                    if self.label.image_type != "local":
36                        raise RuntimeError(
37                            "Called Checksum on non-local image!"
38                        )
39                    if self.label.chromeos_image:
40                        if os.path.exists(self.label.chromeos_image):
41                            self._checksum = FileUtils().Md5File(
42                                self.label.chromeos_image,
43                                log_level=self.log_level,
44                            )
45                            logger.GetLogger().LogOutput(
46                                "Computed checksum is " ": %s" % self._checksum
47                            )
48                    if not self._checksum:
49                        raise RuntimeError("Checksum computing error.")
50                    logger.GetLogger().LogOutput(
51                        "Checksum is: %s" % self._checksum
52                    )
53                return self._checksum
54
55    _instance = None
56    _lock = threading.Lock()
57    _per_image_checksummers = {}
58
59    def __new__(cls, *args, **kwargs):
60        with cls._lock:
61            if not cls._instance:
62                cls._instance = super(ImageChecksummer, cls).__new__(
63                    cls, *args, **kwargs
64                )
65            return cls._instance
66
67    def Checksum(self, label, log_level):
68        if label.image_type != "local":
69            raise RuntimeError("Attempt to call Checksum on non-local image.")
70        with self._lock:
71            if label.name not in self._per_image_checksummers:
72                self._per_image_checksummers[
73                    label.name
74                ] = ImageChecksummer.PerImageChecksummer(label, log_level)
75            checksummer = self._per_image_checksummers[label.name]
76
77        try:
78            return checksummer.Checksum()
79        except:
80            logger.GetLogger().LogError(
81                "Could not compute checksum of image in label"
82                " '%s'." % label.name
83            )
84            raise
85