-
Notifications
You must be signed in to change notification settings - Fork 861
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mca/base: add a new MCA variable type for include lists
It is not uncommon in Open MPI to register a string variable to allow specifying an exclude or exclude list (every framework registers one). Given this common patten it is worthwhile to formalize an MCA include list variable type: MCA_BASE_VAR_TYPE_INCLUDE_LIST. Variables of this type use a new opal object (mca_base_var_include_list_t) that stores and argv-style array and an exclude- list flag. To register an include list variable the caller must first either OBJ_CONSTRUCT the object or allocate it with OBJ_NEW. Variables of this type are exposed as strings to MPI_T. Signed-off-by: Nathan Hjelm <[email protected]>
- Loading branch information
Showing
15 changed files
with
910 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ | ||
/* | ||
* Copyright (c) 2024 Google, LLC. All rights reserved. | ||
* $COPYRIGHT$ | ||
* | ||
* Additional copyrights may follow | ||
* | ||
* $HEADER$ | ||
*/ | ||
|
||
#include <regex.h> | ||
|
||
#include "opal_config.h" | ||
|
||
#include "opal/class/opal_include_list.h" | ||
#include "opal/class/opal_object.h" | ||
#include "opal/include/opal/constants.h" | ||
#include "opal/mca/base/base.h" | ||
#include "opal/util/argv.h" | ||
#include "opal/util/output.h" | ||
#include "opal/util/printf.h" | ||
|
||
static void include_list_destructor(opal_include_list_t *p); | ||
|
||
static int opal_include_list_deserialize(opal_include_list_t *object, const char *value) | ||
{ | ||
/* release any current value and set to defaults */ | ||
include_list_destructor(object); | ||
|
||
if (NULL == value || 0 == strlen(value)) { | ||
return OPAL_SUCCESS; | ||
} | ||
|
||
if ('^' == value[0]) { | ||
object->is_exclude = true; | ||
++value; | ||
} | ||
|
||
object->items = opal_argv_split(value, ','); | ||
return OPAL_SUCCESS; | ||
} | ||
|
||
static char *opal_include_list_serialize(const opal_include_list_t *object) | ||
{ | ||
if (NULL == object->items) { | ||
return strdup(""); | ||
} | ||
|
||
char *tmp = opal_argv_join(object->items, ','); | ||
if (object->is_exclude) { | ||
char *value_str = NULL; | ||
(void) opal_asprintf(&value_str, "^%s", tmp); | ||
free(tmp); | ||
return value_str; | ||
} | ||
|
||
return tmp; | ||
} | ||
|
||
static bool opal_include_list_is_set(const opal_include_list_t *object) | ||
{ | ||
return (object->items != NULL); | ||
} | ||
|
||
static void include_list_contructor(opal_include_list_t *p) | ||
{ | ||
p->super.deserialize = (opal_serializable_deserialize_fn_t)opal_include_list_deserialize; | ||
p->super.serialize = (opal_serializable_serialize_fn_t)opal_include_list_serialize; | ||
p->super.is_set = (opal_serializable_is_set_fn_t)opal_include_list_is_set; | ||
p->items = NULL; | ||
p->is_exclude = false; | ||
} | ||
|
||
static void include_list_destructor(opal_include_list_t *p) | ||
{ | ||
opal_argv_free(p->items); | ||
include_list_contructor(p); | ||
} | ||
|
||
OBJ_CLASS_INSTANCE(opal_include_list_t, opal_object_t, include_list_contructor, | ||
include_list_destructor); | ||
|
||
static int include_list_match_regex(opal_include_list_t *include_list, const char *value, | ||
bool case_sensitive) | ||
{ | ||
int regex_flags = REG_EXTENDED | REG_NOSUB; | ||
regex_t regex; | ||
|
||
if (!case_sensitive) { | ||
regex_flags |= REG_ICASE; | ||
} | ||
|
||
for (int i = 0 ; include_list->items[i] ; ++i) { | ||
int rc = regcomp(®ex, include_list->items[i], regex_flags); | ||
if (rc != 0) { | ||
/* incorrectly formatted regular expression */ | ||
opal_output_verbose(MCA_BASE_VERBOSE_WARN, 0, "error compiling regular expression: %s, " | ||
"ignoring", include_list->items[i]); | ||
continue; | ||
} | ||
|
||
rc = regexec(®ex, value, /*nmatch=*/0, /*pmatch=*/NULL, /*eflags=*/0); | ||
regfree(®ex); | ||
if (0 == rc) { | ||
return (include_list->is_exclude ? -1 : 1) * (i + 1); | ||
} | ||
} | ||
|
||
return include_list->is_exclude ? 1 : -1; | ||
} | ||
|
||
static int include_list_match(opal_include_list_t *include_list, const char *value, | ||
bool case_sensitive) | ||
{ | ||
for (int i = 0 ; include_list->items[i] ; ++i) { | ||
bool match = false; | ||
if (case_sensitive) { | ||
if (0 == strcmp(include_list->items[i], value)) { | ||
match = true; | ||
} | ||
} else if (0 == strcasecmp(include_list->items[i], value)) { | ||
match = true; | ||
} | ||
|
||
if (match) { | ||
return (include_list->is_exclude ? -1 : 1) * (i + 1); | ||
} | ||
} | ||
|
||
return include_list->is_exclude ? 1 : -1; | ||
} | ||
|
||
int opal_include_list_match(opal_include_list_t *include_list, const char *value, | ||
bool regex_match, bool case_sensitive) | ||
{ | ||
if (include_list == NULL || value == NULL || include_list->items == NULL) { | ||
opal_output_verbose(MCA_BASE_VERBOSE_ERROR, 0, "error matching in include list"); | ||
return -1; | ||
} | ||
|
||
if (regex_match) { | ||
return include_list_match_regex(include_list, value, case_sensitive); | ||
} | ||
|
||
return include_list_match(include_list, value, case_sensitive); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ | ||
/* | ||
* Copyright (c) 2024 Google, LLC. All rights reserved. | ||
* $COPYRIGHT$ | ||
* | ||
* Additional copyrights may follow | ||
* | ||
* $HEADER$ | ||
*/ | ||
|
||
#if !defined(OPAL_INCLUDE_LIST_H) | ||
#define OPAL_INCLUDE_LIST_H | ||
|
||
#include "opal_config.h" | ||
#include "opal/class/opal_object.h" | ||
#include "opal/class/opal_serializable.h" | ||
|
||
/** | ||
* An include list. These are strings of the form: | ||
* foo,bar,baz (include) | ||
* ^foo,bar,baz (exclude) | ||
*/ | ||
struct opal_include_list { | ||
opal_serializable_t super; | ||
/** argv array of items */ | ||
char **items; | ||
/** is this an exclude list */ | ||
bool is_exclude; | ||
}; | ||
typedef struct opal_include_list opal_include_list_t; | ||
|
||
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_include_list_t); | ||
|
||
/** | ||
* Match a string against the include list and return the list rank. | ||
* | ||
* @param[in] include_list Include list | ||
* @param[in] value Value to match | ||
* @param[in] regex_match Treat the entries in the include list as regular expressions | ||
* @param[in] case_sensitive Make matching case sensitive | ||
* | ||
* This method searches the include list for value. If an entry matches then the rank of the | ||
* include list match is returned. A negative number is returned if the list is an exclude | ||
* list. | ||
*/ | ||
OPAL_DECLSPEC int opal_include_list_match(opal_include_list_t *include_list, const char *value, | ||
bool regex_match, bool case_sensitive); | ||
|
||
|
||
#endif /* OPAL_INCLUDE_LIST_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ | ||
/* | ||
* Copyright (c) 2024 Google, LLC. All rights reserved. | ||
* $COPYRIGHT$ | ||
* | ||
* Additional copyrights may follow | ||
* | ||
* $HEADER$ | ||
*/ | ||
|
||
#include <regex.h> | ||
|
||
#include "opal_config.h" | ||
|
||
#include "opal/class/opal_include_list.h" | ||
#include "opal/class/opal_object.h" | ||
#include "opal/include/opal/constants.h" | ||
#include "opal/mca/base/base.h" | ||
#include "opal/util/argv.h" | ||
#include "opal/util/output.h" | ||
|
||
static int opal_serializable_deserialize(opal_serializable_t *object, const char *value) | ||
{ | ||
(void)object; | ||
(void)value; | ||
return OPAL_ERR_NOT_IMPLEMENTED; | ||
} | ||
|
||
static char *opal_serializable_serialize(const opal_serializable_t *object) | ||
{ | ||
(void)object; | ||
return NULL; | ||
} | ||
|
||
static bool opal_serializable_is_set(const opal_serializable_t *object) | ||
{ | ||
(void)object; | ||
return false; | ||
} | ||
|
||
static void opal_serializable_constructor(opal_serializable_t *p) | ||
{ | ||
p->deserialize = opal_serializable_deserialize; | ||
p->serialize = opal_serializable_serialize; | ||
p->is_set = opal_serializable_is_set; | ||
} | ||
|
||
static void opal_serializable_destructor(opal_serializable_t *p) | ||
{ | ||
} | ||
|
||
OBJ_CLASS_INSTANCE(opal_serializable_t, opal_object_t, opal_serializable_constructor, | ||
opal_serializable_destructor); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ | ||
/* | ||
* Copyright (c) 2024 Google, LLC. All rights reserved. | ||
* $COPYRIGHT$ | ||
* | ||
* Additional copyrights may follow | ||
* | ||
* $HEADER$ | ||
*/ | ||
|
||
#if !defined(OPAL_SERIALIZABLE_H) | ||
#define OPAL_SERIALIZABLE_H | ||
|
||
#include "opal_config.h" | ||
#include "opal/class/opal_object.h" | ||
|
||
struct opal_serializable; | ||
typedef struct opal_serializable opal_serializable_t; | ||
|
||
typedef int (*opal_serializable_deserialize_fn_t)(opal_serializable_t *object, const char *value); | ||
typedef char *(*opal_serializable_serialize_fn_t)(const opal_serializable_t *object); | ||
typedef bool (*opal_serializable_is_set_fn_t)(const opal_serializable_t *object); | ||
|
||
struct opal_serializable { | ||
opal_object_t super; | ||
/** de-serialize the object from a string */ | ||
opal_serializable_deserialize_fn_t deserialize; | ||
/** serialize the object into a string */ | ||
opal_serializable_serialize_fn_t serialize; | ||
/** object has a value set */ | ||
opal_serializable_is_set_fn_t is_set; | ||
}; | ||
|
||
OPAL_DECLSPEC OBJ_CLASS_DECLARATION(opal_serializable_t); | ||
|
||
#endif /* OPAL_SERIALIZABLE_H */ |
Oops, something went wrong.