Skip to content

Commit f907468

Browse files
committed
load ctl defaults from env variable/file
1 parent a882507 commit f907468

File tree

10 files changed

+344
-50
lines changed

10 files changed

+344
-50
lines changed

src/ctl/ctl.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <limits.h>
2121
#include <stdarg.h>
2222
#include <stdint.h>
23+
#include <stdio.h>
2324
#include <stdlib.h>
2425
#include <string.h>
2526

@@ -33,8 +34,6 @@
3334

3435
#ifdef _WIN32
3536
#define strtok_r strtok_s
36-
#else
37-
#include <stdio.h>
3837
#endif
3938

4039
#define MAX_CONFIG_FILE_LEN (1 << 20) /* 1 megabyte */
@@ -578,7 +577,7 @@ static umf_result_t ctl_load_config_helper(struct ctl *ctl, void *ctx,
578577
// we do not need to copy va_list before call as we know that for query_config_input
579578
// ctl_query will not call va_arg on it. Ref 7.15/3 of C99 standard
580579
ret = ctl_query(ctl, ctx, CTL_QUERY_CONFIG_INPUT, name, CTL_QUERY_WRITE,
581-
value, 0, empty_args);
580+
value, strlen(value) + 1, empty_args);
582581

583582
if (ret != UMF_RESULT_SUCCESS && ctx != NULL) {
584583
goto end;
@@ -621,7 +620,6 @@ umf_result_t ctl_load_config_from_string(struct ctl *ctl, void *ctx,
621620
* This function opens up the config file, allocates a buffer of size equal to
622621
* the size of the file, reads its content and sanitizes it for ctl_load_config.
623622
*/
624-
#ifndef _WIN32 // TODO: implement for Windows
625623
umf_result_t ctl_load_config_from_file(struct ctl *ctl, void *ctx,
626624
const char *cfg_file) {
627625
umf_result_t ret = UMF_RESULT_ERROR_UNKNOWN;
@@ -679,7 +677,6 @@ umf_result_t ctl_load_config_from_file(struct ctl *ctl, void *ctx,
679677
(void)fclose(fp);
680678
return ret;
681679
}
682-
#endif
683680

684681
/*
685682
* ctl_parse_ll -- (internal) parses and returns a long long signed integer

src/ctl/ctl_internal.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,6 @@ struct ctl {
121121
int first_free;
122122
};
123123

124-
void initialize_global_ctl(void);
125124
void ctl_init(void *(*Malloc)(size_t), void (*Free)(void *));
126125

127126
umf_result_t ctl_load_config_from_string(struct ctl *ctl, void *ctx,

src/libumf.c

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "base_alloc_global.h"
1515
#include "ctl/ctl_internal.h"
1616
#include "ipc_cache.h"
17+
#include "libumf.h"
1718
#include "memory_pool_internal.h"
1819
#include "memory_provider_internal.h"
1920
#include "memspace_internal.h"
@@ -37,7 +38,23 @@ static void initialize_init_mutex(void) { utils_mutex_init(&initMutex); }
3738
static umf_ctl_node_t CTL_NODE(umf)[] = {CTL_CHILD(provider), CTL_CHILD(pool),
3839
CTL_CHILD(logger), CTL_NODE_END};
3940

40-
void initialize_global_ctl(void) { CTL_REGISTER_MODULE(NULL, umf); }
41+
void initialize_ctl(void) {
42+
ctl_init(umf_ba_global_alloc, umf_ba_global_free);
43+
44+
CTL_REGISTER_MODULE(NULL, umf);
45+
const char *env_var = getenv("UMF_CONF");
46+
if (env_var && env_var[0] != '\0') {
47+
LOG_INFO("Loading UMF configuration from environment variable: %s",
48+
env_var);
49+
ctl_load_config_from_string(NULL, NULL, env_var);
50+
}
51+
52+
const char *file_var = getenv("UMF_CONF_FILE");
53+
if (file_var && file_var[0] != '\0') {
54+
LOG_INFO("Loading UMF configuration from file: %s", file_var);
55+
ctl_load_config_from_file(NULL, NULL, file_var);
56+
}
57+
}
4158

4259
umf_result_t umfInit(void) {
4360
utils_init_once(&initMutexOnce, initialize_init_mutex);
@@ -46,6 +63,8 @@ umf_result_t umfInit(void) {
4663

4764
if (umfRefCount == 0) {
4865
utils_log_init();
66+
initialize_ctl();
67+
4968
umf_result_t umf_result = umfMemoryTrackerCreate(&TRACKER);
5069
if (umf_result != UMF_RESULT_SUCCESS) {
5170
LOG_ERR("Failed to create memory tracker");
@@ -64,8 +83,6 @@ umf_result_t umfInit(void) {
6483
}
6584

6685
LOG_DEBUG("UMF IPC cache initialized");
67-
ctl_init(umf_ba_global_alloc, umf_ba_global_free);
68-
initialize_global_ctl();
6986
}
7087

7188
umfRefCount++;
@@ -111,6 +128,8 @@ umf_result_t umfTearDown(void) {
111128
umfMemoryTrackerDestroy(t);
112129
LOG_DEBUG("UMF tracker destroyed");
113130

131+
umfPoolCtlDefaultsDestroy();
132+
114133
umf_ba_destroy_global();
115134
LOG_DEBUG("UMF base allocator destroyed");
116135

@@ -127,6 +146,7 @@ umf_result_t umfTearDown(void) {
127146
int umfGetCurrentVersion(void) { return UMF_VERSION_CURRENT; }
128147

129148
umf_result_t umfCtlGet(const char *name, void *arg, size_t size, ...) {
149+
libumfInit();
130150
// ctx can be NULL when getting defaults
131151
if (name == NULL || arg == NULL || size == 0) {
132152
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
@@ -141,6 +161,7 @@ umf_result_t umfCtlGet(const char *name, void *arg, size_t size, ...) {
141161
}
142162

143163
umf_result_t umfCtlSet(const char *name, void *arg, size_t size, ...) {
164+
libumfInit();
144165
// ctx can be NULL when setting defaults
145166
if (name == NULL || arg == NULL || size == 0) {
146167
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
@@ -154,6 +175,7 @@ umf_result_t umfCtlSet(const char *name, void *arg, size_t size, ...) {
154175
}
155176

156177
umf_result_t umfCtlExec(const char *name, void *arg, size_t size, ...) {
178+
libumfInit();
157179
// arg can be NULL when executing a command
158180
// ctx can be NULL when executing defaults
159181
// size can depends on the arg

src/memory_pool.c

Lines changed: 110 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,21 @@
2424
#include "utils_assert.h"
2525
#include "utils_concurrency.h"
2626
#include "utils_log.h"
27+
#include "utlist.h"
2728

28-
#define UMF_DEFAULT_SIZE 100
29-
#define UMF_DEFAULT_LEN 100
29+
typedef struct ctl_default_entry_t {
30+
char *name;
31+
void *value;
32+
size_t value_size;
33+
umf_ctl_query_source_t source;
34+
struct ctl_default_entry_t *next;
35+
} ctl_default_entry_t;
36+
37+
static ctl_default_entry_t *ctl_default_list = NULL;
3038

3139
utils_mutex_t ctl_mtx;
3240
static UTIL_ONCE_FLAG mem_pool_ctl_initialized = UTIL_ONCE_FLAG_INIT;
3341

34-
char CTL_DEFAULT_ENTRIES[UMF_DEFAULT_SIZE][UMF_DEFAULT_LEN] = {0};
35-
char CTL_DEFAULT_VALUES[UMF_DEFAULT_SIZE][UMF_DEFAULT_LEN] = {0};
36-
3742
static struct ctl umf_pool_ctl_root;
3843

3944
static void pool_ctl_init(void);
@@ -79,36 +84,76 @@ static umf_result_t CTL_SUBTREE_HANDLER(default)(
7984

8085
utils_mutex_lock(&ctl_mtx);
8186

87+
ctl_default_entry_t *entry = NULL;
88+
LL_FOREACH(ctl_default_list, entry) {
89+
if (strcmp(entry->name, extra_name) == 0) {
90+
break;
91+
}
92+
}
93+
8294
if (queryType == CTL_QUERY_WRITE) {
83-
int i = 0;
84-
for (; i < UMF_DEFAULT_SIZE; i++) {
85-
if (CTL_DEFAULT_ENTRIES[i][0] == '\0' ||
86-
strcmp(CTL_DEFAULT_ENTRIES[i], extra_name) == 0) {
87-
strncpy(CTL_DEFAULT_ENTRIES[i], extra_name, UMF_DEFAULT_LEN);
88-
CTL_DEFAULT_ENTRIES[i][UMF_DEFAULT_LEN - 1] = '\0';
89-
strncpy(CTL_DEFAULT_VALUES[i], arg, UMF_DEFAULT_LEN);
90-
CTL_DEFAULT_VALUES[i][UMF_DEFAULT_LEN - 1] = '\0';
91-
break;
95+
bool is_new_entry = false;
96+
if (entry == NULL) {
97+
entry = umf_ba_global_alloc(sizeof(*entry));
98+
if (entry == NULL) {
99+
utils_mutex_unlock(&ctl_mtx);
100+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
92101
}
102+
103+
entry->name = NULL;
104+
entry->value = NULL;
105+
entry->next = NULL;
106+
is_new_entry = true;
93107
}
94-
if (UMF_DEFAULT_SIZE == i) {
95-
LOG_ERR("Default entries array is full");
108+
109+
size_t name_len = strlen(extra_name) + 1;
110+
char *new_name = umf_ba_global_alloc(name_len);
111+
if (new_name == NULL) {
96112
utils_mutex_unlock(&ctl_mtx);
97-
return UMF_RESULT_ERROR_OUT_OF_RESOURCES;
113+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
98114
}
99-
} else if (queryType == CTL_QUERY_READ) {
100-
int i = 0;
101-
for (; i < UMF_DEFAULT_SIZE; i++) {
102-
if (strcmp(CTL_DEFAULT_ENTRIES[i], extra_name) == 0) {
103-
strncpy(arg, CTL_DEFAULT_VALUES[i], size);
104-
break;
115+
116+
memcpy(new_name, extra_name, name_len);
117+
if (entry->name) {
118+
umf_ba_global_free(entry->name);
119+
}
120+
entry->name = new_name;
121+
122+
void *new_value = NULL;
123+
if (size > 0) {
124+
new_value = umf_ba_global_alloc(size);
125+
if (new_value == NULL) {
126+
utils_mutex_unlock(&ctl_mtx);
127+
return UMF_RESULT_ERROR_OUT_OF_HOST_MEMORY;
105128
}
129+
memcpy(new_value, arg, size);
106130
}
107-
if (UMF_DEFAULT_SIZE == i) {
131+
132+
if (entry->value) {
133+
umf_ba_global_free(entry->value);
134+
}
135+
136+
entry->value = new_value;
137+
entry->value_size = size;
138+
entry->source = source;
139+
140+
if (is_new_entry) {
141+
LL_APPEND(ctl_default_list, entry);
142+
}
143+
} else if (queryType == CTL_QUERY_READ) {
144+
if (entry == NULL) {
108145
LOG_WARN("Wrong path name: %s", extra_name);
109146
utils_mutex_unlock(&ctl_mtx);
110147
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
111148
}
149+
150+
if (entry->value_size > size) {
151+
utils_mutex_unlock(&ctl_mtx);
152+
LOG_ERR("Provided buffer size %zu is smaller then field size %zu",
153+
size, entry->value_size);
154+
return UMF_RESULT_ERROR_INVALID_ARGUMENT;
155+
}
156+
memcpy(arg, entry->value, entry->value_size);
112157
}
113158

114159
utils_mutex_unlock(&ctl_mtx);
@@ -174,12 +219,11 @@ static const umf_pool_create_flags_t UMF_POOL_CREATE_FLAG_ALL =
174219
// windows do not allow to use uninitialized va_list so this function help us to initialize it.
175220
static umf_result_t default_ctl_helper(const umf_memory_pool_ops_t *ops,
176221
void *ctl, const char *name, void *arg,
177-
...) {
222+
size_t size, ...) {
178223
va_list empty_args;
179-
va_start(empty_args, arg);
180-
umf_result_t ret =
181-
ops->ext_ctl(ctl, CTL_QUERY_PROGRAMMATIC, name, arg, UMF_DEFAULT_LEN,
182-
CTL_QUERY_WRITE, empty_args);
224+
va_start(empty_args, size);
225+
umf_result_t ret = ops->ext_ctl(ctl, CTL_QUERY_PROGRAMMATIC, name, arg,
226+
size, CTL_QUERY_WRITE, empty_args);
183227
va_end(empty_args);
184228
return ret;
185229
}
@@ -246,18 +290,23 @@ static umf_result_t umfPoolCreateInternal(const umf_memory_pool_ops_t *ops,
246290
}
247291

248292
// Set default property "name" to pool if exists
249-
for (int i = 0; i < UMF_DEFAULT_SIZE; i++) {
250-
const char *pname = NULL;
251-
ret = ops->get_name(NULL, &pname);
252-
if (ret != UMF_RESULT_SUCCESS) {
253-
LOG_ERR("Failed to get pool name");
254-
goto err_pool_init;
255-
}
256-
if (CTL_DEFAULT_ENTRIES[i][0] != '\0' && pname &&
257-
strstr(CTL_DEFAULT_ENTRIES[i], pname)) {
258-
259-
default_ctl_helper(ops, pool->pool_priv, CTL_DEFAULT_ENTRIES[i],
260-
CTL_DEFAULT_VALUES[i]);
293+
const char *pname = NULL;
294+
ret = ops->get_name(NULL, &pname);
295+
if (ret != UMF_RESULT_SUCCESS) {
296+
LOG_ERR("Failed to get pool name");
297+
goto err_pool_init;
298+
}
299+
assert(pname != NULL);
300+
301+
size_t pname_len = strlen(pname);
302+
ctl_default_entry_t *it = NULL;
303+
LL_FOREACH(ctl_default_list, it) {
304+
if (strlen(it->name) > pname_len + 1 &&
305+
strncmp(it->name, pname, pname_len) == 0 &&
306+
it->name[pname_len] == '.') {
307+
const char *ctl_name = it->name + pname_len + 1;
308+
default_ctl_helper(ops, pool->pool_priv, ctl_name, it->value,
309+
it->value_size);
261310
}
262311
}
263312

@@ -454,3 +503,23 @@ umf_result_t umfPoolGetTag(umf_memory_pool_handle_t hPool, void **tag) {
454503
utils_mutex_unlock(&hPool->lock);
455504
return UMF_RESULT_SUCCESS;
456505
}
506+
507+
void umfPoolCtlDefaultsDestroy(void) {
508+
utils_init_once(&mem_pool_ctl_initialized, pool_ctl_init);
509+
510+
utils_mutex_lock(&ctl_mtx);
511+
512+
ctl_default_entry_t *entry = NULL, *tmp = NULL;
513+
LL_FOREACH_SAFE(ctl_default_list, entry, tmp) {
514+
LL_DELETE(ctl_default_list, entry);
515+
if (entry->name) {
516+
umf_ba_global_free(entry->name);
517+
}
518+
if (entry->value) {
519+
umf_ba_global_free(entry->value);
520+
}
521+
umf_ba_global_free(entry);
522+
}
523+
524+
utils_mutex_unlock(&ctl_mtx);
525+
}

src/memory_pool_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ typedef struct umf_memory_pool_t {
4747

4848
extern umf_ctl_node_t CTL_NODE(pool)[];
4949

50+
void umfPoolCtlDefaultsDestroy(void);
51+
5052
#ifdef __cplusplus
5153
}
5254
#endif

test/CMakeLists.txt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,26 @@ if(LINUX)
221221
LIBS ${UMF_UTILS_FOR_TEST})
222222
endif()
223223

224+
build_umf_test(
225+
NAME ctl_env_app
226+
SRCS ctl/ctl_env_app.cpp
227+
LIBS ${UMF_UTILS_FOR_TEST} umf)
228+
229+
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/ctl/ctl_env_config1.cfg
230+
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ctl)
231+
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/ctl/ctl_env_config2.cfg
232+
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/ctl)
233+
234+
add_umf_test(
235+
NAME ctl_env_driver
236+
SRCS ctl/ctl_env_driver.cpp
237+
LIBS ${UMF_UTILS_FOR_TEST})
238+
239+
target_compile_definitions(
240+
test_ctl_env_driver
241+
PRIVATE CTL_ENV_APP="$<TARGET_FILE:test_ctl_env_app>"
242+
CTL_CONF_FILE_DIR="${CMAKE_CURRENT_BINARY_DIR}/ctl")
243+
224244
add_umf_test(
225245
NAME coarse_lib
226246
SRCS coarse_lib.cpp

0 commit comments

Comments
 (0)