1 /* 2 * Copyright (C) 2009-2014 Codership Oy <info@codership.com> 3 */ 4 5 /*! 6 * @file conf.hpp 7 * 8 * @brief Configuration parameters and utility templates. 9 */ 10 11 #ifndef GCOMM_CONF_HPP 12 #define GCOMM_CONF_HPP 13 14 #include "gu_config.hpp" 15 #include "gu_uri.hpp" 16 #include "gu_throw.hpp" 17 18 namespace gcomm 19 { 20 /*! 21 * Configuration parameter definitions. 22 * 23 * Transport definition and configuration parameters are passed to 24 * Transport::create() in the URI form. URI scheme part defines 25 * which transport is returned. Currently recognized are "tcp", "gmcast" 26 * and "pc". This will change in the future. 27 * 28 * URI format is the following: 29 * gcomm://[<peer_host>[:<peer_port>]][?<key1>=<val1>&<key2>=<val2>]... 30 * The key/value pairs can be used to pass configuration parameters to 31 * gcomm layers. 32 * 33 * Time periods as parameter values follow ISO8601 duration representation 34 * (as represented in http://en.wikipedia.org/wiki/ISO_8601#Durations). 35 * Examples: 36 * - PT1S - one second 37 * - PT1M30S = one minute 30 secs 38 * - P1DT6H = one day, 6 hours 39 * 40 * To get subsecond resolution, second part can be represented as decimal 41 * number, but currently it is not recommended due to bug in Period 42 * parsing routine (rounding errors can result inaccurate boundary 43 * value checking). 44 */ 45 struct Conf 46 { 47 static std::string const ProtonetBackend; 48 static std::string const ProtonetVersion; 49 50 /*! 51 * @brief TCP non-blocking flag ("socket.non_blocking") 52 * 53 * Parameter value is boolean (passed 0 or 1) denoting whether 54 * the socket should or should not be in non-blocking state. 55 */ 56 static std::string const TcpNonBlocking; 57 58 /*! 59 * @brief Algorithm for message checksums: 60 * 0 - none (backward compatible) 61 * 1 - CRC-32 (backward compatible) 62 * 2 - CRC-32C (optimized and potentially HW-accelerated on Intel CPUs) 63 */ 64 static std::string const SocketChecksum; 65 66 /*! 67 * @brief Socket receive buffer size in bytes 68 */ 69 static std::string const SocketRecvBufSize; 70 71 /*! 72 * @brief Socket send buffer size in bytes. 73 */ 74 static std::string const SocketSendBufSize; 75 76 /*! 77 * @brief GMCast scheme for transport URI ("gmcast") 78 */ 79 static std::string const GMCastScheme; 80 81 /*! 82 * @brief GMCast protocol version 83 */ 84 static std::string const GMCastVersion; 85 86 /*! 87 * @brief GMCast group name ("gmcast.group") 88 * 89 * String denoting group name. Max length of string is 16. Peer nodes 90 * accept GMCast connection only if the group names match. 91 */ 92 static std::string const GMCastGroup; 93 94 /*! 95 * @brief GMCast listening address ("gmcast.listen_addr") 96 * 97 * Listening address for GMCast. Address is currently passed in 98 * URI format (for example tcp://192.168.3.1:4567) and it should 99 * be passed as the last configuration parameter in order to 100 * avoid confusion. If parameter value is undefined, GMCast 101 * starts listening all interfaces at default port 4567. 102 */ 103 static std::string const GMCastListenAddr; 104 105 /*! 106 * @brief GMCast multicast address ("gmcast.mcast_addr") 107 * 108 * Multicast address for GMCast. By default multicast socket 109 * is bound to the same interface as conf::GMCastListenAddr. 110 * If multicast interface must be specified, the only way 111 * to do it is currently via listening address configuration. 112 */ 113 static std::string const GMCastMCastAddr; 114 115 /*! 116 * @brief GMCast multicast port ("gmcast.mcast_port") 117 * 118 * Multicast port for GMCast. By default multicast uses the 119 * same port as GMCast TCP connections. 120 */ 121 static std::string const GMCastMCastPort; 122 123 /*! 124 * @brief GMCast multicast TTL ("gmcast.mcast_ttl") 125 * 126 * This parameter controls multicast packet TTL. By default it 127 * is set to 1 and usually it should not be changed unless 128 * adviced so. This means that multicast is limited to single LAN 129 * segment. 130 */ 131 static std::string const GMCastMCastTTL; 132 133 static std::string const GMCastTimeWait; 134 static std::string const GMCastPeerTimeout; 135 136 /*! 137 * @brief Maximum initial reconnect attempts 138 * 139 * Maximum initial reconnect attempts for address reported by peer. 140 */ 141 static std::string const GMCastMaxInitialReconnectAttempts; 142 143 /*! 144 * @brief Add or remove peer address. 145 * 146 * Setting value to add:<scheme>://<ip>:<port> will inject new peer 147 * address in address list. Setting value to del:<scheme>://<ip>:<port> 148 * will remove peer address from list (via forget procedure). 149 */ 150 static std::string const GMCastPeerAddr; 151 152 /*! 153 * @brief Isolate node from peers 154 * 155 * Setting this value to 'true' closes all conections 156 * and will prevent forming of new connections until 157 * value is set again to 'false'. This parameter should be 158 * used for testing purposes only and it will not be visible 159 * in global configuration array. 160 */ 161 static std::string const GMCastIsolate; 162 163 /*! 164 * @brief Segment identifier for segmentation. 165 */ 166 static std::string const GMCastSegment; 167 168 169 /*! 170 * @brief EVS scheme for transport URI ("evs") 171 */ 172 static std::string const EvsScheme; 173 174 /*! 175 * @brief EVS protocol version 176 */ 177 static std::string const EvsVersion; 178 179 /*! 180 * @brief EVS view forget timeout ("evs.view_forget_timeout") 181 * 182 * This timeout controls how long information about 183 * known group views is maintained. This information is needed 184 * to filter out delayed messages from previous views that are not 185 * live anymore. Default value is 5 minutes and there is usually not 186 * need to change it. 187 */ 188 static std::string const EvsViewForgetTimeout; 189 190 /*! 191 * @brief EVS suspect timeout ("evs.suspect_timeout") 192 * 193 * This timeout controls how long node can remain silent until 194 * it is put under suspicion. If majority of the current group 195 * agree that the node is under suspicion, it is discarded from 196 * group and new group view is formed immediately. If majority 197 * of the group does not agree about suspicion, Conf::EvsInactiveTimeout 198 * is waited until forming of new group will be attempted. 199 * Default value is 5 seconds. 200 */ 201 static std::string const EvsSuspectTimeout; 202 203 /*! 204 * @brief EVS inactive timeout ("evs.inactive_timeout") 205 * 206 * This timeout control how long node can remain completely silent 207 * until it is discarded from the group. This is hard limit, unlike 208 * Conf::EvsSuspectTimeout, and the node is discarded even if it 209 * becomes live during the formation of the new group. Default value 210 * is 15 seconds. 211 */ 212 static std::string const EvsInactiveTimeout; 213 214 /*! 215 * @brief EVS inactive check period ("evs.inactive_check_period") 216 * 217 * This period controls how often node liveness is checked. Default 218 * is 1 second and there is no need to change this unless 219 * Conf::EvsSuspectTimeout or Conf::EvsInactiveTimeout is adjusted 220 * to smaller value. Default value is 1 second, minimum is 0.1 seconds 221 * and maximum is Conf::EvsSuspectTimeout/2. 222 */ 223 static std::string const EvsInactiveCheckPeriod; 224 225 226 static std::string const EvsInstallTimeout; 227 228 /*! 229 * @brief EVS keepalive period ("evs.keepalive_period") 230 * 231 * This timeout controls how often keepalive messages are 232 * sent into network. Node liveness is determined with 233 * these keepalives, so the value sould be significantly smaller 234 * than Conf::EvsSuspectTimeout. Default value is 1 second, 235 * minimum is 0.1 seconds and maximum is Conf::EvsSuspectTimeout/3. 236 */ 237 static std::string const EvsKeepalivePeriod; 238 239 /*! 240 * @brief EVS join retransmission period ("evs.join_retrans_period") 241 * 242 * This parameter controls how often join messages are retransmitted 243 * during group formation. There is usually no need to adjust 244 * this value. Default value is 0.3 seconds, minimum is 0.1 seconds 245 * and maximum is Conf::EvsSuspectTimeout/3. 246 */ 247 static std::string const EvsJoinRetransPeriod; 248 249 /*! 250 * @brief EVS statistics reporting period ("evs.stats_report_period") 251 * 252 * This parameters controls how often statistics information is 253 * printed in the log. This parameter has effect only if 254 * statistics reporting is enabled via Conf::EvsInfoLogMask. Default 255 * value is 1 minute. 256 */ 257 static std::string const EvsStatsReportPeriod; 258 259 /*! 260 * @brief EVS debug log mask ("evs.debug_log_mask") 261 * 262 * This mask controls what debug information is printed in the logs 263 * if debug logging is turned on. Mask value is bitwise-or 264 * from values gcomm::evs::Proto::DebugFlags. By default only 265 * state information is printed. 266 */ 267 static std::string const EvsDebugLogMask; 268 269 /*! 270 * @brief EVS info log mask ("evs.info_log_mask") 271 * 272 * This mask controls what info log is printed in the logs. 273 * Mask value is bitwise-or from values gcomm::evs::Proto::InfoFlags. 274 */ 275 static std::string const EvsInfoLogMask; 276 277 /*! 278 * @brief EVS send window ("evs.send_window") 279 * 280 * This parameter controls how many messages protocol layer is 281 * allowed to send without getting all acknowledgements for any of them. 282 * Default value is 32. 283 */ 284 static std::string const EvsSendWindow; 285 286 /*! 287 * @brief EVS user send window ("evs.user_send_window") 288 * 289 * Like Conf::EvsSendWindow, but for messages for which sending 290 * is initiated by call from upper layer. Default value is 16. 291 */ 292 static std::string const EvsUserSendWindow; 293 294 /*! 295 * @brief EVS message aggregation mode ("evs.use_aggregate") 296 * 297 * This parameter controls whether EVS is allowed to aggregate 298 * several user messages into one message. By default this option 299 * is enabled and there should be no need to disable it unless 300 * adviced so. 301 */ 302 static std::string const EvsUseAggregate; 303 304 /*! 305 * @brief Period to generate keepalives for causal messages 306 * 307 */ 308 static std::string const EvsCausalKeepalivePeriod; 309 310 /*! 311 * @brief EVS maximum install timeouts ("evs.max_install_timeouts") 312 * 313 * This parameter controls how many install attempts are done 314 * before declaring other nodes as inactive and trying to re-establish 315 * group via singleton views. 316 */ 317 static std::string const EvsMaxInstallTimeouts; 318 319 /*! 320 * @brief Margin over keepalive period after which node is declared 321 * delayed. This should be greater than the largest RTT 322 * between cluster nodes. 323 */ 324 static std::string const EvsDelayMargin; 325 326 /*! 327 * @brief Period which determines how long delayed node is kept in 328 * delayed list after it becomes responsive again. 329 * 330 * The actual time that node stays in delayed list is 331 * EvsDelayedKeepPeriod times the number of changes between 332 * OK and DELAYED state. 333 */ 334 static std::string const EvsDelayedKeepPeriod; 335 336 /*! 337 * @brief List of nodes (UUIDs) that should be evicted permanently from 338 * cluster. 339 * 340 * Setting value to nil UUID will clear the evict list. 341 */ 342 static std::string const EvsEvict; 343 344 /*! 345 * @brief Autoevict threshold. 346 */ 347 static std::string const EvsAutoEvict; 348 349 /*! 350 * @brief PC scheme for transport URI ("pc") 351 */ 352 static std::string const PcScheme; 353 354 /*! 355 * @brief PC protocol version 356 */ 357 static std::string const PcVersion; 358 359 /*! 360 * @brief PC split-brain mode 361 * 362 * This parameter controls whether PC is allowed to continue 363 * operation despite of possible split brain condition. 364 */ 365 static std::string const PcIgnoreSb; 366 367 /*! 368 * @brief PC quorum mode 369 * 370 * This parameter controls whether PC is allowed to continue 371 * operation despite of quorum loss. 372 */ 373 static std::string const PcIgnoreQuorum; 374 375 /*! 376 * @brief PC message checksumming 377 * 378 * This parameter controls whether PC layer does message 379 * checksumming. 380 */ 381 static std::string const PcChecksum; 382 383 /*! 384 * @brief PC starup announce timeout 385 */ 386 static std::string const PcAnnounceTimeout; 387 388 /*! 389 * @brief PC close linger timeout 390 */ 391 static std::string const PcLinger; 392 393 /*! 394 * @brief PC newer prim view overrides 395 */ 396 static std::string const PcNpvo; 397 398 /*! 399 * @brief If set during runtime bootstraps new PC 400 */ 401 static std::string const PcBootstrap; 402 403 /*! 404 * @brief Wait for prim comp unconditionally if set to true 405 */ 406 static std::string const PcWaitPrim; 407 408 /*! 409 * @brief Timeout on waiting for primary component 410 */ 411 static std::string const PcWaitPrimTimeout; 412 413 /*! 414 * @brief Node weight in prim comp voting 415 */ 416 static std::string const PcWeight; 417 418 /*! 419 * @brief PC recovery from cluster crash 420 */ 421 static std::string const PcRecovery; 422 423 static void register_params(gu::Config&); 424 425 static void check_params(const gu::Config&); 426 427 struct Check 428 { Checkgcomm::Conf::Check429 Check(gu::Config& conf) { check_params(conf); } ~Checkgcomm::Conf::Check430 virtual ~Check() {} // to pacify older GCCs with -Werror=effc++ 431 }; 432 433 static size_t check_recv_buf_size(const std::string& val); 434 static size_t check_send_buf_size(const std::string& val); 435 }; 436 437 438 // Helper templates to read configuration parameters. 439 _conf_param(const gu::URI & uri,const std::string & param,const T * default_value=0,const T * min_value=0,const T * max_value=0)440 template <typename T> T _conf_param(const gu::URI& uri, 441 const std::string& param, 442 const T* default_value = 0, 443 const T* min_value = 0, 444 const T* max_value = 0) 445 { 446 T ret; 447 try 448 { 449 ret = gu::from_string<T>(uri.get_option(param)); 450 } 451 catch (gu::NotFound& e) 452 { 453 // cppcheck-suppress nullPointer 454 if (default_value == 0) 455 { 456 gu_throw_error(EINVAL) 457 << "param " << param << " not found from uri " 458 << uri.to_string(); 459 } 460 // cppcheck-suppress nullPointer 461 ret = *default_value; 462 } 463 464 if (min_value != 0 && *min_value > ret) 465 { 466 gu_throw_error(EINVAL) 467 << "param " << param << " value " << ret << " out of range " 468 << "min allowed " << *min_value; 469 } 470 471 if (max_value != 0 && *max_value < ret) 472 { 473 gu_throw_error(EINVAL) 474 << "param " << param << " value " << ret << " out of range " 475 << "max allowed " << *max_value; 476 } 477 return ret; 478 } 479 conf_param(const gu::URI & uri,const std::string & param)480 template <typename T> T conf_param(const gu::URI& uri, 481 const std::string& param) 482 { 483 return _conf_param<T>(uri, param, 0, 0, 0); 484 } 485 conf_param_def(const gu::URI & uri,const std::string & param,const T & default_value)486 template <typename T> T conf_param_def(const gu::URI& uri, 487 const std::string& param, 488 const T& default_value) 489 { 490 return _conf_param(uri, param, &default_value); 491 } 492 conf_param_range(const gu::URI & uri,const std::string & param,const T & min_value,const T & max_value)493 template <typename T> T conf_param_range(const gu::URI& uri, 494 const std::string& param, 495 const T& min_value, 496 const T& max_value) 497 { 498 return _conf_param(uri, param, 0, &min_value, &max_value); 499 } 500 conf_param_def_min(const gu::URI & uri,const std::string & param,const T & default_value,const T & min_value)501 template <typename T> T conf_param_def_min(const gu::URI& uri, 502 const std::string& param, 503 const T& default_value, 504 const T& min_value) 505 506 { 507 return _conf_param(uri, param, &default_value, &min_value); 508 } 509 conf_param_def_max(const gu::URI & uri,const std::string & param,const T & default_value,const T & max_value)510 template <typename T> T conf_param_def_max(const gu::URI& uri, 511 const std::string& param, 512 const T& default_value, 513 const T& max_value) 514 515 { 516 return _conf_param(uri, param, &default_value, 517 reinterpret_cast<const T*>(0), &max_value); 518 } 519 conf_param_def_range(const gu::URI & uri,const std::string & param,const T & default_value,const T & min_value,const T & max_value)520 template <typename T> T conf_param_def_range(const gu::URI& uri, 521 const std::string& param, 522 const T& default_value, 523 const T& min_value, 524 const T& max_value) 525 { 526 return _conf_param(uri, param, &default_value, &min_value, &max_value); 527 } 528 529 530 531 template <typename T> param(gu::Config & conf,const gu::URI & uri,const std::string & key,const std::string & def,std::ios_base & (* f)(std::ios_base &)=std::dec)532 T param(gu::Config& conf, 533 const gu::URI& uri, 534 const std::string& key, 535 const std::string& def, 536 std::ios_base& (*f)(std::ios_base&) = std::dec) 537 { 538 T ret; 539 540 try 541 { 542 std::string cnf(conf.get(key, def)); 543 std::string val(uri.get_option(key, cnf)); 544 try 545 { 546 ret = gu::from_string<T>(val, f); 547 } 548 catch (gu::NotFound) 549 { 550 gu_throw_error(EINVAL) << "Bad value '" << val 551 << "' for parameter '" << key << "'"; 552 } 553 } 554 catch (gu::NotFound) 555 { 556 gu_throw_error(EINVAL) << "Unrecognized parameter '" << key << "'"; 557 } 558 559 return ret; 560 } 561 562 template <typename T> check_range(const std::string & key,const T & val,const T & min,const T & max)563 T check_range(const std::string& key, 564 const T& val, 565 const T& min, 566 const T& max) 567 { 568 if (val < min || val >= max) 569 { 570 gu_throw_error(ERANGE) << "parameter '" << key << "' value " << val 571 << " is out of range [" << min 572 << "," << max << ")"; 573 } 574 return val; 575 } 576 577 template <typename T> check_range(const std::string & key,const std::string & val,const T & min,const T & max)578 T check_range(const std::string& key, 579 const std::string& val, 580 const T& min, 581 const T& max) 582 { 583 return check_range<T>(key, gu::Config::from_config<T>(val), min, max); 584 } 585 586 template <typename T> check_range(const gu::Config & conf,const std::string & key,const T & min,const T & max)587 T check_range(const gu::Config& conf, 588 const std::string& key, 589 const T& min, 590 const T& max) 591 { 592 return check_range<T>(key, conf.get(key), min, max); 593 } 594 595 } // namespace gcomm 596 597 #endif // GCOMM_CONF_HPP 598