1
+ #include " config_manager.h"
2
+ #include " loaders/inline_loader.h"
3
+ #include " loaders/json_loader.h"
4
+ #include " descriptor_providers/json_descriptor_provider.h"
5
+ #include " core/util/xlio_exception.h"
6
+
7
+ #include < fstream>
8
+
9
+ static bool cmdline_contains (const std::string &pattern)
10
+ {
11
+ std::ifstream cmdline (" /proc/self/cmdline" , std::ios::binary);
12
+ std::string content;
13
+
14
+ if (cmdline.is_open ()) {
15
+ std::string arg;
16
+ while (std::getline (cmdline, arg, ' \0 ' )) {
17
+ content += arg + ' ' ;
18
+ }
19
+ }
20
+
21
+ return content.find (pattern) != std::string::npos;
22
+ }
23
+
24
+ config_manager::config_manager ()
25
+ {
26
+ std::queue<std::unique_ptr<loader>> loaders;
27
+
28
+ const char *inline_env = std::getenv (" XLIO_INLINE_CONFIG" );
29
+ if (inline_env) {
30
+ loaders.push (std::make_unique<inline_loader>(" XLIO_INLINE_CONFIG" ));
31
+ }
32
+
33
+ try {
34
+ const char *custom_path = std::getenv (" XLIO_CUSTOM_CONFIG_FILE" );
35
+ if (custom_path) {
36
+ loaders.push (std::make_unique<json_loader>(custom_path));
37
+ } else {
38
+ loaders.push (std::make_unique<json_loader>(" /etc/libxlio_config.json" ));
39
+ }
40
+ } catch (const xlio_exception &) {
41
+ // If the file is not found, we can continue with the inline config or the deprecated
42
+ // method.
43
+ }
44
+
45
+ // legacy method - config manager is not relevant for this case
46
+ if (cmdline_contains (" XLIO_" ) && loaders.empty ()) {
47
+ throw_xlio_exception (" Aborting config manager initialization. Legacy method chosen." );
48
+ }
49
+
50
+ initialize_manager (std::move (loaders), std::make_unique<json_descriptor_provider>());
51
+ }
52
+
53
+ void config_manager::initialize_manager (std::queue<std::unique_ptr<loader>> &&value_loaders,
54
+ std::unique_ptr<descriptor_provider> descriptor_provider)
55
+ {
56
+ if (value_loaders.empty () || !descriptor_provider) {
57
+ throw_xlio_exception (" loader/descriptor_provider cannot be null" );
58
+ }
59
+
60
+ // 1) Load raw config data - first in queue means higher priority.
61
+ std::map<std::string, std::experimental::any> aggregated_config_data;
62
+ while (!value_loaders.empty ()) {
63
+ auto loaded_data = value_loaders.front ()->load_all ();
64
+ aggregated_config_data.insert (loaded_data.begin (), loaded_data.end ());
65
+
66
+ value_loaders.pop ();
67
+ }
68
+
69
+ m_config_bundle.m_config_data = std::move (aggregated_config_data);
70
+
71
+ // 2) Load or build the descriptor structure
72
+ m_config_bundle.m_config_descriptor = descriptor_provider->load_descriptors ();
73
+
74
+ // 3) Validate all settings on construction (fail fast if invalid)
75
+ validate_config ();
76
+ }
77
+
78
+ config_manager::config_manager (std::queue<std::unique_ptr<loader>> &&value_loaders,
79
+ std::unique_ptr<descriptor_provider> descriptor_provider)
80
+ {
81
+ initialize_manager (std::move (value_loaders), std::move (descriptor_provider));
82
+ }
83
+
84
+ // Validate all config items against their descriptors & constraints.
85
+ // A real application might do more elaborate error handling/logging.
86
+ void config_manager::validate_config () const
87
+ {
88
+ // For each key-value in config_data, see if we have descriptor constraints
89
+ for (auto const &kv : m_config_bundle.m_config_data ) {
90
+ const auto &key = kv.first ;
91
+ const auto &value = kv.second ;
92
+
93
+ // Retrieve the descriptor (could be empty if not found)
94
+ auto param_desc = m_config_bundle.m_config_descriptor .get_parameter (key);
95
+ // If there's a specific type required, check constraints
96
+ if (!param_desc.validate (value)) {
97
+ // Throw an exception if validation fails
98
+ throw_xlio_exception (" Validation failed for key: " + key);
99
+ }
100
+ }
101
+ }
102
+
103
+ std::experimental::any config_manager::get_value_as_any (const std::string &key) const
104
+ {
105
+ // Try to find the key in the loaded data
106
+ auto it = m_config_bundle.m_config_data .find (key);
107
+ if (it == m_config_bundle.m_config_data .end ()) {
108
+ // Not found in data. Fallback to descriptor's default.
109
+ return m_config_bundle.m_config_descriptor .get_parameter (key).default_value ();
110
+ }
111
+
112
+ return (it->second );
113
+ }
0 commit comments