Restructure and more generic plugin API for backend
This commit is contained in:
parent
7fbd95d491
commit
b9a54f07f3
19 changed files with 570 additions and 629 deletions
|
|
@ -62,8 +62,7 @@
|
|||
#include "clixon_string.h"
|
||||
#include "clixon_file.h"
|
||||
|
||||
/*
|
||||
* qsort function
|
||||
/*! qsort "compar" for directory alphabetically sorting, see qsort(3)
|
||||
*/
|
||||
static int
|
||||
clicon_file_dirent_sort(const void* arg1,
|
||||
|
|
@ -79,8 +78,7 @@ clicon_file_dirent_sort(const void* arg1,
|
|||
#endif /* HAVE_STRVERSCMP */
|
||||
}
|
||||
|
||||
|
||||
/*! Return sorted matching files from a directory
|
||||
/*! Return alphabetically sorted files from a directory matching regexp
|
||||
* @param[in] dir Directory path
|
||||
* @param[out] ent Entries pointer, will be filled in with dir entries. Free
|
||||
* after use
|
||||
|
|
@ -120,16 +118,13 @@ clicon_file_dirent(const char *dir,
|
|||
struct dirent *new = NULL;
|
||||
struct dirent *dvecp = NULL;
|
||||
|
||||
|
||||
*ent = NULL;
|
||||
nent = 0;
|
||||
|
||||
if (regexp && (res = regcomp(&re, regexp, REG_EXTENDED)) != 0) {
|
||||
regerror(res, &re, errbuf, sizeof(errbuf));
|
||||
clicon_err(OE_DB, 0, "regcomp: %s", errbuf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dirp = opendir (dir)) == NULL) {
|
||||
if (errno == ENOENT) /* Dir does not exist -> return 0 matches */
|
||||
retval = 0;
|
||||
|
|
@ -137,7 +132,6 @@ clicon_file_dirent(const char *dir,
|
|||
clicon_err(OE_UNIX, errno, "opendir(%s)", dir);
|
||||
goto quit;
|
||||
}
|
||||
|
||||
for (res = readdir_r (dirp, &dent, &dresp);
|
||||
dresp;
|
||||
res = readdir_r (dirp, &dent, &dresp)) {
|
||||
|
|
@ -162,7 +156,6 @@ clicon_file_dirent(const char *dir,
|
|||
if ((type & st.st_mode) == 0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((tmp = realloc(new, (nent+1)*sizeof(*dvecp))) == NULL) {
|
||||
clicon_err(OE_UNIX, errno, "realloc");
|
||||
goto quit;
|
||||
|
|
|
|||
|
|
@ -64,9 +64,83 @@
|
|||
static clixon_plugin *_clixon_plugins = NULL; /* List of plugins (of client) */
|
||||
static int _clixon_nplugins = 0; /* Number of plugins */
|
||||
|
||||
/*! Iterator over clixon plugins
|
||||
*
|
||||
* @note Never manipulate the plugin during operation or using the
|
||||
* same object recursively
|
||||
*
|
||||
* @param[in] plugin previous plugin, or NULL on init
|
||||
* @code
|
||||
* clicon_plugin *cp = NULL;
|
||||
* while ((cp = plugin_each(cp)) != NULL) {
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
* @note Not optimized, alwasy iterates from the start of the list
|
||||
*/
|
||||
clixon_plugin *
|
||||
plugin_each(clixon_plugin *cpprev)
|
||||
{
|
||||
int i;
|
||||
clixon_plugin *cp;
|
||||
clixon_plugin *cpnext = NULL;
|
||||
|
||||
if (cpprev == NULL)
|
||||
cpnext = _clixon_plugins;
|
||||
else{
|
||||
for (i = 0; i < _clixon_nplugins; i++) {
|
||||
cp = &_clixon_plugins[i];
|
||||
if (cp == cpprev)
|
||||
break;
|
||||
cp = NULL;
|
||||
}
|
||||
if (cp && i < _clixon_nplugins-1)
|
||||
cpnext = &_clixon_plugins[i+1];
|
||||
}
|
||||
return cpnext;
|
||||
}
|
||||
|
||||
/*! Reverse iterator over clixon plugins, iterater from nr to 0
|
||||
*
|
||||
* @note Never manipulate the plugin during operation or using the
|
||||
* same object recursively
|
||||
*
|
||||
* @param[in] plugin previous plugin, or NULL on init
|
||||
* @code
|
||||
* clicon_plugin *cp = NULL;
|
||||
* while ((cp = plugin_each_revert(cp, nr)) != NULL) {
|
||||
* ...
|
||||
* }
|
||||
* @endcode
|
||||
* @note Not optimized, alwasy iterates from the start of the list
|
||||
*/
|
||||
clixon_plugin *
|
||||
plugin_each_revert(clixon_plugin *cpprev,
|
||||
int nr)
|
||||
{
|
||||
int i;
|
||||
clixon_plugin *cp;
|
||||
clixon_plugin *cpnext = NULL;
|
||||
|
||||
if (cpprev == NULL)
|
||||
cpnext = &_clixon_plugins[nr-1];
|
||||
else{
|
||||
for (i = nr-1; i >= 0; i--) {
|
||||
cp = &_clixon_plugins[i];
|
||||
if (cp == cpprev)
|
||||
break;
|
||||
cp = NULL;
|
||||
}
|
||||
if (cp && i > 0)
|
||||
cpnext = &_clixon_plugins[i-1];
|
||||
}
|
||||
return cpnext;
|
||||
}
|
||||
|
||||
/*! Load a dynamic plugin object and call its init-function
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] file Which plugin to load
|
||||
* @param[in] function Which function symbol to load and call
|
||||
* @param[in] dlflags See man(3) dlopen
|
||||
* @retval cp Clixon plugin structure
|
||||
* @retval NULL Error
|
||||
|
|
@ -74,7 +148,8 @@ static int _clixon_nplugins = 0; /* Number of plugins */
|
|||
*/
|
||||
static clixon_plugin *
|
||||
plugin_load_one(clicon_handle h,
|
||||
char *file,
|
||||
char *file,
|
||||
char *function,
|
||||
int dlflags)
|
||||
{
|
||||
char *error;
|
||||
|
|
@ -82,16 +157,17 @@ plugin_load_one(clicon_handle h,
|
|||
plginit2_t *initfn;
|
||||
clixon_plugin_api *api = NULL;
|
||||
clixon_plugin *cp = NULL;
|
||||
char *name;
|
||||
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
dlerror(); /* Clear any existing error */
|
||||
if ((handle = dlopen (file, dlflags)) == NULL) {
|
||||
if ((handle = dlopen(file, dlflags)) == NULL) {
|
||||
error = (char*)dlerror();
|
||||
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
|
||||
goto done;
|
||||
}
|
||||
/* call plugin_init() if defined */
|
||||
if ((initfn = dlsym(handle, CLIXON_PLUGIN_INIT)) == NULL){
|
||||
/* call plugin_init() if defined, eg CLIXON_PLUGIN_INIT or CLIXON_BACKEND_INIT */
|
||||
if ((initfn = dlsym(handle, function)) == NULL){
|
||||
clicon_err(OE_PLUGIN, errno, "Failed to find %s when loading clixon plugin %s", CLIXON_PLUGIN_INIT, file);
|
||||
goto err;
|
||||
}
|
||||
|
|
@ -106,11 +182,15 @@ plugin_load_one(clicon_handle h,
|
|||
file);
|
||||
goto err;
|
||||
}
|
||||
if ((cp = (clixon_plugin *)malloc(sizeof(*cp))) == NULL){
|
||||
/* Note: sizeof clixon_plugin_api which is largest of clixon_plugin_api:s */
|
||||
if ((cp = (clixon_plugin *)malloc(sizeof(struct clixon_plugin))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
cp->cp_handle = handle;
|
||||
name = strrchr(file, '/') ? strrchr(file, '/')+1 : file;
|
||||
snprintf(cp->cp_name, sizeof(cp->cp_name), "%*s",
|
||||
(int)strlen(name)-2, name);
|
||||
cp->cp_api = *api;
|
||||
clicon_debug(1, "%s", __FUNCTION__);
|
||||
done:
|
||||
|
|
@ -123,12 +203,14 @@ plugin_load_one(clicon_handle h,
|
|||
|
||||
/*! Load a set of plugin objects from a directory and and call their init-function
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] function Which function symbol to load and call (eg CLIXON_PLUGIN_INIT)
|
||||
* @param[in] dir Directory. .so files in this dir will be loaded.
|
||||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
*/
|
||||
int
|
||||
clixon_plugins_load(clicon_handle h,
|
||||
char *function,
|
||||
char *dir)
|
||||
{
|
||||
int retval = -1;
|
||||
|
|
@ -147,7 +229,7 @@ clixon_plugins_load(clicon_handle h,
|
|||
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
|
||||
clicon_debug(1, "DEBUG: Loading plugin '%.*s' ...",
|
||||
(int)strlen(filename), filename);
|
||||
if ((cp = plugin_load_one(h, filename, RTLD_NOW)) == NULL)
|
||||
if ((cp = plugin_load_one(h, filename, function, RTLD_NOW)) == NULL)
|
||||
goto done;
|
||||
_clixon_nplugins++;
|
||||
if ((_clixon_plugins = realloc(_clixon_plugins, _clixon_nplugins*sizeof(clixon_plugin))) == NULL) {
|
||||
|
|
@ -169,7 +251,7 @@ done:
|
|||
* @param[in] h Clicon handle
|
||||
* @param[in] file Which plugin to load
|
||||
* @param[in] dlflags See man(3) dlopen
|
||||
* @see plugin_load_one for netxgen, this is soon OBSOLETE
|
||||
* @note OBSOLETE
|
||||
*/
|
||||
plghndl_t
|
||||
plugin_load(clicon_handle h,
|
||||
|
|
@ -211,10 +293,10 @@ plugin_load(clicon_handle h,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/*! Unload a plugin
|
||||
* @param[in] h Clicon handle
|
||||
* @param[in] handle Clicon handle
|
||||
* @note OBSOLETE
|
||||
*/
|
||||
int
|
||||
plugin_unload(clicon_handle h,
|
||||
|
|
@ -238,27 +320,6 @@ plugin_unload(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Unload all plugins
|
||||
* @param[in] h Clicon handle
|
||||
*/
|
||||
int
|
||||
clixon_plugin_unload(clicon_handle h)
|
||||
{
|
||||
clixon_plugin *cp;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _clixon_nplugins; i++) {
|
||||
cp = &_clixon_plugins[i];
|
||||
plugin_unload(h, cp->cp_handle);
|
||||
}
|
||||
if (_clixon_plugins){
|
||||
free(_clixon_plugins);
|
||||
_clixon_plugins = NULL;
|
||||
}
|
||||
_clixon_nplugins = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! Call plugin_start in all plugins
|
||||
* @param[in] h Clicon handle
|
||||
*/
|
||||
|
|
@ -275,6 +336,7 @@ clixon_plugin_start(clicon_handle h,
|
|||
cp = &_clixon_plugins[i];
|
||||
if ((startfn = cp->cp_api.ca_start) == NULL)
|
||||
continue;
|
||||
// optind = 0;
|
||||
if (startfn(h, argc, argv) < 0) {
|
||||
clicon_debug(1, "plugin_start() failed\n");
|
||||
return -1;
|
||||
|
|
@ -283,6 +345,39 @@ clixon_plugin_start(clicon_handle h,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Unload all plugins: call exit function and close shared handle
|
||||
* @param[in] h Clicon handle
|
||||
*/
|
||||
int
|
||||
clixon_plugin_exit(clicon_handle h)
|
||||
{
|
||||
clixon_plugin *cp;
|
||||
plgexit_t *exitfn;
|
||||
int i;
|
||||
char *error;
|
||||
|
||||
for (i = 0; i < _clixon_nplugins; i++) {
|
||||
cp = &_clixon_plugins[i];
|
||||
if ((exitfn = cp->cp_api.ca_exit) == NULL)
|
||||
continue;
|
||||
if (exitfn(h) < 0) {
|
||||
clicon_debug(1, "plugin_exit() failed\n");
|
||||
return -1;
|
||||
}
|
||||
if (dlclose(cp->cp_handle) != 0) {
|
||||
error = (char*)dlerror();
|
||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
|
||||
}
|
||||
}
|
||||
if (_clixon_plugins){
|
||||
free(_clixon_plugins);
|
||||
_clixon_plugins = NULL;
|
||||
}
|
||||
_clixon_nplugins = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*! Run the restconf user-defined credentials callback if present
|
||||
* Find first authentication callback and call that, then return.
|
||||
* The callback is to set the authenticated user
|
||||
|
|
|
|||
|
|
@ -433,7 +433,7 @@ xml_child_i_set(cxobj *xt,
|
|||
|
||||
/*! Iterator over xml children objects
|
||||
*
|
||||
* NOTE: Never manipulate the child-list during operation or using the
|
||||
* @note Never manipulate the child-list during operation or using the
|
||||
* same object recursively, the function uses an internal field to remember the
|
||||
* index used. It works as long as the same object is not iterated concurrently.
|
||||
*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue