重构文件结构

This commit is contained in:
2024-12-08 16:53:09 +08:00
parent f33d61e315
commit 5a71970731
25 changed files with 143 additions and 68 deletions

View File

@@ -10,7 +10,7 @@ import asyncio
from typing import List, Union from typing import List, Union
from .tree_object import TreeObject from .tree_object import TreeObject
from .blob_object import BlobObject from .blob_object import BlobObject
from utils.log import Logger from ThousandHands.utils.log import Logger
logger = Logger("BackupObject") logger = Logger("BackupObject")
@@ -19,16 +19,14 @@ class BackupObject:
""" """
备份对象负责管理存储对象(treeblob)对象备份信息恢复等操作 备份对象负责管理存储对象(treeblob)对象备份信息恢复等操作
""" """
backup_name: str backup_name: str
backup_time_lately: str backup_time_lately: str
backup_time_create: str backup_time_create: str
backup_size: int backup_size: int
backup_version_number: int backup_version_number: int
backup_trees: List[Union[TreeObject, BlobObject]] = [] backup_trees: List[Union[TreeObject, BlobObject]] = []
new_backup_flag: bool
def __init__(self, backup_name: str, backup_base_path: str): def __init__(self, backup_name: str, backup_base_path: str, backup_dirs: List[str] = []):
self.backup_name = backup_name self.backup_name = backup_name
# 获取备份路径的绝对路径 # 获取备份路径的绝对路径
@@ -39,18 +37,18 @@ class BackupObject:
os.path.abspath(backup_base_path), backup_name os.path.abspath(backup_base_path), backup_name
) )
logger.debug(f"Backup path: {self.backup_path}") logger.debug(f"new backup object,Backup path: {self.backup_path}")
if not os.path.exists(self.backup_path): if backup_dirs != []:
self.new_backup_flag = True logger.info("load existing backups")
else: self.addBackup(backup_dirs)
self.new_backup_flag = False
pass # TODO 读取备份信息
def createNewBackup(self, backup_dirs: List[str]): def addBackup(self, backup_dirs: List[str]):
""" """
创建新的备份 创建新的备份
:param backup_dirs: 备份目录列表
:return :return
""" """
for backup_dir in backup_dirs: for backup_dir in backup_dirs:
@@ -62,19 +60,23 @@ class BackupObject:
logger.info("New backup created successfully.") logger.info("New backup created successfully.")
logger.debug(f"Backup trees: {self.backup_trees}") logger.debug(f"Backup trees: {self.backup_trees}")
def backup(self): async def __writeTree(self):
asyncio.run(self.__writeBlobs())
async def __writeBlobs(self):
""" """
写入所有对象到备份路径 写入所有对象到备份路径
""" """
obj_save_path = os.path.join(self.backup_path, "objects") obj_save_path = os.path.join(self.backup_path, "objects")
for obj in self.backup_trees: for obj in self.backup_trees:
if isinstance(obj, TreeObject): if isinstance(obj, TreeObject):
await obj.writeBlobs(obj_save_path) # 如果是TreeObject则调用writeBlobs方法 await obj.writeTree(
obj_save_path
) # 如果是TreeObject则调用writeTree方法
else: else:
await obj.writeBlob(obj_save_path) # 如果是BlobObject则调用writeBlob方法 await obj.writeBlob(
obj_save_path
) # 如果是BlobObject则调用writeBlob方法
def backup(self):
asyncio.run(self.__writeTree())
def recover(self, recover_path: str): def recover(self, recover_path: str):
""" """
@@ -91,3 +93,11 @@ class BackupObject:
:return :return
""" """
pass pass
def writeBackupInfo(self):
"""
写入备份信息
:return
"""
pass

View File

@@ -68,8 +68,4 @@ class BlobObject:
if not data: if not data:
break break
sha1.update(data) sha1.update(data)
return sha1.hexdigest() return sha1.hexdigest()
def newBlobObject(file_path: str) -> BlobObject:
return BlobObject(file_path)

View File

@@ -26,7 +26,7 @@ class TreeObject:
self.__children.append(blob) self.__children.append(blob)
self.__file_map[blob_path] = blob.object_id self.__file_map[blob_path] = blob.object_id
async def writeBlobs(self, base_path: str): async def writeTree(self, base_path: str):
tasks = [] tasks = []
for child in self.__children: for child in self.__children:
tasks.append(asyncio.create_task(child.writeBlob(base_path))) tasks.append(asyncio.create_task(child.writeBlob(base_path)))

View File

@@ -0,0 +1,21 @@
from typing import List
from .PlanBase import PlanBase
from ThousandHands.core.objects.backup_object import BackupObject
class PlanBackup(PlanBase):
"""
备份计划,负责管理存储对象的备份
"""
__backup_object: BackupObject
def __init__(
self, backup_name: str, backup_base_path: str, backup_dirs: List[str] = []
):
super().__init__()
self.__backup_object = BackupObject(backup_name, backup_base_path, backup_dirs)
self.name = backup_name
def execute(self):
self.__backup_object.backup()

View File

@@ -0,0 +1,31 @@
from abc import ABC, abstractmethod
class PlanBase(ABC):
__priority_factor: int # 优先级因子
__executed: bool
__time_hour: int
__time_minute: int
name: str
def __init__(self):
self.__priority_factor = 0
self.name = ""
@abstractmethod
def execute(self):
pass
def getPriorityFactor(self) -> int:
"""
获取优先级因子
"""
return self.__priority_factor
def getNextTime(self) -> int:
# TODO: 实现计划执行
return 0
def isExecuted(self) -> bool:
return self.__executed

View File

@@ -0,0 +1,4 @@
class TimeHandler(object):
pass

View File

@@ -0,0 +1,44 @@
from typing import Dict
from ThousandHands.core.plan.PlanBase import PlanBase
import sched
import time
import concurrent.futures
class Scheduler:
__plans: Dict[str, sched.Event]
__scheduler: sched.scheduler
__executor: concurrent.futures.ThreadPoolExecutor
def __init__(self):
self.__plans = {}
self.__scheduler = sched.scheduler(time.time, time.sleep)
self.__executor = concurrent.futures.ThreadPoolExecutor(max_workers=3)
def add_plan(self, plan: PlanBase) -> None:
if plan.name in self.__plans:
raise ValueError("Plan already exists")
event = self.__scheduler.enter(
plan.getNextTime(), plan.getPriorityFactor(), self.__execute_plan, (plan,)
)
self.__plans[plan.name] = event
def remove_plan(self, plan_name: str) -> None:
if plan_name in self.__plans:
del self.__plans[plan_name]
raise ValueError("Plan name not found")
def run(self):
self.__scheduler.run()
def stop(self):
self.__executor.shutdown(wait=True)
def __execute_plan(self, plan: PlanBase):
"""
执行计划,并在执行后重新安排(如果需要)
"""
self.__executor.submit(plan.execute)

View File

@@ -17,8 +17,4 @@ class TargetBase(ABC):
:param :param
:return :return
""" """
pass pass
@abstractmethod
def back(self, back_object: BackupObject):
pass

View File

@@ -0,0 +1,10 @@
from .targetBase import TargetBase
class TargetNative(TargetBase):
def __init__(self) -> None:
pass
def test(self) -> bool:
return True

View File

@@ -1,11 +0,0 @@
class Plan:
__priority_factor: float # 优先级因子
def __init__(self):
pass
def getPriorityFactor(self) -> float:
'''
获取优先级因子
'''
return self.__priority_factor

View File

@@ -1,15 +0,0 @@
from typing import List
from .Plan import Plan
class PlanPriorityMinHeap:
"""
计划优先小顶堆,按照优先级存储多个计划
"""
plans: List[Plan]
def __init__(self):
self.plans = []
def addPlan(self, plan: Plan):
pass

View File

View File

@@ -1,11 +0,0 @@
from typing import Callable
class Timer:
def __init__(self, name: str, interval: float, callback: Callable):
self.name = name
self.interval = interval
self.callback = callback
def start(self):
pass

View File

View File

@@ -1,5 +1,5 @@
from core.objects.backup_object import BackupObject from ThousandHands.core.objects.backup_object import BackupObject
import tempfile import tempfile
import os import os
@@ -25,7 +25,7 @@ class TestBackup():
with tempfile.TemporaryDirectory() as tmpdir: with tempfile.TemporaryDirectory() as tmpdir:
temp_data_dir = self.createTempDataDir() temp_data_dir = self.createTempDataDir()
b = BackupObject("testBackup", tmpdir) b = BackupObject("testBackup", tmpdir)
b.createNewBackup([temp_data_dir.name]) b.addBackup([temp_data_dir.name])
b.backup() b.backup()
temp_data_dir.cleanup() temp_data_dir.cleanup()
assert os.path.exists(b.backup_path+"/objects") assert os.path.exists(b.backup_path+"/objects")

View File

@@ -1,5 +1,5 @@
import asyncio import asyncio
from core.objects.blob_object import BlobObject from ThousandHands.core.objects.blob_object import BlobObject
import hashlib import hashlib
import tempfile import tempfile