/* * Copyright (c) 2014-2018 Intel, Inc. All rights reserved. * Copyright (c) 2014-2017 Research Organization for Information Science * and Technology (RIST). All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ */ #include "orte_config.h" #include "orte/types.h" #include "orte/constants.h" #include "opal/dss/dss.h" #include "opal/util/output.h" #include "orte/mca/errmgr/errmgr.h" #include "orte/util/attr.h" #define MAX_CONVERTERS 5 #define MAX_CONVERTER_PROJECT_LEN 10 typedef struct { int init; char project[MAX_CONVERTER_PROJECT_LEN]; orte_attribute_key_t key_base; orte_attribute_key_t key_max; orte_attr2str_fn_t converter; } orte_attr_converter_t; /* all default to NULL */ static orte_attr_converter_t converters[MAX_CONVERTERS]; bool orte_get_attribute(opal_list_t *attributes, orte_attribute_key_t key, void **data, opal_data_type_t type) { orte_attribute_t *kv; int rc; OPAL_LIST_FOREACH(kv, attributes, orte_attribute_t) { if (key == kv->key) { if (kv->type != type) { ORTE_ERROR_LOG(ORTE_ERR_TYPE_MISMATCH); return false; } if (NULL != data) { if (ORTE_SUCCESS != (rc = orte_attr_unload(kv, data, type))) { ORTE_ERROR_LOG(rc); } } return true; } } /* not found */ return false; } int orte_set_attribute(opal_list_t *attributes, orte_attribute_key_t key, bool local, void *data, opal_data_type_t type) { orte_attribute_t *kv; int rc; OPAL_LIST_FOREACH(kv, attributes, orte_attribute_t) { if (key == kv->key) { if (kv->type != type) { return ORTE_ERR_TYPE_MISMATCH; } if (ORTE_SUCCESS != (rc = orte_attr_load(kv, data, type))) { ORTE_ERROR_LOG(rc); } return rc; } } /* not found - add it */ kv = OBJ_NEW(orte_attribute_t); kv->key = key; kv->local = local; if (OPAL_SUCCESS != (rc = orte_attr_load(kv, data, type))) { OBJ_RELEASE(kv); return rc; } opal_list_append(attributes, &kv->super); return ORTE_SUCCESS; } orte_attribute_t* orte_fetch_attribute(opal_list_t *attributes, orte_attribute_t *prev, orte_attribute_key_t key) { orte_attribute_t *kv, *end, *next; /* if prev is NULL, then find the first attr on the list * that matches the key */ if (NULL == prev) { OPAL_LIST_FOREACH(kv, attributes, orte_attribute_t) { if (key == kv->key) { return kv; } } /* if we get, then the key isn't on the list */ return NULL; } /* if we are at the end of the list, then nothing to do */ end = (orte_attribute_t*)opal_list_get_end(attributes); if (prev == end || end == (orte_attribute_t*)opal_list_get_next(&prev->super) || NULL == opal_list_get_next(&prev->super)) { return NULL; } /* starting with the next item on the list, search * for the next attr with the matching key */ next = (orte_attribute_t*)opal_list_get_next(&prev->super); while (NULL != next) { if (next->key == key) { return next; } next = (orte_attribute_t*)opal_list_get_next(&next->super); } /* if we get here, then no matching key was found */ return NULL; } int orte_add_attribute(opal_list_t *attributes, orte_attribute_key_t key, bool local, void *data, opal_data_type_t type) { orte_attribute_t *kv; int rc; kv = OBJ_NEW(orte_attribute_t); kv->key = key; kv->local = local; if (OPAL_SUCCESS != (rc = orte_attr_load(kv, data, type))) { OBJ_RELEASE(kv); return rc; } opal_list_append(attributes, &kv->super); return ORTE_SUCCESS; } int orte_prepend_attribute(opal_list_t *attributes, orte_attribute_key_t key, bool local, void *data, opal_data_type_t type) { orte_attribute_t *kv; int rc; kv = OBJ_NEW(orte_attribute_t); kv->key = key; kv->local = local; if (OPAL_SUCCESS != (rc = orte_attr_load(kv, data, type))) { OBJ_RELEASE(kv); return rc; } opal_list_prepend(attributes, &kv->super); return ORTE_SUCCESS; } void orte_remove_attribute(opal_list_t *attributes, orte_attribute_key_t key) { orte_attribute_t *kv; OPAL_LIST_FOREACH(kv, attributes, orte_attribute_t) { if (key == kv->key) { opal_list_remove_item(attributes, &kv->super); OBJ_RELEASE(kv); return; } } } int orte_attr_register(const char *project, orte_attribute_key_t key_base, orte_attribute_key_t key_max, orte_attr2str_fn_t converter) { int i; for (i = 0 ; i < MAX_CONVERTERS ; ++i) { if (0 == converters[i].init) { converters[i].init = 1; strncpy(converters[i].project, project, MAX_CONVERTER_PROJECT_LEN); converters[i].project[MAX_CONVERTER_PROJECT_LEN-1] = '\0'; converters[i].key_base = key_base; converters[i].key_max = key_max; converters[i].converter = converter; return ORTE_SUCCESS; } } return ORTE_ERR_OUT_OF_RESOURCE; } const char *orte_attr_key_to_str(orte_attribute_key_t key) { int i; if (ORTE_ATTR_KEY_BASE < key && key < ORTE_ATTR_KEY_MAX) { /* belongs to ORTE, so we handle it */ switch(key) { case ORTE_APP_HOSTFILE: return "APP-HOSTFILE"; case ORTE_APP_ADD_HOSTFILE: return "APP-ADD-HOSTFILE"; case ORTE_APP_DASH_HOST: return "APP-DASH-HOST"; case ORTE_APP_ADD_HOST: return "APP-ADD-HOST"; case ORTE_APP_USER_CWD: return "APP-USER-CWD"; case ORTE_APP_SSNDIR_CWD: return "APP-USE-SESSION-DIR-AS-CWD"; case ORTE_APP_PRELOAD_BIN: return "APP-PRELOAD-BIN"; case ORTE_APP_PRELOAD_FILES: return "APP-PRELOAD-FILES"; case ORTE_APP_SSTORE_LOAD: return "APP-SSTORE-LOAD"; case ORTE_APP_RECOV_DEF: return "APP-RECOVERY-DEFINED"; case ORTE_APP_MAX_RESTARTS: return "APP-MAX-RESTARTS"; case ORTE_APP_MIN_NODES: return "APP-MIN-NODES"; case ORTE_APP_MANDATORY: return "APP-NODES-MANDATORY"; case ORTE_APP_MAX_PPN: return "APP-MAX-PPN"; case ORTE_APP_PREFIX_DIR: return "APP-PREFIX-DIR"; case ORTE_APP_NO_CACHEDIR: return "ORTE_APP_NO_CACHEDIR"; case ORTE_APP_SET_ENVAR: return "ORTE_APP_SET_ENVAR"; case ORTE_APP_UNSET_ENVAR: return "ORTE_APP_UNSET_ENVAR"; case ORTE_APP_PREPEND_ENVAR: return "ORTE_APP_PREPEND_ENVAR"; case ORTE_APP_APPEND_ENVAR: return "ORTE_APP_APPEND_ENVAR"; case ORTE_APP_ADD_ENVAR: return "ORTE_APP_ADD_ENVAR"; case ORTE_NODE_USERNAME: return "NODE-USERNAME"; case ORTE_NODE_PORT: return "NODE-PORT"; case ORTE_NODE_LAUNCH_ID: return "NODE-LAUNCHID"; case ORTE_NODE_HOSTID: return "NODE-HOSTID"; case ORTE_NODE_ALIAS: return "NODE-ALIAS"; case ORTE_NODE_SERIAL_NUMBER: return "NODE-SERIAL-NUM"; case ORTE_JOB_LAUNCH_MSG_SENT: return "JOB-LAUNCH-MSG-SENT"; case ORTE_JOB_LAUNCH_MSG_RECVD: return "JOB-LAUNCH-MSG-RECVD"; case ORTE_JOB_MAX_LAUNCH_MSG_RECVD: return "JOB-MAX-LAUNCH-MSG-RECVD"; case ORTE_JOB_CKPT_STATE: return "JOB-CKPT-STATE"; case ORTE_JOB_SNAPSHOT_REF: return "JOB-SNAPSHOT-REF"; case ORTE_JOB_SNAPSHOT_LOC: return "JOB-SNAPSHOT-LOC"; case ORTE_JOB_SNAPC_INIT_BAR: return "JOB-SNAPC-INIT-BARRIER-ID"; case ORTE_JOB_SNAPC_FINI_BAR: return "JOB-SNAPC-FINI-BARRIER-ID"; case ORTE_JOB_NUM_NONZERO_EXIT: return "JOB-NUM-NONZERO-EXIT"; case ORTE_JOB_FAILURE_TIMER_EVENT: return "JOB-FAILURE-TIMER-EVENT"; case ORTE_JOB_ABORTED_PROC: return "JOB-ABORTED-PROC"; case ORTE_JOB_MAPPER: return "JOB-MAPPER"; case ORTE_JOB_REDUCER: return "JOB-REDUCER"; case ORTE_JOB_COMBINER: return "JOB-COMBINER"; case ORTE_JOB_INDEX_ARGV: return "JOB-INDEX-ARGV"; case ORTE_JOB_NO_VM: return "JOB-NO-VM"; case ORTE_JOB_SPIN_FOR_DEBUG: return "JOB-SPIN-FOR-DEBUG"; case ORTE_JOB_CONTINUOUS_OP: return "JOB-CONTINUOUS-OP"; case ORTE_JOB_RECOVER_DEFINED: return "JOB-RECOVERY-DEFINED"; case ORTE_JOB_NON_ORTE_JOB: return "JOB-NON-ORTE-JOB"; case ORTE_JOB_STDOUT_TARGET: return "JOB-STDOUT-TARGET"; case ORTE_JOB_POWER: return "JOB-POWER"; case ORTE_JOB_MAX_FREQ: return "JOB-MAX_FREQ"; case ORTE_JOB_MIN_FREQ: return "JOB-MIN_FREQ"; case ORTE_JOB_GOVERNOR: return "JOB-FREQ-GOVERNOR"; case ORTE_JOB_FAIL_NOTIFIED: return "JOB-FAIL-NOTIFIED"; case ORTE_JOB_TERM_NOTIFIED: return "JOB-TERM-NOTIFIED"; case ORTE_JOB_PEER_MODX_ID: return "JOB-PEER-MODX-ID"; case ORTE_JOB_INIT_BAR_ID: return "JOB-INIT-BAR-ID"; case ORTE_JOB_FINI_BAR_ID: return "JOB-FINI-BAR-ID"; case ORTE_JOB_FWDIO_TO_TOOL: return "JOB-FWD-IO-TO-TOOL"; case ORTE_JOB_PHYSICAL_CPUIDS: return "JOB-PHYSICAL-CPUIDS"; case ORTE_JOB_LAUNCHED_DAEMONS: return "JOB-LAUNCHED-DAEMONS"; case ORTE_JOB_REPORT_BINDINGS: return "JOB-REPORT-BINDINGS"; case ORTE_JOB_CPU_LIST: return "JOB-CPU-LIST"; case ORTE_JOB_NOTIFICATIONS: return "JOB-NOTIFICATIONS"; case ORTE_JOB_ROOM_NUM: return "JOB-ROOM-NUM"; case ORTE_JOB_LAUNCH_PROXY: return "JOB-LAUNCH-PROXY"; case ORTE_JOB_NSPACE_REGISTERED: return "JOB-NSPACE-REGISTERED"; case ORTE_JOB_FIXED_DVM: return "ORTE-JOB-FIXED-DVM"; case ORTE_JOB_DVM_JOB: return "ORTE-JOB-DVM-JOB"; case ORTE_JOB_CANCELLED: return "ORTE-JOB-CANCELLED"; case ORTE_JOB_OUTPUT_TO_FILE: return "ORTE-JOB-OUTPUT-TO-FILE"; case ORTE_JOB_MERGE_STDERR_STDOUT: return "ORTE-JOB-MERGE-STDERR-STDOUT"; case ORTE_JOB_TAG_OUTPUT: return "ORTE-JOB-TAG-OUTPUT"; case ORTE_JOB_TIMESTAMP_OUTPUT: return "ORTE-JOB-TIMESTAMP-OUTPUT"; case ORTE_JOB_MULTI_DAEMON_SIM: return "ORTE_JOB_MULTI_DAEMON_SIM"; case ORTE_JOB_NOTIFY_COMPLETION: return "ORTE_JOB_NOTIFY_COMPLETION"; case ORTE_JOB_TRANSPORT_KEY: return "ORTE_JOB_TRANSPORT_KEY"; case ORTE_JOB_INFO_CACHE: return "ORTE_JOB_INFO_CACHE"; case ORTE_JOB_FULLY_DESCRIBED: return "ORTE_JOB_FULLY_DESCRIBED"; case ORTE_JOB_SILENT_TERMINATION: return "ORTE_JOB_SILENT_TERMINATION"; case ORTE_JOB_SET_ENVAR: return "ORTE_JOB_SET_ENVAR"; case ORTE_JOB_UNSET_ENVAR: return "ORTE_JOB_UNSET_ENVAR"; case ORTE_JOB_PREPEND_ENVAR: return "ORTE_JOB_PREPEND_ENVAR"; case ORTE_JOB_APPEND_ENVAR: return "ORTE_JOB_APPEND_ENVAR"; case ORTE_JOB_ADD_ENVAR: return "ORTE_APP_ADD_ENVAR"; case ORTE_JOB_APP_SETUP_DATA: return "ORTE_JOB_APP_SETUP_DATA"; case ORTE_PROC_NOBARRIER: return "PROC-NOBARRIER"; case ORTE_PROC_CPU_BITMAP: return "PROC-CPU-BITMAP"; case ORTE_PROC_HWLOC_LOCALE: return "PROC-HWLOC-LOCALE"; case ORTE_PROC_HWLOC_BOUND: return "PROC-HWLOC-BOUND"; case ORTE_PROC_PRIOR_NODE: return "PROC-PRIOR-NODE"; case ORTE_PROC_NRESTARTS: return "PROC-NUM-RESTARTS"; case ORTE_PROC_RESTART_TIME: return "PROC-RESTART-TIME"; case ORTE_PROC_FAST_FAILS: return "PROC-FAST-FAILS"; case ORTE_PROC_CKPT_STATE: return "PROC-CKPT-STATE"; case ORTE_PROC_SNAPSHOT_REF: return "PROC-SNAPHOT-REF"; case ORTE_PROC_SNAPSHOT_LOC: return "PROC-SNAPSHOT-LOC"; case ORTE_PROC_NODENAME: return "PROC-NODENAME"; case ORTE_PROC_CGROUP: return "PROC-CGROUP"; case ORTE_PROC_NBEATS: return "PROC-NBEATS"; case ORTE_RML_TRANSPORT_TYPE: return "RML-TRANSPORT-TYPE"; case ORTE_RML_PROTOCOL_TYPE: return "RML-PROTOCOL-TYPE"; case ORTE_RML_CONDUIT_ID: return "RML-CONDUIT-ID"; case ORTE_RML_INCLUDE_COMP_ATTRIB: return "RML-INCLUDE"; case ORTE_RML_EXCLUDE_COMP_ATTRIB: return "RML-EXCLUDE"; case ORTE_RML_TRANSPORT_ATTRIB: return "RML-TRANSPORT"; case ORTE_RML_QUALIFIER_ATTRIB: return "RML-QUALIFIER"; case ORTE_RML_PROVIDER_ATTRIB: return "RML-DESIRED-PROVIDERS"; case ORTE_RML_PROTOCOL_ATTRIB: return "RML-DESIRED-PROTOCOLS"; case ORTE_RML_ROUTED_ATTRIB: return "RML-DESIRED-ROUTED-MODULES"; default: return "UNKNOWN-KEY"; } } /* see if one of the converters can handle it */ for (i = 0 ; i < MAX_CONVERTERS ; ++i) { if (0 != converters[i].init) { if (converters[i].key_base < key && key < converters[i].key_max) { return converters[i].converter(key); } } } /* get here if nobody know what to do */ return "UNKNOWN-KEY"; } int orte_attr_load(orte_attribute_t *kv, void *data, opal_data_type_t type) { opal_byte_object_t *boptr; struct timeval *tv; opal_envar_t *envar; kv->type = type; if (NULL == data) { /* if the type is BOOL, then the user wanted to * use the presence of the attribute to indicate * "true" - so let's mark it that way just in * case a subsequent test looks for the value */ if (OPAL_BOOL == type) { kv->data.flag = true; } else { /* otherwise, check to see if this type has storage * that is already allocated, and free it if so */ if (OPAL_STRING == type && NULL != kv->data.string) { free(kv->data.string); } else if (OPAL_BYTE_OBJECT == type && NULL != kv->data.bo.bytes) { free(kv->data.bo.bytes); } /* just set the fields to zero */ memset(&kv->data, 0, sizeof(kv->data)); } return OPAL_SUCCESS; } switch (type) { case OPAL_BOOL: kv->data.flag = *(bool*)(data); break; case OPAL_BYTE: kv->data.byte = *(uint8_t*)(data); break; case OPAL_STRING: if (NULL != kv->data.string) { free(kv->data.string); } if (NULL != data) { kv->data.string = strdup( (const char *) data); } else { kv->data.string = NULL; } break; case OPAL_SIZE: kv->data.size = *(size_t*)(data); break; case OPAL_PID: kv->data.pid = *(pid_t*)(data); break; case OPAL_INT: kv->data.integer = *(int*)(data); break; case OPAL_INT8: kv->data.int8 = *(int8_t*)(data); break; case OPAL_INT16: kv->data.int16 = *(int16_t*)(data); break; case OPAL_INT32: kv->data.int32 = *(int32_t*)(data); break; case OPAL_INT64: kv->data.int64 = *(int64_t*)(data); break; case OPAL_UINT: kv->data.uint = *(unsigned int*)(data); break; case OPAL_UINT8: kv->data.uint8 = *(uint8_t*)(data); break; case OPAL_UINT16: kv->data.uint16 = *(uint16_t*)(data); break; case OPAL_UINT32: kv->data.uint32 = *(uint32_t*)data; break; case OPAL_UINT64: kv->data.uint64 = *(uint64_t*)(data); break; case OPAL_BYTE_OBJECT: if (NULL != kv->data.bo.bytes) { free(kv->data.bo.bytes); } boptr = (opal_byte_object_t*)data; if (NULL != boptr && NULL != boptr->bytes && 0 < boptr->size) { kv->data.bo.bytes = (uint8_t *) malloc(boptr->size); memcpy(kv->data.bo.bytes, boptr->bytes, boptr->size); kv->data.bo.size = boptr->size; } else { kv->data.bo.bytes = NULL; kv->data.bo.size = 0; } break; case OPAL_FLOAT: kv->data.fval = *(float*)(data); break; case OPAL_TIMEVAL: tv = (struct timeval*)data; kv->data.tv.tv_sec = tv->tv_sec; kv->data.tv.tv_usec = tv->tv_usec; break; case OPAL_PTR: kv->data.ptr = data; break; case OPAL_VPID: kv->data.vpid = *(orte_vpid_t *)data; break; case OPAL_JOBID: kv->data.jobid = *(orte_jobid_t *)data; break; case OPAL_NAME: kv->data.name = *(opal_process_name_t *)data; break; case OPAL_ENVAR: OBJ_CONSTRUCT(&kv->data.envar, opal_envar_t); envar = (opal_envar_t*)data; if (NULL != envar->envar) { kv->data.envar.envar = strdup(envar->envar); } if (NULL != envar->value) { kv->data.envar.value = strdup(envar->value); } kv->data.envar.separator = envar->separator; break; default: OPAL_ERROR_LOG(OPAL_ERR_NOT_SUPPORTED); return OPAL_ERR_NOT_SUPPORTED; } return OPAL_SUCCESS; } int orte_attr_unload(orte_attribute_t *kv, void **data, opal_data_type_t type) { opal_byte_object_t *boptr; opal_envar_t *envar; if (type != kv->type) { return OPAL_ERR_TYPE_MISMATCH; } if (NULL == data || (OPAL_STRING != type && OPAL_BYTE_OBJECT != type && OPAL_BUFFER != type && OPAL_PTR != type && NULL == *data)) { assert(0); OPAL_ERROR_LOG(OPAL_ERR_BAD_PARAM); return OPAL_ERR_BAD_PARAM; } switch (type) { case OPAL_BOOL: memcpy(*data, &kv->data.flag, sizeof(bool)); break; case OPAL_BYTE: memcpy(*data, &kv->data.byte, sizeof(uint8_t)); break; case OPAL_STRING: if (NULL != kv->data.string) { *data = strdup(kv->data.string); } else { *data = NULL; } break; case OPAL_SIZE: memcpy(*data, &kv->data.size, sizeof(size_t)); break; case OPAL_PID: memcpy(*data, &kv->data.pid, sizeof(pid_t)); break; case OPAL_INT: memcpy(*data, &kv->data.integer, sizeof(int)); break; case OPAL_INT8: memcpy(*data, &kv->data.int8, sizeof(int8_t)); break; case OPAL_INT16: memcpy(*data, &kv->data.int16, sizeof(int16_t)); break; case OPAL_INT32: memcpy(*data, &kv->data.int32, sizeof(int32_t)); break; case OPAL_INT64: memcpy(*data, &kv->data.int64, sizeof(int64_t)); break; case OPAL_UINT: memcpy(*data, &kv->data.uint, sizeof(unsigned int)); break; case OPAL_UINT8: memcpy(*data, &kv->data.uint8, 1); break; case OPAL_UINT16: memcpy(*data, &kv->data.uint16, 2); break; case OPAL_UINT32: memcpy(*data, &kv->data.uint32, 4); break; case OPAL_UINT64: memcpy(*data, &kv->data.uint64, 8); break; case OPAL_BYTE_OBJECT: boptr = (opal_byte_object_t*)malloc(sizeof(opal_byte_object_t)); if (NULL != kv->data.bo.bytes && 0 < kv->data.bo.size) { boptr->bytes = (uint8_t *) malloc(kv->data.bo.size); memcpy(boptr->bytes, kv->data.bo.bytes, kv->data.bo.size); boptr->size = kv->data.bo.size; } else { boptr->bytes = NULL; boptr->size = 0; } *data = boptr; break; case OPAL_BUFFER: *data = OBJ_NEW(opal_buffer_t); opal_dss.copy_payload(*data, &kv->data.buf); break; case OPAL_FLOAT: memcpy(*data, &kv->data.fval, sizeof(float)); break; case OPAL_TIMEVAL: memcpy(*data, &kv->data.tv, sizeof(struct timeval)); break; case OPAL_PTR: *data = kv->data.ptr; break; case OPAL_VPID: memcpy(*data, &kv->data.vpid, sizeof(orte_vpid_t)); break; case OPAL_JOBID: memcpy(*data, &kv->data.jobid, sizeof(orte_jobid_t)); break; case OPAL_NAME: memcpy(*data, &kv->data.name, sizeof(orte_process_name_t)); break; case OPAL_ENVAR: envar = OBJ_NEW(opal_envar_t); if (NULL != kv->data.envar.envar) { envar->envar = strdup(kv->data.envar.envar); } if (NULL != kv->data.envar.value) { envar->value = strdup(kv->data.envar.value); } envar->separator = kv->data.envar.separator; *data = envar; break; default: OPAL_ERROR_LOG(OPAL_ERR_NOT_SUPPORTED); return OPAL_ERR_NOT_SUPPORTED; } return OPAL_SUCCESS; }