Apply CP HiCache page-floor policy before backup and insert
Backed CP HiCache tail splits were floored during match, but write preparation and radix insertion could still observe the raw sub-page prefix. That could skip one token during pre-forward reservation or call CpHiCacheNodeMetadata.split() with a non-page boundary. The shared helper now floors backed partial-tail prefixes before probe, match, and insert. Constraint: CP HiCache uses page-granular physical ownership while radix keys may keep valid-tail lengths. Rejected: Let probe and insert keep token-precise tail prefixes | it reintroduces half-page ownership through a different entry point. Confidence: high Scope-risk: moderate Directive: Any CP radix path that can split or reserve against backed HiCache metadata must use the same page-floor policy. Tested: Remote red tests first for probe and insert failures in g0034 container. Tested: Remote py_compile for hiradix_cache.py and test_cp_hicache_metadata.py. Tested: Remote targeted C7 tests: 4 passed, 3 warnings. Tested: Remote pytest test_cp_hicache_metadata.py test_cp_hicache_load_back_owner_lanes.py: 94 passed, 5 warnings. Not-tested: Live ETE traffic with concurrent divergent tail prompts. Co-authored-by: OmX <omx@oh-my-codex.dev>
This commit is contained in:
@@ -2009,6 +2009,12 @@ class HiRadixCache(RadixCache):
|
||||
prefix_len = self.key_match_fn(child.key, key)
|
||||
if prefix_len <= 0:
|
||||
break
|
||||
if prefix_len < len(child.key):
|
||||
prefix_len = self._cp_floor_backed_partial_split_len(
|
||||
child, prefix_len
|
||||
)
|
||||
if prefix_len <= 0:
|
||||
break
|
||||
|
||||
total_prefix_len += prefix_len
|
||||
if prefix_len < len(child.key):
|
||||
@@ -2021,6 +2027,19 @@ class HiRadixCache(RadixCache):
|
||||
|
||||
return total_prefix_len
|
||||
|
||||
def _cp_floor_backed_partial_split_len(
|
||||
self, child: TreeNode, prefix_len: int
|
||||
) -> int:
|
||||
if (
|
||||
not self._uses_cp_hicache
|
||||
or self.page_size <= 1
|
||||
or prefix_len <= 0
|
||||
or prefix_len % self.page_size == 0
|
||||
or not self._node_backuped(child)
|
||||
):
|
||||
return prefix_len
|
||||
return prefix_len // self.page_size * self.page_size
|
||||
|
||||
def prepare_write_backup_for_req(self, req) -> None:
|
||||
if self.disable or not self._uses_cp_hicache:
|
||||
return
|
||||
@@ -3356,7 +3375,9 @@ class HiRadixCache(RadixCache):
|
||||
and self._node_backuped(child)
|
||||
and prefix_len % self.page_size != 0
|
||||
):
|
||||
prefix_len = prefix_len // self.page_size * self.page_size
|
||||
prefix_len = self._cp_floor_backed_partial_split_len(
|
||||
child, prefix_len
|
||||
)
|
||||
if prefix_len == 0:
|
||||
break
|
||||
new_node = self._split_node(child.key, child, prefix_len)
|
||||
@@ -3464,6 +3485,11 @@ class HiRadixCache(RadixCache):
|
||||
total_prefix_length += prefix_len
|
||||
else:
|
||||
# partial match, split the node
|
||||
prefix_len = self._cp_floor_backed_partial_split_len(
|
||||
node, prefix_len
|
||||
)
|
||||
if prefix_len <= 0:
|
||||
break
|
||||
new_node = self._split_node(node.key, node, prefix_len)
|
||||
# shared-prefix node should also reflect max priority
|
||||
new_node.priority = max(new_node.priority, priority)
|
||||
|
||||
Reference in New Issue
Block a user