Skip to content

Commit c9f041e

Browse files
1a1a11ahaochengxia
andauthored
Add a doc for plugin (#256)
* Enhancement: Improve cache handling and error management in plugin (#254) - Added a cache free hook and default parameter for cache management. - Enhanced error handling for parsing to ensure robustness. - Unified description and improved resource management with handle closure. * Add description for cache_free_hook For some experimental situations where memory safety is not required, the "cache_free_hook" can be skipped. * Add function signature --------- Co-authored-by: Percy <xhc_1007@163.com>
1 parent 5afb2fe commit c9f041e

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

doc/quickstart_plugin.md

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# libCacheSim Plugin System – Quick-Start Guide
2+
3+
> **Audience**: Developers who want to add custom cache–replacement policies to *libCacheSim* without modifying the core library.
4+
>
5+
> **Goal**: Build a shared-library plugin that implements a few well-defined hook functions, then load it at runtime via `pluginCache`.
6+
7+
---
8+
9+
## 1 . How the Plugin System Works
10+
11+
`plugin_cache.c` ships with *libCacheSim* and delegates **all policy-specific logic** to a user-supplied shared library (``.so`` / ``.dylib``). At run-time the library is
12+
13+
1. loaded with `dlopen()`;
14+
2. each required *hook* is resolved with `dlsym()`; and
15+
3. the hooks are invoked on cache hits, misses, evictions, and removals.
16+
17+
Because the plugin is completely decoupled from core code you can:
18+
* experiment with new algorithms quickly,
19+
* write the plugin in **C or C++**, and
20+
* distribute it independently from *libCacheSim*.
21+
22+
### 1.1 Required Hook Functions
23+
24+
Your library **must** export the following C-symbols:
25+
26+
| Hook | Prototype | Called When |
27+
|------|-----------|-------------|
28+
| `cache_init_hook` | `void *cache_init_hook(const common_cache_params_t ccache_params);` | Once at cache creation. Return an opaque pointer to plugin state. |
29+
| `cache_hit_hook` | `void cache_hit_hook(void *data, const request_t *req);` | A requested object is found in the cache. |
30+
| `cache_miss_hook` | `void cache_miss_hook(void *data, const request_t *req);` | A requested object is **not** in the cache *after* insertion. |
31+
| `cache_eviction_hook` | `obj_id_t cache_eviction_hook(void *data, const request_t *req);` | Cache is full – must return the object-ID to evict. |
32+
| `cache_remove_hook` | `void cache_remove_hook(void *data, const obj_id_t obj_id);` | An object is explicitly removed (not necessarily due to eviction). |
33+
34+
The opaque pointer returned by `cache_init_hook` is passed back to every other hook via the `data` parameter, letting your plugin maintain arbitrary state (linked lists, hash maps, statistics, …). For memory safety, your library can export `cache_free_hook` (`void cache_free_hook(void *data);`) to free the resources used by your cache struct according to your demands.
35+
36+
---
37+
38+
## 2 . Minimal Plugin Skeleton (C++)
39+
40+
Below is an **abridged** version of the LRU example in `example/plugin_v2/plugin_lru.cpp`. You can copy this as a starting point for your own policy:
41+
42+
```cpp
43+
#include <libCacheSim.h> // public headers installed by libCacheSim
44+
#include <unordered_map>
45+
46+
class MyPolicy {
47+
/* your data structures */
48+
public:
49+
MyPolicy() {/*init*/}
50+
void on_hit(obj_id_t id) {/*...*/}
51+
void on_miss(obj_id_t id, uint64_t size) {/*...*/}
52+
obj_id_t evict() {/* decide victim */}
53+
void on_remove(obj_id_t id) {/*...*/}
54+
};
55+
56+
extern "C" {
57+
void *cache_init_hook(const common_cache_params_t /*params*/) {
58+
return new MyPolicy();
59+
}
60+
61+
void cache_hit_hook(void *data, const request_t *req) {
62+
static_cast<MyPolicy *>(data)->on_hit(req->obj_id);
63+
}
64+
65+
void cache_miss_hook(void *data, const request_t *req) {
66+
static_cast<MyPolicy *>(data)->on_miss(req->obj_id, req->obj_size);
67+
}
68+
69+
obj_id_t cache_eviction_hook(void *data, const request_t * /*req*/) {
70+
return static_cast<MyPolicy *>(data)->evict();
71+
}
72+
73+
void cache_remove_hook(void *data, const obj_id_t obj_id) {
74+
static_cast<MyPolicy *>(data)->on_remove(obj_id);
75+
}
76+
} // extern "C"
77+
```
78+
79+
*Notes*
80+
1. The plugin can allocate dynamic memory; it will live until the cache is destroyed.
81+
2. Thread safety is up to you – core *libCacheSim* is single-threaded today.
82+
83+
---
84+
85+
## 3 . Building the Plugin
86+
87+
### 3.1 Dependencies
88+
89+
* **CMake ≥ 3.12** (recommended)
90+
* A C/C++ compiler (``gcc``, ``clang``)
91+
92+
### 3.2 Sample `CMakeLists.txt`
93+
94+
```cmake
95+
cmake_minimum_required(VERSION 3.12)
96+
project(my_cache_plugin CXX C)
97+
98+
# Tell CMake to create a shared library
99+
add_library(plugin_my_policy SHARED plugin_my_policy.cpp)
100+
101+
# Location of libCacheSim headers – adjust if you installed elsewhere
102+
target_include_directories(plugin_my_policy PRIVATE
103+
${CMAKE_CURRENT_SOURCE_DIR}/../../include)
104+
105+
# Position-independent code is implicit for shared libs but keep for clarity
106+
set_property(TARGET plugin_my_policy PROPERTY POSITION_INDEPENDENT_CODE ON)
107+
108+
# Optional: strip symbols & set output name
109+
set_target_properties(plugin_my_policy PROPERTIES
110+
OUTPUT_NAME "plugin_my_policy_hooks")
111+
```
112+
113+
### 3.3 Build Commands
114+
115+
```bash
116+
mkdir build && cd build
117+
cmake -G Ninja .. # or "cmake .. && make"
118+
ninja # produces libplugin_my_policy_hooks.so
119+
```
120+
121+
> On macOS the file extension will be `.dylib` instead of `.so`.
122+
123+
---
124+
125+
## 4 . Using the Plugin with `cachesim`
126+
127+
1. **Compile** the plugin (`libplugin_my_policy_hooks.so`).
128+
2. **Run** `cachesim` with `pluginCache` **and** supply `plugin_path=`:
129+
130+
```bash
131+
./bin/cachesim data/cloudPhysicsIO.vscsi vscsi pluginCache 0.01 \
132+
-e "plugin_path=/absolute/path/libplugin_my_policy_hooks.so,cache_name=myPolicy"
133+
```
134+
135+
* Keys after `-e` are comma-separated. Supported keys today:
136+
* `plugin_path` (required) – absolute or relative path to the `.so` / `.dylib`.
137+
* `cache_name` (optional) – override the cache’s display name.
138+
* `print` – debug helper: print current parameters and exit.
139+
140+
If you omit `cache_name`, the runtime will default to `pluginCache-<fileName>` for easier identification in logs.
141+
142+
---
143+
144+
## 5 . A full example
145+
146+
A comprehensive example lives in `example/plugin_v2`. After building the example plugin:
147+
148+
---
149+
150+
## 6 . Troubleshooting Checklist
151+
152+
* **Plugin not found?** Verify the path passed via `plugin_path=` is correct, you may want to use absolute path.
153+
* **Missing symbols?** Make sure the function names exactly match the prototypes above and are declared `extern "C"` when compiling as C++.
154+
* **Link-time errors?** Pass the same architecture flags (`-m64`, etc.) that *libCacheSim* was built with.
155+
* **Runtime crash inside plugin?** Use `gdb -ex r --args cachesim …` and place breakpoints in your hook functions.
156+
157+
---
158+
159+
160+
Happy caching!

0 commit comments

Comments
 (0)