Index: ChangeLog
===================================================================
--- ChangeLog	(revision 5484)
+++ ChangeLog	(revision 5488)
@@ -12,11 +12,12 @@
 	* Some small, general improvements to roarclients.
 	* Changed roard plugin ABI version to 1.0beta1.
-	* Corrected usage of -Wextra (pr0).
-	* Updated build options for RAT (pr0).
-	* Work around bugs in win32 while using stdvios (pr0).
-	* Added support to load plugins on win32 (pr0).
+	* Corrected usage of -Wextra (pr1).
+	* Updated build options for RAT (pr1).
+	* Work around bugs in win32 while using stdvios (pr1).
+	* Added support to load plugins on win32 (pr1).
 	* Added support for quotes strings to kv split and
-	  roardl para argument splitting (pr0).
-	* Added support for an application mode in roarpluginrunner (pr0).
+	  roardl para argument splitting (pr1).
+	* Added support for an application mode in roarpluginrunner (pr1).
+	* Improved plugincontainer (pr1).
 
 v. 1.0beta0 - Fri Mar 16 2012 19:39 CET
Index: include/libroar/plugincontainer.h
===================================================================
--- include/libroar/plugincontainer.h	(revision 5487)
+++ include/libroar/plugincontainer.h	(revision 5488)
@@ -41,4 +41,64 @@
 struct roar_plugincontainer;
 
+struct roar_plugincontainer_callbacks {
+ /* prefree() is called before the container is freed.
+  */
+ int (*prefree)(struct roar_plugincontainer * cont, void ** userdata);
+
+ /* freeuserdata() is called when the userdata needs to be freed.
+  * This is the case then the container is freed.
+  * It is not called when the current userdata is NULL.
+  * If not set or userdata is still non-NULL after this call the userdata
+  * is freed using roar_mm_free().
+  */
+ int (*freeuserdata)(struct roar_plugincontainer * cont, void ** userdata);
+
+ /* freecontext() is called when the context needs to be freed.
+  * It is not called when the current context is NULL.
+  * If not set or context is still non-NULL after this call the context
+  * is freed using roar_mm_free().
+  */
+ int (*freecontext)(struct roar_plugincontainer * cont, void ** context);
+
+ /* preload() and postload() are called before and after a plugin is loaded.
+  */
+ int (*preload) (struct roar_plugincontainer * cont, void ** context,
+                 const char * name, int flags, struct roar_dl_librarypara * para);
+ int (*postload)(struct roar_plugincontainer * cont, void ** context, struct roar_dl_lhandle * lhandle,
+                 const char * name, int flags, struct roar_dl_librarypara * para);
+
+ /* preunload() and postunload() are called before and after a plugin is unloaded.
+  * Those functions are also called if the plugin was loaded but ra_init was not yet done or failed.
+  */
+ int (*preunload) (struct roar_plugincontainer * cont, void ** context, struct roar_dl_lhandle * lhandle);
+ int (*postunload)(struct roar_plugincontainer * cont, void ** context);
+
+ /* prera_init() and postra_init() are called before and after a plugin is ra_init-ed.
+  * This is also true if the plugin is ra_init-ed while being loaded.
+  * Note the limits of roar_plugincontainer_ra_init() if this is used
+  * with roar_plugincontainer_ra_init().
+  * postra_init() is also called in case the ra_init failed.
+  */
+ int (*prera_init) (struct roar_plugincontainer * cont, void ** context, struct roar_dl_lhandle * lhandle,
+                    struct roar_dl_librarypara * para);
+ int (*postra_init)(struct roar_plugincontainer * cont, void ** context, struct roar_dl_lhandle * lhandle,
+                    struct roar_dl_librarypara * para);
+};
+
+struct roar_plugincontainer_plugininfo {
+ /* The name of the plugin.
+  */
+ const char * libname;
+ /* The roardl's library handle.
+  */
+ struct roar_dl_lhandle * handle;
+ /* The number of librarys/plugins depending on this plugin.
+  */
+ size_t rdepends;
+ /* A pointer to the current user context.
+  */
+ void ** context;
+};
+
 /* Create a new plugin container.
  * Takes a default parameter set.
@@ -58,8 +118,26 @@
 int roar_plugincontainer_unref(struct roar_plugincontainer * cont);
 
-/* Get a lhandle by name of the loaded plugin
+/* Set callbacks.
+ */
+int roar_plugincontainer_set_callbacks(struct roar_plugincontainer * cont,
+                                       const struct roar_plugincontainer_callbacks * callbacks);
+
+/* Set container's userdata.
+ */
+int roar_plugincontainer_set_userdata(struct roar_plugincontainer * cont, void * userdata);
+
+/* Get container's userdata.
+ */
+void * roar_plugincontainer_get_userdata(struct roar_plugincontainer * cont);
+
+/* Get a lhandle by name of the loaded plugin.
  */
 struct roar_dl_lhandle * roar_plugincontainer_get_lhandle_by_name (struct roar_plugincontainer * cont,
                                                                    const char * name);
+
+/* Get infos about current state of plugin.
+ */
+struct roar_plugincontainer_plugininfo roar_plugincontainer_get_info_by_name (struct roar_plugincontainer * cont,
+                                                                              const char * name);
 
 // plugin loading and unloading:
Index: libroar/plugincontainer.c
===================================================================
--- libroar/plugincontainer.c	(revision 5487)
+++ libroar/plugincontainer.c	(revision 5488)
@@ -40,9 +40,39 @@
 struct roar_plugincontainer {
  size_t refc;
+ const struct roar_plugincontainer_callbacks * callbacks;
+ void * userdata;
  struct roar_dl_librarypara * default_para;
  struct roar_dl_lhandle * handle[MAX_PLUGINS];
  size_t deprefc[MAX_PLUGINS];
+ void * context[MAX_PLUGINS];
  size_t numhandles;
 };
+
+static inline void _unload(struct roar_plugincontainer * cont, size_t index) {
+ int err = roar_error;
+
+ if ( cont->callbacks != NULL && cont->callbacks->preunload != NULL )
+  cont->callbacks->preunload(cont, &(cont->context[index]), cont->handle[index]);
+
+ roar_err_set(err);
+ roar_dl_unref(cont->handle[index]);
+ err = roar_error;
+ cont->handle[index] = NULL;
+ cont->numhandles--;
+
+ if ( cont->callbacks != NULL && cont->callbacks->postunload != NULL )
+  cont->callbacks->postunload(cont, &(cont->context[index]));
+
+ if ( cont->context[index] != NULL )
+  if ( cont->callbacks != NULL && cont->callbacks->freecontext != NULL )
+  cont->callbacks->freecontext(cont, &(cont->context[index]));
+
+ if ( cont->context[index] != NULL ) {
+  roar_mm_free(cont->context[index]);
+  cont->context[index] = NULL;
+ }
+
+ roar_err_set(err);
+}
 
 static int _loader(struct roar_dl_librarypara * lhandle, void * loader_userdata, enum roar_dl_loadercmd cmd, void * argp) {
@@ -209,4 +239,7 @@
  }
 
+ if ( cont->callbacks != NULL && cont->callbacks->prefree != NULL )
+  cont->callbacks->prefree(cont, &(cont->userdata));
+
  while (cont->numhandles) {
   for (i = 0; i < MAX_PLUGINS; i++) {
@@ -218,9 +251,18 @@
     continue;
 
-   roar_dl_close(cont->handle[i]);
-   cont->handle[i] = NULL;
-   cont->numhandles--;
-  }
- }
+   _unload(cont, i);
+  }
+ }
+
+ // try to free user data...
+ if ( cont->userdata != NULL ) {
+  if ( cont->callbacks != NULL && cont->callbacks->freeuserdata != NULL ) {
+   cont->callbacks->freeuserdata(cont, &(cont->userdata));
+  }
+ }
+
+ // if still not freed by caller, free it using memmgr.
+ if ( cont->userdata != NULL )
+  roar_mm_free(cont->userdata);
 
  if ( cont->default_para != NULL )
@@ -233,12 +275,52 @@
 }
 
-struct roar_dl_lhandle * roar_plugincontainer_get_lhandle_by_name (struct roar_plugincontainer * cont,
-                                                                   const char * name) {
+int roar_plugincontainer_set_callbacks(struct roar_plugincontainer * cont,
+                                       const struct roar_plugincontainer_callbacks * callbacks) {
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ cont->callbacks = callbacks;
+
+ return 0;
+}
+
+int roar_plugincontainer_set_userdata(struct roar_plugincontainer * cont, void * userdata) {
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return -1;
+ }
+
+ cont->userdata = userdata;
+
+ return 0;
+}
+
+void * roar_plugincontainer_get_userdata(struct roar_plugincontainer * cont) {
+ if ( cont == NULL ) {
+  roar_err_set(ROAR_ERROR_FAULT);
+  return NULL;
+ }
+
+ if ( cont->userdata == NULL ) {
+  roar_err_set(ROAR_ERROR_NOENT);
+  return NULL;
+ }
+
+ return cont->userdata;
+}
+
+struct roar_plugincontainer_plugininfo roar_plugincontainer_get_info_by_name (struct roar_plugincontainer * cont,
+                                                                              const char * name) {
+ struct roar_plugincontainer_plugininfo ret;
  const struct roar_dl_libraryname * libname;
  size_t i;
 
+ memset(&ret, 0, sizeof(ret));
+
  if ( cont == NULL || name == NULL ) {
   roar_err_set(ROAR_ERROR_FAULT);
-  return NULL;
+  return ret;
  }
 
@@ -252,12 +334,26 @@
   if ( !strcmp(libname->name, name) ) {
    if ( roar_dl_ref(cont->handle[i]) == -1 )
-    return NULL;
-
-   return cont->handle[i];
+    return ret;
+
+   ret.libname  = libname->name;
+   ret.handle   = cont->handle[i];
+   ret.rdepends = cont->deprefc[i];
+   ret.context  = &(cont->context[i]);
+   return ret;
   }
  }
 
  roar_err_set(ROAR_ERROR_NOENT);
- return NULL;
+ return ret;
+}
+
+struct roar_dl_lhandle * roar_plugincontainer_get_lhandle_by_name (struct roar_plugincontainer * cont,
+                                                                   const char * name) {
+ struct roar_plugincontainer_plugininfo info = roar_plugincontainer_get_info_by_name(cont, name);
+
+ if ( info.libname == NULL )
+  return NULL;
+
+ return info.handle;
 }
 
@@ -316,5 +412,11 @@
  }
 
- cont->handle[idx] = roar_dl_open(name, flags, ra_init, para);
+ cont->context[idx] = NULL; // clear context.
+ cont->deprefc[idx] = 0;
+
+ if ( cont->callbacks != NULL && cont->callbacks->preload != NULL )
+  cont->callbacks->preload(cont, &(cont->context[idx]), name, flags, para);
+
+ cont->handle[idx] = roar_dl_open(name, flags, 0, para);
  if ( cont->handle[idx] == NULL ) {
   err = roar_error;
@@ -324,6 +426,29 @@
  }
 
- cont->deprefc[idx] = 0;
  cont->numhandles++;
+
+ if ( cont->callbacks != NULL && cont->callbacks->postload != NULL )
+  cont->callbacks->postload(cont, &(cont->context[idx]), cont->handle[idx], name, flags, para);
+
+ if ( ra_init ) {
+  if ( cont->callbacks != NULL && cont->callbacks->prera_init != NULL )
+   cont->callbacks->prera_init(cont, &(cont->context[idx]), cont->handle[idx], para);
+  if ( roar_dl_ra_init(cont->handle[idx], NULL, para) == -1 ) {
+   err = roar_error;
+
+   if ( cont->callbacks != NULL && cont->callbacks->postra_init != NULL )
+    cont->callbacks->postra_init(cont, &(cont->context[idx]), cont->handle[idx], para);
+
+   _unload(cont, idx);
+
+   roar_dl_para_unref(para);
+   cont->handle[idx] = NULL;
+   roar_error = err;
+   return NULL;
+  }
+
+  if ( cont->callbacks != NULL && cont->callbacks->postra_init != NULL )
+   cont->callbacks->postra_init(cont, &(cont->context[idx]), cont->handle[idx], para);
+ }
 
  roar_dl_para_unref(para);
@@ -369,7 +494,5 @@
     return -1;
    }
-   roar_dl_close(cont->handle[i]);
-   cont->handle[i] = NULL;
-   cont->numhandles--;
+   _unload(cont, i);
    return 0;
   }
@@ -391,5 +514,12 @@
   if ( cont->handle[i] == NULL )
    continue;
+
+  if ( cont->callbacks != NULL && cont->callbacks->prera_init != NULL )
+   cont->callbacks->prera_init(cont, &(cont->context[i]), cont->handle[i], cont->default_para);
+
   roar_dl_ra_init(cont->handle[i], NULL, cont->default_para);
+
+  if ( cont->callbacks != NULL && cont->callbacks->postra_init != NULL )
+   cont->callbacks->postra_init(cont, &(cont->context[i]), cont->handle[i], cont->default_para);
  }
 
