-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathconfig.cpp.tt
96 lines (72 loc) · 2.94 KB
/
config.cpp.tt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <mutex>
#include "golpe.h"
#include <tao/config.hpp>
std::atomic<ConfigValues*> currentCfg;
std::mutex currentCfgModificationMutex;
tao::config::value loadRawTaoConfig(const std::string &configFile) {
tao::config::value configJson;
try {
configJson = tao::config::from_file(configFile);
} catch (std::exception &e) {
throw herr("Failed to load config file '", configFile, "': ", e.what());
}
return configJson;
}
void loadConfig(const std::string &configFile) {
std::lock_guard<std::mutex> guard(currentCfgModificationMutex);
LI << "CONFIG: Loading config from file: " << configFile;
tao::config::value configJson = loadRawTaoConfig(configFile);
std::unique_ptr<ConfigValues> tmpCfg = std::make_unique<ConfigValues>(currentCfg.load() ? currentCfg.load()->version() + 1 : 1);
// Load from configJson into tmpCfg
[% FOREACH c IN config %]
// [% c.name %]
do {
auto val = configJson;
[% FOREACH p IN c.path %]
if (!val.is_object()) break;
if (!val.get_object().contains("[% p %]")) break;
val = val.at("[% p %]");
[% END %]
[% IF c.type == 'uint64' %]
if (!val.is_unsigned()) throw herr("[% c.name %] not a uint64");
tmpCfg->[% c.nameCpp %] = val.get_unsigned();
[% ELSIF c.type == 'string' %]
if (!val.is_string()) throw herr("[% c.name %] not a string");
tmpCfg->[% c.nameCpp %] = val.get_string();
[% ELSIF c.type == 'bool' %]
if (!val.is_boolean()) throw herr("[% c.name %] not a bool");
tmpCfg->[% c.nameCpp %] = val.get_boolean();
[% ELSE %]
#error "unknown type [% c.type %]"
[% END %]
} while(0);
[% END %]
// Log config changes and check for non-reloadable changes
uint64_t changes = 0;
if (currentCfg.load()) {
[% FOREACH c IN config %]
{
auto &oldVal = currentCfg.load()->[% c.nameCpp %];
auto &newVal = tmpCfg->[% c.nameCpp %];
if (oldVal != newVal) {
[% IF c.noReload %]
LI << " * '[% c.name %]' changed but is a noReload field. Ignoring.";
newVal = oldVal;
[% ELSE %]
LI << " * '[% c.name %]' changed from '" << oldVal << "' to '" << newVal << "'";
changes++;
[% END %]
}
}
[% END %]
}
if (!currentCfg.load() || changes) {
LI << "CONFIG: successfully installed";
// Atomically swap in new config, and load old one into unique_ptr so it's destroyed:
ConfigValues *oldCfg = currentCfg.exchange(tmpCfg.release());
// Intentionally leak this memory! Threads may still have references to it.
(void)oldCfg;
} else {
LI << "CONFIG: no changes detected, doing nothing";
}
}