rm.page의 소스 코드

from contextlib import (
    contextmanager,
)

from bluebase.pf import (
    PfLayoutField,
    PfLayoutView,
    PfPageHeader,
    PfPageData,
    PfPage,
)
from .error import (
    RmInvalidSidError,
    RmUnoccupiedSlotError,
    RmInvalidRecordDataSizeError,
)
from .record import (
    RmRecordKey,
    RmRecordData,
    RmRecord,
)


__all__ = (
    'RmSlotId',
    'RmPageId',
    'RmPageHeader',
    'RmPage',
)


[문서] class RmSlotId(int): """ slot의 ID를 나타내는 클래스입니다. """ pass
[문서] class RmPageId(int): """ page의 ID를 나타내는 클래스입니다. """ pass
[문서] class RmPageHeader(PfLayoutView): """ RM page의 header를 나타내는 클래스입니다. PF page content의 첫 4바이트를 사용하는 layout view입니다. layout view의 property를 사용 할 때는 항상 해당 PF page가 pin 되어있어야 합니다. Attributes: next_available_pid (RmPageId): 다음 available RM page의 ID. """ NO_NEXT_AVAILABLE_PAGE = RmPageId(-1) """ 다음 available page가 없다는 뜻을 나타내는 상수. """ NOT_IN_AVAILABLE_PAGE_LIST = RmPageId(-2) """ page가 available page list에 없다는 뜻을 나타내는 상수. """ _fields = ( PfLayoutField('next_available_pid', '<i'), ) @property def next_available_pid(self) -> RmPageId: return RmPageId(self.get('next_available_pid')) @next_available_pid.setter def next_available_pid(self, pid: RmPageId) -> None: self.set('next_available_pid', int(pid))
class RmPageBitmap: """ RM page의 bitmap을 나타내는 클래스입니다. PF page content의 4바이트 이후의 `size` 바이트를 사용하는 layout view-like입니다. layout view-like의 메서드를 사용 할 때는 항상 해당 PF page가 pin 되어있어야 합니다. Attributes: _page (PfPage): bitmap이 들어있는 PF page. _offset (int): bitmap의 시작 오프셋. _record_capacity (int): record의 최대 수. size (int): bitmap의 크기. _view (memoryview): bitmap의 데이터. """ @staticmethod def calc_size(record_capacity: int) -> int: """ record의 최대 수에 필요한 bitmap의 크기를 계산합니다. 예를 들어 bitmap의 크기가 2인 경우, record를 최대 16개까지 표현할 수 있습니다. Args: record_capacity (int): record의 최대 수. Returns: int: bitmap의 크기. """ raise NotImplementedError def __init__(self, page: PfPage, offset: int, record_capacity: int, ) -> None: """ bitmap을 초기화합니다. Args: page (PfPage): bitmap이 들어있는 PF page. offset (int): bitmap의 시작 오프셋. record_capacity (int): record의 최대 수. """ self._page = page self._offset = offset self._record_capacity = record_capacity self.size = RmPageBitmap.calc_size(record_capacity) self._view = memoryview(page.data)[offset: offset + self.size] def find_first_zero_bit(self) -> int: """ bitmap에서 첫번째로 0인 bit의 index를 반환합니다. 찾지 못하는 경우는 없다고 가정합니다. Returns: int: 첫번째로 0인 bit의 index. """ raise NotImplementedError def set_bit(self, index: int) -> None: """ bitmap의 대상 bit를 1로 설정합니다. Args: index (int): 대상 bit의 index. """ raise NotImplementedError def clear_bit(self, index: int) -> None: """ bitmap의 대상 bit를 0으로 설정합니다. Args: index (int): 대상 bit의 index. """ raise NotImplementedError def check_bit(self, index: int) -> bool: """ bitmap의 대상 bit가 1인지 여부를 반환합니다. Args: index (int): 대상 bit의 index. Returns: bool: bit가 1인지 여부. """ raise NotImplementedError def clear_all(self) -> None: """ bitmap의 모든 bit를 0으로 설정합니다. """ raise NotImplementedError def is_full(self) -> bool: """ bitmap이 가득 찼는지 여부를 반환합니다. bitmap이 모두 1인 경우가 아니라, record capacity 만큼 1이 연속으로 있는 경우를 가득 찼다고 합니다. Returns: bool: bitmap이 가득 찼는지 여부. """ raise NotImplementedError
[문서] class RmPage: """ RM page를 나타내는 클래스입니다. Attributes: _pf_page (PfPage): RM page가 wrapping하고 있는 PF page. pid (RmPageId): RM page의 ID. record_size (int): record의 크기. record_capacity (int): record의 최대 수. header (RmPageHeader): RM page의 header. _bitmap (RmPageBitmap): RM page의 bitmap. """
[문서] def __init__(self, pf_page: PfPage, pid: RmPageId, record_size: int, ) -> None: """ RM page를 초기화합니다. Args: pf_page (PfPage): RM page가 wrapping하고 있는 PF page. pid (RmPageId): RM page의 ID. record_size (int): record의 크기. """ self._pf_page = pf_page self.pid = pid self.record_size = record_size self.record_capacity = self._calc_record_capacity() self.header = RmPageHeader( page=pf_page, offset=PfPageHeader.SIZE, limit=RmPageHeader.SIZE, ) self._bitmap = RmPageBitmap( page=pf_page, offset=PfPageHeader.SIZE + RmPageHeader.SIZE, record_capacity=self.record_capacity, )
def _calc_record_capacity(self) -> int: base = PfPageHeader.SIZE + RmPageHeader.SIZE capacity = 0 while True: bitmap_size = RmPageBitmap.calc_size(capacity + 1) estimate = base + bitmap_size + self.record_size * (capacity + 1) if estimate > self._pf_page.size: break capacity += 1 return capacity
[문서] @contextmanager def pinned(self): """ RM page를 pin 상태로 사용할 수 있는 context를 생성합니다. PF page의 `pinned` 메서드를 사용합니다. Examples: >>> with page.pinned(): ... ... """ raise NotImplementedError
[문서] def get_record(self, sid: RmSlotId) -> RmRecord: """ 대상 slot에 있는 record를 가져옵니다. PF page의 `get_content` 메서드를 사용합니다. Args: sid (RmSlotId): 대상 record의 slot ID. Returns: RmRecord: 가져온 record. Raises: RmInvalidSidError: `sid` 가 유효하지 않은 경우. RmUnoccupiedSlotError: `sid` 가 비어있는 경우. """ raise NotImplementedError
[문서] def set_record(self, sid: RmSlotId, data: RmRecordData, new: bool = False, ) -> None: """ 대상 slot에 record data를 설정합니다. bitmap의 `check_bit`, `set_bit` 메서드와 PF page의 `set_content` 메서드를 사용합니다. Args: sid (RmSlotId): 대상 record의 slot ID. data (RmRecordData): 설정할 record의 data. new (bool): 새로운 record를 생성할지 여부. Raises: RmInvalidSidError: `sid` 가 유효하지 않은 경우. RmUnoccupiedSlotError: `sid` 가 비어있는 경우이면서 `new` 가 `False` 인 경우. RmInvalidRecordDataSizeError: `data` 의 크기가 유효하지 않은 경우. """ raise NotImplementedError
[문서] def clear_record(self, sid: RmSlotId) -> None: """ record를 삭제합니다. 실제로 삭제하지는 않고, bitmap의 해당 bit를 0으로 설정합니다. bitmap의 `clear_bit` 메서드를 사용합니다. Args: sid (RmSlotId): 대상 record의 slot ID. Raises: RmInvalidSidError: `sid` 가 유효하지 않은 경우. RmUnoccupiedSlotError: `sid` 가 비어있는 경우. """ raise NotImplementedError
[문서] def clear_all_records(self) -> None: """ 모든 record를 삭제합니다. 실제로 삭제하지는 않고, bitmap의 모든 bit를 0으로 설정합니다. bitmap의 `clear_all` 메서드를 사용합니다. """ raise NotImplementedError
[문서] def find_first_free_sid(self) -> RmSlotId: """ 첫번째로 비어있는 slot의 ID를 반환합니다. bitmap의 `find_first_zero_bit` 메서드를 사용합니다. Returns: RmSlotId: 첫번째로 비어있는 slot의 ID. """ raise NotImplementedError
[문서] def is_full(self) -> bool: """ slot이 가득 찼는지 여부를 반환합니다. bitmap의 `is_full` 메서드를 사용합니다. Returns: bool: slot이 가득 찼는지 여부. """ raise NotImplementedError