Skip to content

Commit

Permalink
bh_component: Now with support for multiple component "instances".
Browse files Browse the repository at this point in the history
  • Loading branch information
safl committed Jun 1, 2015
1 parent bf44d42 commit 9f2d84d
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 109 deletions.
242 changes: 143 additions & 99 deletions core/bh_component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,59 +98,155 @@ static bh_component_type get_type(dictionary *dict, const char *name)
return BH_COMPONENT_ERROR;
}

/**
* Extract component symbol from the given string.
*
* Expects a string like: "anythinglibbh_componenttype_COMPONENTNAME.anything"
*
* No error-checking in this thing...
*
*/
static void extract_symbol_from_path(const char* path, char* symbol)
{
const char* prefix = "libbh_"; // Component prefix
int prefix_len = strlen(prefix);

const char* filename = strstr(path, prefix); // Filename
filename += prefix_len; // Skip the prefix

const char* sep = "_";
int sep_len = strlen(sep);
const char* name = strstr(filename, sep);
name += sep_len; // Skip the seperator
int name_len = strlen(name);

strncpy(symbol, name, name_len); // Copy the symbol

for(int i=0; // Terminate at extension
(symbol[i]!='\0') || (i>=(name_len-1));
++i) {
if (symbol[i] == '.') {
*(symbol+i) = '\0';
break;
}
}
}

static void *get_dlsym(void *handle, const char *name,
bh_component_type type, const char *fun)
{
if (!((type == BH_BRIDGE) || (type == BH_VEM) || (type == BH_VE) ||
(type == BH_FILTER) || (type == BH_FUSER))) {
char tmp[1024];
const char *stype;
void *ret;
if(type == BH_BRIDGE)
stype = "bridge";
else if(type == BH_VEM)
stype = "vem";
else if(type == BH_VE)
stype = "ve";
else if(type == BH_FILTER)
stype = "filter";
else if(type == BH_FUSER)
stype = "fuser";
else
{
fprintf(stderr, "Internal error get_dlsym() got unknown type\n");
return NULL;
}

char tmp[1024];
snprintf(tmp, BH_COMPONENT_NAME_SIZE, "bh_%s_%s", name, fun);
dlerror(); //Clear old errors.
void* ret = dlsym(handle, tmp);
snprintf(tmp, BH_COMPONENT_NAME_SIZE, "bh_%s_%s_%s", stype, name, fun);
dlerror();//Clear old errors.
ret = dlsym(handle, tmp);
char *err = dlerror();
if (err != NULL) {
if(err != NULL)
{
fprintf(stderr, "Failed to load %s() from %s (%s).\n"
"Make sure to define all four interface functions, eg. the NODE-VEM "
"must define: bh_vem_node_init(), bh_vem_node_shutdown(), "
"bh_vem_node_reg_func(), and bh_vem_node_execute().\n", fun, name, err);
"bh_vem_node_extmethod(), and bh_vem_node_execute().\n",
fun, name, err);
return NULL;
}

return ret;
}

/**
* Extract component symbol from the given string.
*
* Expects a string like: "anythinglibbh_COMPONENTNAME.anything"
* The returned pointer must be freed.
*
* No error-checking in this thing...
* Dynamically load component interface.
*
*/
char* get_component_symbol(const char* source)
static bh_error component_dl_iface(dictionary* config, bh_component_iface* comp)
{
const char* prefix = "libbh_"; // Component prefix
int prefix_len = strlen(prefix);
if (!iniparser_find_entry(config, comp->name)) { // Check for config-entry
fprintf(stderr,
"component_dl_iface: Failed retrieving config section for '%s'.\n",
comp->name);
return BH_ERROR;
}

const char* filename = strstr(source, prefix); // Filename
filename += prefix_len; // Skip the prefix
int filename_len = strlen(filename);
char impl_inikey[BH_COMPONENT_NAME_SIZE+5]; // Get path to shared-object
snprintf(impl_inikey, BH_COMPONENT_NAME_SIZE+5, "%s:impl", comp->name);
char *impl = iniparser_getstring(config, impl_inikey, NULL);
if (impl == NULL) {
fprintf(stderr,
"component_dl_iface: Failed retrieving 'impl' for component '%s'\n",
comp->name);
return BH_ERROR;
}

char* match = (char*)malloc(sizeof(char)*filename_len); // Allocate symbol
strncpy(match, filename, filename_len);
bh_component_type comp_type = get_type(config, comp->name);
if (comp_type == BH_COMPONENT_ERROR) {
fprintf(stderr,
"component_dl_iface: Failed getting type of component(%s).\n",
comp->name);
}

for(int i=0; (match[i]!='\0') || (i>=(filename_len-1)); ++i) {
if (match[i] == '.') { // Terminate at extension
*(match+i) = '\0';
break;
}
char symbol[BH_COMPONENT_NAME_SIZE];
extract_symbol_from_path(impl, symbol); // Get the component "symbol"

//
// Load component-interface functions
//

void *lib_handle = dlopen(impl, RTLD_NOW); // Open the library
if (lib_handle == NULL) {
fprintf(stderr,
"component_dl_iface: Error in [%s:impl]: %s\n",
comp->name,
dlerror());
return BH_ERROR;
}
comp->lib_handle = lib_handle; // Store library handle

// Grab component interface symbols init, shutdown, execute, extmethod
comp->init = (bh_init)get_dlsym(lib_handle, symbol, comp_type, "init");
if (comp->init == NULL) {
fprintf(stderr,
"component_dl_iface: Failed retrieving iface-init for %s.",
comp->name);
return BH_ERROR;
}
comp->shutdown = (bh_shutdown)get_dlsym(lib_handle, symbol, comp_type, "shutdown");
if (comp->shutdown == NULL) {
fprintf(stderr,
"component_dl_iface: Failed retrieving iface-shutdown for %s.",
comp->name);
return BH_ERROR;
}
comp->execute = (bh_execute)get_dlsym(lib_handle, symbol, comp_type, "execute");
if (comp->execute == NULL) {
fprintf(stderr,
"component_dl_iface: Failed retrieving iface-execute for %s.",
comp->name);
return BH_ERROR;
}
comp->extmethod = (bh_extmethod)get_dlsym(lib_handle, symbol, comp_type, "extmethod");
if (comp->extmethod == NULL) {
fprintf(stderr,
"component_dl_iface: Failed retrieving iface-extmethod for %s.",
comp->name);
return BH_ERROR;
}
return match;
return BH_SUCCESS;
}

/* Initilize children of the given component
Expand All @@ -161,86 +257,35 @@ char* get_component_symbol(const char* source)
*/
static bh_error component_children_init(bh_component *self, char* stack)
{
char tmp[BH_COMPONENT_NAME_SIZE];
self->nchildren = 0;

char child_inikey[BH_COMPONENT_NAME_SIZE]; // Where to look for children
if (stack) {
snprintf(tmp, BH_COMPONENT_NAME_SIZE, "%s:%s", stack, self->iname);
snprintf(child_inikey, BH_COMPONENT_NAME_SIZE, "%s:%s", stack, self->name);
} else {
snprintf(tmp, BH_COMPONENT_NAME_SIZE, "%s:children", self->iname);
snprintf(child_inikey, BH_COMPONENT_NAME_SIZE, "%s:children", self->name);
}

char *children_str = iniparser_getstring(self->config, tmp, NULL);
if (children_str == NULL) { //No children -- we are finished
char *children_str = iniparser_getstring(self->config, child_inikey, NULL);
if (children_str == NULL) { // No children -- we are finished
return BH_SUCCESS;
}

char *instance_name = strtok(children_str, ",");
self->nchildren = 0;
while(instance_name != NULL) { // Handle one child at a time.
bh_component_iface *child = &self->children[self->nchildren];
bh_component_type child_type = get_type(self->config, instance_name);
if (child_type == BH_COMPONENT_ERROR) {
return BH_ERROR;
}

// Store instance name
strncpy(child->iname, instance_name, BH_COMPONENT_NAME_SIZE);

// Open the config-entry for the component instance
if (!iniparser_find_entry(self->config, instance_name)) {
fprintf(stderr, "Reference '%s' is not declared.\n", instance_name);
return BH_ERROR;
}

// Path to shared library containing the component
snprintf(tmp, BH_COMPONENT_NAME_SIZE, "%s:impl", instance_name);
char *impl = iniparser_getstring(self->config, tmp, NULL);
if (impl == NULL) {
fprintf(stderr,"in section '%s' impl is not set.\n", instance_name);
return BH_ERROR;
}

// Store component name
char* component_name = get_component_symbol(impl);
strncpy(child->name, component_name, BH_COMPONENT_NAME_SIZE);
free(component_name);

//
// Load interface functions
//

// Open the library
void *lib_handle = dlopen(impl, RTLD_NOW);
if (lib_handle == NULL) {
fprintf(stderr, "Error in [%s:impl]: %s\n", instance_name, dlerror());
return BH_ERROR;
}

// Grab symbols
child->init = (bh_init)get_dlsym(lib_handle, child->name, child_type, "init");
if (child->init == NULL) {
return BH_ERROR;
}
child->shutdown = (bh_shutdown)get_dlsym(lib_handle, child->name, child_type, "shutdown");
if (child->shutdown == NULL) {
return BH_ERROR;
}
child->execute = (bh_execute)get_dlsym(lib_handle, child->name, child_type, "execute");
if (child->execute == NULL) {
return BH_ERROR;
}
child->extmethod = (bh_extmethod)get_dlsym(lib_handle, child->name, child_type, "extmethod");
if (child->extmethod == NULL) {
return BH_ERROR;
}
char *child_name = strtok(children_str, ",");
while(child_name != NULL) {
bh_component_iface *child = &self->children[self->nchildren]; // Grab child
strncpy(child->name, child_name, BH_COMPONENT_NAME_SIZE); // Store name
component_dl_iface(self->config, child); // Load interface

if (++self->nchildren > BH_COMPONENT_MAX_CHILDS) {
++(self->nchildren); // Increment count
if (self->nchildren > BH_COMPONENT_MAX_CHILDS) {
fprintf(stderr,
"Number of children of %s is greater "
"than BH_COMPONENT_MAX_CHILDS.\n", self->name);
return BH_ERROR;
}

instance_name = strtok(NULL, ","); // Go to next child
child_name = strtok(NULL, ","); // Go to next child
}
return BH_SUCCESS;
}
Expand Down Expand Up @@ -397,7 +442,7 @@ bh_error bh_component_init(bh_component *self, const char* name)
stack = NULL;
}

if (name == NULL) { // Assign name
if (name == NULL) { // Store component name
if (stack) {
strcpy(self->name, stack);
} else {
Expand All @@ -406,14 +451,13 @@ bh_error bh_component_init(bh_component *self, const char* name)
} else {
strcpy(self->name, name);
}
strcpy(self->iname, self->name);

self->type = get_type(self->config, self->iname); // Assign type
self->type = get_type(self->config, self->name); // Store type
if (BH_COMPONENT_ERROR == self->type) {
return BH_ERROR;
}

return component_children_init(self, stack); // Initialize children
return component_children_init(self, stack); // Initialize children
}

/* Destroyes the component object.
Expand Down
4 changes: 3 additions & 1 deletion filter/bcexp/component_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ bh_error bh_filter_bcexp_init(const char* name)
}

if (myself.nchildren != 1) { // For now only one child is supported
fprintf(stderr, "[FILTER-bcexp] Only a single child is supported.");
fprintf(stderr,
"[FILTER-bcexp] Only a single child is supported, has %ld.",
myself.nchildren);
return BH_ERROR;
}

Expand Down
16 changes: 7 additions & 9 deletions include/bh_component.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,9 @@ typedef bh_error (*bh_extmethod_impl)(bh_instruction *instr, void* arg);
/* The interface functions of a component */
typedef struct
{
char name[BH_COMPONENT_NAME_SIZE]; // Name of the component
char iname[BH_COMPONENT_NAME_SIZE]; // Name of the instance
void *lib_handle; // Handle for the dynamic linked library.
bh_init init; // The interface function pointers
char name[BH_COMPONENT_NAME_SIZE]; // Name of the component
void *lib_handle; // Handle for the dynamic linked library.
bh_init init; // The interface function pointers
bh_shutdown shutdown;
bh_execute execute;
bh_extmethod extmethod;
Expand All @@ -105,11 +104,10 @@ typedef enum
/* The component object */
typedef struct
{
char name[BH_COMPONENT_NAME_SIZE]; // Name of the component
char iname[BH_COMPONENT_NAME_SIZE]; // Name of the instance
dictionary *config; // The ini-config dictionary
bh_component_type type; // The component type
bh_intp nchildren; // Number of children
char name[BH_COMPONENT_NAME_SIZE]; // Name of the component
dictionary *config; // The ini-config dictionary
bh_component_type type; // The component type
bh_intp nchildren; // Number of children
// The interface of the children of this component
bh_component_iface children[BH_COMPONENT_MAX_CHILDS];
} bh_component;
Expand Down

0 comments on commit 9f2d84d

Please sign in to comment.