Compare commits

..

3 Commits

Author SHA1 Message Date
Christian Kruse
0a71123920 Merge branch 'master' into REL2_0_STABLE 2014-03-03 09:25:08 +01:00
Christian Kruse
a72c2296e9 Merge branch 'master' into REL2_0_STABLE 2014-02-11 09:28:40 +01:00
Christian Kruse
9c3d79147b now version.h contains the right version 2014-02-07 21:47:39 +01:00
26 changed files with 1558 additions and 2385 deletions

View File

@@ -1,11 +1,3 @@
2.0.1 2014-07-16
Documentation fixes and new QUICKSTART file (Ian)
Explicitly specify directories to ignore when cloning (Ian)
Fix log level for some log messages (Ian)
RHEL/CentOS specfile, init script and Makefile fixes (Nathan Van Overloop)
Debian init script and config file documentation fixes (József Kószó)
Typo fixes (Riegie Godwin Jeyaranchen, PriceChild)
2.0stable 2014-01-30 2.0stable 2014-01-30
Documentation fixes (Christian) Documentation fixes (Christian)
General refactoring, code quality improvements and stabilization work (Christian) General refactoring, code quality improvements and stabilization work (Christian)

View File

@@ -36,24 +36,12 @@ endif
install: install_prog install_ext install: install_prog install_ext
install_prog: install_prog:
mkdir -p '$(DESTDIR)$(bindir)' $(INSTALL_PROGRAM) repmgrd$(X) '$(DESTDIR)$(bindir)'
$(INSTALL_PROGRAM) repmgrd$(X) '$(DESTDIR)$(bindir)/' $(INSTALL_PROGRAM) repmgr$(X) '$(DESTDIR)$(bindir)'
$(INSTALL_PROGRAM) repmgr$(X) '$(DESTDIR)$(bindir)/'
install_ext: install_ext:
$(MAKE) -C sql install $(MAKE) -C sql install
install_rhel:
mkdir -p '$(DESTDIR)/etc/init.d/'
$(INSTALL_PROGRAM) RHEL/repmgrd.init '$(DESTDIR)/etc/init.d/repmgrd'
mkdir -p '$(DESTDIR)/etc/sysconfig/'
$(INSTALL_PROGRAM) RHEL/repmgrd.sysconfig '$(DESTDIR)/etc/sysconfig/repmgrd'
mkdir -p '$(DESTDIR)/etc/repmgr/'
$(INSTALL_PROGRAM) repmgr.conf.sample '$(DESTDIR)/etc/repmgr/'
mkdir -p '$(DESTDIR)/usr/bin/'
$(INSTALL_PROGRAM) repmgrd$(X) '$(DESTDIR)/usr/bin/'
$(INSTALL_PROGRAM) repmgr$(X) '$(DESTDIR)/usr/bin/'
ifneq (,$(DATA)$(DATA_built)) ifneq (,$(DATA)$(DATA_built))
@for file in $(addprefix $(srcdir)/, $(DATA)) $(DATA_built); do \ @for file in $(addprefix $(srcdir)/, $(DATA)) $(DATA_built); do \
echo "$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/$(datamoduledir)'"; \ echo "$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/$(datamoduledir)'"; \
@@ -79,4 +67,3 @@ deb: repmgrd repmgr
mv debian.deb ../postgresql-repmgr-9.0_1.0.0.deb mv debian.deb ../postgresql-repmgr-9.0_1.0.0.deb
rm -rf ./debian/usr rm -rf ./debian/usr

View File

@@ -1,286 +0,0 @@
repmgr: Quickstart guide
========================
repmgr is an open-source tool suite for mananaging replication and failover
among multiple PostgreSQL server nodes. It enhances PostgreSQL's built-in
hot-standby capabilities with a set of administration tools for monitoring
replication, setting up standby servers and performing failover/switchover
operations.
This quickstart guide assumes you are familiar with PostgreSQL replication
setup and Linux/UNIX system administration. For a more detailed tutorial
covering setup on a variety of different systems, see the README.rst file.
Conceptual Overview
-------------------
repmgr provides two binaries:
- `repmgr`: a command-line client to manage replication and repmgr configuration
- `repmgrd`: an optional daemon process which runs on standby nodes to monitor
replication and node status
Each PostgreSQL node requires a repmgr configuration file; additionally
it must be "registered" using the repmgr command-line client. repmgr stores
information about managed nodes in a custom schema on the node's current master
database.
Requirements
------------
repmgr works with PostgreSQL 9.0 and later. All server nodes must be running the
same PostgreSQL major version, and preferably should be running the same minor
version.
repmgr will work on any Linux or UNIX-like environment capable of running
PostgreSQL. `rsync` must also be installed.
Installation
------------
repmgr must be installed on each PostgreSQL server node.
* Packages
- RPM packages for RedHat-based distributions are available from PGDG
- Debian/Ubuntu provide .deb packages.
It is also possible to build .deb packages directly from the repmgr source;
see README.rst for further details.
* Source installation
- repmgr source code is hosted at github (https://github.com/2ndQuadrant/repmgr);
tar.gz files can be downloaded from https://github.com/2ndQuadrant/repmgr/releases .
repmgr can be built easily using PGXS:
sudo make USE_PGXS=1 install
Configuration
-------------
### Server configuration
Password-less SSH logins must be enabled for the database system user (typically `postgres`)
between all server nodes to enable repmgr to copy required files.
### PostgreSQL configuration
The master PostgreSQL node needs to be configured for replication with the
following settings:
wal_level = 'hot_standby' # minimal, archive, hot_standby, or logical
archive_mode = on # allows archiving to be done
archive_command = 'cd .' # command to use to archive a logfile segment
max_wal_senders = 10 # max number of walsender processes
wal_keep_segments = 5000 # in logfile segments, 16MB each; 0 disables
hot_standby = on # "on" allows queries during recovery
Note that repmgr expects a default of 5000 wal_keep_segments, although this
value can be overridden when executing the `repmgr` client.
Additionally, repmgr requires a dedicated PostgreSQL superuser account
and a database in which to store monitoring and replication data. The
database can in principle be any database, including the default postgres
one, however it's probably advisable to create a dedicated repmgr database.
### repmgr configuration
Each PostgreSQL node requires a repmgr configuration file containing
identification and database connection information:
cluster=test
node=1
node_name=node1
conninfo='host=repmgr_node1 user=repmgr_usr dbname=repmgr_db'
pg_bindir=/path/to/postgres/bin
* `cluster`: common name for the replication cluster; this must be the same on all nodes
* `node`: a unique, abitrary integer identifier
* `name`: a unique, human-readable name
* `conninfo`: a standard conninfo string enabling repmgr to connect to the
control database; user and name must be the same on all nodes, while other
parameters such as port may differ. The `host` parameter *must* be a hostname
resolvable by all nodes on the cluster.
* `pg_bindir`: (optional) location of PostgreSQL binaries, if not in the default $PATH
Note that the configuration file should *not* be stored inside the PostgreSQL
data directory.
Each node configuration needs to be registered with repmgr, either using the
`repmgr` command line tool, or the `repmgrd` daemon; for details see below. Details
about each node are inserted into the repmgr database (for details see below).
Replication setup and monitoring
--------------------------------
For the purposes of this guide, we'll assume the database user will be
`repmgr_usr` and the database will be `repmgr_db`, and that the following
environment variables are set on each node:
- $HOME: the PostgreSQL system user's home directory
- $PGDATA: the PostgreSQL data directory
Master setup
------------
1. Configure PostgreSQL
- create user and database:
```
CREATE ROLE repmgr_usr LOGIN SUPERUSER;
CREATE DATABASE repmgr_db OWNER repmgr_usr;
```
- configure postgresql.conf for replication (see above)
- update pg_hba.conf:
```
host repmgr_usr repmgr_db 192.168.1.0/24 trust
host replication all 192.168.1.0/24 trust
```
Restart the PostgreSQL server after making these changes.
2. Create the repmgr configuration file:
$ cat $HOME/repmgr/repmgr.conf
cluster=test
node=1
node_name=node1
conninfo='host=repmgr_node1 user=repmgr_usr dbname=repmgr_db'
pg_bindir=/path/to/postgres/bin
3. Register the master node with repmgr:
$ repmgr -f $HOME/repmgr/repmgr.conf --verbose master register
[2014-07-04 10:43:42] [INFO] repmgr mgr connecting to master database
[2014-07-04 10:43:42] [INFO] repmgr connected to master, checking its state
[2014-07-04 10:43:42] [INFO] master register: creating database objects inside the repmgr_test schema
[2014-07-04 10:43:43] [NOTICE] Master node correctly registered for cluster test with id 1 (conninfo: host=localhost user=repmgr_usr dbname=repmgr_db)
Slave/standby setup
-------------------
1. Use repmgr to clone the master:
$ repmgr -f $HOME/repmgr/repmgr.conf -D $PGDATA -d repmgr_db -U repmgr_usr -R postgres --verbose standby clone 192.168.1.2
Opening configuration file: ./repmgr.conf
[2014-07-04 10:49:00] [ERROR] Did not find the configuration file './repmgr.conf', continuing
[2014-07-04 10:49:00] [INFO] repmgr connecting to master database
[2014-07-04 10:49:00] [INFO] repmgr connected to master, checking its state
[2014-07-04 10:49:00] [INFO] Successfully connected to primary. Current installation size is 1807 MB
[2014-07-04 10:49:00] [NOTICE] Starting backup...
[2014-07-04 10:49:00] [INFO] creating directory "/path/to/data/"...
(...)
[2014-07-04 10:53:19] [NOTICE] Finishing backup...
NOTICE: pg_stop_backup complete, all required WAL segments have been archived
[2014-07-04 10:53:21] [INFO] repmgr requires primary to keep WAL files 0000000100000000000000AD until at least 0000000100000000000000AD
[2014-07-04 10:53:21] [NOTICE] repmgr standby clone complete
[2014-07-04 10:53:21] [NOTICE] HINT: You can now start your postgresql server
[2014-07-04 10:53:21] [NOTICE] for example : /etc/init.d/postgresql start
-R is the database system user on the master node. At this point it does not matter
if the `repmgr.conf` file is not found.
This will clone the PostgreSQL database files from the master, and additionally
create an appropriate `recovery.conf` file.
2. Start the PostgreSQL server
3. Create the repmgr configuration file:
$ cat $HOME/repmgr/repmgr.conf
cluster=test
node=2
node_name=node2
conninfo='host=repmgr_node2 user=repmgr_usr dbname=repmgr_db'
pg_bindir=/path/to/postgres/bin
4. Register the master node with repmgr:
$ repmgr -f $HOME/repmgr/repmgr.conf --verbose standby register
Opening configuration file: /path/to/repmgr/repmgr.conf
[2014-07-04 11:48:13] [INFO] repmgr connecting to standby database
[2014-07-04 11:48:13] [INFO] repmgr connected to standby, checking its state
[2014-07-04 11:48:13] [INFO] repmgr connecting to master database
[2014-07-04 11:48:13] [INFO] finding node list for cluster 'test'
[2014-07-04 11:48:13] [INFO] checking role of cluster node 'host=repmgr_node1 user=repmgr_usr dbname=repmgr_db'
[2014-07-04 11:48:13] [INFO] repmgr connected to master, checking its state
[2014-07-04 11:48:13] [INFO] repmgr registering the standby
[2014-07-04 11:48:13] [INFO] repmgr registering the standby complete
[2014-07-04 11:48:13] [NOTICE] Standby node correctly registered for cluster test with id 2 (conninfo: host=localhost user=repmgr_usr dbname=repmgr_db)
Monitoring
----------
`repmgrd` is a management and monitoring daemon which runs on standby nodes
and which and can automate remote actions. It can be started simply with e.g.:
repmgrd -f $HOME/repmgr/repmgr.conf --verbose > $HOME/repmgr/repmgr.log 2>&1
or alternatively:
repmgrd -f $HOME/repmgr/repmgr.conf --verbose --monitoring-history > $HOME/repmgr/repmgrd.log 2>&1
which will track advance or lag of the replication in every standby in the
`repl_monitor` table.
Example log output:
[2014-07-04 11:55:17] [INFO] repmgrd Connecting to database 'host=localhost user=repmgr_usr dbname=repmgr_db'
[2014-07-04 11:55:17] [INFO] repmgrd Connected to database, checking its state
[2014-07-04 11:55:17] [INFO] repmgrd Connecting to primary for cluster 'test'
[2014-07-04 11:55:17] [INFO] finding node list for cluster 'test'
[2014-07-04 11:55:17] [INFO] checking role of cluster node 'host=repmgr_node1 user=repmgr_usr dbname=repmgr_db'
[2014-07-04 11:55:17] [INFO] repmgrd Checking cluster configuration with schema 'repmgr_test'
[2014-07-04 11:55:17] [INFO] repmgrd Checking node 2 in cluster 'test'
[2014-07-04 11:55:17] [INFO] Reloading configuration file and updating repmgr tables
[2014-07-04 11:55:17] [INFO] repmgrd Starting continuous standby node monitoring
Failover
--------
To promote a standby to master, on the standby execute e.g.:
repmgr -f $HOME/repmgr/repmgr.conf --verbose standby promote
repmgr will attempt to connect to the current master to verify that it
is not available (if it is, repmgr will not promote the standby).
Other standby servers need to be told to follow the new master with:
repmgr -f $HOME/repmgr/repmgr.conf --verbose standby follow
See file `autofailover_quick_setup.rst` for details on setting up
automated failover.
repmgr database schema
----------------------
repmgr creates a small schema for its own use in the database specified in
each node's conninfo configuration parameter. This database can in principle
be any database. The schema name is the global `cluster` name prefixed
with `repmgr_`, so for the example setup above the schema name is
`repmgr_test`.
The schema contains two tables:
* `repl_nodes`
stores information about all registered servers in the cluster
* `repl_monitor`
stores monitoring information about each node
and one view, `repl_status`, which summarizes the latest monitoring information
for each node.

View File

@@ -23,7 +23,7 @@ databases as a single cluster. repmgr includes two components:
Supported Releases Supported Releases
------------------ ------------------
repmgr works with PostgreSQL versions 9.0 and later. repmgr works with PostgreSQL versions 9.0 and superior.
There are currently no incompatibilities when upgrading repmgr from 9.0 to 9.1, There are currently no incompatibilities when upgrading repmgr from 9.0 to 9.1,
so your 9.0 configuration will work with 9.1 so your 9.0 configuration will work with 9.1
@@ -77,7 +77,7 @@ and run::
And if a previously failed node becomes available again, such as And if a previously failed node becomes available again, such as
the lost node1 above, you can get it to resynchronize by only copying the lost node1 above, you can get it to resynchronize by only copying
over changes made while it was down. That happens with what's over changes made while it was down using. That hapens with what's
called a forced clone, which overwrites existing data rather than called a forced clone, which overwrites existing data rather than
assuming it starts with an empty database directory tree:: assuming it starts with an empty database directory tree::
@@ -138,7 +138,7 @@ Using a full source code tree
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In this method, the repmgr distribution is copied into the PostgreSQL source In this method, the repmgr distribution is copied into the PostgreSQL source
code tree, assumed to be under ${postgresql_sources} for this example. code tree, assumed to be at the ${postgresql_sources} for this example.
The resulting subdirectory must be named ``contrib/repmgr``, without any The resulting subdirectory must be named ``contrib/repmgr``, without any
version number:: version number::
@@ -237,7 +237,7 @@ If you already tried to build repmgr before doing this, you'll need to do::
make USE_PGXS=1 clean make USE_PGXS=1 clean
to get rid of leftover files from the wrong architecture. To get rid of leftover files from the wrong architecture.
Notes on Ubuntu, Debian or other Debian-based Builds Notes on Ubuntu, Debian or other Debian-based Builds
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -279,8 +279,8 @@ Confirm software was built correctly
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You should now find the repmgr programs available in the subdirectory where You should now find the repmgr programs available in the subdirectory where
the rest of your PostgreSQL binary files are located. You can confirm the the rest of your PostgreSQL installation is at. You can confirm the software
software is available by checking its version:: is available by checking its version::
repmgr --version repmgr --version
repmgrd --version repmgrd --version
@@ -374,10 +374,10 @@ Usage walkthrough
This assumes you've already followed the steps in "Installation Outline" to This assumes you've already followed the steps in "Installation Outline" to
install repmgr and repmgrd on the system. install repmgr and repmgrd on the system.
A typical production installation of ``repmgr`` might involve two PostgreSQL A normal production installation of ``repmgr`` will normally involve two
instances on seperate servers, both running under the ``postgres`` user account different systems running on the same port, typically the default of 5432,
and both using the default port (5432). This walkthrough assumes the following with both using files owned by the ``postgres`` user account. This
setup: walkthrough assumes the following setup:
* A primary (master) server called "node1," running as the "postgres" user * A primary (master) server called "node1," running as the "postgres" user
who is also the owner of the files. This server is operating on port 5432. This who is also the owner of the files. This server is operating on port 5432. This
@@ -625,18 +625,18 @@ Now restore to the original configuration by stopping
primary server, then bringing up "node2" as a standby with a valid primary server, then bringing up "node2" as a standby with a valid
``recovery.conf`` file. ``recovery.conf`` file.
Stop the "node2" server and type the following on "node1" server:: Stop the "node2" server::
repmgr -f /var/lib/pgsql/repmgr/repmgr.conf standby promote repmgr -f /var/lib/pgsql/repmgr/repmgr.conf standby promote
Now the original primary, "node1", is acting again as primary. Now the original primary, "node1" is acting again as primary.
Start the "node2" server and type this on "node2":: Start the "node2" server and type this on "node1"::
repmgr standby clone --force -h node2 -p 5432 -U postgres -R postgres --verbose repmgr standby clone --force -h node2 -p 5432 -U postgres -R postgres --verbose
Verify the roles have reversed by attempting to insert a record on "node1" Verify the roles have reversed by attempting to insert a record on "node"
and on "node2". and on "node1".
The servers are now again acting as primary on "node1" and standby on "node2". The servers are now again acting as primary on "node1" and standby on "node2".
@@ -660,7 +660,7 @@ You can usually leave out changes to the port number in this case too.
* A database exists on "prime" called "testdb." * A database exists on "prime" called "testdb."
* The Postgres installation in each of the above is defined as $PGDATA, * The Postgress installation in each of the above is defined as $PGDATA,
which is represented here with ``/data/prime`` as the "prime" server and which is represented here with ``/data/prime`` as the "prime" server and
``/data/standby`` as the "standby" server. ``/data/standby`` as the "standby" server.
@@ -890,7 +890,7 @@ The output from this program looks like this::
Configuration options: Configuration options:
-D, --data-dir=DIR local directory where the files will be copied to -D, --data-dir=DIR local directory where the files will be copied to
-f, --config-file=PATH path to the configuration file -f, --config_file=PATH path to the configuration file
-R, --remote-user=USERNAME database server username for rsync -R, --remote-user=USERNAME database server username for rsync
-w, --wal-keep-segments=VALUE minimum value for the GUC wal_keep_segments (default: 5000) -w, --wal-keep-segments=VALUE minimum value for the GUC wal_keep_segments (default: 5000)
-I, --ignore-rsync-warning ignore rsync partial transfer warning -I, --ignore-rsync-warning ignore rsync partial transfer warning
@@ -1014,7 +1014,7 @@ The output from this program looks like this::
--version output version information, then exit --version output version information, then exit
--verbose output verbose activity information --verbose output verbose activity information
--monitoring-history track advance or lag of the replication in every standby in repl_monitor --monitoring-history track advance or lag of the replication in every standby in repl_monitor
-f, --config-file=PATH path to the configuration file -f, --config_file=PATH database to connect to
repmgrd monitors a cluster of servers. repmgrd monitors a cluster of servers.

View File

@@ -1,57 +0,0 @@
Summary: repmgr
Name: repmgr
Version: 2.0
Release: 2
License: GPLv3
Group: System Environment/Daemons
URL: http://repmgr.org
Packager: Nathan Van Overloop <nathan.van.overloop@nexperteam.be>
Vendor: 2ndQuadrant Limited
Distribution: centos
Source0: %{name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
%description
repmgr for centos6
%prep
%setup
%build
export PATH=$PATH:/usr/pgsql-9.3/bin/
%{__make} USE_PGXS=1
%install
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
export PATH=$PATH:/usr/pgsql-9.3/bin/
%{__make} USE_PGXS=1 install DESTDIR=%{buildroot} INSTALL="install -p"
%{__make} USE_PGXS=1 install_prog DESTDIR=%{buildroot} INSTALL="install -p"
%{__make} USE_PGXS=1 install_rhel DESTDIR=%{buildroot} INSTALL="install -p"
%clean
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%files
%defattr(-,root,root)
/usr/bin/repmgr
/usr/bin/repmgrd
/usr/pgsql-9.3/bin/repmgr
/usr/pgsql-9.3/bin/repmgrd
/usr/pgsql-9.3/lib/repmgr_funcs.so
/usr/pgsql-9.3/share/contrib/repmgr.sql
/usr/pgsql-9.3/share/contrib/repmgr_funcs.sql
/usr/pgsql-9.3/share/contrib/uninstall_repmgr.sql
/usr/pgsql-9.3/share/contrib/uninstall_repmgr_funcs.sql
%attr(0755,root,root)/etc/init.d/repmgrd
%attr(0644,root,root)/etc/sysconfig/repmgrd
%attr(0644,root,root)/etc/repmgr/repmgr.conf.sample
%changelog
* Thu Jun 05 2014 Nathan Van Overloop <nathan.van.overloop@nexperteam.be> 2.0.2
- fix witness creation to create db and user if needed
* Fri Apr 04 2014 Nathan Van Overloop <nathan.van.overloop@nexperteam.be> 2.0.1
- initial build for RHEL6

View File

@@ -1,114 +0,0 @@
#!/bin/bash
#
# repmgrd Start up the repmgrd daemon
# repmrgd (replication manager daemon)
#
# chkconfig: - 75 16
# description: repmgrd is the repliation manager daemon \
# The repmgrd replication management and monitoring daemon for PostgreSQL.
### BEGIN INIT INFO
# Provides: repmgrd
# Required-Start: $local_fs $remote_fs $network $syslog postgresql
# Required-Stop: $local_fs $remote_fs $network $syslog postgresql
# Should-Start: $syslog postgresql-9.3
# Should-Stop: $syslog postgresql-9.3
# Short-Description: start and stop repmrgd
# Description: Enable repmgrd replication management and monitoring daemon for PostgreSQL
# this is used to monitor a postgresql cluster.
### END INIT INFO
# Source function library.
. /etc/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
prog=repmgrd
REPMGRD_ENABLED=yes
REPMGRD_OPTS=
REPMGRD_USER=postgres
DAEMONIZE="-d"
# pull in sysconfig settings
[ -f /etc/sysconfig/repmgrd ] && . /etc/sysconfig/repmgrd
LOCKFILE=/var/lock/subsys/$prog
RETVAL=0
case "$REPMGRD_ENABLED" in
[Yy]*)
#nothing to do here
;;
*)
exit 2
;;
esac
if [ -z "$REPMGRD_OPTS" ]
then
echo "Not starting $prog, REPMGRD_OPTS not set in /etc/sysconfig/$prog"
exit 2
fi
start() {
[ "$EUID" != "0" ] && exit 4
[ "$NETWORKING" = "no" ] && exit 1
# Start daemons.
echo -n $"Starting $prog: "
daemon --user $REPMGRD_USER $prog $DAEMONIZE $REPMGRD_OPTS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch $LOCKFILE
return $RETVAL
}
stop() {
[ "$EUID" != "0" ] && exit 4
echo -n $"Shutting down $prog: "
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f $LOCKFILE
return $RETVAL
}
status() {
if [ -f "$LOCKFILE" ]; then
echo "$prog is running"
else
RETVAL=3
echo "$prog is stopped"
fi
return $RETVAL
}
# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status $prog
;;
restart|force-reload)
stop
start
;;
try-restart|condrestart)
if status $prog > /dev/null; then
stop
start
fi
;;
reload)
exit 3
;;
*)
echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}"
exit 2
esac

View File

@@ -1,4 +0,0 @@
#default sysconfig file for repmrgd
#custom overrides can be placed here
REPMGRD_OPTS="-f /etc/repmgr/repmgr.conf"

View File

@@ -49,19 +49,19 @@ cluster to communicate with other repmgrd daemons.
8. Start the repmgrd daemons in all nodes 8. Start the repmgrd daemons in all nodes
**Note** A complete High-Availability design needs at least 3 servers to still have **Note** A complete Hight-Availability design need at least 3 servers to still have
a backup node after a first failure. a backup node after a first failure.
Install PostgreSQL Install PostgreSQL
------------------ ------------------
You can install PostgreSQL using any of the recommended methods. You should ensure You can install PostgreSQL using any of the recommended methods. You should ensure
it's 9.0 or later. it's 9.0 or superior.
Install repmgr Install repmgr
-------------- --------------
Install repmgr following the steps in the README file. Install repmgr following the steps in the README.
Configure PostreSQL Configure PostreSQL
------------------- -------------------
@@ -217,7 +217,7 @@ Edit the repmgr.conf of the node to remove from automatic processing and change:
Then, signal repmgrd daemon:: Then, signal repmgrd daemon::
su - postgres su - postgres
kill -HUP `pidof repmgrd` kill -HUP `pidoff repmgrd`
Usage Usage
===== =====

View File

@@ -71,7 +71,6 @@ check_dir(char *dir)
} }
#ifdef WIN32 #ifdef WIN32
/* /*
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
* released version * released version
@@ -90,10 +89,10 @@ check_dir(char *dir)
/* /*
* Create directory with error log message when failing * Create directory
*/ */
bool bool
create_dir(char *dir) create_directory(char *dir)
{ {
if (mkdir_p(dir, 0700) == 0) if (mkdir_p(dir, 0700) == 0)
return true; return true;
@@ -105,7 +104,7 @@ create_dir(char *dir)
} }
bool bool
set_dir_permissions(char *dir) set_directory_permissions(char *dir)
{ {
return (chmod(dir, 0700) != 0) ? false : true; return (chmod(dir, 0700) != 0) ? false : true;
} }
@@ -242,7 +241,7 @@ is_pg_dir(char *dir)
bool bool
create_pg_dir(char *dir, bool force) create_pgdir(char *dir, bool force)
{ {
bool pg_dir = false; bool pg_dir = false;
@@ -253,7 +252,7 @@ create_pg_dir(char *dir, bool force)
/* dir not there, must create it */ /* dir not there, must create it */
log_info(_("creating directory \"%s\"...\n"), dir); log_info(_("creating directory \"%s\"...\n"), dir);
if (!create_dir(dir)) if (!create_directory(dir))
{ {
log_err(_("couldn't create directory \"%s\"...\n"), log_err(_("couldn't create directory \"%s\"...\n"),
dir); dir);
@@ -265,7 +264,7 @@ create_pg_dir(char *dir, bool force)
log_info(_("checking and correcting permissions on existing directory %s ...\n"), log_info(_("checking and correcting permissions on existing directory %s ...\n"),
dir); dir);
if (!set_dir_permissions(dir)) if (!set_directory_permissions(dir))
{ {
log_err(_("could not change permissions of directory \"%s\": %s\n"), log_err(_("could not change permissions of directory \"%s\": %s\n"),
dir, strerror(errno)); dir, strerror(errno));

View File

@@ -22,9 +22,9 @@
int mkdir_p(char *path, mode_t omode); int mkdir_p(char *path, mode_t omode);
int check_dir(char *dir); int check_dir(char *dir);
bool create_dir(char *dir); bool create_directory(char *dir);
bool set_dir_permissions(char *dir); bool set_directory_permissions(char *dir);
bool is_pg_dir(char *dir); bool is_pg_dir(char *dir);
bool create_pg_dir(char *dir, bool force); bool create_pgdir(char *dir, bool force);
#endif #endif

View File

@@ -25,8 +25,7 @@
void void
parse_config(const char *config_file, t_configuration_options *options) parse_config(const char *config_file, t_configuration_options *options)
{ {
char *s, char *s, buff[MAXLINELENGTH];
buff[MAXLINELENGTH];
char name[MAXLEN]; char name[MAXLEN];
char value[MAXLEN]; char value[MAXLEN];
@@ -57,13 +56,12 @@ parse_config(const char *config_file, t_configuration_options * options)
options->retry_promote_interval_secs = 300; options->retry_promote_interval_secs = 300;
/* /*
* Since some commands don't require a config file at all, not having one * Since some commands don't require a config file at all, not
* isn't necessarily a problem. * having one isn't necessarily a problem.
*/ */
if (fp == NULL) if (fp == NULL)
{ {
log_err(_("Did not find the configuration file '%s', continuing\n"), log_err(_("Did not find the configuration file '%s', continuing\n"), config_file);
config_file);
return; return;
} }
@@ -95,7 +93,6 @@ parse_config(const char *config_file, t_configuration_options * options)
else if (strcmp(name, "failover") == 0) else if (strcmp(name, "failover") == 0)
{ {
char failoverstr[MAXLEN]; char failoverstr[MAXLEN];
strncpy(failoverstr, value, MAXLEN); strncpy(failoverstr, value, MAXLEN);
if (strcmp(failoverstr, "manual") == 0) if (strcmp(failoverstr, "manual") == 0)
@@ -140,7 +137,7 @@ parse_config(const char *config_file, t_configuration_options * options)
fclose (fp); fclose (fp);
/* Check config settings */ /* Check config settings */
if (*options->cluster_name == '\0') if (strnlen(options->cluster_name, MAXLEN)==0)
{ {
log_err(_("Cluster name is missing. Check the configuration file.\n")); log_err(_("Cluster name is missing. Check the configuration file.\n"));
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
@@ -182,8 +179,7 @@ char *
trim (char *s) trim (char *s)
{ {
/* Initialize start, end pointers */ /* Initialize start, end pointers */
char *s1 = s, char *s1 = s, *s2 = &s[strlen (s) - 1];
*s2 = &s[strlen(s) - 1];
/* Trim and delimit right side */ /* Trim and delimit right side */
while ( (isspace (*s2)) && (s2 >= s1) ) while ( (isspace (*s2)) && (s2 >= s1) )
@@ -235,7 +231,7 @@ parse_line(char *buff, char *name, char *value)
} }
bool bool
reload_config(char *config_file, t_configuration_options * orig_options) reload_configuration(char *config_file, t_configuration_options *orig_options)
{ {
PGconn *conn; PGconn *conn;
@@ -295,7 +291,7 @@ reload_config(char *config_file, t_configuration_options * orig_options)
} }
/* Test conninfo string */ /* Test conninfo string */
conn = establish_db_connection(new_options.conninfo, false); conn = establishDBConnection(new_options.conninfo, false);
if (!conn || (PQstatus(conn) != CONNECTION_OK)) if (!conn || (PQstatus(conn) != CONNECTION_OK))
{ {
log_warning(_("conninfo string is not valid, will keep current configuration.\n")); log_warning(_("conninfo string is not valid, will keep current configuration.\n"));
@@ -317,15 +313,15 @@ reload_config(char *config_file, t_configuration_options * orig_options)
orig_options->master_response_timeout = new_options.master_response_timeout; orig_options->master_response_timeout = new_options.master_response_timeout;
orig_options->reconnect_attempts = new_options.reconnect_attempts; orig_options->reconnect_attempts = new_options.reconnect_attempts;
orig_options->reconnect_intvl = new_options.reconnect_intvl; orig_options->reconnect_intvl = new_options.reconnect_intvl;
/* /*
* XXX These ones can change with a simple SIGHUP? * XXX These ones can change with a simple SIGHUP?
*
* strcpy (orig_options->loglevel, new_options.loglevel); strcpy strcpy (orig_options->loglevel, new_options.loglevel);
* (orig_options->logfacility, new_options.logfacility); strcpy (orig_options->logfacility, new_options.logfacility);
*
* logger_shutdown(); XXX do we have progname here ? logger_init(progname, logger_shutdown();
* orig_options.loglevel, orig_options.logfacility); XXX do we have progname here ?
logger_init(progname, orig_options.loglevel, orig_options.logfacility);
*/ */
return true; return true;

View File

@@ -52,6 +52,6 @@ typedef struct
void parse_config(const char *config_file, t_configuration_options *options); void parse_config(const char *config_file, t_configuration_options *options);
void parse_line(char *buff, char *name, char *value); void parse_line(char *buff, char *name, char *value);
char *trim(char *s); char *trim(char *s);
bool reload_config(char *config_file, t_configuration_options * orig_options); bool reload_configuration(char *config_file, t_configuration_options *orig_options);
#endif #endif

View File

@@ -26,7 +26,7 @@
#include "log.h" #include "log.h"
PGconn * PGconn *
establish_db_connection(const char *conninfo, const bool exit_on_error) establishDBConnection(const char *conninfo, const bool exit_on_error)
{ {
/* Make a connection to the database */ /* Make a connection to the database */
PGconn *conn = NULL; PGconn *conn = NULL;
@@ -53,8 +53,7 @@ establish_db_connection(const char *conninfo, const bool exit_on_error)
} }
PGconn * PGconn *
establish_db_connection_by_params(const char *keywords[], const char *values[], establishDBConnectionByParams(const char *keywords[], const char *values[],const bool exit_on_error)
const bool exit_on_error)
{ {
/* Make a connection to the database */ /* Make a connection to the database */
PGconn *conn = PQconnectdbParams(keywords, values, true); PGconn *conn = PQconnectdbParams(keywords, values, true);
@@ -125,7 +124,6 @@ bool
is_pgup(PGconn *conn, int timeout) is_pgup(PGconn *conn, int timeout)
{ {
char sqlquery[QUERY_STR_LEN]; char sqlquery[QUERY_STR_LEN];
/* Check the connection status twice in case it changes after reset */ /* Check the connection status twice in case it changes after reset */
bool twice = false; bool twice = false;
@@ -144,7 +142,7 @@ is_pgup(PGconn *conn, int timeout)
/* /*
* Send a SELECT 1 just to check if the connection is OK * Send a SELECT 1 just to check if the connection is OK
*/ */
if (!cancel_query(conn, timeout)) if (!CancelQuery(conn, timeout))
goto failed; goto failed;
if (wait_connection_availability(conn, timeout) != 1) if (wait_connection_availability(conn, timeout) != 1)
goto failed; goto failed;
@@ -162,11 +160,7 @@ is_pgup(PGconn *conn, int timeout)
break; break;
failed: failed:
/* we need to retry, because we might just have loose the connection once */
/*
* we need to retry, because we might just have loose the
* connection once
*/
if (twice) if (twice)
return false; return false;
PQreset(conn); /* reconnect */ PQreset(conn); /* reconnect */
@@ -320,7 +314,7 @@ get_cluster_size(PGconn *conn)
* connection string is placed there. * connection string is placed there.
*/ */
PGconn * PGconn *
get_master_connection(PGconn *standby_conn, char *schema, char *cluster, getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
int *master_id, char *master_conninfo_out) int *master_id, char *master_conninfo_out)
{ {
PGconn *master_conn = NULL; PGconn *master_conn = NULL;
@@ -377,15 +371,15 @@ get_master_connection(PGconn *standby_conn, char *schema, char *cluster,
strncpy(master_conninfo, PQgetvalue(res1, i, 1), MAXCONNINFO); strncpy(master_conninfo, PQgetvalue(res1, i, 1), MAXCONNINFO);
log_info(_("checking role of cluster node '%s'\n"), log_info(_("checking role of cluster node '%s'\n"),
master_conninfo); master_conninfo);
master_conn = establish_db_connection(master_conninfo, false); master_conn = establishDBConnection(master_conninfo, false);
if (PQstatus(master_conn) != CONNECTION_OK) if (PQstatus(master_conn) != CONNECTION_OK)
continue; continue;
/* /*
* Can't use the is_standby() function here because on error that * Can't use the is_standby() function here because on error that
* function closes the connection passed and exits. This still needs * function closes the connection passed and exits. This still
* to close master_conn first. * needs to close master_conn first.
*/ */
res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()"); res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()");
@@ -414,13 +408,14 @@ get_master_connection(PGconn *standby_conn, char *schema, char *cluster,
} }
} }
/* /* If we finish this loop without finding a master then
* If we finish this loop without finding a master then we doesn't have * we doesn't have the info or the master has failed (or we
* the info or the master has failed (or we reached max_connections or * reached max_connections or superuser_reserved_connections,
* superuser_reserved_connections, anything else I'm missing?). * anything else I'm missing?).
* *
* Probably we will need to check the error to know if we need to start * Probably we will need to check the error to know if we need
* failover procedure or just fix some situation on the standby. * to start failover procedure or just fix some situation on the
* standby.
*/ */
PQclear(res1); PQclear(res1);
return NULL; return NULL;
@@ -428,8 +423,8 @@ get_master_connection(PGconn *standby_conn, char *schema, char *cluster,
/* /*
* wait until current query finishes ignoring any results, this could be an * wait until current query finishes ignoring any results, this could be an async command
* async command or a cancelation of a query * or a cancelation of a query
* return 1 if Ok; 0 if any error ocurred; -1 if timeout reached * return 1 if Ok; 0 if any error ocurred; -1 if timeout reached
*/ */
int int
@@ -438,9 +433,7 @@ wait_connection_availability(PGconn *conn, long long timeout)
PGresult *res; PGresult *res;
fd_set read_set; fd_set read_set;
int sock = PQsocket(conn); int sock = PQsocket(conn);
struct timeval tmout, struct timeval tmout, before, after;
before,
after;
struct timezone tz; struct timezone tz;
/* recalc to microseconds */ /* recalc to microseconds */
@@ -457,8 +450,7 @@ wait_connection_availability(PGconn *conn, long long timeout)
if (PQisBusy(conn) == 0) if (PQisBusy(conn) == 0)
{ {
do do {
{
res = PQgetResult(conn); res = PQgetResult(conn);
PQclear(res); PQclear(res);
} while(res != NULL); } while(res != NULL);
@@ -499,7 +491,7 @@ wait_connection_availability(PGconn *conn, long long timeout)
bool bool
cancel_query(PGconn *conn, int timeout) CancelQuery(PGconn *conn, int timeout)
{ {
char errbuf[ERRBUFF_SIZE]; char errbuf[ERRBUFF_SIZE];
PGcancel *pgcancel; PGcancel *pgcancel;
@@ -513,8 +505,9 @@ cancel_query(PGconn *conn, int timeout)
return false; return false;
/* /*
* PQcancel can only return 0 if socket()/connect()/send() fails, in any * PQcancel can only return 0 if socket()/connect()/send()
* of those cases we can assume something bad happened to the connection * fails, in any of those cases we can assume something
* bad happened to the connection
*/ */
if (PQcancel(pgcancel, errbuf, ERRBUFF_SIZE) == 0) if (PQcancel(pgcancel, errbuf, ERRBUFF_SIZE) == 0)
{ {

View File

@@ -22,9 +22,8 @@
#include "strutil.h" #include "strutil.h"
PGconn *establish_db_connection(const char *conninfo, PGconn *establishDBConnection(const char *conninfo, const bool exit_on_error);
const bool exit_on_error); PGconn *establishDBConnectionByParams(const char *keywords[],
PGconn *establish_db_connection_by_params(const char *keywords[],
const char *values[], const char *values[],
const bool exit_on_error); const bool exit_on_error);
int is_standby(PGconn *conn); int is_standby(PGconn *conn);
@@ -37,10 +36,9 @@ int guc_set_typed(PGconn *conn, const char *parameter, const char *op,
const char *value, const char *datatype); const char *value, const char *datatype);
const char *get_cluster_size(PGconn *conn); const char *get_cluster_size(PGconn *conn);
PGconn *get_master_connection(PGconn *standby_conn, char *schema, char *cluster, PGconn *getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
int *master_id, char *master_conninfo_out); int *master_id, char *master_conninfo_out);
int wait_connection_availability(PGconn *conn, long long timeout); int wait_connection_availability(PGconn *conn, long long timeout);
bool cancel_query(PGconn *conn, int timeout); bool CancelQuery(PGconn *conn, int timeout);
#endif #endif

View File

@@ -1,18 +1,14 @@
#!/bin/sh
# default settings for repmgrd. This file is source by /bin/sh from # default settings for repmgrd. This file is source by /bin/sh from
# /etc/init.d/repmgrd # /etc/init.d/repmgrd
# disable repmgrd by default so it won't get started upon installation # Options for repmgrd
# valid values: yes/no REPMGRD_OPTS=""
REPMGRD_ENABLED=no
# Options for repmgrd (required)
#REPMGRD_OPTS="--config-file /path/to/repmgr.conf"
# User to run repmgrd as
#REPMGRD_USER=postgres
# repmgrd binary # repmgrd binary
#REPMGR_BIN=/usr/bin/repmgr REPMGR_BIN="/usr/bin/repmgr"
# pid file # pid file
#REPMGR_PIDFILE=/var/run/repmgrd.pid REPMGR_PIDFILE="/var/run/repmgrd.pid"

View File

@@ -1,100 +1,47 @@
#!/bin/sh #!/bin/sh
### BEGIN INIT INFO ### BEGIN INIT INFO
# Provides: repmgrd # Provides: repmgrd
# Required-Start: $local_fs $remote_fs $network $syslog postgresql # Required-Start: $local_fs $remote_fs $network $syslog $postgresql
# Required-Stop: $local_fs $remote_fs $network $syslog postgresql # Required-Stop: $local_fs $remote_fs $network $syslog $postgresql
# Should-Start: $syslog postgresql # Should-Start: $syslog $postgresql
# Should-Start: $syslog $postgresql
# Default-Start: 2 3 4 5 # Default-Start: 2 3 4 5
# Default-Stop: 0 1 6 # Default-Stop: 0 1 6
# Short-Description: Start/stop repmgrd # Short-Description: Start/stop repmgrd
# Description: Enable repmgrd replication management and monitoring daemon for PostgreSQL
### END INIT INFO ### END INIT INFO
set -e set -e
DESC="PostgreSQL replication management and monitoring daemon" if test -f /etc/default/repmgrd; then
NAME=repmgrd . /etc/default/repmgrd
fi
REPMGRD_ENABLED=no if [ -z "$REPMGRD_BIN" ]; then
REPMGRD_OPTS= REPMGRD_BIN="/usr/bin/repmgrd"
REPMGRD_USER=postgres fi
REPMGRD_BIN=/usr/bin/repmgrd
REPMGRD_PIDFILE=/var/run/repmgrd.pid
# Read configuration variable file if it is present if [ -z "$REPMGRD_PIDFILE" ]; then
[ -r /etc/default/$NAME ] && . /etc/default/$NAME REPMGRD_PIDFILE="/var/run/repmgrd.pid"
fi
test -x $REPMGRD_BIN || exit 0 test -x $REPMGRD_BIN || exit 0
case "$REPMGRD_ENABLED" in
[Yy]*)
break
;;
*)
exit 0
;;
esac
# Define LSB log_* functions.
. /lib/lsb/init-functions
if [ -z "$REPMGRD_OPTS" ]
then
log_warning_msg "Not starting $NAME, REPMGRD_OPTS not set in /etc/default/$NAME"
exit 0
fi
do_start()
{
# Return
# 0 if daemon has been started
# 1 if daemon was already running
# other if daemon could not be started or a failure occured
start-stop-daemon --start --quiet --background --chuid $REPMGRD_USER --make-pidfile --pidfile $REPMGRD_PIDFILE --exec $REPMGRD_BIN -- $REPMGRD_OPTS
}
do_stop()
{
# Return
# 0 if daemon has been stopped
# 1 if daemon was already stopped
# other if daemon could not be stopped or a failure occurred
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $REPMGRD_PIDFILE --exec $REPMGRD_BIN
}
case "$1" in case "$1" in
start) start)
log_daemon_msg "Starting $DESC" "$NAME" start-stop-daemon --start --quiet --make-pidfile --pidfile $REPMGRD_PIDFILE --exec $REPMGRD_BIN $REPMGRD_OPTS
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_progress_msg "already started"
log_end_msg 0 ;;
*) log_end_msg 1 ;;
esac
;; ;;
stop) stop)
log_daemon_msg "Stopping $DESC" "$NAME" start-stop-daemon --stop --oknodo --quiet --pidfile $REPMGRD_PIDFILE
do_stop ;;
case "$?" in
0) log_end_msg 0 ;;
1) log_progress_msg "already stopped"
log_end_msg 0 ;;
*) log_end_msg 1 ;;
esac
restart)
$0 stop && $0 start || exit 1
;; ;;
restart|force-reload)
$0 stop
$0 start
;;
status)
status_of_proc -p $REPMGRD_PIDFILE $REPMGRD_BIN $NAME && exit 0 || exit $?
;;
*) *)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|status}" >&2 echo "Usage: $0 {start|stop|restart}"
exit 3 exit 1
;; ;;
esac esac

46
log.c
View File

@@ -39,23 +39,24 @@
/* #define REPMGR_DEBUG */ /* #define REPMGR_DEBUG */
void void stderr_log_with_level(const char *level_name, int level, const char *fmt, ...) {
stderr_log_with_level(const char *level_name, int level, const char *fmt, ...) size_t len = strlen(fmt);
{ char fmt1[len + 150];
time_t t; time_t t;
struct tm *tm; struct tm *tm;
char buff[100]; char buff[100];
va_list ap; va_list ap;
if (log_level >= level) if(log_level >= level) {
{
time(&t); time(&t);
tm = localtime(&t); tm = localtime(&t);
strftime(buff, 100, "[%Y-%m-%d %H:%M:%S]", tm);
fprintf(stderr, "%s [%s] ", buff, level_name);
va_start(ap, fmt); va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
strftime(buff, 100, "[%Y-%m-%d %H:%M:%S]", tm);
snprintf(fmt1, len + 150, "%s [%s] %s", buff, level_name, fmt);
vfprintf(stderr, fmt1, ap);
va_end(ap); va_end(ap);
fflush(stderr); fflush(stderr);
@@ -69,9 +70,9 @@ static int detect_log_facility(const char *facility);
int log_type = REPMGR_STDERR; int log_type = REPMGR_STDERR;
int log_level = LOG_NOTICE; int log_level = LOG_NOTICE;
bool bool logger_init(t_configuration_options *opts, const char* ident, const char* level, const char* facility)
logger_init(t_configuration_options * opts, const char *ident, const char *level, const char *facility)
{ {
int l; int l;
int f; int f;
@@ -138,28 +139,21 @@ logger_init(t_configuration_options * opts, const char *ident, const char *level
stderr_log_notice(_("Setup syslog (level: %s, facility: %s)\n"), level, facility); stderr_log_notice(_("Setup syslog (level: %s, facility: %s)\n"), level, facility);
} }
#endif #endif
if (*opts->logfile) if (*opts->logfile)
{ {
FILE *fd; freopen(opts->logfile, "a", stderr);
fd = freopen(opts->logfile, "a", stderr);
if (fd == NULL)
{
fprintf(stderr, "error reopening stderr to '%s': %s",
opts->logfile, strerror(errno));
}
} }
return true; return true;
} }
bool bool logger_shutdown(void)
logger_shutdown(void)
{ {
#ifdef HAVE_SYSLOG #ifdef HAVE_SYSLOG
if (log_type == REPMGR_SYSLOG) if (log_type == REPMGR_SYSLOG)
closelog(); closelog();
@@ -173,15 +167,13 @@ logger_shutdown(void)
* options, which might increase requested logging over what's specified * options, which might increase requested logging over what's specified
* in the regular configuration file. * in the regular configuration file.
*/ */
void void logger_min_verbose(int minimum)
logger_min_verbose(int minimum)
{ {
if (log_level < minimum) if (log_level < minimum)
log_level = minimum; log_level = minimum;
} }
int int detect_log_level(const char* level)
detect_log_level(const char *level)
{ {
if (!strcmp(level, "DEBUG")) if (!strcmp(level, "DEBUG"))
return LOG_DEBUG; return LOG_DEBUG;
@@ -203,11 +195,9 @@ detect_log_level(const char *level)
return 0; return 0;
} }
int int detect_log_facility(const char* facility)
detect_log_facility(const char *facility)
{ {
int local = 0; int local = 0;
if (!strncmp(facility, "LOCAL", 5) && strlen(facility) == 6) if (!strncmp(facility, "LOCAL", 5) && strlen(facility) == 6)
{ {

11
log.h
View File

@@ -25,9 +25,7 @@
#define REPMGR_SYSLOG 1 #define REPMGR_SYSLOG 1
#define REPMGR_STDERR 2 #define REPMGR_STDERR 2
void void stderr_log_with_level(const char *level_name, int level, const char *fmt, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 3, 4)));
stderr_log_with_level(const char *level_name, int level, const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
/* Standard error logging */ /* Standard error logging */
#define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__) #define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__)
@@ -90,6 +88,7 @@ __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \ if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \
else stderr_log_alert(__VA_ARGS__); \ else stderr_log_alert(__VA_ARGS__); \
} }
#else #else
#define LOG_EMERG 0 /* system is unusable */ #define LOG_EMERG 0 /* system is unusable */
@@ -109,15 +108,13 @@ __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
#define log_crit(...) stderr_log_crit(__VA_ARGS__) #define log_crit(...) stderr_log_crit(__VA_ARGS__)
#define log_alert(...) stderr_log_alert(__VA_ARGS__) #define log_alert(...) stderr_log_alert(__VA_ARGS__)
#define log_emerg(...) stderr_log_emerg(__VA_ARGS__) #define log_emerg(...) stderr_log_emerg(__VA_ARGS__)
#endif #endif
/* Logger initialisation and shutdown */ /* Logger initialisation and shutdown */
bool logger_shutdown(void); bool logger_shutdown(void);
bool logger_init(t_configuration_options *opts, const char* ident, const char* level, const char* facility);
bool logger_init(t_configuration_options * opts, const char *ident,
const char *level, const char *facility);
void logger_min_verbose(int minimum); void logger_min_verbose(int minimum);
extern int log_type; extern int log_type;

555
repmgr.c

File diff suppressed because it is too large Load Diff

View File

@@ -67,10 +67,8 @@ typedef struct
/* parameter used by CLUSTER CLEANUP */ /* parameter used by CLUSTER CLEANUP */
int keep_history; int keep_history;
char min_recovery_apply_delay[MAXLEN];
} t_runtime_options; } t_runtime_options;
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, "", "", 0, "" } #define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, "", "", 0 }
#endif #endif

639
repmgrd.c

File diff suppressed because it is too large Load Diff

View File

@@ -68,9 +68,9 @@ _PG_init(void)
* In order to create our shared memory area, we have to be loaded via * In order to create our shared memory area, we have to be loaded via
* shared_preload_libraries. If not, fall out without hooking into any of * shared_preload_libraries. If not, fall out without hooking into any of
* the main system. (We don't throw error here because it seems useful to * the main system. (We don't throw error here because it seems useful to
* allow the repmgr functions to be created even when the module isn't * allow the repmgr functions to be created even when the
* active. The functions must protect themselves against being called * module isn't active. The functions must protect themselves against
* then, however.) * being called then, however.)
*/ */
if (!process_shared_preload_libraries_in_progress) if (!process_shared_preload_libraries_in_progress)
return; return;

View File

@@ -25,9 +25,17 @@
#include "log.h" #include "log.h"
#include "strutil.h" #include "strutil.h"
static int static int xvsnprintf(char *str, size_t size, const char *format, va_list ap) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 3, 0)));
xvsnprintf(char *str, size_t size, const char *format, va_list ap)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0))); /* Add strnlen on platforms that don't have it, like OS X */
#ifndef strnlen
size_t
strnlen(const char *s, size_t n)
{
const char *end = (const char *) memchr(s, '\0', n);
return(end ? end - s : n);
}
#endif
static int static int
xvsnprintf(char *str, size_t size, const char *format, va_list ap) xvsnprintf(char *str, size_t size, const char *format, va_list ap)
@@ -75,8 +83,7 @@ sqlquery_snprintf(char *str, const char *format,...)
} }
int int maxlen_snprintf(char *str, const char *format, ...)
maxlen_snprintf(char *str, const char *format,...)
{ {
va_list arglist; va_list arglist;
int retval; int retval;

View File

@@ -31,16 +31,13 @@
#define MAXCONNINFO 1024 #define MAXCONNINFO 1024
extern int extern int xsnprintf(char *str, size_t size, const char *format, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 3, 4)));
xsnprintf(char *str, size_t size, const char *format,...) extern int sqlquery_snprintf(char *str, const char *format, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 2, 3)));
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); extern int maxlen_snprintf(char *str, const char *format, ...) __attribute__ ((format (PG_PRINTF_ATTRIBUTE, 2, 3)));
extern int /* Add strnlen on platforms that don't have it, like OS X */
sqlquery_snprintf(char *str, const char *format,...) #ifndef strnlen
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); extern size_t strnlen(const char *s, size_t n);
#endif
extern int
maxlen_snprintf(char *str, const char *format,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
#endif /* _STRUTIL_H_ */ #endif /* _STRUTIL_H_ */

View File

@@ -1,6 +1,5 @@
#ifndef _VERSION_H_ #ifndef _VERSION_H_
#define _VERSION_H_ #define _VERSION_H_
#define REPMGR_VERSION "2.1dev" #define REPMGR_VERSION "2.0RC1"
#endif #endif