1 /* 2 * dbutils.h 3 * 4 * Copyright (c) 2ndQuadrant, 2010-2020 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef _REPMGR_DBUTILS_H_ 21 #define _REPMGR_DBUTILS_H_ 22 23 #include "access/timeline.h" 24 #include "access/xlogdefs.h" 25 #include "pqexpbuffer.h" 26 #include "portability/instr_time.h" 27 28 #include "configfile.h" 29 #include "strutil.h" 30 #include "voting.h" 31 32 #define REPMGR_NODES_COLUMNS \ 33 "n.node_id, " \ 34 "n.type, " \ 35 "n.upstream_node_id, " \ 36 "n.node_name, " \ 37 "n.conninfo, " \ 38 "n.repluser, " \ 39 "n.slot_name, " \ 40 "n.location, " \ 41 "n.priority, " \ 42 "n.active, " \ 43 "n.config_file, " \ 44 "'' AS upstream_node_name, " \ 45 "NULL AS attached " 46 47 #define REPMGR_NODES_COLUMNS_WITH_UPSTREAM \ 48 "n.node_id, " \ 49 "n.type, " \ 50 "n.upstream_node_id, " \ 51 "n.node_name, " \ 52 "n.conninfo, " \ 53 "n.repluser, " \ 54 "n.slot_name, " \ 55 "n.location, " \ 56 "n.priority, " \ 57 "n.active, "\ 58 "n.config_file, " \ 59 "un.node_name AS upstream_node_name, " \ 60 "NULL AS attached " 61 62 63 #define ERRBUFF_SIZE 512 64 65 typedef enum 66 { 67 UNKNOWN = 0, 68 PRIMARY, 69 STANDBY, 70 WITNESS 71 } t_server_type; 72 73 typedef enum 74 { 75 REPMGR_INSTALLED = 0, 76 REPMGR_OLD_VERSION_INSTALLED, 77 REPMGR_AVAILABLE, 78 REPMGR_UNAVAILABLE, 79 REPMGR_UNKNOWN 80 } ExtensionStatus; 81 82 typedef enum 83 { 84 RECTYPE_UNKNOWN = -1, 85 RECTYPE_PRIMARY, 86 RECTYPE_STANDBY 87 } RecoveryType; 88 89 typedef enum 90 { 91 RECORD_ERROR = -1, 92 RECORD_FOUND, 93 RECORD_NOT_FOUND 94 } RecordStatus; 95 96 typedef enum 97 { 98 MS_NORMAL = 0, 99 MS_DEGRADED = 1 100 } MonitoringState; 101 102 typedef enum 103 { 104 NODE_STATUS_UNKNOWN = -1, 105 NODE_STATUS_UP, 106 NODE_STATUS_SHUTTING_DOWN, 107 NODE_STATUS_DOWN, 108 NODE_STATUS_UNCLEAN_SHUTDOWN, 109 NODE_STATUS_REJECTED 110 } NodeStatus; 111 112 typedef enum 113 { 114 CONN_UNKNOWN = -1, 115 CONN_OK, 116 CONN_BAD, 117 CONN_ERROR 118 } ConnectionStatus; 119 120 typedef enum 121 { 122 /* unable to query "pg_stat_replication" or other error */ 123 NODE_ATTACHED_UNKNOWN = -1, 124 /* node has record in "pg_stat_replication" and state is not "streaming" */ 125 NODE_ATTACHED, 126 /* node has record in "pg_stat_replication" but state is not "streaming" */ 127 NODE_NOT_ATTACHED, 128 /* node has no record in "pg_stat_replication" */ 129 NODE_DETACHED 130 } NodeAttached; 131 132 typedef enum 133 { 134 SLOT_UNKNOWN = -1, 135 SLOT_NOT_FOUND, 136 SLOT_NOT_PHYSICAL, 137 SLOT_INACTIVE, 138 SLOT_ACTIVE 139 } ReplSlotStatus; 140 141 typedef enum 142 { 143 BACKUP_STATE_UNKNOWN = -1, 144 BACKUP_STATE_IN_BACKUP, 145 BACKUP_STATE_NO_BACKUP 146 } BackupState; 147 148 149 150 /* 151 * Struct to store extension version information 152 */ 153 154 typedef struct s_extension_versions { 155 char default_version[8]; 156 int default_version_num; 157 char installed_version[8]; 158 int installed_version_num; 159 } t_extension_versions; 160 161 #define T_EXTENSION_VERSIONS_INITIALIZER { \ 162 "", \ 163 UNKNOWN_SERVER_VERSION_NUM, \ 164 "", \ 165 UNKNOWN_SERVER_VERSION_NUM \ 166 } 167 168 169 typedef struct 170 { 171 char current_timestamp[MAXLEN]; 172 bool in_recovery; 173 TimeLineID timeline_id; 174 char timeline_id_str[MAXLEN]; 175 XLogRecPtr last_wal_receive_lsn; 176 XLogRecPtr last_wal_replay_lsn; 177 char last_xact_replay_timestamp[MAXLEN]; 178 int replication_lag_time; 179 bool receiving_streamed_wal; 180 bool wal_replay_paused; 181 int upstream_last_seen; 182 int upstream_node_id; 183 } ReplInfo; 184 185 /* 186 * Struct to store node information. 187 * 188 * The first section represents the contents of the "repmgr.nodes" 189 * table; subsequent section contain information collated in 190 * various contexts. 191 */ 192 typedef struct s_node_info 193 { 194 /* contents of "repmgr.nodes" */ 195 int node_id; 196 int upstream_node_id; 197 t_server_type type; 198 char node_name[NAMEDATALEN]; 199 char upstream_node_name[NAMEDATALEN]; 200 char conninfo[MAXLEN]; 201 char repluser[NAMEDATALEN]; 202 char location[MAXLEN]; 203 int priority; 204 bool active; 205 char slot_name[MAXLEN]; 206 char config_file[MAXPGPATH]; 207 /* used during failover to track node status */ 208 XLogRecPtr last_wal_receive_lsn; 209 NodeStatus node_status; 210 RecoveryType recovery_type; 211 MonitoringState monitoring_state; 212 PGconn *conn; 213 /* for ad-hoc use e.g. when working with a list of nodes */ 214 char details[MAXLEN]; 215 bool reachable; 216 NodeAttached attached; 217 /* various statistics */ 218 int max_wal_senders; 219 int attached_wal_receivers; 220 int max_replication_slots; 221 int total_replication_slots; 222 int active_replication_slots; 223 int inactive_replication_slots; 224 /* replication info */ 225 ReplInfo *replication_info; 226 } t_node_info; 227 228 229 #define T_NODE_INFO_INITIALIZER { \ 230 /* contents of "repmgr.nodes" */ \ 231 NODE_NOT_FOUND, \ 232 NO_UPSTREAM_NODE, \ 233 UNKNOWN, \ 234 "", \ 235 "", \ 236 "", \ 237 "", \ 238 DEFAULT_LOCATION, \ 239 DEFAULT_PRIORITY, \ 240 true, \ 241 "", \ 242 "", \ 243 /* used during failover to track node status */ \ 244 InvalidXLogRecPtr, \ 245 NODE_STATUS_UNKNOWN, \ 246 RECTYPE_UNKNOWN, \ 247 MS_NORMAL, \ 248 NULL, \ 249 /* for ad-hoc use e.g. when working with a list of nodes */ \ 250 "", true, true, \ 251 /* various statistics */ \ 252 -1, -1, -1, -1, -1, -1, \ 253 NULL \ 254 } 255 256 257 /* structs to store a list of repmgr node records */ 258 typedef struct NodeInfoListCell 259 { 260 struct NodeInfoListCell *next; 261 t_node_info *node_info; 262 } NodeInfoListCell; 263 264 typedef struct NodeInfoList 265 { 266 NodeInfoListCell *head; 267 NodeInfoListCell *tail; 268 int node_count; 269 } NodeInfoList; 270 271 #define T_NODE_INFO_LIST_INITIALIZER { \ 272 NULL, \ 273 NULL, \ 274 0 \ 275 } 276 277 typedef struct s_event_info 278 { 279 char *node_name; 280 char *conninfo_str; 281 int node_id; 282 } t_event_info; 283 284 #define T_EVENT_INFO_INITIALIZER { \ 285 NULL, \ 286 NULL, \ 287 UNKNOWN_NODE_ID \ 288 } 289 290 291 /* 292 * Struct to store list of conninfo keywords and values 293 */ 294 typedef struct 295 { 296 int size; 297 char **keywords; 298 char **values; 299 } t_conninfo_param_list; 300 301 #define T_CONNINFO_PARAM_LIST_INITIALIZER { \ 302 0, \ 303 NULL, \ 304 NULL, \ 305 } 306 307 /* 308 * Struct to store replication slot information 309 */ 310 typedef struct s_replication_slot 311 { 312 char slot_name[MAXLEN]; 313 char slot_type[MAXLEN]; 314 bool active; 315 } t_replication_slot; 316 317 #define T_REPLICATION_SLOT_INITIALIZER { "", "", false } 318 319 320 typedef struct s_connection_user 321 { 322 char username[MAXLEN]; 323 bool is_superuser; 324 } t_connection_user; 325 326 #define T_CONNECTION_USER_INITIALIZER { "", false } 327 328 329 typedef struct 330 { 331 char filepath[MAXPGPATH]; 332 char filename[MAXPGPATH]; 333 bool in_data_directory; 334 } t_configfile_info; 335 336 #define T_CONFIGFILE_INFO_INITIALIZER { "", "", false } 337 338 339 typedef struct 340 { 341 int size; 342 int entries; 343 t_configfile_info **files; 344 } t_configfile_list; 345 346 #define T_CONFIGFILE_LIST_INITIALIZER { 0, 0, NULL } 347 348 349 typedef struct 350 { 351 uint64 system_identifier; 352 TimeLineID timeline; 353 XLogRecPtr xlogpos; 354 } t_system_identification; 355 356 #define T_SYSTEM_IDENTIFICATION_INITIALIZER { \ 357 UNKNOWN_SYSTEM_IDENTIFIER, \ 358 UNKNOWN_TIMELINE_ID, \ 359 InvalidXLogRecPtr \ 360 } 361 362 363 typedef struct RepmgrdInfo { 364 int node_id; 365 int pid; 366 char pid_text[MAXLEN]; 367 char pid_file[MAXLEN]; 368 bool pg_running; 369 char pg_running_text[MAXLEN]; 370 RecoveryType recovery_type; 371 bool running; 372 char repmgrd_running[MAXLEN]; 373 bool paused; 374 bool wal_paused_pending_wal; 375 int upstream_last_seen; 376 char upstream_last_seen_text[MAXLEN]; 377 } RepmgrdInfo; 378 379 380 /* macros */ 381 382 #define is_streaming_replication(x) (x == PRIMARY || x == STANDBY) 383 #define format_lsn(x) (uint32) (x >> 32), (uint32) x 384 385 /* utility functions */ 386 387 XLogRecPtr parse_lsn(const char *str); 388 bool atobool(const char *value); 389 390 /* connection functions */ 391 PGconn *establish_db_connection(const char *conninfo, 392 const bool exit_on_error); 393 PGconn *establish_db_connection_quiet(const char *conninfo); 394 PGconn *establish_db_connection_by_params(t_conninfo_param_list *param_list, 395 const bool exit_on_error); 396 PGconn *establish_db_connection_with_replacement_param(const char *conninfo, 397 const char *param, 398 const char *value, 399 const bool exit_on_error); 400 PGconn *establish_replication_connection_from_conn(PGconn *conn, const char *repluser); 401 PGconn *establish_replication_connection_from_conninfo(const char *conninfo, const char *repluser); 402 403 PGconn *establish_primary_db_connection(PGconn *conn, 404 const bool exit_on_error); 405 PGconn *get_primary_connection(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out); 406 PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out); 407 PGconn *duplicate_connection(PGconn *conn, const char *user, bool replication); 408 409 void close_connection(PGconn **conn); 410 411 /* conninfo manipulation functions */ 412 bool get_conninfo_value(const char *conninfo, const char *keyword, char *output); 413 bool get_conninfo_default_value(const char *param, char *output, int maxlen); 414 void initialize_conninfo_params(t_conninfo_param_list *param_list, bool set_defaults); 415 void free_conninfo_params(t_conninfo_param_list *param_list); 416 void copy_conninfo_params(t_conninfo_param_list *dest_list, t_conninfo_param_list *source_list); 417 void conn_to_param_list(PGconn *conn, t_conninfo_param_list *param_list); 418 void param_set(t_conninfo_param_list *param_list, const char *param, const char *value); 419 void param_set_ine(t_conninfo_param_list *param_list, const char *param, const char *value); 420 char *param_get(t_conninfo_param_list *param_list, const char *param); 421 bool validate_conninfo_string(const char *conninfo_str, char **errmsg); 422 bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *param_list, char **errmsg, bool ignore_local_params); 423 char *param_list_to_string(t_conninfo_param_list *param_list); 424 char *normalize_conninfo_string(const char *conninfo_str); 425 bool has_passfile(void); 426 427 428 /* transaction functions */ 429 bool begin_transaction(PGconn *conn); 430 bool commit_transaction(PGconn *conn); 431 bool rollback_transaction(PGconn *conn); 432 433 /* GUC manipulation functions */ 434 bool set_config(PGconn *conn, const char *config_param, const char *config_value); 435 bool set_config_bool(PGconn *conn, const char *config_param, bool state); 436 int guc_set(PGconn *conn, const char *parameter, const char *op, const char *value); 437 bool get_pg_setting(PGconn *conn, const char *setting, char *output); 438 bool get_pg_setting_bool(PGconn *conn, const char *setting, bool *output); 439 bool get_pg_setting_int(PGconn *conn, const char *setting, int *output); 440 bool alter_system_int(PGconn *conn, const char *name, int value); 441 bool pg_reload_conf(PGconn *conn); 442 443 /* server information functions */ 444 bool get_cluster_size(PGconn *conn, char *size); 445 int get_server_version(PGconn *conn, char *server_version_buf); 446 447 RecoveryType get_recovery_type(PGconn *conn); 448 int get_primary_node_id(PGconn *conn); 449 int get_ready_archive_files(PGconn *conn, const char *data_directory); 450 bool identify_system(PGconn *repl_conn, t_system_identification *identification); 451 uint64 system_identifier(PGconn *conn); 452 TimeLineHistoryEntry *get_timeline_history(PGconn *repl_conn, TimeLineID tli); 453 454 /* user/role information functions */ 455 bool can_execute_pg_promote(PGconn *conn); 456 bool connection_has_pg_monitor_role(PGconn *conn, const char *subrole); 457 bool is_replication_role(PGconn *conn, char *rolname); 458 bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo); 459 460 /* repmgrd shared memory functions */ 461 bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id); 462 int repmgrd_get_local_node_id(PGconn *conn); 463 bool repmgrd_check_local_node_id(PGconn *conn); 464 BackupState server_in_exclusive_backup_mode(PGconn *conn); 465 void repmgrd_set_pid(PGconn *conn, pid_t repmgrd_pid, const char *pidfile); 466 pid_t repmgrd_get_pid(PGconn *conn); 467 bool repmgrd_is_running(PGconn *conn); 468 bool repmgrd_is_paused(PGconn *conn); 469 bool repmgrd_pause(PGconn *conn, bool pause); 470 pid_t get_wal_receiver_pid(PGconn *conn); 471 int repmgrd_get_upstream_node_id(PGconn *conn); 472 bool repmgrd_set_upstream_node_id(PGconn *conn, int node_id); 473 474 /* extension functions */ 475 ExtensionStatus get_repmgr_extension_status(PGconn *conn, t_extension_versions *extversions); 476 477 /* node management functions */ 478 void checkpoint(PGconn *conn); 479 bool vacuum_table(PGconn *conn, const char *table); 480 bool promote_standby(PGconn *conn, bool wait, int wait_seconds); 481 bool resume_wal_replay(PGconn *conn); 482 483 /* node record functions */ 484 t_server_type parse_node_type(const char *type); 485 const char *get_node_type_string(t_server_type type); 486 487 RecordStatus get_node_record(PGconn *conn, int node_id, t_node_info *node_info); 488 RecordStatus refresh_node_record(PGconn *conn, int node_id, t_node_info *node_info); 489 490 RecordStatus get_node_record_with_upstream(PGconn *conn, int node_id, t_node_info *node_info); 491 492 RecordStatus get_node_record_by_name(PGconn *conn, const char *node_name, t_node_info *node_info); 493 t_node_info *get_node_record_pointer(PGconn *conn, int node_id); 494 495 bool get_local_node_record(PGconn *conn, int node_id, t_node_info *node_info); 496 bool get_primary_node_record(PGconn *conn, t_node_info *node_info); 497 498 bool get_all_node_records(PGconn *conn, NodeInfoList *node_list); 499 bool get_all_nodes_count(PGconn *conn, int *count); 500 void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *nodes); 501 void get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, NodeInfoList *node_list); 502 bool get_child_nodes(PGconn *conn, int node_id, NodeInfoList *node_list); 503 void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list); 504 bool get_all_node_records_with_upstream(PGconn *conn, NodeInfoList *node_list); 505 bool get_downstream_nodes_with_missing_slot(PGconn *conn, int this_node_id, NodeInfoList *noede_list); 506 507 bool create_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info); 508 bool update_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info); 509 bool delete_node_record(PGconn *conn, int node); 510 bool truncate_node_records(PGconn *conn); 511 512 bool update_node_record_set_active(PGconn *conn, int this_node_id, bool active); 513 bool update_node_record_set_primary(PGconn *conn, int this_node_id); 514 bool update_node_record_set_active_standby(PGconn *conn, int this_node_id); 515 bool update_node_record_set_upstream(PGconn *conn, int this_node_id, int new_upstream_node_id); 516 bool update_node_record_status(PGconn *conn, int this_node_id, char *type, int upstream_node_id, bool active); 517 bool update_node_record_conn_priority(PGconn *conn, t_configuration_options *options); 518 bool update_node_record_slot_name(PGconn *primary_conn, int node_id, char *slot_name); 519 520 bool witness_copy_node_records(PGconn *primary_conn, PGconn *witness_conn); 521 522 void clear_node_info_list(NodeInfoList *nodes); 523 524 /* PostgreSQL configuration file location functions */ 525 bool get_datadir_configuration_files(PGconn *conn, KeyValueList *list); 526 bool get_configuration_file_locations(PGconn *conn, t_configfile_list *list); 527 void config_file_list_init(t_configfile_list *list, int max_size); 528 void config_file_list_add(t_configfile_list *list, const char *file, const char *filename, bool in_data_dir); 529 530 /* event functions */ 531 bool create_event_record(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details); 532 bool create_event_notification(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details); 533 bool create_event_notification_extended(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details, t_event_info *event_info); 534 PGresult *get_event_records(PGconn *conn, int node_id, const char *node_name, const char *event, bool all, int limit); 535 536 /* replication slot functions */ 537 void create_slot_name(char *slot_name, int node_id); 538 539 bool create_replication_slot_sql(PGconn *conn, char *slot_name, PQExpBufferData *error_msg); 540 bool create_replication_slot_replprot(PGconn *conn, PGconn *repl_conn, char *slot_name, PQExpBufferData *error_msg); 541 bool drop_replication_slot_sql(PGconn *conn, char *slot_name); 542 bool drop_replication_slot_replprot(PGconn *repl_conn, char *slot_name); 543 544 RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record); 545 int get_free_replication_slot_count(PGconn *conn, int *max_replication_slots); 546 int get_inactive_replication_slots(PGconn *conn, KeyValueList *list); 547 548 /* tablespace functions */ 549 bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name); 550 551 /* asynchronous query functions */ 552 bool cancel_query(PGconn *conn, int timeout); 553 int wait_connection_availability(PGconn *conn, int timeout); 554 555 /* node availability functions */ 556 bool is_server_available(const char *conninfo); 557 bool is_server_available_quiet(const char *conninfo); 558 bool is_server_available_params(t_conninfo_param_list *param_list); 559 ExecStatusType connection_ping(PGconn *conn); 560 ExecStatusType connection_ping_reconnect(PGconn *conn); 561 562 /* monitoring functions */ 563 void 564 add_monitoring_record(PGconn *primary_conn, 565 PGconn *local_conn, 566 int primary_node_id, 567 int local_node_id, 568 char *monitor_standby_timestamp, 569 XLogRecPtr primary_last_wal_location, 570 XLogRecPtr last_wal_receive_lsn, 571 char *last_xact_replay_timestamp, 572 long long unsigned int replication_lag_bytes, 573 long long unsigned int apply_lag_bytes 574 ); 575 576 int get_number_of_monitoring_records_to_delete(PGconn *primary_conn, int keep_history, int node_id); 577 bool delete_monitoring_records(PGconn *primary_conn, int keep_history, int node_id); 578 579 580 581 /* node voting functions */ 582 void initialize_voting_term(PGconn *conn); 583 int get_current_term(PGconn *conn); 584 void increment_current_term(PGconn *conn); 585 bool announce_candidature(PGconn *conn, t_node_info *this_node, t_node_info *other_node, int electoral_term); 586 void notify_follow_primary(PGconn *conn, int primary_node_id); 587 bool get_new_primary(PGconn *conn, int *primary_node_id); 588 void reset_voting_status(PGconn *conn); 589 590 /* replication status functions */ 591 XLogRecPtr get_primary_current_lsn(PGconn *conn); 592 XLogRecPtr get_node_current_lsn(PGconn *conn); 593 XLogRecPtr get_last_wal_receive_location(PGconn *conn); 594 void init_replication_info(ReplInfo *replication_info); 595 bool get_replication_info(PGconn *conn, t_server_type node_type, ReplInfo *replication_info); 596 int get_replication_lag_seconds(PGconn *conn); 597 TimeLineID get_node_timeline(PGconn *conn, char *timeline_id_str); 598 void get_node_replication_stats(PGconn *conn, t_node_info *node_info); 599 NodeAttached is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state); 600 void set_upstream_last_seen(PGconn *conn, int upstream_node_id); 601 int get_upstream_last_seen(PGconn *conn, t_server_type node_type); 602 603 bool is_wal_replay_paused(PGconn *conn, bool check_pending_wal); 604 605 /* miscellaneous debugging functions */ 606 const char *print_node_status(NodeStatus node_status); 607 const char *print_pqping_status(PGPing ping_status); 608 609 #endif /* _REPMGR_DBUTILS_H_ */ 610