• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4# Copyright (c) 2021 Huawei Device Co., Ltd.
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16"""
17Description: create actions_list and transfer package
18"""
19
20import os
21import re
22from collections import OrderedDict
23from enum import Enum
24
25from blocks_manager import BlocksManager
26from log_exception import UPDATE_LOGGER
27from utils import FILE_MAP_ZERO_KEY
28from utils import FILE_MAP_COPY_KEY
29from utils import OptionsManager
30
31VERSION_NAME_RE = r"[0-9]+"
32REPLACE_CONTENT = "#"
33
34
35class ActionType(Enum):
36    NEW = 0
37    ZERO = 1
38    DIFFERENT = 2
39    MOVE = 3
40
41OPTIONS_MANAGER = OptionsManager()
42
43
44class ActionInfo:
45    def __init__(self, type_str, tgt_name, src_name, tgt_block_set,
46                 src_block_set):
47        self.type_str = type_str
48        self.tgt_name = tgt_name
49        self.src_name = src_name
50        self.tgt_block_set = tgt_block_set
51        if src_block_set is not None:
52            self.src_block_set = src_block_set
53        else:
54            self.src_block_set = BlocksManager()
55        self.child = OrderedDict()
56        self.parent = OrderedDict()
57        self.stash_before = []
58        self.use_stash = []
59
60    def get_max_block_number(self):
61        if self.src_block_set and self.src_block_set.size() != 0:
62            return max(self.src_block_set.range_data)
63        else:
64            return 0
65
66    def net_stash_change(self):
67        return (sum(sr.size() for (_, sr) in self.stash_before) -
68                sum(sr.size() for (_, sr) in self.use_stash))
69
70
71class TransfersManager(object):
72    def __init__(self, partition, tgt_img_obj, src_img_obj,
73                 disable_img_diff=False):
74        self.tgt_img_obj = tgt_img_obj
75        self.src_img_obj = src_img_obj
76        self.partition = partition
77        self.disable_img_diff = disable_img_diff
78
79        self.action_file_list = []
80        self.no_copy_list = []
81
82    @staticmethod
83    def simplify_file_name(file_name):
84        base_name = os.path.basename(file_name)
85        no_version_name = re.sub(VERSION_NAME_RE, REPLACE_CONTENT, base_name)
86        return base_name, no_version_name
87
88    def arrange_source_file(self):
89        base_names = {}
90        version_patterns = {}
91        for file_name in self.src_img_obj.file_map.keys():
92            base_name, no_version_name = self.simplify_file_name(file_name)
93            base_names[base_name] = file_name
94            version_patterns[no_version_name] = file_name
95        return base_names, version_patterns
96
97    def find_process_needs(self):
98        """
99        generate action_list
100        """
101        src_base_names, src_version_patterns = self.arrange_source_file()
102        max_size = -1
103
104        for tgt_file_name, tgt_blocks in \
105                self.tgt_img_obj.file_map.items():
106            if FILE_MAP_ZERO_KEY == tgt_file_name:
107                UPDATE_LOGGER.print_log("Apply ZERO type!")
108                self.action_file_list.append(
109                    ActionInfo(
110                        ActionType.ZERO, tgt_file_name, FILE_MAP_ZERO_KEY,
111                        tgt_blocks, self.src_img_obj.
112                        file_map.get(FILE_MAP_ZERO_KEY, None)))
113                if OPTIONS_MANAGER.stream_update:
114                    self.no_copy_list.append(tgt_blocks)
115                continue
116            if FILE_MAP_COPY_KEY == tgt_file_name:
117                UPDATE_LOGGER.print_log("Apply COPY type!")
118                self.action_file_list.append(
119                    ActionInfo(ActionType.NEW, tgt_file_name,
120                               None, tgt_blocks, None))
121                if OPTIONS_MANAGER.stream_update:
122                    self.no_copy_list.append(tgt_blocks)
123                continue
124            if tgt_file_name in self.src_img_obj.file_map:
125                UPDATE_LOGGER.print_log("Apply DIFF type!")
126                action_info = ActionInfo(
127                    ActionType.DIFFERENT, tgt_file_name, tgt_file_name,
128                    tgt_blocks,
129                    self.src_img_obj.file_map[tgt_file_name])
130                max_size = action_info.get_max_block_number() \
131                    if action_info.get_max_block_number() > \
132                    max_size else max_size
133                self.action_file_list.append(action_info)
134                if OPTIONS_MANAGER.stream_update:
135                    self.no_copy_list.append(tgt_blocks)
136                continue
137            src_file_name = self.get_file_name(
138                src_base_names, src_version_patterns, tgt_file_name)
139            if src_file_name:
140                max_size = self.process_diff_action(src_file_name, tgt_blocks, max_size, tgt_file_name)
141                continue
142            self.action_file_list.append(
143                ActionInfo(ActionType.NEW, tgt_file_name,
144                           None, tgt_blocks, None))
145            if OPTIONS_MANAGER.stream_update:
146                self.no_copy_list.append(tgt_blocks)
147
148        return max_size
149
150    def process_diff_action(self, src_file_name, tgt_blocks, max_size, tgt_file_name=None):
151        action_info = ActionInfo(
152            ActionType.DIFFERENT, tgt_file_name, src_file_name,
153            tgt_blocks,
154            self.src_img_obj.file_map[src_file_name])
155        max_size = action_info.get_max_block_number() if \
156            action_info.get_max_block_number() > max_size else max_size
157        self.action_file_list.append(action_info)
158        if OPTIONS_MANAGER.stream_update:
159            self.no_copy_list.append(tgt_blocks)
160        return max_size
161
162    def get_file_name(self, src_base_names, src_version_patterns,
163                      tgt_file_name):
164        tgt_base_name, tgt_version_patterns = \
165            self.simplify_file_name(tgt_file_name)
166        has_diff_name = True if tgt_base_name in src_base_names else False
167        has_diff_version = \
168            True if tgt_version_patterns in src_version_patterns else False
169        src_file_name = \
170            src_base_names[tgt_base_name] if has_diff_name else \
171            src_version_patterns[tgt_version_patterns] if \
172            has_diff_version else None
173        return src_file_name
174
175    def get_action_list(self):
176        return self.action_file_list
177
178    # 返回所有action_list中涉及的块
179    def get_no_copy_list(self):
180        return self.no_copy_list
181