#include "pmix_config.h"
#include <string.h>
#include "pmix_common.h"
#include "src/class/pmix_hash_table.h"
#include "src/mca/base/pmix_mca_base_alias.h"
static void pmix_mca_base_alias_init(pmix_mca_base_alias_t *alias)
{
PMIX_CONSTRUCT(&alias->component_aliases, pmix_list_t);
}
static void pmix_mca_base_alias_fini(pmix_mca_base_alias_t *alias)
{
PMIX_LIST_DESTRUCT(&alias->component_aliases);
}
PMIX_CLASS_INSTANCE(pmix_mca_base_alias_t, pmix_object_t, pmix_mca_base_alias_init,
pmix_mca_base_alias_fini);
static void pmix_mca_base_alias_item_init(pmix_mca_base_alias_item_t *alias_item)
{
alias_item->component_alias = NULL;
}
static void pmix_mca_base_alias_item_fini(pmix_mca_base_alias_item_t *alias_item)
{
free(alias_item->component_alias);
}
PMIX_CLASS_INSTANCE(pmix_mca_base_alias_item_t, pmix_list_item_t, pmix_mca_base_alias_item_init,
pmix_mca_base_alias_item_fini);
static pmix_hash_table_t *alias_hash_table;
void pmix_mca_base_alias_cleanup(void)
{
if (!alias_hash_table) {
return;
}
void *key;
pmix_object_t *value;
PMIX_HASH_TABLE_FOREACH_PTR(key, value, alias_hash_table, { PMIX_RELEASE(value); });
PMIX_RELEASE(alias_hash_table);
alias_hash_table = NULL;
}
static int pmix_mca_base_alias_setup(void)
{
if (NULL != alias_hash_table) {
return PMIX_SUCCESS;
}
alias_hash_table = PMIX_NEW(pmix_hash_table_t);
if (NULL == alias_hash_table) {
return PMIX_ERR_OUT_OF_RESOURCE;
}
int ret = pmix_hash_table_init(alias_hash_table, 32);
if (PMIX_SUCCESS != ret) {
PMIX_RELEASE(alias_hash_table);
alias_hash_table = NULL;
return ret;
}
return PMIX_SUCCESS;
}
static char *pmix_mca_base_alias_generate_name(const char *project, const char *framework,
const char *component_name)
{
size_t project_length = project ? strlen(project) : 0;
size_t framework_length = framework ? strlen(framework) : 0;
size_t component_name_length = strlen(component_name);
size_t length = project_length + framework_length + component_name_length + 2;
char *tmp = calloc(1, length + 1);
if (NULL == tmp) {
return tmp;
}
if (project_length) {
strncat(tmp, project, length);
strcat(tmp, "_");
length -= project_length + 1;
}
if (framework_length) {
strncat(tmp, framework, length);
strcat(tmp, "_");
length -= framework_length + 1;
}
strncat(tmp, component_name, length);
return tmp;
}
static pmix_mca_base_alias_t *pmix_mca_base_alias_lookup_internal(const char *name)
{
pmix_mca_base_alias_t *alias = NULL;
if (NULL == alias_hash_table) {
return NULL;
}
(void) pmix_hash_table_get_value_ptr(alias_hash_table, name, strlen(name), (void **) &alias);
return alias;
}
int pmix_mca_base_alias_register(const char *project, const char *framework,
const char *component_name, const char *component_alias,
uint32_t alias_flags)
{
if (NULL == component_name) {
return PMIX_ERR_BAD_PARAM;
}
int ret = pmix_mca_base_alias_setup();
if (PMIX_SUCCESS != ret) {
return ret;
}
char *name = pmix_mca_base_alias_generate_name(project, framework, component_name);
assert(NULL != name);
pmix_mca_base_alias_t *alias = pmix_mca_base_alias_lookup_internal(name);
if (NULL == alias) {
alias = PMIX_NEW(pmix_mca_base_alias_t);
if (NULL == alias) {
free(name);
return PMIX_ERR_OUT_OF_RESOURCE;
}
pmix_hash_table_set_value_ptr(alias_hash_table, name, strlen(name), alias);
free(name);
name = NULL;
}
pmix_mca_base_alias_item_t *alias_item = PMIX_NEW(pmix_mca_base_alias_item_t);
if (NULL == alias_item) {
if (NULL != name) {
free(name);
}
return PMIX_ERR_OUT_OF_RESOURCE;
}
alias_item->component_alias = strdup(component_alias);
alias_item->alias_flags = alias_flags;
pmix_list_append(&alias->component_aliases, &alias_item->super);
if (NULL != name) {
free(name);
}
return PMIX_SUCCESS;
}
const pmix_mca_base_alias_t *pmix_mca_base_alias_lookup(const char *project, const char *framework,
const char *component_name)
{
if (NULL == component_name) {
return NULL;
}
char *name = pmix_mca_base_alias_generate_name(project, framework, component_name);
assert(NULL != name);
const pmix_mca_base_alias_t *alias = pmix_mca_base_alias_lookup_internal(name);
free(name);
return alias;
}