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