import mmap import os import struct import threading import typing from dataclasses import dataclass from pathlib import Path from communication.define import ValType, IVar, T_Val from communication.model import DevModel, VarModel @dataclass class BlockInfo(object): index: int offset: int bit: int var_type: ValType length: int class MemCache(object): index: typing.Dict[int, BlockInfo] path: typing.Optional[Path] mmap: typing.Optional[mmap.mmap] # 设计容量 20w 个 D64 点, # 16m, 20w * D64 = 200k*8 = 1.6m MAX_SIZE = 1024 * 1024 * 16 def __init__(self): self.path = None self.mmap = None self.index = {} self.lock = threading.RLock() def setup(self, path: Path) -> None: with self.lock: self.path = path self.__create_mmap() self.__create_index() def __create_mmap(self): fd = os.open( self.path.joinpath('var', 'memory.dat').as_posix(), flags=os.O_CREAT | os.O_RDWR ) os.write(fd, b'\0' * self.MAX_SIZE) self.mmap = mmap.mmap( fileno=fd, length=self.MAX_SIZE, access=mmap.ACCESS_WRITE | mmap.ACCESS_READ ) def __create_index(self): dev_list = DevModel.select().order_by(DevModel.id) self.index.clear() block = [0, 0, 0] for dev in dev_list: var_list = VarModel.filter(VarModel.slot == dev.slot) for var in var_list: self.__register(block, var) block[0] += 1 block[1] = 0 block[2] = 0 self.__dump_index() self.__load_index() def __register(self, block, var): idx, off, bit = block vt = var.chr if '*' in vt: vt, length = vt.split('*') vt, length = ValType[vt], int(length) else: vt, length = ValType[vt], 1 self.index[var.id] = BlockInfo(idx, off, bit, vt, length) if vt == ValType.B1: bit += length _off, bit = divmod(bit, 8) off += _off _idx, off = divmod(off, 1000) idx += _idx elif vt in (ValType.U8, ValType.I8): bit = 0 off += 1 * length _idx, off = divmod(off, 1000) idx += _idx elif vt in (ValType.U16, ValType.I16): bit = 0 off += 2 * length _idx, off = divmod(off, 1000) idx += _idx elif vt in (ValType.U32, ValType.I32, ValType.F32): bit = 0 off += 4 * length _idx, off = divmod(off, 1000) idx += _idx elif vt in (ValType.U64, ValType.I64, ValType.D64): bit = 0 off += 8 * length _idx, off = divmod(off, 1000) idx += _idx block[:] = [idx, off, bit] __idx_fmt = struct.Struct(' T_Val: block_info = self.index[var.id] off = block_info.index * self.__block_size + block_info.offset if block_info.var_type == ValType.U8: return struct.unpack_from(' T_Val: bi = self.index[var.id] off = bi.index * self.__block_size + bi.offset with self.lock: if bi.var_type == ValType.U8: struct.pack_into(' 0: byte = byte | op else: byte = byte & ~op struct.pack_into('