Skip to content

Commit a7ede08

Browse files
committed
Proof of concept implementation of PluginAdmissioner (still uncertain about naming)
1 parent e389e05 commit a7ede08

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

libcachesim/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
SizeAdmissioner,
6363
SizeProbabilisticAdmissioner,
6464
AdaptSizeAdmissioner,
65+
PluginAdmissioner,
6566
)
6667

6768
from .trace_reader import TraceReader
@@ -124,6 +125,7 @@
124125
"SizeAdmissioner",
125126
"SizeProbabilisticAdmissioner",
126127
"AdaptSizeAdmissioner",
128+
"PluginAdmissioner",
127129
# Readers and analyzers
128130
"TraceReader",
129131
"TraceAnalyzer",

libcachesim/admissioner.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
create_size_admissioner,
88
create_size_probabilistic_admissioner,
99
create_adaptsize_admissioner,
10+
create_plugin_admissioner,
1011
)
1112

1213

@@ -67,3 +68,21 @@ def __init__(self, max_iteration: int = None, reconf_interval: int = None):
6768

6869
admissioner = create_adaptsize_admissioner(params)
6970
super().__init__(admissioner)
71+
72+
73+
class PluginAdmissioner(AdmissionerBase):
74+
def __init__(self,
75+
admissioner_name,
76+
admissioner_init_hook,
77+
admissioner_admit_hook,
78+
admissioner_clone_hook,
79+
admissioner_update_hook,
80+
admissioner_free_hook):
81+
admissioner = create_plugin_admissioner(
82+
admissioner_name,
83+
admissioner_init_hook,
84+
admissioner_admit_hook,
85+
admissioner_clone_hook,
86+
admissioner_update_hook,
87+
admissioner_free_hook)
88+
super().__init__(admissioner)

src/export_admissioner.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,92 @@ namespace libcachesim {
1616

1717
namespace py = pybind11;
1818

19+
typedef struct __attribute__((visibility("hidden")))
20+
pypluginAdmissioner_params {
21+
py::object data; ///< Plugin's internal data structure (python object)
22+
py::function admissioner_init_hook;
23+
py::function admissioner_admit_hook;
24+
py::function admissioner_clone_hook;
25+
py::function admissioner_update_hook;
26+
py::function admissioner_free_hook;
27+
std::string admissioner_name;
28+
} pypluginAdmissioner_params_t;
29+
30+
static bool pypluginAdmissioner_admit(admissioner_t *, const request_t *);
31+
static admissioner_t *pypluginAdmissioner_clone(admissioner_t *);
32+
static void pypluginAdmissioner_free(admissioner_t *);
33+
static void pypluginAdmissioner_update(admissioner_t *, const request_t *, const uint64_t);
34+
35+
// TODO: Free hook is currently not invoked at all, see export_cache.cpp and follow
36+
// their implementation pattern of using a custom deleter alongside std::unique_ptr
37+
admissioner_t *create_plugin_admissioner(std::string admissioner_name,
38+
py::function admissioner_init_hook,
39+
py::function admissioner_admit_hook,
40+
py::function admissioner_clone_hook,
41+
py::function admissioner_update_hook,
42+
py::function admissioner_free_hook) {
43+
admissioner_t *admissioner = nullptr;
44+
try{
45+
admissioner = (admissioner_t *)malloc(sizeof(admissioner_t));
46+
if (!admissioner) {
47+
throw std::runtime_error("Failed to initialize admissioner structure");
48+
}
49+
memset(admissioner, 0, sizeof(admissioner_t));
50+
51+
// We will pass a raw pointer for C++ to take ownership of
52+
admissioner->admit = pypluginAdmissioner_admit;
53+
admissioner->clone = pypluginAdmissioner_clone;
54+
admissioner->free = pypluginAdmissioner_free;
55+
admissioner->update = pypluginAdmissioner_update;
56+
57+
// Initialize pointers to python hook functions
58+
std::unique_ptr<pypluginAdmissioner_params_t> params =
59+
std::make_unique<pypluginAdmissioner_params_t>(
60+
pypluginAdmissioner_params_t());
61+
params->data = admissioner_init_hook();
62+
params->admissioner_admit_hook = admissioner_admit_hook;
63+
params->admissioner_clone_hook = admissioner_clone_hook;
64+
params->admissioner_update_hook = admissioner_update_hook;
65+
params->admissioner_free_hook = admissioner_free_hook;
66+
params->admissioner_name = admissioner_name;
67+
68+
// Transfer ownership of params to admissioner
69+
admissioner->params = params.release();
70+
return admissioner;
71+
72+
} catch (...) {
73+
if (admissioner)
74+
free(admissioner);
75+
throw;
76+
}
77+
}
78+
79+
static bool pypluginAdmissioner_admit(admissioner_t *admissioner, const request_t *req) {
80+
pypluginAdmissioner_params_t* params =
81+
(pypluginAdmissioner_params_t*)admissioner->params;
82+
return params->admissioner_admit_hook(params->data, req).cast<bool>();
83+
}
84+
85+
static admissioner_t *pypluginAdmissioner_clone(admissioner_t *admissioner) {
86+
pypluginAdmissioner_params_t* params =
87+
(pypluginAdmissioner_params_t*)admissioner->params;
88+
return params->admissioner_clone_hook(params->data).cast<admissioner_t *>();
89+
}
90+
91+
static void pypluginAdmissioner_free(admissioner_t *admissioner) {
92+
pypluginAdmissioner_params_t* params =
93+
(pypluginAdmissioner_params_t*)admissioner->params;
94+
params->admissioner_free_hook(params->data);
95+
}
96+
97+
static void pypluginAdmissioner_update(admissioner_t *admissioner,
98+
const request_t *req,
99+
const uint64_t cache_size) {
100+
pypluginAdmissioner_params_t* params =
101+
(pypluginAdmissioner_params_t*)admissioner->params;
102+
params->admissioner_update_hook(params->data, req, cache_size);
103+
}
104+
19105
template <admissioner_t *(*fn)(const char *)>
20106
void export_admissioner_creator(py::module &m, const std::string &name) {
21107
m.def(
@@ -107,6 +193,7 @@ void export_admissioner(py::module &m) {
107193
// **** ****
108194
// ***********************************************************************
109195

196+
// Exposing existing implementations of admission algorithms
110197
export_admissioner_creator<create_bloomfilter_admissioner>(
111198
m, "create_bloomfilter_admissioner");
112199
export_admissioner_creator<create_prob_admissioner>(
@@ -117,6 +204,18 @@ void export_admissioner(py::module &m) {
117204
m, "create_size_probabilistic_admissioner");
118205
export_admissioner_creator<create_adaptsize_admissioner>(
119206
m, "create_adaptsize_admissioner");
207+
208+
m.def(
209+
"create_plugin_admissioner",
210+
&create_plugin_admissioner,
211+
"admissioner_name",
212+
"admissioner_init_hook",
213+
"admissioner_admit_hook",
214+
"admissioner_clone_hook",
215+
"admissioner_update_hook",
216+
"admissioner_free_hook",
217+
py::return_value_policy::take_ownership
218+
);
120219
}
121220

122221
} // namespace libcachesim

0 commit comments

Comments
 (0)