Skip to content

Commit d6e90f2

Browse files
committed
Merge pull request #1483 from hjelmn/flag_enum_2
RFC: Add support for flag enumerators for MCA variables
2 parents 2410275 + 7572c8b commit d6e90f2

File tree

8 files changed

+376
-61
lines changed

8 files changed

+376
-61
lines changed

ompi/info/info.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,15 +275,17 @@ int ompi_info_set (ompi_info_t *info, const char *key, const char *value)
275275
int ompi_info_set_value_enum (ompi_info_t *info, const char *key, int value,
276276
mca_base_var_enum_t *var_enum)
277277
{
278-
const char *string_value;
278+
char *string_value;
279279
int ret;
280280

281281
ret = var_enum->string_from_value (var_enum, value, &string_value);
282282
if (OPAL_SUCCESS != ret) {
283283
return ret;
284284
}
285285

286-
return ompi_info_set (info, key, string_value);
286+
ret = ompi_info_set (info, key, string_value);
287+
free (string_value);
288+
return ret;
287289
}
288290

289291

opal/mca/base/mca_base_var.c

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ int mca_base_var_register (const char *project_name, const char *framework_name,
15261526
mca_base_var_scope_t scope, void *storage)
15271527
{
15281528
/* Only integer variables can have enumerator */
1529-
assert (NULL == enumerator || MCA_BASE_VAR_TYPE_INT == type);
1529+
assert (NULL == enumerator || (MCA_BASE_VAR_TYPE_INT == type || MCA_BASE_VAR_TYPE_UNSIGNED_INT == type));
15301530

15311531
return register_variable (project_name, framework_name, component_name,
15321532
variable_name, description, type, enumerator,
@@ -1927,7 +1927,6 @@ static char *source_name(mca_base_var_t *var)
19271927
static int var_value_string (mca_base_var_t *var, char **value_string)
19281928
{
19291929
const mca_base_var_storage_t *value;
1930-
const char *tmp;
19311930
int ret;
19321931

19331932
assert (MCA_BASE_VAR_TYPE_MAX > var->mbv_type);
@@ -1974,19 +1973,14 @@ static int var_value_string (mca_base_var_t *var, char **value_string)
19741973
} else {
19751974
/* we use an enumerator to handle string->bool and bool->string conversion */
19761975
if (MCA_BASE_VAR_TYPE_BOOL == var->mbv_type) {
1977-
ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->boolval, &tmp);
1976+
ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->boolval, value_string);
19781977
} else {
1979-
ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->intval, &tmp);
1978+
ret = var->mbv_enumerator->string_from_value(var->mbv_enumerator, value->intval, value_string);
19801979
}
19811980

19821981
if (OPAL_SUCCESS != ret) {
19831982
return ret;
19841983
}
1985-
1986-
*value_string = strdup (tmp);
1987-
if (NULL == *value_string) {
1988-
ret = OPAL_ERR_OUT_OF_RESOURCE;
1989-
}
19901984
}
19911985

19921986
return ret;

opal/mca/base/mca_base_var_enum.c

Lines changed: 239 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#include "opal/mca/base/mca_base_var_enum.h"
2626
#include "opal/mca/base/base.h"
27+
#include "opal/util/argv.h"
2728

2829
#include <stdio.h>
2930
#include <string.h>
@@ -34,6 +35,11 @@ static void mca_base_var_enum_destructor (mca_base_var_enum_t *enumerator);
3435
OBJ_CLASS_INSTANCE(mca_base_var_enum_t, opal_object_t, mca_base_var_enum_constructor,
3536
mca_base_var_enum_destructor);
3637

38+
static void mca_base_var_enum_flag_constructor (mca_base_var_enum_flag_t *enumerator);
39+
static void mca_base_var_enum_flag_destructor (mca_base_var_enum_flag_t *enumerator);
40+
OBJ_CLASS_INSTANCE(mca_base_var_enum_flag_t, opal_object_t, mca_base_var_enum_flag_constructor,
41+
mca_base_var_enum_flag_destructor);
42+
3743
static int enum_dump (mca_base_var_enum_t *self, char **out);
3844
static int enum_get_count (mca_base_var_enum_t *self, int *count);
3945
static int enum_get_value (mca_base_var_enum_t *self, int index, int *value, const char **string_value);
@@ -85,10 +91,10 @@ static int mca_base_var_enum_bool_vfs (mca_base_var_enum_t *self, const char *st
8591
}
8692

8793
static int mca_base_var_enum_bool_sfv (mca_base_var_enum_t *self, const int value,
88-
const char **string_value)
94+
char **string_value)
8995
{
9096
if (string_value) {
91-
*string_value = value ? "true" : "false";
97+
*string_value = strdup (value ? "true" : "false");
9298
}
9399

94100
return OPAL_SUCCESS;
@@ -155,24 +161,26 @@ static int mca_base_var_enum_verbose_vfs (mca_base_var_enum_t *self, const char
155161
}
156162

157163
static int mca_base_var_enum_verbose_sfv (mca_base_var_enum_t *self, const int value,
158-
const char **string_value)
164+
char **string_value)
159165
{
160-
static char buffer[4];
166+
int ret;
161167

162168
if (value < 0 || value > 100) {
163169
return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
164170
}
165171

166172
for (int i = 0 ; verbose_values[i].string ; ++i) {
167173
if (verbose_values[i].value == value) {
168-
*string_value = verbose_values[i].string;
174+
*string_value = strdup (verbose_values[i].string);
169175
return OPAL_SUCCESS;
170176
}
171177
}
172178

173-
snprintf (buffer, 4, "%d", value);
174179
if (string_value) {
175-
*string_value = buffer;
180+
ret = asprintf (string_value, "%d", value);
181+
if (0 > ret) {
182+
return OPAL_ERR_OUT_OF_RESOURCE;
183+
}
176184
}
177185

178186
return OPAL_SUCCESS;
@@ -251,6 +259,52 @@ int mca_base_var_enum_create (const char *name, const mca_base_var_enum_value_t
251259
return OPAL_SUCCESS;
252260
}
253261

262+
int mca_base_var_enum_create_flag (const char *name, const mca_base_var_enum_value_flag_t *flags, mca_base_var_enum_flag_t **enumerator)
263+
{
264+
mca_base_var_enum_flag_t *new_enum;
265+
int i;
266+
267+
*enumerator = NULL;
268+
269+
new_enum = OBJ_NEW(mca_base_var_enum_flag_t);
270+
if (NULL == new_enum) {
271+
return OPAL_ERR_OUT_OF_RESOURCE;
272+
}
273+
274+
new_enum->super.enum_name = strdup (name);
275+
if (NULL == new_enum->super.enum_name) {
276+
return OPAL_ERR_OUT_OF_RESOURCE;
277+
}
278+
279+
for (i = 0 ; flags[i].string ; ++i);
280+
new_enum->super.enum_value_count = i;
281+
282+
/* make a copy of the values */
283+
new_enum->enum_flags = calloc (new_enum->super.enum_value_count + 1, sizeof (*new_enum->enum_flags));
284+
if (NULL == new_enum->enum_flags) {
285+
OBJ_RELEASE(new_enum);
286+
return OPAL_ERR_OUT_OF_RESOURCE;
287+
}
288+
289+
int all_flags = 0;
290+
for (i = 0 ; i < new_enum->super.enum_value_count ; ++i) {
291+
new_enum->enum_flags[i].flag = flags[i].flag;
292+
new_enum->enum_flags[i].string = strdup (flags[i].string);
293+
new_enum->enum_flags[i].conflicting_flag = flags[i].conflicting_flag;
294+
/* ensure flags are only set a single bit, doesn't conflict with itself, and
295+
* hasn't already been specified. */
296+
assert (!(flags[i].flag & (flags[i].flag - 1)));
297+
assert (!(flags[i].flag & flags[i].conflicting_flag));
298+
assert (!(all_flags & flags[i].flag));
299+
assert (flags[i].flag);
300+
all_flags |= flags[i].flag;
301+
}
302+
303+
*enumerator = new_enum;
304+
305+
return OPAL_SUCCESS;
306+
}
307+
254308
static int enum_dump (mca_base_var_enum_t *self, char **out)
255309
{
256310
int i;
@@ -301,7 +355,7 @@ static int enum_get_value (mca_base_var_enum_t *self, int index, int *value, con
301355
}
302356

303357
if (string_value) {
304-
*string_value = self->enum_values[index].string;
358+
*string_value = strdup (self->enum_values[index].string);
305359
}
306360

307361
return OPAL_SUCCESS;
@@ -338,7 +392,7 @@ static int enum_value_from_string(mca_base_var_enum_t *self, const char *string_
338392
return OPAL_SUCCESS;
339393
}
340394

341-
static int enum_string_from_value(mca_base_var_enum_t *self, const int value, const char **string_value) {
395+
static int enum_string_from_value(mca_base_var_enum_t *self, const int value, char **string_value) {
342396
int count, ret, i;
343397

344398
ret = self->get_count(self, &count);
@@ -357,7 +411,7 @@ static int enum_string_from_value(mca_base_var_enum_t *self, const int value, co
357411
}
358412

359413
if (string_value) {
360-
*string_value = self->enum_values[i].string;
414+
*string_value = strdup (self->enum_values[i].string);
361415
}
362416

363417
return OPAL_SUCCESS;
@@ -389,3 +443,178 @@ static void mca_base_var_enum_destructor (mca_base_var_enum_t *enumerator)
389443
free (enumerator->enum_values);
390444
}
391445
}
446+
447+
static int enum_get_value_flag (mca_base_var_enum_t *self, int index, int *value, const char **string_value)
448+
{
449+
mca_base_var_enum_flag_t *flag_enum = (mca_base_var_enum_flag_t *) self;
450+
int count, ret;
451+
452+
ret = self->get_count(self, &count);
453+
if (OPAL_SUCCESS != ret) {
454+
return ret;
455+
}
456+
457+
if (index >= count) {
458+
return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
459+
}
460+
461+
if (value) {
462+
*value = flag_enum->enum_flags[index].flag;
463+
}
464+
465+
if (string_value) {
466+
*string_value = strdup (flag_enum->enum_flags[index].string);
467+
}
468+
469+
return OPAL_SUCCESS;
470+
}
471+
472+
static int enum_value_from_string_flag (mca_base_var_enum_t *self, const char *string_value, int *value_out) {
473+
mca_base_var_enum_flag_t *flag_enum = (mca_base_var_enum_flag_t *) self;
474+
int value, count, ret, flag;
475+
char **flags;
476+
bool is_int;
477+
char *tmp;
478+
479+
ret = self->get_count(self, &count);
480+
if (OPAL_SUCCESS != ret) {
481+
return ret;
482+
}
483+
484+
flags = opal_argv_split (string_value, ',');
485+
if (NULL == flags) {
486+
return OPAL_ERR_BAD_PARAM;
487+
}
488+
489+
flag = 0;
490+
491+
for (int i = 0 ; flags[i] ; ++i) {
492+
value = strtol (flags[i], &tmp, 0);
493+
is_int = tmp[0] == '\0';
494+
495+
bool found = false, conflict = false;
496+
for (int j = 0 ; j < count ; ++j) {
497+
if ((is_int && (value == flag_enum->enum_flags[i].flag)) ||
498+
0 == strcasecmp (flags[i], flag_enum->enum_flags[i].string)) {
499+
found = true;
500+
501+
if (flag & flag_enum->enum_flags[i].conflicting_flag) {
502+
conflict = true;
503+
} else {
504+
flag |= flag_enum->enum_flags[i].flag;
505+
}
506+
507+
break;
508+
}
509+
}
510+
511+
if (!found || conflict) {
512+
opal_argv_free (flags);
513+
return !found ? OPAL_ERR_VALUE_OUT_OF_BOUNDS : OPAL_ERR_BAD_PARAM;
514+
}
515+
}
516+
517+
*value_out = flag;
518+
519+
return OPAL_SUCCESS;
520+
}
521+
522+
static int enum_string_from_value_flag (mca_base_var_enum_t *self, const int value, char **string_value) {
523+
mca_base_var_enum_flag_t *flag_enum = (mca_base_var_enum_flag_t *) self;
524+
int count, ret, current;
525+
char *out = NULL, *tmp;
526+
527+
ret = self->get_count(self, &count);
528+
if (OPAL_SUCCESS != ret) {
529+
return ret;
530+
}
531+
532+
current = value;
533+
for (int i = 0 ; i < count ; ++i) {
534+
if (!(flag_enum->enum_flags[i].flag & current)) {
535+
continue;
536+
}
537+
538+
tmp = out;
539+
540+
ret = asprintf (&out, "%s%s%s", tmp ? tmp : "", tmp ? "," : "", flag_enum->enum_flags[i].string);
541+
free (tmp);
542+
543+
if (0 > ret) {
544+
return OPAL_ERR_OUT_OF_RESOURCE;
545+
}
546+
547+
if (value & flag_enum->enum_flags[i].conflicting_flag) {
548+
free (out);
549+
return OPAL_ERR_BAD_PARAM;
550+
}
551+
552+
current &= ~flag_enum->enum_flags[i].flag;
553+
}
554+
555+
if (current) {
556+
free (out);
557+
return OPAL_ERR_VALUE_OUT_OF_BOUNDS;
558+
}
559+
560+
if (string_value) {
561+
*string_value = out ? out : strdup ("");
562+
} else {
563+
free (out);
564+
}
565+
566+
return OPAL_SUCCESS;
567+
}
568+
569+
static int enum_dump_flag (mca_base_var_enum_t *self, char **out)
570+
{
571+
mca_base_var_enum_flag_t *flag_enum = (mca_base_var_enum_flag_t *) self;
572+
char *tmp;
573+
int ret;
574+
575+
*out = NULL;
576+
577+
if (NULL == self) {
578+
return OPAL_ERROR;
579+
}
580+
581+
*out = strdup ("Comma-delimited list of: ");
582+
if (NULL == *out) {
583+
return OPAL_ERR_OUT_OF_RESOURCE;
584+
}
585+
586+
for (int i = 0; i < self->enum_value_count ; ++i) {
587+
tmp = *out;
588+
589+
ret = asprintf (out, "%s%s0x%x:\"%s\"", tmp, i ? ", " : " ", flag_enum->enum_flags[i].flag,
590+
flag_enum->enum_flags[i].string);
591+
free (tmp);
592+
if (0 > ret) {
593+
return OPAL_ERR_OUT_OF_RESOURCE;
594+
}
595+
}
596+
597+
return OPAL_SUCCESS;
598+
}
599+
600+
static void mca_base_var_enum_flag_constructor (mca_base_var_enum_flag_t *enumerator)
601+
{
602+
enumerator->enum_flags = NULL;
603+
enumerator->super.get_value = enum_get_value_flag;
604+
enumerator->super.get_count = enum_get_count;
605+
enumerator->super.value_from_string = enum_value_from_string_flag;
606+
enumerator->super.string_from_value = enum_string_from_value_flag;
607+
enumerator->super.dump = enum_dump_flag;
608+
enumerator->super.enum_is_static = false;
609+
}
610+
611+
static void mca_base_var_enum_flag_destructor (mca_base_var_enum_flag_t *enumerator)
612+
{
613+
/* release the copy of the values */
614+
if (enumerator->enum_flags) {
615+
for (int i = 0 ; i < enumerator->super.enum_value_count ; ++i) {
616+
free ((void *) enumerator->enum_flags[i].string);
617+
}
618+
free (enumerator->enum_flags);
619+
}
620+
}

0 commit comments

Comments
 (0)