Artem Senichev | efd5d74 | 2018-10-24 16:14:04 +0300 | [diff] [blame^] | 1 | /** |
| 2 | * @brief Host logger service entry point. |
| 3 | * |
| 4 | * This file is part of HostLogger project. |
| 5 | * |
| 6 | * Copyright (c) 2018 YADRO |
| 7 | * |
| 8 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 9 | * you may not use this file except in compliance with the License. |
| 10 | * You may obtain a copy of the License at |
| 11 | * |
| 12 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 13 | * |
| 14 | * Unless required by applicable law or agreed to in writing, software |
| 15 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 17 | * See the License for the specific language governing permissions and |
| 18 | * limitations under the License. |
| 19 | */ |
| 20 | |
| 21 | #include "config.hpp" |
| 22 | #include "dbus_server.hpp" |
| 23 | #include "dbus_watch.hpp" |
| 24 | #include "log_manager.hpp" |
| 25 | #include <getopt.h> |
| 26 | #include <cstdio> |
| 27 | #include <cstdlib> |
| 28 | #include <climits> |
| 29 | |
| 30 | |
| 31 | // Global logger configuration instance |
| 32 | Config loggerConfig = { |
| 33 | .path = LOG_OUTPUT_PATH, |
| 34 | .storageSizeLimit = LOG_STORAGE_SIZE_LIMIT, |
| 35 | .storageTimeLimit = LOG_STORAGE_TIME_LIMIT, |
| 36 | .flushPeriod = LOG_FLUSH_PERIOD, |
| 37 | .rotationLimit = LOG_ROTATION_LIMIT |
| 38 | }; |
| 39 | |
| 40 | |
| 41 | /** @brief Print title with version info. */ |
| 42 | static void printTitle() |
| 43 | { |
| 44 | printf("Host logger service " PACKAGE_VERSION ".\n"); |
| 45 | } |
| 46 | |
| 47 | |
| 48 | /** @brief Print help usage info. |
| 49 | * |
| 50 | * @param[in] app - application's file name |
| 51 | */ |
| 52 | static void printHelp(const char* app) |
| 53 | { |
| 54 | printTitle(); |
| 55 | printf("Copyright (c) 2018 YADRO.\n"); |
| 56 | printf("Usage: %s [options]\n", app); |
| 57 | printf("Options (defaults are specified in brackets):\n" |
| 58 | " -p, --path=PATH Path used to store logs [%s]\n" |
| 59 | "Intermediate storage buffer capacity setup:\n" |
| 60 | " -s, --szlimit=N Store up to N last messages [%i], 0=unlimited\n" |
| 61 | " -t, --tmlimit=N Store messages for last N hours [%i], 0=unlimited\n" |
| 62 | "Flush storage buffer policy:\n" |
| 63 | " -f, --flush=N Flush logs every N hours [%i]\n" |
| 64 | " If this option is set to 0 flush will be called at\n" |
| 65 | " every host state change event from D-Bus.\n" |
| 66 | "Log files rotation policy:\n" |
| 67 | " -r, --rotate=N Store up to N files in the log directory [%i],\n" |
| 68 | " 0=unlimited\n" |
| 69 | "Common options:\n" |
| 70 | " -v, --version Print version and exit\n" |
| 71 | " -h, --help Print this help and exit\n", |
| 72 | loggerConfig.path, |
| 73 | loggerConfig.storageSizeLimit, |
| 74 | loggerConfig.storageTimeLimit, |
| 75 | loggerConfig.flushPeriod, |
| 76 | loggerConfig.rotationLimit); |
| 77 | } |
| 78 | |
| 79 | |
| 80 | /** @brief Get numeric positive value from string argument. |
| 81 | * |
| 82 | * @param[in] param - parameter name |
| 83 | * @param[in] arg - parameter text value |
| 84 | * |
| 85 | * @return positive numeric value from string argument or -1 on errors |
| 86 | */ |
| 87 | static int getNumericArg(const char* param, const char* arg) |
| 88 | { |
| 89 | char* ep = nullptr; |
| 90 | const unsigned long val = strtoul(arg, &ep, 0); |
| 91 | if (val > INT_MAX || !ep || ep == arg || *ep != 0) { |
| 92 | fprintf(stderr, "Invalid %s param: %s, expected 0<=N<=%i\n", |
| 93 | param, arg, INT_MAX); |
| 94 | return -1; |
| 95 | } |
| 96 | return static_cast<int>(val); |
| 97 | } |
| 98 | |
| 99 | |
| 100 | /** @brief Application entry point. */ |
| 101 | int main(int argc, char *argv[]) |
| 102 | { |
| 103 | int opt_val; |
| 104 | const struct option opts[] = { |
| 105 | { "path", required_argument, 0, 'p' }, |
| 106 | { "szlimit", required_argument, 0, 's' }, |
| 107 | { "tmlimit", required_argument, 0, 't' }, |
| 108 | { "flush", required_argument, 0, 'f' }, |
| 109 | { "rotate", required_argument, 0, 'r' }, |
| 110 | { "version", no_argument, 0, 'v' }, |
| 111 | { "help", no_argument, 0, 'h' }, |
| 112 | { 0, 0, 0, 0 } |
| 113 | }; |
| 114 | |
| 115 | opterr = 0; |
| 116 | while ((opt_val = getopt_long(argc, argv, "p:s:t:f:r:vh", opts, NULL)) != -1) { |
| 117 | switch (opt_val) { |
| 118 | case 'p': |
| 119 | loggerConfig.path = optarg; |
| 120 | if (*loggerConfig.path != '/') { |
| 121 | fprintf(stderr, "Invalid directory: %s, expected absolute path\n", loggerConfig.path); |
| 122 | return EXIT_FAILURE; |
| 123 | } |
| 124 | break; |
| 125 | case 's': |
| 126 | loggerConfig.storageSizeLimit = getNumericArg(opts[optind - 1].name, optarg); |
| 127 | if (loggerConfig.storageSizeLimit < 0) |
| 128 | return EXIT_FAILURE; |
| 129 | break; |
| 130 | case 't': |
| 131 | loggerConfig.storageTimeLimit = getNumericArg(opts[optind - 1].name, optarg); |
| 132 | if (loggerConfig.storageTimeLimit < 0) |
| 133 | return EXIT_FAILURE; |
| 134 | break; |
| 135 | case 'f': |
| 136 | loggerConfig.flushPeriod = getNumericArg(opts[optind - 1].name, optarg); |
| 137 | if (loggerConfig.flushPeriod < 0) |
| 138 | return EXIT_FAILURE; |
| 139 | break; |
| 140 | case 'r': |
| 141 | loggerConfig.rotationLimit = getNumericArg(opts[optind - 1].name, optarg); |
| 142 | if (loggerConfig.rotationLimit < 0) |
| 143 | return EXIT_FAILURE; |
| 144 | break; |
| 145 | case 'v': |
| 146 | printTitle(); |
| 147 | return EXIT_SUCCESS; |
| 148 | case 'h': |
| 149 | printHelp(argv[0]); |
| 150 | return EXIT_SUCCESS; |
| 151 | default: |
| 152 | fprintf(stderr, "Invalid option: %s\n", argv[optind - 1]); |
| 153 | return EXIT_FAILURE; |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | int rc; |
| 158 | |
| 159 | // Initialize log manager |
| 160 | LogManager logManager; |
| 161 | rc = logManager.openHostLog(); |
| 162 | if (rc != 0) |
| 163 | return rc; |
| 164 | |
| 165 | // Initialize D-Bus server |
| 166 | sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); |
| 167 | sd_event* event = nullptr; |
| 168 | rc = sd_event_default(&event); |
| 169 | if (rc < 0) { |
| 170 | fprintf(stderr, "Error occurred during the sd_event_default: %i\n", rc); |
| 171 | return EXIT_FAILURE; |
| 172 | } |
| 173 | EventPtr eventPtr(event); |
| 174 | bus.attach_event(eventPtr.get(), SD_EVENT_PRIORITY_NORMAL); |
| 175 | |
| 176 | DbusServer dbusMgr(logManager, bus); |
| 177 | bus.request_name(HOSTLOGGER_DBUS_IFACE); |
| 178 | |
| 179 | // Initialize D-Bus watcher |
| 180 | DbusWatcher dbusWatch(logManager, bus); |
| 181 | rc = dbusWatch.initialize(); |
| 182 | if (rc < 0) |
| 183 | return EXIT_FAILURE; |
| 184 | |
| 185 | // D-Bus event processing |
| 186 | rc = sd_event_loop(eventPtr.get()); |
| 187 | if (rc != 0) |
| 188 | fprintf(stderr, "Error occurred during the sd_event_loop: %i\n", rc); |
| 189 | |
| 190 | return rc ? rc : -1; // Allways retrun an error code |
| 191 | } |