|
30 | 30 | from .base import KVCacheBase |
31 | 31 | from .block_pool import DeviceBlockPool, HostBlockPool |
32 | 32 | from .cache_utils import storage_key_for_block |
33 | | -from .metadata import BlockNode, CacheLevel, CacheStatus, CacheSwapMetadata, MatchResult |
| 33 | +from .metadata import ( |
| 34 | + BlockNode, |
| 35 | + CacheLevel, |
| 36 | + CacheStatus, |
| 37 | + CacheSwapMetadata, |
| 38 | + MatchResult, |
| 39 | + PendingPrefetch, |
| 40 | + StorageMetadata, |
| 41 | +) |
34 | 42 | from .radix_tree import RadixTree |
35 | 43 | from .storage import create_storage_scheduler |
36 | 44 |
|
@@ -111,6 +119,10 @@ def __init__( |
111 | 119 | # used to quickly update status to HOST once prefetch completes. |
112 | 120 | self._prefetch_node_map: Dict[int, BlockNode] = {} |
113 | 121 |
|
| 122 | + # Pending prefetch queue: tasks waiting to be dispatched by scheduler |
| 123 | + self._pending_prefetch_list: List[PendingPrefetch] = [] |
| 124 | + self._pending_prefetch_lock = threading.Lock() |
| 125 | + |
114 | 126 | # Storage scheduler (create using factory method if backend is configured) |
115 | 127 | self._storage_scheduler = create_storage_scheduler(self.cache_config) |
116 | 128 |
|
@@ -504,10 +516,11 @@ def match_prefix( |
504 | 516 | # Split matched_nodes into device blocks and host blocks |
505 | 517 | if self.enable_host_cache: |
506 | 518 | for node in matched_nodes: |
507 | | - if node.is_on_device(): |
508 | | - result.device_nodes.append(node) |
509 | | - elif node.is_on_host(): |
510 | | - result.host_nodes.append(node) |
| 519 | + pass |
| 520 | + # if node.is_on_device(): |
| 521 | + # result.device_nodes.append(node) |
| 522 | + # elif node.is_on_host(): |
| 523 | + # result.host_nodes.append(node) |
511 | 524 | else: |
512 | 525 | result.device_nodes = matched_nodes |
513 | 526 |
|
@@ -968,6 +981,61 @@ def load_from_host(self, block_indices: List[int]) -> bool: |
968 | 981 |
|
969 | 982 | # ============ Prefetch Methods ============ |
970 | 983 |
|
| 984 | + def prefetch_storage(self, request: "Request") -> bool: |
| 985 | + """ |
| 986 | + Execute storage matching and enqueue prefetch info for later dispatch. |
| 987 | +
|
| 988 | + Called from the preprocess thread. Does match_prefix(skip_storage=False) |
| 989 | + to probe storage, allocate host blocks, and enqueue PendingPrefetch |
| 990 | + into the pending list. The scheduler will drain and dispatch later. |
| 991 | +
|
| 992 | + Args: |
| 993 | + request: The request to prefetch cache for. |
| 994 | +
|
| 995 | + Returns: |
| 996 | + True if storage blocks were matched and enqueued, False otherwise. |
| 997 | + """ |
| 998 | + if not self.enable_prefix_caching: |
| 999 | + return False |
| 1000 | + |
| 1001 | + self.match_prefix(request, skip_storage=False) |
| 1002 | + match_result = request.match_result |
| 1003 | + request.match_result = None |
| 1004 | + |
| 1005 | + if match_result is None or match_result.matched_storage_nums == 0: |
| 1006 | + return False |
| 1007 | + |
| 1008 | + storage_nodes = match_result.storage_nodes |
| 1009 | + host_block_ids = [node.block_id for node in storage_nodes] |
| 1010 | + hash_values = [node.hash_value for node in storage_nodes] |
| 1011 | + |
| 1012 | + metadata = StorageMetadata( |
| 1013 | + hash_values=hash_values, |
| 1014 | + block_ids=host_block_ids, |
| 1015 | + direction="load", |
| 1016 | + ) |
| 1017 | + |
| 1018 | + pending = PendingPrefetch( |
| 1019 | + request_id=request.request_id, |
| 1020 | + metadata=metadata, |
| 1021 | + host_block_ids=host_block_ids, |
| 1022 | + ) |
| 1023 | + with self._pending_prefetch_lock: |
| 1024 | + self._pending_prefetch_list.append(pending) |
| 1025 | + |
| 1026 | + logger.info( |
| 1027 | + f"[Debug][StoragePrefetch] request_id={request.request_id} " |
| 1028 | + f"storage_matched={match_result.matched_storage_nums} blocks, enqueued for dispatch" |
| 1029 | + ) |
| 1030 | + return True |
| 1031 | + |
| 1032 | + def drain_pending_prefetches(self) -> List[PendingPrefetch]: |
| 1033 | + """Atomically drain all pending prefetch tasks for scheduler dispatch.""" |
| 1034 | + with self._pending_prefetch_lock: |
| 1035 | + items = self._pending_prefetch_list |
| 1036 | + self._pending_prefetch_list = [] |
| 1037 | + return items |
| 1038 | + |
971 | 1039 | def prepare_prefetch_metadata( |
972 | 1040 | self, |
973 | 1041 | storage_hashes: List[str], |
|
0 commit comments