Skip to content
Draft
54 changes: 54 additions & 0 deletions src/ucp/core/ucp_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <ucs/debug/debug_int.h>
#include <ucs/sys/compiler.h>
#include <ucs/sys/string.h>
#include <ucs/type/init_once.h>
#include <ucs/vfs/base/vfs_cb.h>
#include <ucs/vfs/base/vfs_obj.h>
#include <string.h>
Expand Down Expand Up @@ -863,6 +864,47 @@ ucs_status_t ucp_config_modify_internal(ucp_config_t *config, const char *name,
value);
}

static void ucp_config_query_uct_components(void)
{
static ucs_init_once_t init_once = UCS_INIT_ONCE_INITIALIZER;
uct_component_h *components;
unsigned num_components;
ucs_status_t status;

UCS_INIT_ONCE(&init_once) {
status = uct_query_components(&components, &num_components);
if (status == UCS_OK) {
uct_release_component_list(components);
} else {
ucs_warn("failed to query UCT components: %s",
ucs_status_string(status));
}
}
}

static int ucp_config_global_list_has_field(const char *name)
{
const ucs_config_global_list_entry_t *entry;
const char *field_name;
size_t prefix_len;

ucs_list_for_each(entry, &ucs_config_global_list, list) {
field_name = name;
if (entry->prefix != NULL) {
prefix_len = strlen(entry->prefix);
if (!strncmp(entry->prefix, field_name, prefix_len)) {
field_name += prefix_len;
}
}

if (ucs_config_parser_has_field(entry->table, field_name)) {
return 1;
}
}

return 0;
}

ucs_status_t ucp_config_modify(ucp_config_t *config, const char *name,
const char *value)
{
Expand All @@ -878,6 +920,18 @@ ucs_status_t ucp_config_modify(ucp_config_t *config, const char *name,
return status;
}

if (ucs_global_opts_is_unmodifiable(name)) {
ucs_debug("%s configuration cannot be changed, the change is only "
"available through the environment variable",
name);
return UCS_ERR_UNSUPPORTED;
}

ucp_config_query_uct_components();
if (!ucp_config_global_list_has_field(name)) {
return UCS_ERR_NO_ELEM;
}

return ucp_config_cached_key_add(&config->cached_key_list, name, value);
}

Expand Down
5 changes: 5 additions & 0 deletions src/ucs/config/global_opts.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ ucs_status_t ucs_global_opts_set_value_modifiable(const char *name,
NULL, name, value);
}

int ucs_global_opts_is_unmodifiable(const char *name)
{
return ucs_config_parser_has_field(ucs_global_opts_read_only_table, name);
}

ucs_status_t ucs_global_opts_get_value(const char *name, char *value,
size_t max)
{
Expand Down
8 changes: 8 additions & 0 deletions src/ucs/config/global_opts.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,14 @@ ucs_status_t ucs_global_opts_clone(void *dst);
void ucs_global_opts_release(void);
void ucs_global_opts_print(FILE *stream, ucs_config_print_flags_t print_flags);

/**
* Check if a field is unmodifiable.
*
* @param name Field name to check.
* @return 1 if the field is unmodifiable, 0 otherwise.
*/
int ucs_global_opts_is_unmodifiable(const char *name);

END_C_DECLS

#endif
28 changes: 28 additions & 0 deletions src/ucs/config/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2461,3 +2461,31 @@ void ucs_config_parser_cleanup()
})
kh_destroy_inplace(ucs_config_map, &ucs_config_file_vars);
}

int ucs_config_parser_has_field(const ucs_config_field_t *fields,
const char *name)
{
const ucs_config_field_t *field;
size_t table_name_len;

if (!fields || !name) {
return 0;
}

for (field = fields; !ucs_config_field_is_last(field); ++field) {
if (!strncmp(field->name, name, strlen(name))) {
return 1;
}

if (ucs_config_is_table_field(field)) {
table_name_len = strlen(field->name);
if (!strncmp(field->name, name, table_name_len) &&
ucs_config_parser_has_field(field->parser.arg,
name + table_name_len)) {
return 1;
}
}
}

return 0;
}
10 changes: 10 additions & 0 deletions src/ucs/config/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -640,6 +640,16 @@ void ucs_config_parser_get_env_vars(ucs_string_buffer_t *env_strb,
void ucs_config_parser_cleanup(void);


/**
* Check if a field exists in the configuration table.
*
* @param fields Array of fields which define the configuration table.
* @param name Field name to check.
* @return 1 if the field exists, 0 otherwise.
*/
int ucs_config_parser_has_field(const ucs_config_field_t *fields,
const char *name);

END_C_DECLS

#endif
12 changes: 9 additions & 3 deletions test/gtest/ucp/test_ucp_worker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -826,8 +826,13 @@ UCP_INSTANTIATE_TEST_CASE_TLS(test_ucp_worker_address_version, self, "self")
class test_ucp_modify_uct_cfg : public test_ucp_context {
public:
test_ucp_modify_uct_cfg() : m_seg_size((ucs::rand() & 0x3ff) + 1024) {
ucp_config_modify(m_ucp_config, "IB_SEG_SIZE",
ucs::to_string(m_seg_size).c_str());
const auto status = ucp_config_modify(
m_ucp_config, "IB_SEG_SIZE",
ucs::to_string(m_seg_size).c_str());
if (status != UCS_OK) {
UCS_TEST_ABORT("Failed to set IB_SEG_SIZE: " <<
ucs_status_string(status));
}
}

void verify_seg_size(ucp_worker_h worker) const {
Expand All @@ -838,7 +843,8 @@ class test_ucp_modify_uct_cfg : public test_ucp_context {

if (wiface->attr.cap.flags & UCT_IFACE_FLAG_PUT_BCOPY) {
EXPECT_EQ(m_seg_size, wiface->attr.cap.put.max_bcopy)
<< "tl : " << worker->context->tl_rscs[tl_id].tl_rsc.tl_name;
<< "tl : " << worker->context->tl_rscs[tl_id].tl_rsc.tl_name
<< "dev : " << worker->context->tl_rscs[tl_id].tl_rsc.dev_name;
}
}
}
Expand Down
Loading