from .cache import Cache class Node: def __init__(self, key, value): self.key = key self.value = value self.visited = False self.next = None self.prev = None class SeiveCache(Cache): def __init__(self, limit: int): super().__init__(limit) self.limit = limit # Fix: Store limit properly self.cache = {} # Hash map for O(1) access self.head = None self.tail = None self.hand = None def print_cache_state(self): print("Current cache state:") node = self.head if not node: print("Cache is empty.") return for _ in range(len(self.cache)): print(f"Key: {node.key}, Value: {node.value}, Visited: {node.visited}") node = node.next if node == self.head: break def get(self, key: str) -> str: if key in self.cache: node = self.cache[key] node.visited = True print(f"GET {key}: {node.value}") self.print_cache_state() return node.value print(f"GET {key}: MISS") self.print_cache_state() return None def put(self, key: str, val: str) -> bool: print(f"PUT {key}: {val}") if key in self.cache: node = self.cache[key] node.value = val node.visited = True self.print_cache_state() return False # No eviction needed new_node = Node(key, val) if len(self.cache) >= self.limit: self.evict() if not self.head: self.head = self.tail = new_node new_node.next = new_node.prev = new_node else: new_node.prev = self.tail new_node.next = self.head self.tail.next = new_node self.head.prev = new_node self.tail = new_node self.cache[key] = new_node if not self.hand: self.hand = self.head self.print_cache_state() return False def invalidate(self, key: str) -> bool: print(f"INVALIDATE {key}") if key in self.cache: node = self.cache.pop(key) if node == self.head: self.head = node.next if node == self.tail: self.tail = node.prev if node.next: node.next.prev = node.prev if node.prev: node.prev.next = node.next self.print_cache_state() return True print("INVALIDATE FAILED: Key not found") return False def next_hand(self): self.hand = self.hand.next if self.hand.next else self.head def evict(self): print("EVICTION START") while self.hand.visited: self.hand.visited = False self.next_hand() obj_to_evict = self.hand self.next_hand() if obj_to_evict == self.head: self.head = obj_to_evict.next if obj_to_evict == self.tail: self.tail = obj_to_evict.prev if obj_to_evict.next: obj_to_evict.next.prev = obj_to_evict.prev if obj_to_evict.prev: obj_to_evict.prev.next = obj_to_evict.next del self.cache[obj_to_evict.key] print(f"EVICTED {obj_to_evict.key}") self.print_cache_state() # Basic API demo for future testing if __name__ == "__main__": cache = SeiveCache(3) cache.put("a", "1") cache.put("b", "2") cache.put("c", "3") cache.get("a") cache.put("d", "4") # Should evict "b" assert "b" not in cache.cache, f"Eviction failed, cache contents: {cache.cache.keys()}" print("SeiveCache eviction test passed.")