1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3 * Copyright 2016 Couchbase, Inc
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 #include "config.h"
18 #include "config_parse.h"
19 #include "cmdline.h"
20 #include "config_util.h"
21 #include "settings.h"
22
23 #include <sstream>
24
25 /**
26 * Load the configuration file from disk and parse it to JSON
27 *
28 * @param file the name of the file to load
29 * @return A handle to a JSON representing the config file
30 * @throws std::runtime_error if an error occurs
31 */
load_config_file(const char* file)32 static unique_cJSON_ptr load_config_file(const char* file) {
33 cJSON *sys;
34 config_error_t err = config_load_file(file, &sys);
35
36 if (err != CONFIG_SUCCESS) {
37 throw std::runtime_error(config_strerror(file, err));
38 }
39
40 return unique_cJSON_ptr(sys);
41 }
42
43
44 /******************************************************************************
45 * Public functions
46 *****************************************************************************/
47
load_config_file(const char *file, Settings& settings)48 void load_config_file(const char *file, Settings& settings)
49 {
50 settings.reconfigure(load_config_file(file));
51 }
52
validate_proposed_config_changes(const char* new_cfg, cJSON* errors)53 bool validate_proposed_config_changes(const char* new_cfg, cJSON* errors) {
54
55 unique_cJSON_ptr config(cJSON_Parse(new_cfg));
56 if (config.get() == nullptr) {
57 cJSON_AddItemToArray(errors, cJSON_CreateString("JSON parse error"));
58 return false;
59 }
60
61 // Earlier we returned all of the errors, now I'm terminating on
62 // the first... Ideally all of the errors would be best, but
63 // the code is easier if we can use exceptions to abort the parsing
64 // when we hit an error. Given that this isn't something that the
65 // user would be calling every time I don't think it is a big problem..
66 try {
67 Settings new_settings(config);
68 settings.updateSettings(new_settings, false);
69 return true;
70 } catch (const std::exception& exception) {
71 cJSON_AddItemToArray(errors, cJSON_CreateString(exception.what()));
72 }
73
74 return false;
75 }
76
reload_config_file()77 void reload_config_file() {
78 LOG_INFO("Reloading config file {}", get_config_file());
79
80 try {
81 Settings new_settings(load_config_file(get_config_file()));
82 settings.updateSettings(new_settings, true);
83 } catch (const std::exception& exception) {
84 LOG_WARNING(
85 "Validation failed while reloading config file '{}'. Error: {}",
86 get_config_file(),
87 exception.what());
88 }
89 }
90