1313 * - cache_miss_hook: Handle cache miss events
1414 * - cache_eviction_hook: Determine which object to evict
1515 * - cache_remove_hook: Clean up when objects are removed
16+ * - cache_free_hook: Free plugin resources
1617 *
1718 * The plugin cache delegates core cache operations to these hooks, enabling
1819 * flexible and extensible cache policies.
@@ -46,12 +47,14 @@ extern "C" {
4647 */
4748typedef struct pluginCache_params {
4849 char * plugin_path ; ///< Path to the plugin shared library
50+ void * plugin_handle ; ///< Handle to the loaded plugin library
4951 void * data ; ///< Plugin's internal data structure
5052 cache_init_hook_t cache_init_hook ; ///< Plugin initialization function
5153 cache_hit_hook_t cache_hit_hook ; ///< Cache hit handler function
5254 cache_miss_hook_t cache_miss_hook ; ///< Cache miss handler function
5355 cache_eviction_hook_t cache_eviction_hook ; ///< Eviction decision function
5456 cache_remove_hook_t cache_remove_hook ; ///< Object removal handler function
57+ cache_free_hook_t cache_free_hook ; ///< Cache cleanup function
5558 char * cache_name ;
5659} pluginCache_params_t ;
5760
@@ -137,6 +140,7 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
137140 ERROR ("Failed to load plugin %s: %s\n" , params -> plugin_path , dlerror ());
138141 exit (1 );
139142 }
143+ params -> plugin_handle = handle ;
140144
141145 // Load hook functions from the plugin using unions to avoid pedantic warnings
142146 union {
@@ -159,6 +163,10 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
159163 void * obj ;
160164 cache_remove_hook_t func ;
161165 } cache_remove_u ;
166+ union {
167+ void * obj ;
168+ cache_free_hook_t func ;
169+ } cache_free_u ;
162170
163171 cache_init_u .obj = dlsym (handle , "cache_init_hook" );
164172 params -> cache_init_hook = cache_init_u .func ;
@@ -175,6 +183,9 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
175183 cache_remove_u .obj = dlsym (handle , "cache_remove_hook" );
176184 params -> cache_remove_hook = cache_remove_u .func ;
177185
186+ cache_free_u .obj = dlsym (handle , "cache_free_hook" );
187+ params -> cache_free_hook = cache_free_u .func ;
188+
178189 // Initialize the plugin with cache parameters
179190 params -> data = params -> cache_init_hook (ccache_params );
180191
@@ -205,6 +216,10 @@ cache_t *pluginCache_init(const common_cache_params_t ccache_params,
205216 */
206217static void pluginCache_free (cache_t * cache ) {
207218 pluginCache_params_t * params = (pluginCache_params_t * )cache -> eviction_params ;
219+
220+ if (params -> cache_free_hook != NULL ) params -> cache_free_hook (params -> data );
221+ if (params -> plugin_handle != NULL )
222+ dlclose (params -> plugin_handle ); // Close the plugin shared library handle
208223 if (params -> plugin_path != NULL ) free (params -> plugin_path );
209224 if (params -> cache_name != NULL ) free (params -> cache_name );
210225 free (cache -> eviction_params );
@@ -398,8 +413,16 @@ static void pluginCache_parse_params(cache_t *cache,
398413
399414 // Process recognized parameters
400415 if (strcasecmp (key , "plugin" ) == 0 || strcasecmp (key , "plugin_path" ) == 0 ) {
416+ // Validate plugin path is not empty
417+ if (strlen (value ) == 0 ) {
418+ ERROR ("Parameter 'plugin_path' cannot be empty in cache '%s'\n" ,
419+ cache -> cache_name );
420+ exit (1 );
421+ }
422+ if (params -> plugin_path != NULL ) free (params -> plugin_path );
401423 params -> plugin_path = strdup (value );
402424 } else if (strcasecmp (key , "cache_name" ) == 0 ) {
425+ if (params -> cache_name != NULL ) free (params -> cache_name );
403426 params -> cache_name = strdup (value );
404427 } else if (strcasecmp (key , "print" ) == 0 ) {
405428 printf ("current parameters: plugin_path=%s\n" , params -> plugin_path );
0 commit comments