source: nscp/helpers/settings_manager/settings_manager_impl.cpp @ 8013c0c

0.4.00.4.10.4.2
Last change on this file since 8013c0c was 8013c0c, checked in by Michael Medin <michael@…>, 17 months ago
  • Fixed so NSCAClient parses address correctly
  • settings exception is now derived from exception meaning it will show up more with details (instead of unknown)
  • Added API for handling log level (replaces older debug flag)
  • Added options for settings debug level
  • Changed to --settings is a global argument (meaning you can use it in any mode)
  • Added arguments parsing to test: so you can use global arguments such as --log and --settings.
  • Removed memory leak in settings parsing interface
  • Property mode set to 100644
File size: 8.8 KB
Line 
1#include "StdAfx.h"
2
3#include "settings_manager_impl.h"
4
5#include <settings/settings_ini.hpp>
6#include <settings/settings_dummy.hpp>
7#include <settings/settings_http.hpp>
8#ifdef WIN32
9#include <settings/settings_old.hpp>
10#include <settings/settings_registry.hpp>
11#endif
12
13#include <settings/client/settings_proxy.hpp>
14#include <settings/client/settings_client.hpp>
15#include <file_helpers.hpp>
16#include <config.h>
17
18
19static settings_manager::NSCSettingsImpl* settings_impl = NULL;
20
21namespace settings_manager {
22        // Alias to make handling "compatible" with old syntax
23
24        inline NSCSettingsImpl* internal_get() {
25                if (settings_impl == NULL)
26                        throw settings::settings_exception(_T("Settings has not been initiated!"));
27                return settings_impl;
28        }
29        nscapi::settings_helper::settings_impl_interface_ptr get_proxy() {
30                return nscapi::settings_helper::settings_impl_interface_ptr(new settings_client::settings_proxy(internal_get()));
31        }
32        settings::instance_ptr get_settings() {
33                return internal_get()->get();
34        }
35        settings::instance_ptr get_settings_no_wait() {
36                return internal_get()->get_no_wait();
37        }
38        settings::settings_core* get_core() {
39                return internal_get();
40        }
41        void destroy_settings() {
42                settings_manager::NSCSettingsImpl* old = settings_impl;
43                settings_impl = NULL;
44                delete old;
45        }
46
47        std::wstring NSCSettingsImpl::find_file(std::wstring file, std::wstring fallback) {
48                // @todo: replace this with a proper parser!
49                if (file.size() == 0)
50                        file = fallback;
51                return provider_->expand_path(file);
52        }
53        std::wstring NSCSettingsImpl::expand_path(std::wstring file) {
54                return provider_->expand_path(file);
55        }
56
57
58        //////////////////////////////////////////////////////////////////////////
59        /// Create an instance of a given type.
60        /// Used internally to create instances of various settings types.
61        ///
62        /// @param type the type to create
63        /// @param context the context to use
64        /// @return a new instance of given type.
65        ///
66        /// @author mickem
67        settings::instance_raw_ptr NSCSettingsImpl::create_instance(std::wstring key) {
68                net::wurl url = net::parse(key);
69                if (url.protocol.empty()) {
70                        url = net::parse(key + _T("://"));
71                        get_logger()->debug(__FILE__, __LINE__, _T("No driver specified attemtping to fake one: ") + url.to_string());
72                }
73                get_logger()->debug(__FILE__, __LINE__, _T("Creating instance for: ") + url.to_string());
74                if (url.host.empty() && url.path.empty())
75                        key = _T("");
76#ifdef WIN32
77                if (url.protocol == _T("old")) {
78                        old_ = true;
79                        if (key.empty())
80                                key = DEFAULT_CONF_OLD_LOCATION;
81                        return settings::instance_raw_ptr(new settings::OLDSettings(this, key));
82                }
83                if (url.protocol == _T("registry")) {
84                        if (key.empty())
85                                key = DEFAULT_CONF_REG_LOCATION;
86                        return settings::instance_raw_ptr(new settings::REGSettings(this, key));
87                }
88#endif
89                if (url.protocol == _T("ini")) {
90                        if (key.empty())
91                                key = DEFAULT_CONF_INI_LOCATION;
92                        return settings::instance_raw_ptr(new settings::INISettings(this, key));
93                }
94                if (url.protocol == _T("dummy")) {
95                        return settings::instance_raw_ptr(new settings::settings_dummy(this, key));
96                }
97                if (url.protocol == _T("http")) {
98                        return settings::instance_raw_ptr(new settings::settings_http(this, key));
99                }
100                throw settings::settings_exception(_T("Undefined settings protocol: ") + url.protocol);
101        }
102
103        bool NSCSettingsImpl::check_file(std::wstring file, std::wstring tag, std::wstring &key) {
104                std::wstring tmp = provider_->expand_path(file);
105                if (file_helpers::checks::exists(tmp)) {
106                        key = tag;
107                        return true;
108                }
109                return false;
110        }
111
112        std::wstring NSCSettingsImpl::expand_context(std::wstring key) {
113#ifdef WIN32
114                if (key == _T("old"))
115                        return DEFAULT_CONF_OLD_LOCATION;
116                if (key == _T("registry"))
117                        return DEFAULT_CONF_REG_LOCATION;
118#endif
119                if (key == _T("ini"))
120                        return DEFAULT_CONF_INI_LOCATION;
121                if (key == _T("dummy"))
122                        return _T("dummy://");
123                return key;
124        }
125
126        bool NSCSettingsImpl::context_exists(std::wstring key) {
127                net::wurl url = net::parse(key);
128                if (url.protocol.empty())
129                        url = net::parse(expand_context(key));
130#ifdef WIN32
131                if (url.protocol == _T("old"))
132                        return settings::OLDSettings::context_exists(this, key);
133                if (url.protocol == _T("registry"))
134                        return settings::REGSettings::context_exists(this, key);
135#endif
136                if (url.protocol == _T("ini"))
137                        return settings::INISettings::context_exists(this, key);
138                if (url.protocol == _T("dummy"))
139                        return true;
140                if (url.protocol == _T("http"))
141                        return true;
142                return false;
143        }
144
145        bool NSCSettingsImpl::has_boot_conf() {
146                return file_helpers::checks::exists(boot_.string());
147        }
148
149        //////////////////////////////////////////////////////////////////////////
150        /// Boot the settings subsystem from the given file (boot.ini).
151        ///
152        /// @param file the file to use when booting.
153        ///
154        /// @author mickem
155        void NSCSettingsImpl::boot(std::wstring key) {
156                std::list<std::wstring> order;
157                if (!key.empty()) {
158                        order.push_back(key);
159                }
160                boot_ = provider_->expand_path(BOOT_CONF_LOCATION);
161                if (file_helpers::checks::exists(boot_.string())) {
162                        get_logger()->debug(__FILE__, __LINE__, _T("Boot.ini found in: ") + boot_.string());
163                        for (int i=0;i<20;i++) {
164                                std::wstring v = get_boot_string(_T("settings"), strEx::itos(i), _T(""));
165                                if (!v.empty())
166                                        order.push_back(expand_context(v));
167                        }
168                }
169                if (order.size() == 0) {
170                        get_logger()->debug(__FILE__, __LINE__, _T("No entries found looking in (adding default): ") + boot_.string());
171                        order.push_back(DEFAULT_CONF_OLD_LOCATION);
172                        order.push_back(DEFAULT_CONF_INI_LOCATION);
173                }
174                int i=0;
175                std::wstring boot_order;
176                BOOST_FOREACH(std::wstring k, order) {
177                        strEx::append_list(boot_order, k, _T(", "));
178                }
179                get_logger()->debug(__FILE__, __LINE__, _T("Boot order: ") + boot_order);
180                BOOST_FOREACH(std::wstring k, order) {
181                        if (context_exists(k)) {
182                                get_logger()->debug(__FILE__, __LINE__, _T("Activating: ") + k);
183                                set_instance(k);
184                                return;
185                        }
186                }
187                if (!key.empty()) {
188                        get_logger()->info(__FILE__, __LINE__, _T("No valid settings found but one was given (using that): ") + key);
189                        set_instance(key);
190                        return;
191                }
192
193                get_logger()->debug(__FILE__, __LINE__, _T("No valid settings found (tried): ") + boot_order);
194
195                std::wstring tgt = get_boot_string(_T("main"), _T("write"), _T(""));
196                if (!tgt.empty()) {
197                        get_logger()->debug(__FILE__, __LINE__, _T("Creating new settings file: ") + tgt);
198                        set_instance(tgt);
199                        return;
200                }
201                get_logger()->err(__FILE__, __LINE__, std::wstring(_T("Settings contexts exausted, will create a new ")) + DEFAULT_CONF_INI_LOCATION);
202                set_instance(DEFAULT_CONF_INI_LOCATION);
203        }
204
205        void NSCSettingsImpl::set_primary(std::wstring key) {
206                std::list<std::wstring> order;
207                for (int i=0;i<20;i++) {
208                        std::wstring v = get_boot_string(_T("settings"), strEx::itos(i), _T(""));
209                        if (!v.empty()) {
210                                order.push_back(expand_context(v));
211                                set_boot_string(_T("settings"), strEx::itos(i), _T(""));
212                        }
213                }
214                order.remove(key);
215                order.push_front(key);
216                int i=1;
217                BOOST_FOREACH(std::wstring k, order) {
218                        set_boot_string(_T("settings"), strEx::itos(i++), k);
219                }
220                set_boot_string(_T("main"), _T("write"), key);
221        }
222
223
224        bool NSCSettingsImpl::create_context(std::wstring key) {
225                try {
226                        change_context(key);
227                } catch (settings::settings_exception e) {
228                        provider_->log_fatal_error(_T("Failed to initialize settings: ") + e.getError());
229                        return false;
230                } catch (...) {
231                        provider_->log_fatal_error(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
232                        return false;
233                }
234                return true;
235        }
236
237        void NSCSettingsImpl::change_context(std::wstring context) {
238                try {
239                        get_core()->migrate_to(context);
240                        set_primary(context);
241                        get_core()->boot(context);
242                } catch (settings::settings_exception e) {
243                        provider_->log_fatal_error(_T("Failed to initialize settings: ") + e.getError());
244                } catch (...) {
245                        provider_->log_fatal_error(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
246                }
247        }
248
249        bool init_settings(provider_interface *provider, std::wstring context) {
250                try {
251                        settings_impl = new NSCSettingsImpl(provider);
252                        get_core()->set_logger(provider->create_logger());
253                        get_core()->set_base(provider->expand_path(_T("${base-path}")));
254                        get_core()->boot(context);
255                } catch (settings::settings_exception e) {
256                        provider->log_fatal_error(_T("Failed to initialize settings: ") + e.getError());
257                        return false;
258                } catch (...) {
259                        provider->log_fatal_error(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
260                        return false;
261                }
262                return true;
263        }
264
265        void change_context(std::wstring context) {
266                settings_impl->change_context(context);
267        }
268
269        bool has_boot_conf() {
270                return settings_impl->has_boot_conf();
271        }
272        bool context_exists(std::wstring key) {
273                return settings_impl->context_exists(key);
274        }
275        bool create_context(std::wstring key) {
276                return settings_impl->create_context(key);
277        }
278
279
280}
Note: See TracBrowser for help on using the repository browser.