44# This import causes liblibcachesim.{dll,dylib,so} to be loaded.
55from .libpath import _LIB
66import ctypes
7- from typing import Optional
7+ from typing import Optional , Union , Dict , Any
8+ from pathlib import Path
9+
10+
11+ _ReaderHandle = ctypes .c_void_p
12+ _CacheHandle = ctypes .c_void_p
13+ _ReqHandle = ctypes .c_void_p
14+
815
916def _safe_call (ret : int ) -> None :
1017 """Check the return value from C API call.
@@ -18,7 +25,9 @@ def _safe_call(ret: int) -> None:
1825 # TODO(haocheng):add error message from C API
1926 raise Exception (f"C API call failed with error code { ret } " )
2027
21-
28+ # -----------------------------------------------------------------------------
29+ # Simulation API
30+ # -----------------------------------------------------------------------------
2231def simulate (trace_path : str , trace_type_str : str , eviction_algo : str , cache_size : float ,
2332 eviction_params : Optional [str ]= None , consider_obj_metadata : bool = False ) -> float :
2433 """Simulate the cache performance.
@@ -41,4 +50,119 @@ def simulate(trace_path: str, trace_type_str: str, eviction_algo: str, cache_siz
4150 consider_obj_metadata ,
4251 ctypes .byref (n_req ),
4352 ctypes .byref (n_miss )))
44- return n_req .value , n_miss .value
53+ return n_req .value , n_miss .value
54+
55+ # -----------------------------------------------------------------------------
56+ # Reader API
57+ # -----------------------------------------------------------------------------
58+ class Reader :
59+ def __init__ (self ,
60+ trace_file : Union [str , Path ],
61+ reader_params : Dict [str , Any ] = None ,
62+ ):
63+ """Initialize the Reader.
64+
65+ Parameters
66+ ----------
67+ trace_file : str or pathlib.Path
68+ Path to the trace file.
69+ reader_params : dict
70+ Other parameters for the reader.
71+ reference : Reader
72+ Reference reader.
73+ """
74+ self ._handle = ctypes .c_void_p ()
75+ # TODO(haocheng): implement reader_params and utilize reference
76+ _safe_call (_LIB .LCS_ReaderCreateFromFile (trace_file , b"" ,ctypes .byref (self ._handle )))
77+
78+ def __del__ (self ) -> None :
79+ try :
80+ self ._free_handle ()
81+ except AttributeError :
82+ pass
83+
84+ def _free_handle (self ) -> "Reader" :
85+ if self ._handle is not None :
86+ _safe_call (_LIB .LCS_ReaderFree (self ._handle ))
87+ self ._handle = None
88+ return self
89+
90+ def read (self ) -> "Request" :
91+ """Read a request from the reader.
92+ """
93+ req_handle = ctypes .c_void_p ()
94+ _safe_call (_LIB .LCS_ReaderGetNextRequest (self ._handle , ctypes .byref (req_handle )))
95+ if not req_handle :
96+ raise StopIteration
97+ return Request (req_handle )
98+
99+ def __iter__ (self ):
100+ while True :
101+ try :
102+ yield self .read ()
103+ except StopIteration :
104+ break
105+
106+ def __next__ (self ):
107+ return self .read ()
108+
109+
110+ class Request :
111+ def __init__ (self , handle : _ReqHandle ):
112+ self ._handle = handle
113+
114+ # def __del__(self) -> None:
115+ # try:
116+ # self._free_handle()
117+ # except AttributeError:
118+ # pass
119+
120+ # def _free_handle(self) -> "Request":
121+ # if self._handle is not None:
122+ # _safe_call(_LIB.LCS_RequestFree(self._handle))
123+ # self._handle = None
124+ # return self
125+
126+ # -----------------------------------------------------------------------------
127+ # Cache API
128+ # -----------------------------------------------------------------------------
129+
130+ class Cache :
131+ def __init__ (self , reader : "Reader" ,
132+ cache_size : float = 0.1 ,
133+ ignore_obj_size : bool = True ,
134+ eviction_params : Optional [str ]= None ):
135+ self .reader = reader
136+ self .cache_size = cache_size
137+ self .ignore_obj_size = ignore_obj_size
138+ self .eviction_params = eviction_params
139+ self ._handle = None
140+
141+ def _free_handle (self ) -> "Cache" :
142+ if self ._handle is not None :
143+ _safe_call (_LIB .LCS_CacheFree (self ._handle ))
144+ self ._handle = None
145+ return self
146+
147+
148+ class FIFO (Cache ):
149+ def __init__ (self , reader : "Reader" ,
150+ cache_size : float = 0.1 ,
151+ ignore_obj_size : bool = True ,
152+ eviction_params : Optional [str ]= b"" ):
153+ super ().__init__ (reader , cache_size , ignore_obj_size , eviction_params )
154+ # TODO(haocheng): add more parameters and reference
155+ self ._handle = ctypes .c_void_p ()
156+ _safe_call (_LIB .LCS_CacheCreate (reader ._handle , b"fifo" , ctypes .c_float (cache_size ), ignore_obj_size , eviction_params , ctypes .byref (self ._handle )))
157+
158+ def get (self , request : "Request" ) -> bool :
159+ hit = ctypes .c_bool ()
160+ _safe_call (_LIB .LCS_CacheGet (self ._handle , request ._handle , ctypes .byref (hit )))
161+ return hit .value
162+
163+ def __del__ (self ) -> None :
164+ try :
165+ self ._free_handle ()
166+ except AttributeError :
167+ pass
168+
0 commit comments