Compare commits

..

234 Commits

Author SHA1 Message Date
Jaime Casanova
9209248420 Fix oversight in the header of guc_setted_typed() 2013-12-19 11:09:08 -05:00
Jaime Casanova
6693b99288 Files to create the debian package
Patch by: Christian Kruse
2013-12-19 01:43:12 -05:00
Jaime Casanova
8e7b487838 Update debian control file 2013-12-19 01:41:24 -05:00
Jaime Casanova
7f796e2d15 Update history and credit files 2013-12-19 01:40:00 -05:00
Jaime Casanova
5e04ab6eae Add a ssh_options parameter to allow ssh checking
to consider non-default values (ie: a different port)

Patch by Jay Taylor
2013-12-19 01:22:55 -05:00
Jaime Casanova
a1f4285e2b Add guc_setted_typed() function to allow
wal_keep_segmeents to be checked as an integer instead
of text

Patch by Jay Taylor
2013-12-19 01:22:42 -05:00
Jaime Casanova
493133986d Add timestamps to log line in stderr
Patch by Christian Kruse
2013-12-19 01:15:28 -05:00
Jaime Casanova
8b370dc581 Fix some typos
Patch by Krzysztof Gajdemski
2013-12-07 13:25:46 -05:00
Jaime Casanova
43af00aa12 Ignore pg_log when cloning, just like we ignore pg_xlog 2013-12-04 01:23:48 -05:00
Jaime Casanova
3c8df59eb9 Make repmgr compile in 9.3.
Patch provided by Shawn Ellis with some fixes by me.
2013-11-14 00:43:35 -05:00
Jaime Casanova
b410772627 Rework algorithm to coordinate voting
Make this by waiting for all nodes to finish a step, before starting
a new one. So everyone starts promoting or following in a coordinated
fashion.
Also make a few fixes.
2013-09-26 13:24:31 -05:00
Jaime Casanova
d99024ba11 Make repmgrd survive to the failover
To do this it needs to reconnect to the new master
2013-09-26 11:58:59 -05:00
Jaime Casanova
1afaa3a26f Rearrange the logic in do_failover() for further improvements.
Specially, make this a more coordinated process by making all
nodes waiting for the others before going to the next step.

This is one step further in following Andres Freund advices
but there is still a lot to do in order to complete that,
specially it could be needed to add more fields to repl_nodes
and to the shm area.
2013-09-23 18:28:58 -05:00
Jaime Casanova
3b66a31ac9 In a failover situation get the nodes in a well defined order.
When deciding which node will be the new master, we should get the
nodes in a well defined order otherwise two standbys could process
nodes with the same priority in different order and end up with
a two master situation.
2013-07-26 00:52:31 -05:00
Jaime Casanova
ad3630e7a9 Add a missing ')'. This is a typo introduced in commit
2bc8044fda

Per complaint from Carlos Chapi when compiling for a customer.
2013-07-13 12:37:15 -05:00
Jaime Casanova
2e7acf03c4 If PQgetCancel() returns NULL we should also return false.
Noted by Andres Freund.
2013-07-12 08:01:01 -05:00
Jaime Casanova
2bc8044fda Improve messages in wait_connection_availability, so we know what
error makes the failover procedure to start

By gripe from Andres Freund
2013-07-10 19:25:58 -05:00
Jaime Casanova
b0b44a157f If PQcancel() fails, consider it as if the master is failing.
Because PQcancel() establish a new synchronous connection to the
database, if it fails it means something wrong has happenned with
master. So instead of just ignore the failure, CancelQuery() now
reports a failure condition so we can detect master's death in
that situation.

This is very important specially when only postmaster crashes but
other children/backend connections are still there. Because the
children connection won't fail and CancelQuery() failure is our
only indication of something wrong happenning.
Currently we just ignore the PQcancel() failure which leads us to
a situation in which we just loop forever
trying to cancel the async query.

Reported by: Martin Euser <martin.euser@nl.abnamro.com>
Problem analyzed and bug spotted by: Andres Freund <andres@2ndquadrant.com>
Patch by: Jaime Casanova <jaime@2ndquadrant.com>
2013-07-10 09:53:45 -05:00
Jaime Casanova
49a2531930 Options -F -W -I -v doesn't accept arguments, which means that on
getopt_long shouldn't be marked with the colon (:) character.

This has been wrong since day one, so backpatching all the way until
1.1
2013-01-13 16:37:39 -05:00
Jaime Casanova
4191b77e70 If the node is a witness don't bother asking its position, it always
will be 0/0. We just need to check that we can connect to it to determine
if we are in the majority.
2013-01-11 03:42:08 -05:00
Jaime Casanova
2a5d431481 Fix a problem that caused a standby to promote itself without going to
voting procedure.

This is because of a race condition inside CheckPrimaryConnection().

This has independently reported by Alex Railean and Dumitru, and Frank Jördens.
Analyzed and fixed by Cédric Villemain.

The fix have been verified to work by Frank
2012-12-19 12:01:27 -05:00
Jaime Casanova
93a999adc7 Formatting code using astyle 2012-12-11 11:49:07 -05:00
Jaime Casanova
088ca29fe3 To select new master it needs to know which standby has received more
xlog records from master, so it standby should use pg_last_xlog_receive_location()
to report their positions. This solves a possible situation in which
a standby that is considered as new master when promoted is no longer
the best option.
2012-12-03 09:18:08 -05:00
Jaime Casanova
30e9d06172 Add an option for STANDBY FOLLOW to wait for a master to appear.
This is important for autofailover to do the right thing when
standbys detected master death at different times.

While this is a new option, seems important for the autofailover
to work properly so i will consider the lack of it a bug and
will backpatch to 2.0 where autofailover was introduced.

For gripe from Alex Railean, about a standby not finding the new
master because the new master hasn't finish promoting.
2012-11-14 15:09:26 -05:00
Jaime Casanova
cd1a84252e Fix node decision logic when priorities are involved. Currently if
two nodes with different prorities are equally good to be promoted
the second one (with a lower priority, considering them
in descending order) will win.

Per report from Brailean Dumitru
2012-09-16 02:47:02 -05:00
Jaime Casanova
2e19b3688b Add a comment 2012-09-16 02:26:18 -05:00
Jaime Casanova
de883a4c84 Keep compiler quiet. Noted when compiling in FreeBSD in which i
get a warning for an uninitialized variable.

Also, define InvalidXLogRecPtr. We don't really need it but using
it make the initialization future proof (considering that in 9.3
XLogRecPtr will change its structure).
2012-09-16 02:21:18 -05:00
Jaime Casanova
499a501afd Make repmgr compatible with FreeBSD.
We need to add an #include and make it use a different path for the
"true" binary.

Maybe we need to make this changes for all BSD systems but having no
evidence of that i prefer to make this only for systems with __FreeBSD__
2012-09-15 17:37:59 -05:00
Jaime Casanova
0a9107d76d Improve sample of commands for promote and follow 2012-09-15 17:37:43 -05:00
Jaime Casanova
95ec0450da When we have more command-line arguments than we should have we
need to show that last value and we should use only optind for that
instead of optind+1
2012-08-30 02:11:48 -05:00
Jaime Casanova
57aa95f674 Fix documentation to always use -h sintax to refer to the node we
want to clone or connect to, instead of relying on the fact that
for some time putting that argument at last worked.
2012-08-30 02:10:10 -05:00
Jaime Casanova
56d2ae4e81 Fix HISTORY to show from newest to oldest 2012-07-27 11:26:18 -05:00
Jaime Casanova
3edd87a041 Fix tabs in HISTORY 2012-07-27 11:20:56 -05:00
Jaime Casanova
740208da1c Fix typos in RELEASE NOTES 2012-07-27 11:15:50 -05:00
Jaime Casanova
664e1a8321 Now that we can have no monitoring we need to check all nodes at failover
not only those in repl_monitor
2012-07-21 17:49:38 -05:00
Jaime Casanova
d43c6334da Prepare HISTORY and release notes for release 2012-07-21 12:06:33 -05:00
Jaime Casanova
f984b3fd33 Document tunables added in aaf35947ed 2012-07-21 11:10:59 -05:00
Jaime Casanova
aaf35947ed Add tunables for connection retries to master and interval between
connection retries, these parameters along with master_response_timeout
determines the amount of time since failure to failover
2012-07-21 11:01:00 -05:00
Jaime Casanova
08ed0aa987 Commit 2d24518d9d added an additional
'}' at the end of parse_config(). removing.
2012-07-21 10:42:58 -05:00
Jaime Casanova
2d24518d9d If master_response_timeout hasn't been set in repmgr.conf it defaults
to zero, which was causing to a false positive in the failure detection
logic in wait_connection_availability(). So, change that to defaults to 60s
and add a check to avoid it being set to zero or negative.

Problem reported and analyzed by Andrew Newman
2012-07-21 09:49:05 -05:00
Jaime Casanova
a6c94b29de Change release notes because of commit bf241ba1d6 2012-07-06 02:00:46 -05:00
Jaime Casanova
bf241ba1d6 Make the monitoring history capabilities of repmgr be optional and
turned off by default. Most of it has been superseeded by
pg_stat_replication view, we can still start it by using the switch
--monitoring-history
2012-07-06 01:51:22 -05:00
Jaime Casanova
41dbc39527 Add release notes 2012-07-05 09:35:23 -05:00
Jaime Casanova
50b7147f15 Change Copyright date to cover 2012 2012-07-04 10:47:26 -05:00
Jaime Casanova
f5e57aa433 Add an option for "no-history" mode, where repmgrd just checks the
conectivity of master but don't INSERT any data into it
2012-07-04 10:07:31 -05:00
Jaime Casanova
ac5a9d1fd6 The release changed, just wait a little before setting it.
Also make well known names in HISTORY be only names, without
last name
2012-07-02 00:06:57 -05:00
Jaime Casanova
cb740b68be Add a check of the connection inside the CancelQuery() so it check
that before trying to cancel a query, which can block.
2012-06-26 11:29:02 -05:00
Jaime Casanova
d58ea77798 Add a quick setup for autofailover 2012-06-26 07:49:43 -05:00
Jaime Casanova
e3c3c22b6e Improve the version message to actually show the repmgr version not
only postgresql's one
2012-06-25 22:54:48 -05:00
Jaime Casanova
861a3c8f22 Fix CLUSTER CLEANUP, it needs to establish a local connection in order
to look for the master
2012-06-16 01:32:59 -05:00
Jaime Casanova
e51870b504 Force to enter a password for the superuser in the witness, this is
in case we need to send a password to connect as stated in
master's pg_hba.conf.
2012-06-15 13:51:45 -05:00
Jaime Casanova
5651720560 Remove a variable left in last commit 2012-06-15 09:46:01 -05:00
Jaime Casanova
d32a6cdb24 Remove kludge added to create user and db for witness.
It's too fragile, almost always cause a "segment violation" and
don't seems to be very useful.
2012-06-15 09:41:54 -05:00
Jaime Casanova
9e10987b90 Fix a few bugs introduced when merging features 2012-06-15 09:40:09 -05:00
Jaime Casanova
64fce88e99 Add a CLUSTER CLEANUP command to clean monitor's history,
also include a --keep-history (-k) option to indicate how many
days of history to keep
2012-06-13 00:39:54 -05:00
Jaime Casanova
7a76f1998c getMasterConnection() cannot avoid checking the same node that asks
to find the master.
This was a micro optimization based on the fact that all commands that
needed to detect the master were executed from the standby but now that
we have CLUSTER level commands that is not true anymore
2012-06-12 23:28:24 -05:00
Jaime Casanova
4db046a8ea Allow repmgr to obtain tablespace's locations from pg 9.2 and later
in which we no longer have a spclocation column in pg_tablespaces
2012-06-12 11:08:15 -05:00
Jaime Casanova
331eca447a STANDBY CLONE should be run by a SUPERUSER, otherwise we won't be able
to retrieve data_directory and the other parameters we need by
querying the database.
2012-06-12 09:42:50 -05:00
Jaime Casanova
b5b2f93f7e Merge branches 'master' and 'async' 2011-12-02 00:28:17 -05:00
Jaime Casanova
9d03d4a254 After checking that master is alive, is_pgup() should return not keep
checking forever.
2011-12-01 23:58:12 -05:00
Jaime Casanova
3b2ccc5b78 Add a master_response_timeout parameter and use it to limit the amount
of time we spent a reponse from master before declaring the failure.
Also, change is_pgup() so it use PQsendQuery() instead of PQexec to
execute the check of master
2011-12-01 01:20:33 -05:00
Jaime Casanova
89a1e2bcbd Not even consider old master as an option in failover 2011-11-27 19:17:59 -05:00
Jaime Casanova
7077a7c68f Add -w option to pg_ctl commands so we wait until command is finish.
Or at least, we try. By default, after 60 seconds pg_ctl just return.
This make useless to wait ourselves after pg_ctl start of witness so
remove the sleep
2011-11-27 18:38:53 -05:00
Jaime Casanova
9b8fb7e960 Remove last argument from log_err, left in commit 55c7ea4b5e.
Also rephrase the sentence

Reported by Jeroen Dekkers
2011-11-25 14:59:29 -05:00
Jaime Casanova
55c7ea4b5e Fix a wrong message.
It was saying the problem is the version of the PostgreSQL server while
it actually is because the MASTER REGISTER command was running on a
standby node
2011-11-10 09:38:12 -05:00
Jaime Casanova
0240cb2bfb Fix a typo introduced in commit cb764b180d 2011-11-03 12:50:51 -05:00
Jaime Casanova
2e64028f26 Add the improvement of the view repl_status to the history 2011-10-20 23:26:41 -05:00
Greg Smith
27396f462a Add strnlen on platforms that don't have it, such as OS X 2011-10-20 23:23:31 -05:00
Jaime Casanova
cb764b180d Let the clone happen in a session with synchronous_commit off. This
is because in pg 9.1 the default configuration can easily allow sync
rep to be activated even if no standby is present and will block
pg_start_backup() and pg_stop_backup() in that case.
2011-10-03 14:04:27 -05:00
Jaime Casanova
65cf045a63 Fix a few problems introduced in 020e17b059
while adding standby_name
2011-08-09 02:01:00 -05:00
Jaime Casanova
3d53661d97 Fix a typo introduced in the commit about standby_name
(020e17b059)
2011-08-09 01:14:50 -05:00
Jaime Casanova
7b3a9cbbe4 Rename standby_name configuration option as node_name
per gripe by Cedric
2011-08-09 01:01:37 -05:00
Jaime Casanova
276c947202 Add name to nodes and show it for the standby in repl_status. 2011-08-09 00:58:01 -05:00
Jaime Casanova
020e17b059 Add a new standby_name parameter that, when provided in repmgr.conf,
is included in the primary_conninfo as application_name... This is
a simple first step towards making repmgr works fine with 9.1 and
sync standbys
2011-08-09 00:57:23 -05:00
Jaime Casanova
10817ecffc Add "witness" as a node role in CLUSTER SHOW 2011-08-08 13:29:26 -05:00
Jaime2ndQuadrant
f26e37c087 Merge pull request #2 from 2ndquadrant-it/master
Add function to show nodes with actual roles: repmgr cluster show
2011-08-08 11:10:13 -07:00
Carlo Ascani
61c31eeb0c Added function to show nodes with actual roles: repmgr cluster show 2011-08-08 19:32:32 +02:00
Jaime2ndQuadrant
0b5d2418df Merge pull request #1 from 2ndquadrant-it/master
Added function "write_primary_conninfo" which now adds the username to the primary_conninfo parameter in recovery.conf

Author: Gabriele and Marco
2011-08-05 11:03:54 -07:00
Gabriele Bartolini
f44037088b Added function "write_primary_conninfo" which now adds the username to the primary_conninfo parameter in recovery.conf
Signed-off-by: Gabriele Bartolini <gabriele.bartolini@2ndquadrant.it>
Signed-off-by: Marco Nenciarini <marco.nenciarini@2ndquadrant.it>
2011-08-05 17:41:18 +02:00
Carlo Ascani
e05dd729f8 Fix a typo in documentation 2011-08-05 00:15:13 -05:00
Jaime Casanova
ab8d2673dc Remove useless second parameter from create_recovery_file()
per gripe by Gabriele
2011-08-04 17:45:28 -05:00
Jaime Casanova
28c5ac3d91 Make is_standby() and is_witness() work the same way, actually
is_standby() can show the segmentation fault problem but for code
clearity
2011-07-26 18:36:27 -05:00
Carlo Ascani
c983fdf83c Fix a possible double free that would cause a segfault in
checkNodeConfiguration()
2011-07-26 18:22:06 -05:00
Carlo Ascani
158214acae Only log that we have restored the connection when that already happens,
this fix a flood in logs that make them unnecessarily big
2011-07-26 18:16:22 -05:00
Jaime Casanova
04290c1f60 Another pass reviewing code:
- remove a duplicate check for ssh connection and just exit if
  we can't connect to the remote host.
  stop_backup is only needed if pg_start_backup() has been
  already called
- remove a new connection to master in stop_backup label, AFAIC
  we hadn't close the one we already opened
- add a lot of PQfinish(), a few PQclear() and adjust code to what
  we used to do in 1.x
2011-07-26 16:14:44 -05:00
Jaime Casanova
cedc5e20fb Add a check to ensure 'hot_standby=on' on master. While this parameter
doesn't have an effect here it will be a reminder for users, besides
will reduce things user have to do on the standby
2011-07-26 16:12:51 -05:00
Jaime Casanova
b61ac86b5f Move repmgr_update_standby_location() and
repmgr_get_last_standby_location() functions to repmgr schema.
This will be important when we want to create this as an
extension, so better make it be in the right place from day 1.
2011-07-26 16:12:11 -05:00
Jaime Casanova
64da72b48b repl_monitor.last_wal_standby_location should accept nulls because
of the witness
2011-07-26 16:11:26 -05:00
Jaime Casanova
c4778a83c5 Be consistent in the use of sqlquery_snprintf() for query strings,
which was not used in the new code.
Also add a few "newline" characters in some messages, and other
minutia.
2011-07-19 05:02:51 -05:00
Jaime Casanova
4d26e4d21e Redefining repl_status view to improve performance, also add an
index on repl_monitor to speed up even more the view.
2011-06-13 11:58:43 -05:00
Jaime Casanova
3f4ff5a862 A "HEAD" word remaining from a merge conflict was accidentally left
in... removing it
2011-06-10 21:16:07 -05:00
Simon Riggs
1d05467df1 README additions and improvements 2011-06-07 11:37:09 +01:00
Simon Riggs
15ba3342aa Remove whitespace 2011-06-07 11:12:58 +01:00
Greg Smith
3a950c9f8b Squashed commit of the following:
commit e7ef17117efe6679e154a4905d587c808b48df50
Merge: cd3a280... 43268f2...
Author: Greg Smith <greg@2ndQuadrant.com>
Date:   Tue Jun 7 01:40:08 2011 -0400

    Merge commit 'origin/master' into autofailover

    Conflicts:
    	repmgr.c

commit cd3a280804a01c5270c5c743e5822c7beb9ac77a
Merge: 72ad378... 8200b68...
Author: Greg Smith <greg@2ndQuadrant.com>
Date:   Tue Jun 7 00:52:42 2011 -0400

    Merge commit 'origin/master' into autofailover

    Conflicts:
    	config.c

commit 72ad378bed21d74dab743fec411fe10b19007481
Merge: 17bafa1... 367d0b1...
Author: Greg Smith <greg@2ndQuadrant.com>
Date:   Tue Jun 7 00:38:01 2011 -0400

    Merge commit 'origin/master' into autofailover

    Conflicts:
    	config.c
    	dbutils.c
    	repmgr.c
    	repmgrd.c

commit 17bafa1ca509c1f6614810bab2538e570ebc599e
Author: Greg Smith <greg@2ndQuadrant.com>
Date:   Tue Jun 7 00:31:28 2011 -0400

    Run astyle to fix recent changes

commit a5fbbaecce8fe86bc17c0ebeb1324f9262967316
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Tue May 10 00:46:58 2011 +0200

    Fix a crititcal bug in the decision process

    If the postgresql on the first node returned by the query to find
    candidates in do_failover is down then the initialization of the
    bestCandidate is done with non assigned variables.

    Fix the situation by moving the initialization in the loop above.
    And loop until we have a find_best. Added a log message if no candidate
    is found

commit 42b21475ac248db8f0e50f5956ef96808e92c68c
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Mon May 9 22:39:21 2011 +0200

    Add test_ssh_connection

    The feature was written by Jaime and reworked to fix
    https://github.com/greg2ndQuadrant/repmgr/issues/5

commit 86f01afae631e9541600af6578e649d88c3ece98
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Mon May 9 21:39:42 2011 +0200

    Improve log output

commit db2f29fc1c8ea03a8ff85717873f8a876846b844
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Mon May 9 01:41:34 2011 -0500

    Only compare getenv("USER") when it's actually set, otherwise it
    will segfault

commit ea4f3f20747e2e0294551d5e61869bdde6d3cd7b
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Mon May 9 01:03:39 2011 -0500

    Fix a message to only show when log_info is requested and the verbose
    flag is set.
    This is because it needs a calculation that is only done when the
    verbose flag is set, so if i have requested log INFO level but haven't
    set the flag it shows a null

commit 35a53bac7e341cfdbb64d2c15fa77c9c4e18bd40
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Mon May 9 01:00:54 2011 -0500

    Use log_* functions in do_witness_create()

commit 8c526f758a46ad53b4d391fc76360561d4ff8bdd
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Sun May 8 19:30:34 2011 -0500

    Add a fallback_application_name parameter to the conninfo identify
    the connection if application_name is not set

commit 01057fc12cbc1fb656d619f483044f28a5f08d37
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri May 6 23:57:27 2011 +0200

    Fix the best_candidate loop

    there was an overflow in the loop, already fixed but loosed during merge.

commit e80effa3daf56f08005704fc1a5bbe69c1324212
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri May 6 23:55:15 2011 +0200

    Fix check in do_failover (merge faillure)

    And also remove an unused variable as I was here.

commit 79ba37e2933f4e87523a77375dfda1d96150e7d3
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu May 5 21:15:46 2011 +0200

    Fix compile error

commit 67c7b5d68c95a60bb4cd0cfb750b4c8d047fa2a0
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 24 23:27:57 2011 +0200

    And apply astyle  ....

commit 9a321722537d96983b8162227ff629a267b6ed67
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 24 23:27:09 2011 +0200

    Cosmetic change to reduce diff with master

commit 09037efea3fa2c31896b5dc78b0340516a743ba6
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 24 22:26:03 2011 +0200

    Apply astyle

commit 7c4786f662943558be967be4a8dad976f52155dd
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 24 02:22:12 2011 +0200

    Improve the standby clone action

    By default, all config files and directories are cloned from the master in the
    same place in the slave.
    If a destination directory is provided (-D), everything is copied in the
    provided dir, and if the master have tablespaces repmgr exit without cloning.

commit a6d7f765b9403a2cff7e2e1df8ae45a5a7ee1665
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Apr 22 23:31:09 2011 +0200

    Add success message for repmgr standby register

commit 26bf3b08e661137dd3f3c0d3c00fd6b3b90b08b3
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Apr 22 22:51:28 2011 +0200

    Change the exit to a return in config.c

commit 1bd8f4c119e1dbf9a94b2eaec884abce96eeb174
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Apr 22 22:32:57 2011 +0200

    Reduce duplicate code

commit db553fab45ca075f95f09bdb2147de68948b60c8
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Apr 22 22:24:04 2011 +0200

    Some cosmetic

commit f19d0ad714ebcf7df7726772e887c873d005d350
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Apr 22 22:23:06 2011 +0200

    Move a function declaration into header file

commit 1f328bc438c896a9f2067069d756f901b58d41f2
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Mon Apr 11 00:38:30 2011 -0500

    We don't use conninfo as a separate variable anymore

commit f6ade0d63b8a5dd43377f546f5311b4a151b2bfb
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Sun Apr 10 20:53:22 2011 -0500

    Fix a few typos

commit ceca9fa983c8dbde61a7a78da29a1e1871756d8c
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Sun Apr 10 19:32:57 2011 -0500

    Fix code to allow the code to compile:
    - some log_* had problems with parenthesis
    - some uses of variables without the runtime_options prefix

commit 73431f955afd77560bca5370924e09329566c4b7
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 10 23:21:37 2011 +0200

    Fix the debian package name

commit 688eab371110083ae8715b35f414e29c6d87e1ac
Merge: 5c23375... 7995c42...
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 10 23:17:58 2011 +0200

    Merge branch 'autofailover' of git.2ndquadrant.it:repmgr into autofailover

commit 5c23375f88a53ed469e9d13934d618f7a74669be
Merge: cc3315c... c4ae574...
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 10 23:08:36 2011 +0200

    Merge branch 'master' into autofailover

    Conflicts:
    	repmgr.c

commit 7995c428161566cfc54a67eb16f9134c859e7381
Merge: 788ff98... 1303e49...
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Sun Apr 10 16:14:30 2011 -0500

    Merge branch 'autofailover' of git+ssh://git.2ndquadrant.it/git/repmgr into autofailover

commit cc3315ce235b898711c34fd1f2fa1116dbee4e16
Merge: 1303e49... d77186c...
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 10 23:03:11 2011 +0200

    Merge commit 'd77186c90444b9c5ca2de201651841f56a7ded02' into autofailover

commit 1303e49852705046e15ef64f5f7ab739a1689431
Merge: 7ff621b... 4c792c8...
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sun Apr 10 22:28:08 2011 +0200

    Merge commit '4c792c8013f5713589f53dbdb47721febf139a85' into autofailover

commit 788ff98e94311a33e3e6f7d85a303cbc61288e5f
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Tue Mar 15 19:00:56 2011 -0500

    A few fixes after merge to unbroke what the merge broke, and to make
    the new logging system more consistent through the system

commit 7ff621b96784dfaf40baab4f0f8e7857b4aed6ce
Author: Dan Farina <drfarina@acm.org>
Date:   Tue Dec 7 21:30:44 2010 -0800

    Install install/uninstall SQL also.

    Signed-off-by: Dan Farina <drfarina@acm.org>
    Signed-off-by: Peter van Hardenberg <pvh@heroku.com>

commit c9147dad8223eff20bf5d52ced8a35eed6d82110
Author: Dan Farina <drfarina@acm.org>
Date:   Tue Dec 7 21:30:20 2010 -0800

    Split up install/uninstall actions more like a standard contrib

    Signed-off-by: Dan Farina <drfarina@acm.org>
    Signed-off-by: Peter van Hardenberg <pvh@heroku.com>

commit c8028780b50f2c7fb4384cb9891796647f356e19
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sat Feb 12 13:29:32 2011 +0100

    Fixing SLEEP times and RETRY

commit 39a1bf3d29f3e33fbf0e1b066a311e8a72f2dc38
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Sat Feb 12 01:17:37 2011 +0100

    Add a pause after update_shared_memory() in do_failover

    we pause for SLEEP_MONITOR+1 to let other nodes update themselves.

commit 527af2baa945e3b640352c01c6dd181d93c9529a
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 21:14:22 2011 +0100

    change the debian package filename too

commit c8cb27c7039b2b3a838554187a8add850a42027a
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 15:14:40 2011 +0100

    Change package name for the automatic fail-over branch of repmgr

commit 7427988628f754e57069453d65a71f79117c3a3d
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 14:28:03 2011 +0100

    Exit 1 when SIGINT

commit af366fe731b70e24ead056e50b69269392bd15a1
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 14:27:46 2011 +0100

    Improve log output when reloading configuration

commit 6cc18ce081d7bf55ba9993e9d87567879da35c4d
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 14:20:36 2011 +0100

    Add reload conf on (re)start

commit 4259e2c410fd0ef1273c7d1b4ab8fcf1e778e968
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 14:01:37 2011 +0100

    avoid double free on repmgrd exit as master
    Per commit from Charles Duffy <charles@tippr.com>
    and faillure to cherry-pick it correctly.

    Conflicts:

    	repmgrd.c

commit 431e27b1c005e000f9a346d982419979b4363d77
Author: Greg Smith <greg@2ndQuadrant.com>
Date:   Thu Feb 10 15:09:18 2011 -0500

    Tweak .gitignore to ignore more doc build artifacts

commit b725fa9ae65c7bd5fea7a4e944db5685dee2e8bd
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Sun Mar 13 15:16:27 2011 -0500

    Delete a paragraph that appears twice, because a merge problem

commit d990c77b327a282c1903b7a339f35a22b6a89958
Author: trbs <trbs@trbs.net>
Date:   Tue Jan 11 18:24:17 2011 +0100

    added note about postgresql-server-dev-9.0 and use libxslt-dev instead of version specific package name

commit 69bc1cd3772103b529598978160327e1f9025157
Author: trbs <trbs@trbs.net>
Date:   Fri Jan 7 01:32:31 2011 +0100

    fix line

commit f7b1d1e5e3764c85cec7afa81c164fac3679e1ea
Author: trbs <trbs@trbs.net>
Date:   Thu Dec 23 15:02:23 2010 +0100

    Updated README with Debian/Ubuntu install information

commit 77d28960ff78c3936be0e1029305b0b578e260a9
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 13:34:49 2011 +0100

    Create the function used for shared memory access in create_schema, note that this is incompatible with current master

commit 4a73043f232f0a143ede898841530f4d7442c95b
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Fri Feb 11 10:00:34 2011 +0100

    improve log output

commit 62c90a4e86b2cd56ec14255adcfef564945d0769
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Fri Feb 11 00:40:05 2011 -0500

    Close local connection on witness before exit on error of primary

commit e5156865e05670fa9944d74d472127082556d0a0
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Fri Feb 11 00:34:25 2011 -0500

    Remove a semicolon which is just a typo

commit 7586a09bc321241932adacf6a1431029964dc46f
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Fri Feb 11 00:07:02 2011 -0500

    Fix the computation of quorum, we need to count master and the
    division should not be an integer division

commit a19c0ad2059a00e9e7415fc6ea280c109c809c9c
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu Feb 10 23:54:35 2011 +0100

    move the functions back into public schema

commit 19fc8ffb1dc0fd9acddad5d22bf5c01704687474
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Thu Feb 10 00:48:00 2011 -0500

    A few more fixes.
    Make repmgr functions exists in repmgr schema and fix a typo that
    caused a seg fault.

commit c6d2b8c6421f93074d7d616980feb0175ee4ef36
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Feb 9 17:56:44 2011 -0500

    A few places where i forgot to update the priority field

commit 0ff0bb8d981b868693c6a751e7e80473b25f2399
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Feb 9 14:24:43 2011 -0500

    Fix a few bugs from last commit and make reload configuration also
    update registration on repl_nodes

commit 508c34e9dfb2bfb7e47d5c6836ead7992e6112fe
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Feb 9 13:45:20 2011 -0500

    Add a way for the user to indicate it's preference about which node
    should be promoted in case of a conflict (ie: two nodes with the
    same wal location).

    This will be provided as a parameter in repmgr.conf called priority,
    andd will be registered in the repl_nodes table.

commit 6005f1bbf90de61b4c5ebc34302307fa05b019a7
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Feb 9 11:15:30 2011 -0500

    Add a heartbeat for the witness, this should write to repl_monitor
    table so we can see the witness in repl_status and monitor if it
    is working.

    Also close connection at the end of do_witness_create in repmgr.c

commit ac1c6367ab689aeae2eff3dda22db42337f300c1
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Feb 9 01:26:41 2011 -0500

    Add a sighup handler to reload the configuration

commit 7df2fb7b74a3c5287319e56112840d9c2a3e7d5b
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu Feb 3 18:42:36 2011 +0100

    Change the is_pgup () check test

    remove spurious 'return'

commit 7e58e6aa91ab3f681854a44fe282b44da81768fa
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu Feb 3 16:53:17 2011 +0100

    Add constant for the sleep times and retry, rework monitor functions

    Rename MonitorExecute() to StandbyMonitor()
    Add    WitnessMonitor() # very simple version to start service mode isolation

commit 1b270dab2e2c3c60527b86a33cd0fc9c0d11c08c
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu Feb 3 16:23:01 2011 +0100

    Improve PrimaryCheck

    add a function "bool is_pgup()"

    Now, repmgrd-master can work.

commit c6f07229713c8f2b77596459c06184edddd8d77e
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Wed Feb 2 19:31:06 2011 +0100

    Fix strcmp in config parser, now failover parameter should be set correctly

commit 0b690698a0d9aa87d3e8f1e462ee0771aa2ae9e8
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Wed Feb 2 16:23:50 2011 +0100

    fix sprintf extra param

commit 6050da315824048661be9c425ae6005576e5870f
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Wed Feb 2 13:53:29 2011 +0100

    Add some other files to ignore

commit a146dd581b46ea0e26b7b56b087d6b0d4ae15d44
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Wed Feb 2 13:53:04 2011 +0100

    Fix SQL query

commit 8f5db0f9c0f68ce2519afda72b6a778536427eab
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Wed Feb 2 00:51:54 2011 +0100

    Some more minor fix and remove TODO

commit c9299ad74e8f929bdc24804a6a834f24b66b7074
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Wed Feb 2 00:39:18 2011 +0100

    fix some memory leak and fix testlogic for is_standby is_witness

    * is_standby() must be tested *after* is_witness else we think we are in a master
    * remove SELECT * in favor of SELECT witness

commit cc5d06ea8bf1dcde4c264e95eb90f7fb1e821af3
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Tue Feb 1 23:40:15 2011 +0100

    Forgot to remove a param from fprintf

commit 426e22fa8dfd78f0c256bda1b166a31807de9ec6
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Tue Feb 1 22:47:58 2011 +0100

    Restore previous usage of --force and rsync tablespace before data_dir

    The --force option is used to reduce the time needed to restore a failed
    node: it will overwrite existing files thanks to rsync --delete option

    The tablespaces need to be coyed first, because there are symlinks to
    them from the data_directory

commit 1937973fced703d14159e6aae1cbdabb5619accb
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Tue Feb 1 21:09:12 2011 +0100

    Improve message of repmgrd

commit 035a9bcc1eea55cd95790bc72276727cc492694a
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Tue Feb 1 21:08:38 2011 +0100

    Fix (bool *)PQgetval

commit bf9181654213f898949e9c8f094b974915f82258
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Tue Feb 1 01:54:49 2011 +0100

    Fix pg_hba on witness and connection

    * Copy the pg_hba.conf file from master to witness server
    * createdb and createuser in witness if they are different from getenv(USER)

commit a2d8dcb2fd105d8f02bd76856969aca6605c66fa
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Tue Feb 1 01:01:43 2011 +0100

    Improve initialization of repmgr (+ critical bug and minor fixes)

    * standby clone now *clone* the master files and dir to the *same*
      place on the standby if destination_directory is not provided
    * add preload library to the witness configuration
    * sleep 2 seconds after starting the witness postgresql to let it
      start enough to be able to connect to it.
    * Fix rsync files
    * Fix insert configuration into witness

commit bc1a265d272e4805ac7859c208b51b57edd10fc7
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Mon Jan 31 12:25:20 2011 +0100

    Fix some error message new line

commit e087bd5de5ab43ffac90c6a20df6ef3fb19eed6d
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Mon Jan 31 11:37:08 2011 +0100

    Guess data_directory from master in 'standby clone' and remove --force for dir

    --force does not overwrite directories anymore (it was not working very well anyway)
    dest_dir is the same as the master's one by default.
    Move down the tablespace check directories process

commit 0a961e7ef05f26c87af1946b8141a639076fc488
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Mon Jan 31 11:21:40 2011 +0100

    Add new function: create_pgdir (and fix 2 bugs in the process).
    It also fix function create_schema.

    Reduce repmgr code

commit 7e5958dcc1daa9b54cb6f295af96fbef750c7952
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Mon Jan 31 10:34:58 2011 +0100

    Improve an ERROR message

commit f3a66a65a361f919727fc2d0ff9bf9544a10a822
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Mon Jan 31 10:25:45 2011 +0100

    Improve error message about 'wal_keep_segments'

commit 150dbcc0fe53ce4eff08797210fd2e9e4dd0e17a
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Sat Jan 29 23:35:00 2011 -0500

    Add witness server support

commit 6281e22a9c467da883ad960567f8ab6bdbc155ba
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu Jan 27 21:32:11 2011 +0100

    Build all at once and update debian makefile to include the sql/

commit 50d752bf1ead7c9343900d4b494844284b7aac6c
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu Jan 27 02:10:31 2011 +0100

    Adding information for debian and --version test

commit 16d56dbfa05314eea69869ee2a7a705636432ad9
Author: Cédric Villemain <cedric@2ndQuadrant.fr>
Date:   Thu Jan 27 02:03:20 2011 +0100

    Add a hint at the end of the standby clone
    and minor typo and message shuffle

commit 6404ba247de1e2e3b995f30b6e7626e459849136
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Jan 26 06:13:30 2011 -0500

    Fix compiler warning about variables beign used unintialized

commit a4f48993d5fe3b22bdd2aaefcff315115f8764b7
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Fri Jan 21 21:09:03 2011 -0500

    Fix a new typo

commit 904e61c9edcbbce6b1027c80ff77317d7cbd4919
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Fri Jan 21 19:30:56 2011 -0500

    Use a function to make the call to repmgr_update_standby_location()
    so i avoid typos like the one i fixed in a previous commit. It also
    makes the code cleaner.

commit 4ed388726f4bc0a52cc88d044d1f81697f348a7c
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Jan 19 09:17:16 2011 -0500

    Fix a typo when calling the sql function that writes shared memory

commit d9232266561306eabef90e13c084c051a0e7f458
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Tue Jan 18 01:25:23 2011 -0500

    Define the variable that we are using to test the result status of
    the system() call.

commit 4d131c212b91e40ca027f76637c182456ab12514
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Tue Jan 18 01:04:12 2011 -0500

    Makes repmgrd warn if promote_command or follow_command fails, add
    a "still alive" check for primary.
    Add a few messages and fix a bug in do_failover() in which we were
    using a closed PGresult.

commit a5189e68cf4c8cf84259ea667a35e96de56fa4c9
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Thu Jan 13 15:45:50 2011 -0500

    Initial attempt to get autofailover

commit d0e09010a9d4610997c900b62ea1df2a71b01015
Author: Jaime Casanova <jaime@2ndQuadrant.com>
Date:   Wed Jan 12 14:40:29 2011 -0500

    Add options failover, promote_command and follow_command
    to repmgr.conf, in pass also rename sample repmgr.conf to
    repmgr.conf.sample
    promote_command and follow_command allows to use a custom script
    for those actions.
2011-06-07 01:42:15 -04:00
Greg Smith
43268f2345 Refactor more log messages to use "_" form 2011-06-07 01:17:41 -04:00
Greg Smith
8200b68cf7 Convert some remaining fprintf messages to logger 2011-06-07 00:50:46 -04:00
Greg Smith
06aecbf58a Fix copyright date on repmgr.sql 2011-06-07 00:46:16 -04:00
Greg Smith
367d0b1afa astyle fixes on logging change 2011-06-07 00:30:35 -04:00
Greg Smith
e52f2e88a5 Update use of paranthesis in logging messages.
Extracted portion of what was originally
ceca9fa983c8dbde61a7a78da29a1e1871756d8c , due to be
applied later.
2011-06-07 00:19:11 -04:00
Cédric Villemain
620f8090a3 Add test_ssh_connection
The feature was written by Jaime and reworked by me to fix
https://github.com/greg2ndQuadrant/repmgr/issues/5
2011-05-09 22:52:29 +02:00
Jaime Casanova
534649eb03 Fix a message to only show when log_info is requested and the verbose
flag is set.
This is because it needs a calculation that is only done when the
verbose flag is set, so if i have requested log INFO level but haven't
set the flag it shows a null
2011-05-09 01:07:54 -05:00
Jaime Casanova
1e8b9e8960 Add a fallback_application_name parameter to conninfo to identify
the connection if application_name is not set
2011-05-08 19:26:59 -05:00
Cédric Villemain
c4ae5741a3 Fix getopt for ignore-rsync-warning
The change was loosed during merge and not checked in master/
2011-04-10 22:42:38 +02:00
Greg Smith
f824189692 Cleanup new ignore rsync warning feature. Closes gh-22. 2011-04-05 17:52:39 -04:00
Greg Smith
68b42d16c9 Merge commit '3ca0f2db06c9114c59e0846dda487cca9b1e85ff' 2011-04-05 17:26:33 -04:00
Greg Smith
3ca0f2db06 Fix unapplied astyle. Closes gh-26. 2011-04-05 17:21:48 -04:00
Cédric Villemain
235903e517 Fix rsync return code test 2011-03-28 18:42:20 +02:00
Cédric Villemain
bf29601218 remove the exit on rsync error because it is handle by the caller 2011-03-28 17:08:22 +02:00
Cédric Villemain
02a3fbb303 Add --ignore-rsync-warning to README 2011-03-28 16:46:47 +02:00
Cédric Villemain
b30398bf2a Add --ignore-rsync-warning command line option
This fix the rsync return code in case there are vanished files.

Common situation are DROPed tables and TEMPorary object deletion and
are handled by PostgreSQL.
But as it may exist situation where an external process delete files in
the PGDATA the flag is off by default.

XXX 2 items :

 * is -I a good choice ? maybe we need to prevent future --ignore-foo and
   add something like : --ignore=rsync_warning -I rsync_warning
 * the warning message is not enough explicit with the risk involved by
   --force usage
2011-03-28 16:38:55 +02:00
Cédric Villemain
e74e319e7a Applying indent style 2011-03-28 16:05:09 +02:00
Jaime Casanova
d77186c904 Ignore error 24 from rsync (that could happen if we use a lot of
temp tables for example).
It only ignores that error if we are copying a directory (which means
we are in pg_start_backup() and then ignore changes that happen
due to concurrent access is fine).
2011-03-28 16:02:32 +02:00
Greg Smith
4c792c8013 Add TODO, update history for 1.1.0 release 2011-03-09 15:27:29 -05:00
Greg Smith
e7903a7971 Merge branch 'master' of git+ssh://git@git.2ndquadrant.it/git/repmgr 2011-03-03 09:27:18 -05:00
Greg Smith
f372793114 Merge correction commit 2011-03-03 09:26:22 -05:00
trbs
295a183d0b removing old code which is made invalid after merging the different branches by upstream 2011-03-03 09:25:27 -05:00
trbs
c6693340c1 cleanup help and usage 2011-03-03 09:21:46 -05:00
trbs
cc0c516810 added new lines to log messages 2011-03-03 09:21:38 -05:00
Jaime Casanova
58ec43106e Options -U, -R and -p shouldn't be mandatory. Fix by checking if the string
is empty before use.
2011-03-02 02:44:01 -05:00
Greg Smith
3e960286c7 Update history for 1.1.0-beta1 2011-02-24 19:25:40 -05:00
Greg Smith
bf0bbd747b Fix typos in some logging messages 2011-02-24 19:05:03 -05:00
Greg Smith
459f14b594 Document repmgrd's role on each type of node. Add
logging (when run in verbose mode) showing what
decisions repmgrd is making after it determines
what type of node it is.
2011-02-24 18:58:03 -05:00
Greg Smith
f928edf897 Improve parameter validation, logging, and error
handling in repmgrd
2011-02-24 18:13:16 -05:00
Greg Smith
c7b62003b2 Reorganize README to be easier to follow 2011-02-23 09:50:07 -05:00
Greg Smith
59b7b90169 Update README with better two-node example output 2011-02-23 09:08:08 -05:00
Greg Smith
3cdd6a57fd Add more info level logging around database activity 2011-02-23 08:42:49 -05:00
Greg Smith
5dcec5818f Update README with standard two-host examples 2011-02-23 08:42:06 -05:00
Greg Smith
9c6288993b Fix double free in standby clone 2011-02-23 07:26:39 -05:00
Greg Smith
2675101330 Make PGPASSWORD substitution in recovery.conf optional 2011-02-23 07:19:36 -05:00
Greg Smith
02daccd6e7 Wrap use of PQconnectdbParams, add proper error
checking and logging when the connection fails.
2011-02-23 06:44:10 -05:00
Greg Smith
18ef5b3cf3 Convert more uses of fprintf to use logger 2011-02-23 05:59:09 -05:00
Greg Smith
3b2203c38c Make verbose command line option useful on top of
the new logging infrastructure.
2011-02-23 05:29:29 -05:00
Greg Smith
fee7da1ba7 Fix cast on WAL lag computation to (long long) 2011-02-22 07:43:02 -05:00
Greg Smith
a98aec12e1 And one more round of astyle work 2011-02-15 00:57:12 -05:00
Greg Smith
757457ad85 Fix merge error that removed setting keywords 2011-02-15 00:55:50 -05:00
Greg Smith
45022debc6 Break out error codes, cleanup header files and HISTORY 2011-02-15 00:43:36 -05:00
Greg Smith
f6618a01c7 Post-merge astyle run 2011-02-15 00:14:13 -05:00
Greg Smith
20af4ffc2c Merge commit '3ef1fa126d9c9b9ba3b29deab7f67218cdf7ce10'
Conflicts:
	.gitignore
	Makefile
	README.rst
	check_dir.c
	config.c
	config.h
	dbutils.h
	repmgr.c
	repmgr.conf
	repmgr.h
	repmgrd.c
2011-02-15 00:06:01 -05:00
Greg Smith
3ef1fa126d astyle run against Heroku code 2011-02-14 21:51:14 -05:00
Greg Smith
ce06e6c8e0 Fix some mistakes in the history file 2011-02-10 19:34:50 -05:00
Greg Smith
0ad3d91e9c Cleanup history and credits 2011-02-10 18:57:50 -05:00
Greg Smith
0130420947 astyle cleanup run after recent merges 2011-02-10 18:55:51 -05:00
Greg Smith
c3af4274ae Document astyle command line used to standardize
code formatting
2011-02-10 18:55:17 -05:00
Greg Smith
5460517a43 Protect against duplicate header inclusion 2011-02-10 18:35:56 -05:00
Greg Smith
1d32133d49 Update all the copyrights to add 2011 2011-02-10 18:33:02 -05:00
Greg Smith
1be62fa6b2 Fix use of "options" broken by recent merging 2011-02-10 18:26:44 -05:00
Charles Duffy
b62ad056f1 repmgrd: log restored connection only after a break 2011-02-10 17:57:13 -05:00
Greg Smith
ec30caef0f Merge commit '78b925ea54bb7a131e97c2f5d0a63f54ca58e26f' 2011-02-10 17:52:50 -05:00
Greg Smith
78b925ea54 Unify use of error codes across all exit statements 2011-02-10 17:49:34 -05:00
Charles Duffy
7e7c45c61d exit with status 2 if manual work is needed during standby_clone 2011-02-10 17:08:43 -05:00
Charles Duffy
a02cd43115 repmgr: treat directory access errors during standby clone as failure 2011-02-10 17:03:00 -05:00
Charles Duffy
a67688f198 minor format string and comment fixes (add missing newlines, fix english usage, format string argument order) 2011-02-10 17:01:59 -05:00
Charles Duffy
f74b806e4f repmgr: exit with nonzero status on obvious errors 2011-02-10 17:00:33 -05:00
Charles Duffy
657aa3013b avoid double free on repmgrd exit as master 2011-02-10 16:40:00 -05:00
Greg Smith
8d2aff558d Update history with recent merges 2011-02-10 16:19:35 -05:00
Gabriele Bartolini
6e1306cfb2 Uses a switch to detect the log level 2011-02-10 16:09:46 -05:00
Gabriele Bartolini
308efba95e added explanations about logging 2011-02-10 16:09:46 -05:00
Gabriele Bartolini
556f256bb6 Now standby clone command accepts configuration file - for logging purposes only 2011-02-10 16:08:07 -05:00
Gabriele Bartolini
83eee2ed96 added some messages to the clone command 2011-02-10 16:08:07 -05:00
Gabriele Bartolini
cb36aaddff - Added \n 2011-02-10 16:08:07 -05:00
Gabriele Bartolini
3146d2c676 fixed some bugs with standby clone 2011-02-10 16:08:07 -05:00
Gabriele Bartolini
3f1c6a5852 Removed any sprintf/strcpy call and use snprintf/strncpy - Fixed bug with tblspc_dir - added debug messages after every query 2011-02-10 16:08:07 -05:00
Gabriele Bartolini
716a0ae9d3 removed any malloc operation, added t_runtime_options struct 2011-02-10 16:05:03 -05:00
Gabriele Bartolini
7a3be3a2f9 Cleaned log messages (\n at the end of every line) 2011-02-10 15:58:55 -05:00
Gabriele Bartolini
f6a6632169 Added new log system to both repmgr and repmgrd. Needs cleaning, but it is a good starting point 2011-02-10 15:58:55 -05:00
Gabriele Bartolini
2c1eafd7a9 first alpha version for syslog support 2011-02-10 15:56:10 -05:00
Greg Smith
1787cf1c21 Update credits and history to reflect recent merges 2011-02-10 15:19:00 -05:00
Greg Smith
287e2c1a67 Tweak .gitignore to ignore more doc build artifacts 2011-02-10 15:09:18 -05:00
trbs
b487772b84 added note about postgresql-server-dev-9.0 and use libxslt-dev instead of version specific package name 2011-02-10 15:06:09 -05:00
trbs
52313a2d6e made rsync_options configurable 2011-02-10 15:06:09 -05:00
trbs
814863edf2 use struct for config file information 2011-02-10 15:06:09 -05:00
trbs
e4f431c355 fix line 2011-02-10 15:06:09 -05:00
trbs
c3816d8586 added readme.html to gitignore 2011-02-10 15:05:07 -05:00
trbs
4ea0fc4214 Updated README with Debian/Ubuntu install information 2011-02-10 15:05:07 -05:00
trbs
03ed0e692a fix strformat order reversal in error message 2011-02-10 15:00:44 -05:00
Daniel Farina
ce21291418 Issue a message when a configuration file is passed unnecessarily
Simply intends to set expectations around the fact that a config file
is not used *and* doesn't affect anything material about the standby
clone command.

This uses a notion of "logging level" (like NOTICE) that is not yet
seen this program, but I'll probably introduce that soon.

Signed-off-by: Daniel Farina <daniel@heroku.com>
2011-02-10 03:19:36 -08:00
Daniel Farina
4b007bf4bc Use a better check for when to issue an error message
This patch changes raising the error "You need to use connection
parameters to the master when issuing a STANDBY CLONE command." to
only occur when no host (a global variable, that is abused for at
least two purposes, but is okay in this case) is passed, rather than
when no config file is passed, which is fine for standby clone (which
itself is a wrapper for rsync)

Signed-off-by: Daniel Farina <daniel@heroku.com>
2011-02-10 03:19:30 -08:00
Daniel Farina
da82829659 Avoid checking config file when performing standby clone action
Signed-off-by: Daniel Farina <daniel@heroku.com>
2011-02-10 02:10:58 -08:00
Dan Farina
ebbb7c3a47 Fix more quoting: used an overly-quoted copy
Signed-off-by: Dan Farina <daniel@heroku.com>
2011-02-07 03:59:18 -08:00
Dan Farina
630d716819 Use the proper freeing method
As according to
http://www.postgresql.org/docs/9.0/static/libpq-exec.html#LIBPQ-EXEC-ESCAPE-STRING

Signed-off-by: Dan Farina <daniel@heroku.com>
2011-02-07 03:59:18 -08:00
Dan Farina
c1b84fe9fc Make some fast hacks to quote schema names
Signed-off-by: Dan Farina <drfarina@acm.org>
2011-02-07 03:59:18 -08:00
Dan Farina
bfd3aed33b Fix a myriad of problems introduced by merging
Signed-off-by: Dan Farina <drfarina@acm.org>
2011-02-06 18:32:49 -08:00
Dan Farina
c356f9e97f Merge remote-tracking branch 'tbrs/master' into heroku
Grab the configuration struct changes. It was expeditious to un-do
some of my by-hand line-wrapping that avoids 80 character limit,
though.

Conflicts:
	config.c
	config.h
	repmgr.c
	repmgr.h
	repmgrd.c
2011-02-04 18:35:56 -08:00
Dan Farina
a52ebc412c Merge remote-tracking branch 'origin/master' into heroku
The Great Whitespace Reconciliation

Conflicts:
	check_dir.c
	config.c
	dbutils.c
	repmgr.c
	repmgr.h
	repmgrd.c

Signed-off-by: Dan Farina <drfarina@acm.org>
2011-02-04 18:27:28 -08:00
Cédric Villemain
fbf97807b8 Remove spurious file 2011-01-27 21:33:09 +01:00
Hannu Krosing
3cce9efac0 Merge branch 'master' of git+ssh://git.2ndquadrant.it/git/repmgr 2011-01-27 10:04:25 +02:00
Hannu Krosing
ec8678379f Makefile changes for building debian packages, left out of previous commit 2011-01-27 10:02:59 +02:00
Cédric Villemain
d017edbe47 Adding information for debian and --version test 2011-01-27 02:11:05 +01:00
Hannu Krosing
f41ba482eb dded section on building on Debian and Ubuntu 2011-01-27 01:09:18 +02:00
Hannu Krosing
4c5fad2070 simple support for creating deb file 2011-01-27 00:32:52 +02:00
Greg Smith
0dd31b09dd Additional notes on 32 vs. 64 build issues 2011-01-22 09:59:43 -05:00
Greg Smith
943dda0ad0 Document potential build issues on RPM 2011-01-22 09:09:37 -05:00
Greg Smith
d4de19bc78 Doc warning: need server restart after config change 2011-01-17 15:38:44 -05:00
trbs
1999b534fd added note about postgresql-server-dev-9.0 and use libxslt-dev instead of version specific package name 2011-01-11 18:24:17 +01:00
trbs
57169f51cf made rsync_options configurable 2011-01-08 01:46:39 +01:00
trbs
fc2405f17d use struct for config file information 2011-01-07 01:36:46 +01:00
trbs
4a0e827464 fix line 2011-01-07 01:32:31 +01:00
trbs
745392e3a2 added readme.html to gitignore 2011-01-06 23:46:21 +01:00
Jaime Casanova
170f519d84 Fixing a message, shouldn't show progname in the middle of a line.
Is one message not two.
2010-12-29 00:45:33 -05:00
trbs
cf5717ad59 Updated README with Debian/Ubuntu install information 2010-12-23 15:02:23 +01:00
trbs
cb1192b912 fix strformat order reversal in error message 2010-12-23 15:02:02 +01:00
Dan Farina
156714f3f1 Fix quoting misbehavior
Move the single quote in the formatting string to the end of the line.

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-23 01:04:05 -08:00
Dan Farina
dd5ac660bf Comments and cleanup
Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-23 00:55:39 -08:00
Dan Farina
3a430397dc Avoid overwriting the new password-in-recovery.conf formatting
Previously: did that work, then threw it away/overwrote it.

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-23 00:55:39 -08:00
Dan Farina
1f098c60ac Remove dead-ish code
This is a leftover after having fixed various problems in the verbose
output here.

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-23 00:55:39 -08:00
Dan Farina
0bae682a0d Fix off-by-one in passing buffer size to xsnprintf
This would cause a consistent panic (exit() call) without reason.
This should not enable any overruns (but check my work).

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-23 00:55:32 -08:00
Dan Farina
f969dca821 Hack to get passwords in recovery.conf
Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-22 20:10:32 -08:00
Dan Farina
29c39c21f6 Avoid a use-after-free in verbose logging (again)
Previously, this print would use memory freed by PQClear previously.

Also allocate/free memory to prevent this tiny memory leak.

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-22 20:10:15 -08:00
Dan Farina
620974ba04 Fix unsafe string handling
It looks like the old code would overflow in some cases.

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-22 19:00:21 -08:00
Greg Smith
9843205a4f Reformat all source code using astyle
astyle --style=ansi --indent=tab
2010-12-22 19:07:01 -05:00
Greg Smith
1ddb78ddd8 Merge branch 'license' of https://github.com/gbartolini/repmgr into gbartolini-license 2010-12-22 19:02:50 -05:00
Greg Smith
b0e1428caa Add contribution information 2010-12-22 19:01:58 -05:00
Greg Smith
47349b01e0 Merge branch 'gabriele-2010-12' of https://github.com/gbartolini/repmgr into gbartolini-gabriele-2010-12 2010-12-22 18:43:14 -05:00
Greg Smith
e5d886d651 Add CREDITS file 2010-12-22 18:42:24 -05:00
Greg Smith
91a304e3ee Add HISTORY file. Ignore build artifacts in git. 2010-12-22 18:34:29 -05:00
Dan Farina
faddaed316 Avoid a use-after-free in verbose logging
Previously, this print would use memory freed by PQClear previously.

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-22 15:03:05 -08:00
Dan Farina
7b0a142075 Merge remote branch 'gbartolini/gabriele-2010-12' into heroku
Conflicts:
	config.c
	dbutils.c
	dbutils.h
	repmgrd.c

Signed-off-by: Dan Farina <drfarina@acm.org>
2010-12-21 16:08:07 -08:00
Dan Farina
ec73a07e2f Make various buffers larger
MAXLEN definitely needed to be bigger to properly format fairly common
connection strings.  In addition, the reliance on xsnprintf helps
detect cases where even this buffer is not long enough.

the buffer in parse_config has been made bigger in a bit of sloppy
programming, but what really needs to happen is reporting when a line
cannot be properly parsed/is too big for the buffer.  That is just a
kludge.

Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
fc13d50e37 Canonicalize whitespace
Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
309bb92d95 Prevent a double-free
This can occur because prior to this, there is a code path that looks
like this:

    primaryConn = myLocalConn

CloseConnections will subsequently try to free both with PQFinish.
I'm not sure if this is the right fix -- it's more of hack -- without
more information about design intention.

One reasonable alternative would be to have CloseConnections perform
this check itself. As-is I am pretty sure that this fix leaves a
signal-race (when CloseConnections is called, without the check, in
the interrupt handler) unfixed.

Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
6cea339697 Fix a use-after-free
A result is being cleared while there are still pointers that
refer to datums in it.

Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
3f2094a242 Initialize connection pointers to NULL
This makes some bugs easier to find.

Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
84b69b3bd4 Whitespace to adjust for longer snprintf identifier
This is done in a separate patch to try and reduce the sound and fury
of the patch that actually did the conversion from sprintf to
snprintf-alikes.

Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
916c0492fb sprintf to snprintf conversion
Move out string operations to another file, and introduce a frontend
to snprintf for various situations.  This change is important for
catching and eliminating sprintf overflows, which are as of now many
times silently corrupting memory.

Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
846c0b92e8 Install install/uninstall SQL also.
Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
778303bb6e Split up install/uninstall actions more like a standard contrib
Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Dan Farina
af2edf10a0 Attack of whitespace pedantry
pgsql conventions (tabs, four-spaces-wide, etc) applied all around.

Also tried to fix some very tiny capitalization errors, auto-fill
problems, and some inter-block vertical whitespacing issues.

Long strings in repmgr.c were left intact, though. They are rather
numerous and are less of a problem than tiny bits of function calls
and comments wrapping over a line; the latter kind of problem has been
mostly fixed.

Signed-off-by: Dan Farina <drfarina@acm.org>
Signed-off-by: Peter van Hardenberg <pvh@heroku.com>
2010-12-21 15:19:28 -08:00
Gabriele Bartolini
d88783a4d9 Changed pg_version() prototype in order to remove the small memory leak 2010-12-16 22:48:19 +01:00
Gabriele Bartolini
f2bec9a08f Some cosmetic changes 2010-12-16 22:31:26 +01:00
Gabriele Bartolini
05e88a2cc8 removed strncmp improper usage, initialise values asap 2010-12-16 22:21:27 +01:00
Gabriele Bartolini
763a1e8b3d Reviewed the code, fixed a small bug with option name detection 2010-12-16 22:14:18 +01:00
Gabriele Bartolini
c687d0d670 Reviewed the code, fixed a small bug with option name detection 2010-12-16 22:13:30 +01:00
Gabriele Bartolini
9b7a078e0e Added license information in every source file 2010-12-16 21:50:15 +01:00
Greg Smith
56c65acd99 Add force option to help and docs on help 2010-12-06 00:33:02 -05:00
34 changed files with 5628 additions and 1650 deletions

9
.gitignore vendored
View File

@@ -0,0 +1,9 @@
*~
*.o
*.so
repmgr
repmgrd
README.htm*
README.pdf
sql/repmgr_funcs.so
sql/repmgr_funcs.sql

View File

@@ -1,4 +1,4 @@
Copyright (c) 2009-2010, 2ndQuadrant Limited
Copyright (c) 2010-2012, 2ndQuadrant Limited
All rights reserved.
This program is free software: you can redistribute it and/or modify

16
CREDITS Normal file
View File

@@ -0,0 +1,16 @@
Code and documentation contributors to repmgr include:
Jaime Casanova <jaime@2ndQuadrant.com>
Simon Riggs <simon@2ndQuadrant.com>
Greg Smith <greg@2ndQuadrant.com>
Robert J. Noles <rj@2ndQuadrant.com>
Gabriele Bartolini <gabriele@2ndQuadrant.com>
Bas van Oostveen <v.oostveen@gmail.com>
Hannu Krosing <hannu@2ndQuadrant.com>
Cédric Villemain <cedric@2ndquadrant.com>
Charles Duffy <charles@dyfis.net>
Daniel Farina <daniel@heroku.com>
Shawn Ellis <shawn.ellis17@gmail.com>
Jay Taylor <jay@jaytaylor.com>
Christian Kruse <christian@2ndQuadrant.com>
Krzysztof Gajdemski <songo@debian.org.pl>

64
HISTORY Normal file
View File

@@ -0,0 +1,64 @@
2.0beta2 2013-12-19
Improve autofailover logic and algorithms (Jaime, Andres)
Ignore pg_log when cloning (Jaime)
Add timestamps to log line in stderr (Christian)
Correctly check wal_keep_segments (Jay Taylor)
Add a ssh_options parameter (Jay Taylor)
2.0beta1 2012-07-27
Make CLONE command try to make an exact copy including $PGDATA location (Cedric)
Add detection of master failure (Jaime)
Add the notion of a witness server (Jaime)
Add autofailover capabilities (Jaime)
Add a configuration parameter to indicate the script to execute on failover or follow (Jaime)
Make the monitoring optional and turned off by default, it can be turned on with --monitoring-history switch (Jaime)
Add tunables to specify number of retries to reconnect to master and the time between them (Jaime)
1.2.0 2012-07-27
Test ssh connection before trying to rsync (Cédric)
Add CLUSTER SHOW command (Carlo)
Add CLUSTER CLEANUP command (Jaime)
Add function write_primary_conninfo (Marco)
Teach repmgr how to get tablespace's location in different pg version (Jaime)
Improve version message (Carlo)
1.1.1 2012-04-18
Add --ignore-rsync-warning (Cédric)
Add strnlen for compatibility with OS X (Greg)
Improve performance of the repl_status view (Jaime)
Remove last argument from log_err (Jaime, Reported by Jeroen Dekkers)
Complete documentation about possible error conditions (Jaime)
Document how to clean history (Jaime)
1.1.0 2011-03-09
Make options -U, -R and -p not mandatory (Jaime)
1.1.0b1 2011-02-24
Fix missing "--force" option in help (Greg Smith)
Correct warning message for wal_keep_segments (Bas van Oostveen)
Add Debian build/usage docs (Bas, Hannu Krosing, Cedric Villemain)
Add Debian .deb packaging (Hannu)
Move configuration data into a structure (Bas, Gabriele Bartolini)
Make rsync options configurable (Bas)
Add syslog as alternate logging destination (Gabriele)
Change from using malloc to static memory allocations (Gabriele)
Add debugging messages after every query (Gabriele)
Parameterize schema name used for repmgr (Gabriele)
Avoid buffer overruns by using snprintf etc. (Gabriele)
Fix use of database query after close (Gabriele)
Add information about progress during "standby clone" (Gabriele)
Fix double free errors in repmgrd (Charles Duffy, Greg)
Make repmgr exit with an error code when encountering an error (Charles)
Standardize on error return codes, use in repmgrd too (Greg)
Add [un]install actions/SQL like most contrib modules (Daniel Farina)
Wrap all string construction and produce error on overflow (Daniel)
Correct freeing of memory from first_wal_segment (Daniel)
Allow creating recovery.conf file with a password (Daniel)
Inform when STANDBY CLONE sees an unused config file (Daniel)
Use 64-bit computation for WAL apply_lag (Greg)
Add info messages for database and general work done (Greg)
Map old verbose flag into a useful setting for the new logger (Greg)
Document repmgrd startup restrictions and log info about them (Greg)
1.0.0 2010-12-05
First public release

View File

@@ -1,17 +1,21 @@
#
# Makefile
# Copyright (c) 2ndQuadrant, 2010
# Copyright (c) 2ndQuadrant, 2010-2012
repmgrd_OBJS = dbutils.o config.o repmgrd.o
repmgr_OBJS = dbutils.o check_dir.o config.o repmgr.o
repmgrd_OBJS = dbutils.o config.o repmgrd.o log.o strutil.o
repmgr_OBJS = dbutils.o check_dir.o config.o repmgr.o log.o strutil.o
DATA = repmgr.sql uninstall_repmgr.sql
PG_CPPFLAGS = -I$(libpq_srcdir)
PG_LIBS = $(libpq_pgport)
all: repmgrd repmgr
$(MAKE) -C sql
repmgrd: $(repmgrd_OBJS)
$(CC) $(CFLAGS) $(repmgrd_OBJS) $(PG_LIBS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o repmgrd
$(MAKE) -C sql
repmgr: $(repmgr_OBJS)
$(CC) $(CFLAGS) $(repmgr_OBJS) $(PG_LIBS) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o repmgr
@@ -26,11 +30,35 @@ include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif
# XXX: Try to use PROGRAM construct (see pgxs.mk) someday. Right now
# is overriding pgxs install.
install:
$(INSTALL_PROGRAM) repmgrd$(X) '$(DESTDIR)$(bindir)'
$(INSTALL_PROGRAM) repmgr$(X) '$(DESTDIR)$(bindir)'
$(MAKE) -C sql install
ifneq (,$(DATA)$(DATA_built))
@for file in $(addprefix $(srcdir)/, $(DATA)) $(DATA_built); do \
echo "$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/$(datamoduledir)'"; \
$(INSTALL_DATA) $$file '$(DESTDIR)$(datadir)/$(datamoduledir)'; \
done
endif
clean:
rm -f *.o
rm -f repmgrd
rm -f repmgr
$(MAKE) -C sql clean
deb: repmgrd repmgr
mkdir -p ./debian/usr/bin
cp repmgrd repmgr ./debian/usr/bin/
mkdir -p ./debian/usr/share/postgresql/9.0/contrib/
cp sql/repmgr_funcs.sql ./debian/usr/share/postgresql/9.0/contrib/
cp sql/uninstall_repmgr_funcs.sql ./debian/usr/share/postgresql/9.0/contrib/
mkdir -p ./debian/usr/lib/postgresql/9.0/lib/
cp sql/repmgr_funcs.so ./debian/usr/lib/postgresql/9.0/lib/
dpkg-deb --build debian
mv debian.deb ../postgresql-repmgr-9.0_1.0.0.deb
rm -rf ./debian/usr

File diff suppressed because it is too large Load Diff

21
TODO Normal file
View File

@@ -0,0 +1,21 @@
Known issues in repmgr
======================
* The check for whether ``wal_keep_segments`` is considered large enough
does a string comparison rather than an integer one. It can give both
false positive (setting is large enough but flagged as too small) and
false negative (setting is too small but not noted as such) errors.
* When running repmgr against a remote machine, operations that start
the database server using the ``pg_ctl`` command may accidentally
terminate after their associated ssh session ends.
* After running repmgrd as a regular foreground application, hitting
control-C causes the program to crash.
Planned feature improvements
============================
* Before running ``pg_start_backup()``, a sanity check that there is a
a working ssh connection to the destination would help find
configuration errors before disturbing the database.

View File

@@ -0,0 +1,213 @@
=====================================================
PostgreSQL Automatic Fail-Over - User Documentation
=====================================================
Automatic Failover
==================
repmgr allows setups for automatic failover when it detects the failure of the master node.
Following is a quick setup for this.
Installation
============
For convenience, we define:
* node1 is the hostname fully qualified of the Master server, IP 192.168.1.10
* node2 is the hostname fully qualified of the Standby server, IP 192.168.1.11
* witness is the hostname fully qualified of the server used for witness, IP 192.168.1.12
:Note: It is not recommanded to use name defining status of a server like «masterserver»,
this is a name leading to confusion once a failover take place and the Master is
now on the «standbyserver».
Summary
-------
2 PostgreSQL servers are involved in the replication. Automatic fail-over need
to vote to decide what server it should promote, thus an odd number is required
and a witness-repmgrd is installed in a third server where it uses a PostgreSQL
cluster to communicate with other repmgrd daemons.
1. Install PostgreSQL in all the servers involved (including the server used for
witness)
2. Install repmgr in all the servers involved (including the server used for witness)
3. Configure the Master PostreSQL
4. Clone the Master to the Standby using "repmgr standby clone" command
5. Configure repmgr in all the servers involved (including the server used for witness)
6. Register Master and Standby nodes
7. Initiate witness server
8. Start the repmgrd daemons in all nodes
:Note: A complete Hight-Availability design need at least 3 servers to still have
a backup node after a first failure.
Install PostgreSQL
------------------
You can install PostgreSQL using any of the recommended methods. You should ensure
it's 9.0 or superior.
Install repmgr
--------------
Install repmgr following the steps in the README.
Configure PostreSQL
-------------------
Log in node1.
Edit the file postgresql.conf and modify the parameters::
listen_addresses='*'
wal_level = 'hot_standby'
archive_mode = on
archive_command = 'cd .' # we can also use exit 0, anything that
# just does nothing
max_wal_senders = 10
wal_keep_segments = 5000 # 80 GB required on pg_xlog
hot_standby = on
shared_preload_libraries = 'repmgr_funcs'
Edit the file pg_hba.conf and add lines for the replication::
host repmgr repmgr 127.0.0.1/32 trust
host repmgr repmgr 192.168.1.10/30 trust
host replication all 192.168.1.10/30 trust
:Note: It is also possible to use a password authentication (md5), .pgpass file
should be edited to allow connection between each node.
Create the user and database to manage replication::
su - postgres
createuser -s repmgr
createdb -O repmgr repmgr
psql -f /usr/share/postgresql/9.0/contrib/repmgr_funcs.sql repmgr
Restart the PostgreSQL server::
pg_ctl -D $PGDATA restart
And check everything is fine in the server log.
Create the ssh-key for the postgres user and copy it to other servers::
su - postgres
ssh-keygen # /!\ do not use a passphrase /!\
cat ~/.ssh/id_rsa.pub > ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
exit
rsync -avz ~postgres/.ssh/authorized_keys node2:~postgres/.ssh/
rsync -avz ~postgres/.ssh/authorized_keys witness:~postgres/.ssh/
rsync -avz ~postgres/.ssh/id_rsa* node2:~postgres/.ssh/
rsync -avz ~postgres/.ssh/id_rsa* witness:~postgres/.ssh/
Clone Master
------------
Log in node2.
Clone the node1 (the current Master)::
su - postgres
repmgr -d repmgr -U repmgr -h node1 standby clone
Start the PostgreSQL server::
pg_ctl -D $PGDATA start
And check everything is fine in the server log.
Configure repmgr
----------------
Log in each server and configure repmgr by editing the file
/etc/repmgr/repmgr.conf::
cluster=my_cluster
node=1
node_name=earth
conninfo='host=192.168.1.10 dbname=repmgr user=repmgr'
master_response_timeout=60
reconnect_attempts=6
reconnect_interval=10
failover=automatic
promote_command='promote_command.sh'
follow_command='repmgr standby follow -f /etc/repmgr/repmgr.conf'
* *cluster* is the name of the current replication.
* *node* is the number of the current node (1, 2 or 3 in the current example).
* *node_name* is an identifier for every node.
* *conninfo* is used to connect to the local PostgreSQL server (where the configuration file is) from any node. In the witness server configuration it is needed to add a 'port=5499' to the conninfo.
* *master_response_timeout* is the maximum amount of time we are going to wait before deciding the master has died and start failover procedure.
* *reconnect_attempts* is the number of times we will try to reconnect to master after a failure has been detected and before start failover procedure.
* *reconnect_interval* is the amount of time between retries to reconnect to master after a failure has been detected and before start failover procedure.
* *failover* configure behavior : *manual* or *automatic*.
* *promote_command* the command executed to do the failover (including the PostgreSQL failover itself). The command must return 0 on success.
* *follow_command* the command executed to address the current standby to another Master. The command must return 0 on success.
Register Master and Standby
---------------------------
Log in node1.
Register the node as Master::
su - postgres
repmgr -f /etc/repmgr/repmgr.conf master register
Log in node2.
Register the node as Standby::
su - postgres
repmgr -f /etc/repmgr/repmgr.conf standby register
Initialize witness server
-------------------------
Log in witness.
Initialize the witness server::
su - postgres
repmgr -d repmgr -U repmgr -h 192.168.1.10 -D $WITNESS_PGDATA -f /etc/repmgr/repmgr.conf witness create
It needs information to connect to the master to copy the configuration of the cluster, also it needs to know where it should initialize it's own $PGDATA.
As part of the procees it also ask for the superuser password so it can connect when needed.
Start the repmgrd daemons
-------------------------
Log in node2 and witness.
su - postgres
repmgrd -f /etc/repmgr/repmgr.conf > /var/log/postgresql/repmgr.log 2>&1
:Note: The Master does not need a repmgrd daemon.
Suspend Automatic behavior
==========================
Edit the repmgr.conf of the node to remove from automatic processing and change::
failover=manual
Then, signal repmgrd daemon::
su - postgres
kill -HUP `pidoff repmgrd`
TODO : -HUP configuration update is not implemented and it should check its
configuration file against its configuration in DB, updating
accordingly the SQL conf (especialy the failover manual or auto)
this allow witness-standby and standby-not-promotable features
and simpler usage of the tool ;)
Usage
=====
The repmgr documentation is in the README file (how to build, options, etc.)

View File

@@ -1,8 +1,20 @@
/*
* check_dir.c
* Copyright (c) 2ndQuadrant, 2010
* check_dir.c - Directories management functions
* Copyright (C) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Directories management functions
*/
#include <sys/stat.h>
@@ -12,11 +24,12 @@
#include <stdio.h>
#include <string.h>
/* NB: postgres_fe must be included BEFORE check_dir */
#include "postgres_fe.h"
#include "check_dir.h"
static int mkdir_p(char *path, mode_t omode);
#include "strutil.h"
#include "log.h"
/*
* make sure the directory either doesn't exist or is empty
@@ -31,63 +44,63 @@ static int mkdir_p(char *path, mode_t omode);
int
check_dir(char *dir)
{
DIR *chkdir;
struct dirent *file;
int result = 1;
DIR *chkdir;
struct dirent *file;
int result = 1;
errno = 0;
errno = 0;
chkdir = opendir(dir);
chkdir = opendir(dir);
if (!chkdir)
return (errno == ENOENT) ? 0 : -1;
if (!chkdir)
return (errno == ENOENT) ? 0 : -1;
while ((file = readdir(chkdir)) != NULL)
{
if (strcmp(".", file->d_name) == 0 ||
strcmp("..", file->d_name) == 0)
{
/* skip this and parent directory */
continue;
}
else
{
result = 2; /* not empty */
break;
}
}
while ((file = readdir(chkdir)) != NULL)
{
if (strcmp(".", file->d_name) == 0 ||
strcmp("..", file->d_name) == 0)
{
/* skip this and parent directory */
continue;
}
else
{
result = 2; /* not empty */
break;
}
}
#ifdef WIN32
/*
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
* released version
*/
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
/*
* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
* released version
*/
if (GetLastError() == ERROR_NO_MORE_FILES)
errno = 0;
#endif
closedir(chkdir);
closedir(chkdir);
if (errno != 0)
return -1; /* some kind of I/O error? */
if (errno != 0)
return -1; /* some kind of I/O error? */
return result;
}
/*
* Create directory
* Create directory
*/
bool
create_directory(char *dir)
{
if (mkdir_p(dir, 0700) == 0)
return true;
if (mkdir_p(dir, 0700) == 0)
return true;
fprintf(stderr, _("Could not create directory \"%s\": %s\n"),
dir, strerror(errno));
log_err(_("Could not create directory \"%s\": %s\n"),
dir, strerror(errno));
return false;
return false;
}
bool
@@ -99,7 +112,7 @@ set_directory_permissions(char *dir)
/* function from initdb.c */
/* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
/* source adapted from FreeBSD /src/bin/mkdir/mkdir.c */
/*
* this tries to build all the elements of a path to a directory a la mkdir -p
@@ -109,15 +122,15 @@ set_directory_permissions(char *dir)
* note that on failure, the path arg has been modified to show the particular
* directory level we had problems with.
*/
static int
int
mkdir_p(char *path, mode_t omode)
{
struct stat sb;
mode_t numask,
oumask;
oumask;
int first,
last,
retval;
last,
retval;
char *p;
p = path;
@@ -136,8 +149,8 @@ mkdir_p(char *path, mode_t omode)
return 1;
}
else if (p[1] == ':' &&
((p[0] >= 'a' && p[0] <= 'z') ||
(p[0] >= 'A' && p[0] <= 'Z')))
((p[0] >= 'a' && p[0] <= 'z') ||
(p[0] >= 'A' && p[0] <= 'Z')))
{
/* local drive */
p += 2;
@@ -207,10 +220,88 @@ mkdir_p(char *path, mode_t omode)
bool
is_pg_dir(char *dir)
{
char path[8192];
struct stat sb;
const size_t buf_sz = 8192;
char path[buf_sz];
struct stat sb;
int r;
sprintf(path, "%s/PG_VERSION", dir);
// test pgdata
xsnprintf(path, buf_sz, "%s/PG_VERSION", dir);
if (stat(path, &sb) == 0)
return true;
return (stat(path, &sb) == 0) ? true : false;
// test tablespace dir
sprintf(path, "ls %s/PG_*/ -I*", dir);
r = system(path);
if (r == 0)
return true;
return false;
}
bool
create_pgdir(char *dir, bool force)
{
bool pg_dir = false;
/* Check this directory could be used as a PGDATA dir */
switch (check_dir(dir))
{
case 0:
/* dir not there, must create it */
log_info(_("creating directory \"%s\"...\n"), dir);
if (!create_directory(dir))
{
log_err(_("couldn't create directory \"%s\"...\n"),
dir);
exit(ERR_BAD_CONFIG);
}
break;
case 1:
/* Present but empty, fix permissions and use it */
log_info(_("checking and correcting permissions on existing directory %s ...\n"),
dir);
if (!set_directory_permissions(dir))
{
log_err(_("could not change permissions of directory \"%s\": %s\n"),
dir, strerror(errno));
exit(ERR_BAD_CONFIG);
}
break;
case 2:
/* Present and not empty */
log_warning(_("directory \"%s\" exists but is not empty\n"),
dir);
pg_dir = is_pg_dir(dir);
/*
* we use force to reduce the time needed to restore a node which
* turn async after a failover or anything else
*/
if (pg_dir && force)
{
/* Let it continue */
break;
}
else if (pg_dir && !force)
{
log_warning(_("\nThis looks like a PostgreSQL directory.\n"
"If you are sure you want to clone here, "
"please check there is no PostgreSQL server "
"running and use the --force option\n"));
exit(ERR_BAD_CONFIG);
}
return false;
default:
/* Trouble accessing directory */
log_err(_("could not access directory \"%s\": %s\n"),
dir, strerror(errno));
exit(ERR_BAD_CONFIG);
}
return true;
}

View File

@@ -1,10 +1,30 @@
/*
* check_dir.h
* Copyright (c) 2ndQuadrant, 2010
* Copyright (c) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _REPMGR_CHECK_DIR_H_
#define _REPMGR_CHECK_DIR_H_
int mkdir_p(char *path, mode_t omode);
int check_dir(char *dir);
bool create_directory(char *dir);
bool set_directory_permissions(char *dir);
bool is_pg_dir(char *dir);
bool create_pgdir(char *dir, bool force);
#endif

295
config.c
View File

@@ -1,80 +1,189 @@
/*
* config.c
* Copyright (c) 2ndQuadrant, 2010
* config.c - Functions to parse the config file
* Copyright (C) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Functions to parse the config file
*/
#include "config.h"
#include "log.h"
#include "strutil.h"
#include "repmgr.h"
void
parse_config(const char *config_file, char *cluster_name, int *node, char *conninfo)
parse_config(const char *config_file, t_configuration_options *options)
{
char *s, buff[256];
char *s, buff[MAXLINELENGTH];
char name[MAXLEN];
char value[MAXLEN];
FILE *fp = fopen (config_file, "r");
/* Initialize */
memset(options->cluster_name, 0, sizeof(options->cluster_name));
options->node = -1;
memset(options->conninfo, 0, sizeof(options->conninfo));
options->failover = MANUAL_FAILOVER;
options->priority = 0;
memset(options->node_name, 0, sizeof(options->node_name));
memset(options->promote_command, 0, sizeof(options->promote_command));
memset(options->follow_command, 0, sizeof(options->follow_command));
memset(options->rsync_options, 0, sizeof(options->rsync_options));
memset(options->ssh_options, 0, sizeof(options->ssh_options));
/* if nothing has been provided defaults to 60 */
options->master_response_timeout = 60;
/* it defaults to 6 retries with a time between retries of 10s */
options->reconnect_attempts = 6;
options->reconnect_intvl = 10;
/*
* Since some commands don't require a config file at all, not
* having one isn't necessarily a problem.
*/
if (fp == NULL)
return;
{
log_err(_("Did not find the configuration file '%s', continuing\n"), config_file);
return;
}
/* Read next line */
while ((s = fgets (buff, sizeof buff, fp)) != NULL)
{
char name[MAXLEN];
char value[MAXLEN];
/* Skip blank lines and comments */
if (buff[0] == '\n' || buff[0] == '#')
continue;
/* Skip blank lines and comments */
if (buff[0] == '\n' || buff[0] == '#')
continue;
/* Parse name/value pair from line */
/* Parse name/value pair from line */
parse_line(buff, name, value);
/* Copy into correct entry in parameters struct */
if (strcmp(name, "cluster") == 0)
strncpy (cluster_name, value, MAXLEN);
else if (strcmp(name, "node") == 0)
*node = atoi(value);
else if (strcmp(name, "conninfo") == 0)
strncpy (conninfo, value, MAXLEN);
else
printf ("WARNING: %s/%s: Unknown name/value pair!\n", name, value);
}
/* Copy into correct entry in parameters struct */
if (strcmp(name, "cluster") == 0)
strncpy (options->cluster_name, value, MAXLEN);
else if (strcmp(name, "node") == 0)
options->node = atoi(value);
else if (strcmp(name, "conninfo") == 0)
strncpy (options->conninfo, value, MAXLEN);
else if (strcmp(name, "rsync_options") == 0)
strncpy (options->rsync_options, value, QUERY_STR_LEN);
else if (strcmp(name, "ssh_options") == 0)
strncpy (options->ssh_options, value, QUERY_STR_LEN);
else if (strcmp(name, "loglevel") == 0)
strncpy (options->loglevel, value, MAXLEN);
else if (strcmp(name, "logfacility") == 0)
strncpy (options->logfacility, value, MAXLEN);
else if (strcmp(name, "failover") == 0)
{
char failoverstr[MAXLEN];
strncpy(failoverstr, value, MAXLEN);
/* Close file */
fclose (fp);
if (strcmp(failoverstr, "manual") == 0)
options->failover = MANUAL_FAILOVER;
else if (strcmp(failoverstr, "automatic") == 0)
options->failover = AUTOMATIC_FAILOVER;
else
{
log_warning(_("value for failover option is incorrect, it should be automatic or manual. Defaulting to manual.\n"));
options->failover = MANUAL_FAILOVER;
}
}
else if (strcmp(name, "priority") == 0)
options->priority = atoi(value);
else if (strcmp(name, "node_name") == 0)
strncpy(options->node_name, value, MAXLEN);
else if (strcmp(name, "promote_command") == 0)
strncpy(options->promote_command, value, MAXLEN);
else if (strcmp(name, "follow_command") == 0)
strncpy(options->follow_command, value, MAXLEN);
else if (strcmp(name, "master_response_timeout") == 0)
options->master_response_timeout = atoi(value);
else if (strcmp(name, "reconnect_attempts") == 0)
options->reconnect_attempts = atoi(value);
else if (strcmp(name, "reconnect_interval") == 0)
options->reconnect_intvl = atoi(value);
else
log_warning(_("%s/%s: Unknown name/value pair!\n"), name, value);
}
/* Close file */
fclose (fp);
/* Check config settings */
if (strnlen(options->cluster_name, MAXLEN)==0)
{
log_err(_("Cluster name is missing. Check the configuration file.\n"));
exit(ERR_BAD_CONFIG);
}
if (options->node == -1)
{
log_err(_("Node information is missing. Check the configuration file.\n"));
exit(ERR_BAD_CONFIG);
}
if (options->master_response_timeout <= 0)
{
log_err(_("Master response timeout must be greater than zero. Check the configuration file.\n"));
exit(ERR_BAD_CONFIG);
}
if (options->reconnect_attempts < 0)
{
log_err(_("Reconnect attempts must be zero or greater. Check the configuration file.\n"));
exit(ERR_BAD_CONFIG);
}
if (options->reconnect_intvl <= 0)
{
log_err(_("Reconnect intervals must be zero or greater. Check the configuration file.\n"));
exit(ERR_BAD_CONFIG);
}
}
char *
trim (char *s)
{
/* Initialize start, end pointers */
char *s1 = s, *s2 = &s[strlen (s) - 1];
/* Initialize start, end pointers */
char *s1 = s, *s2 = &s[strlen (s) - 1];
/* Trim and delimit right side */
while ( (isspace (*s2)) && (s2 >= s1) )
s2--;
*(s2+1) = '\0';
/* Trim and delimit right side */
while ( (isspace (*s2)) && (s2 >= s1) )
--s2;
*(s2+1) = '\0';
/* Trim left side */
while ( (isspace (*s1)) && (s1 < s2) )
s1++;
/* Trim left side */
while ( (isspace (*s1)) && (s1 < s2) )
++s1;
/* Copy finished string */
strcpy (s, s1);
return s;
/* Copy finished string */
strcpy (s, s1);
return s;
}
void
parse_line(char *buff, char *name, char *value)
{
int i;
int j;
int i = 0;
int j = 0;
/*
* first we find the name of the parameter
*/
j = 0;
for (i = 0; i < MAXLEN; i++)
for ( ; i < MAXLEN; ++i)
{
if (buff[i] != '=')
name[j++] = buff[i];
@@ -83,12 +192,11 @@ parse_line(char *buff, char *name, char *value)
}
name[j] = '\0';
i++;
/*
* Now the value
*/
*/
j = 0;
for ( ; i < MAXLEN; i++)
for ( ++i ; i < MAXLEN; ++i)
if (buff[i] == '\'')
continue;
else if (buff[i] != '\n')
@@ -96,5 +204,102 @@ parse_line(char *buff, char *name, char *value)
else
break;
value[j] = '\0';
trim(value);
trim(value);
}
bool
reload_configuration(char *config_file, t_configuration_options *orig_options)
{
PGconn *conn;
t_configuration_options new_options;
/*
* Re-read the configuration file: repmgr.conf
*/
log_info(_("Reloading configuration file and updating repmgr tables\n"));
parse_config(config_file, &new_options);
if (new_options.node == -1)
{
log_warning(_("\nCannot load new configuration, will keep current one.\n"));
return false;
}
if (strcmp(new_options.cluster_name, orig_options->cluster_name) != 0)
{
log_warning(_("\nCannot change cluster name, will keep current configuration.\n"));
return false;
}
if (new_options.node != orig_options->node)
{
log_warning(_("\nCannot change node number, will keep current configuration.\n"));
return false;
}
if (new_options.node_name != orig_options->node_name)
{
log_warning(_("\nCannot change standby name, will keep current configuration.\n"));
return false;
}
if (new_options.failover != MANUAL_FAILOVER && new_options.failover != AUTOMATIC_FAILOVER)
{
log_warning(_("\nNew value for failover is not valid. Should be MANUAL or AUTOMATIC.\n"));
return false;
}
if (new_options.master_response_timeout <= 0)
{
log_warning(_("\nNew value for master_response_timeout is not valid. Should be greater than zero.\n"));
return false;
}
if (new_options.reconnect_attempts < 0)
{
log_warning(_("\nNew value for reconnect_attempts is not valid. Should be greater or equal than zero.\n"));
return false;
}
if (new_options.reconnect_intvl < 0)
{
log_warning(_("\nNew value for reconnect_interval is not valid. Should be greater or equal than zero.\n"));
return false;
}
/* Test conninfo string */
conn = establishDBConnection(new_options.conninfo, false);
if (!conn || (PQstatus(conn) != CONNECTION_OK))
{
log_warning(_("\nconninfo string is not valid, will keep current configuration.\n"));
return false;
}
PQfinish(conn);
/* Configuration seems ok, will load new values */
strcpy(orig_options->cluster_name, new_options.cluster_name);
orig_options->node = new_options.node;
strcpy(orig_options->conninfo, new_options.conninfo);
orig_options->failover = new_options.failover;
orig_options->priority = new_options.priority;
strcpy(orig_options->node_name, new_options.node_name);
strcpy(orig_options->promote_command, new_options.promote_command);
strcpy(orig_options->follow_command, new_options.follow_command);
strcpy(orig_options->rsync_options, new_options.rsync_options);
strcpy(orig_options->ssh_options, new_options.ssh_options);
orig_options->master_response_timeout = new_options.master_response_timeout;
orig_options->reconnect_attempts = new_options.reconnect_attempts;
orig_options->reconnect_intvl = new_options.reconnect_intvl;
/*
* XXX These ones can change with a simple SIGHUP?
strcpy (orig_options->loglevel, new_options.loglevel);
strcpy (orig_options->logfacility, new_options.logfacility);
logger_shutdown();
XXX do we have progname here ?
logger_init(progname, orig_options.loglevel, orig_options.logfacility);
*/
return true;
}

View File

@@ -1,9 +1,50 @@
/*
* config.h
* Copyright (c) 2ndQuadrant, 2010
* Copyright (c) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
void parse_config(const char *config_file, char *cluster_name, int *node, char *service);
#ifndef _REPMGR_CONFIG_H_
#define _REPMGR_CONFIG_H_
#include "repmgr.h"
#include "strutil.h"
typedef struct
{
char cluster_name[MAXLEN];
int node;
char conninfo[MAXLEN];
int failover;
int priority;
char node_name[MAXLEN];
char promote_command[MAXLEN];
char follow_command[MAXLEN];
char loglevel[MAXLEN];
char logfacility[MAXLEN];
char rsync_options[QUERY_STR_LEN];
char ssh_options[QUERY_STR_LEN];
int master_response_timeout;
int reconnect_attempts;
int reconnect_intvl;
} t_configuration_options;
void parse_config(const char *config_file, t_configuration_options *options);
void parse_line(char *buff, char *name, char *value);
char *trim(char *s);
bool reload_configuration(char *config_file, t_configuration_options *orig_options);
#endif

488
dbutils.c
View File

@@ -1,122 +1,283 @@
/*
* dbutils.c
* Copyright (c) 2ndQuadrant, 2010
* dbutils.c - Database connection/management functions
* Copyright (C) 2ndQuadrant, 2010-2012
*
* Database connection/management functions
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <unistd.h>
#include "repmgr.h"
#include "strutil.h"
#include "log.h"
PGconn *
establishDBConnection(const char *conninfo, const bool exit_on_error)
{
PGconn *conn;
/* Make a connection to the database */
conn = PQconnectdb(conninfo);
/* Check to see that the backend connection was successfully made */
if ((PQstatus(conn) != CONNECTION_OK))
{
fprintf(stderr, "Connection to database failed: %s",
PQerrorMessage(conn));
/* Make a connection to the database */
PGconn *conn = NULL;
char connection_string[MAXLEN];
strcpy(connection_string, conninfo);
strcat(connection_string, " fallback_application_name='repmgr'");
conn = PQconnectdb(connection_string);
/* Check to see that the backend connection was successfully made */
if ((PQstatus(conn) != CONNECTION_OK))
{
log_err(_("Connection to database failed: %s\n"),
PQerrorMessage(conn));
if (exit_on_error)
{
PQfinish(conn);
exit(1);
PQfinish(conn);
exit(ERR_DB_CON);
}
}
}
return conn;
}
PGconn *
establishDBConnectionByParams(const char *keywords[], const char *values[],const bool exit_on_error)
{
/* Make a connection to the database */
PGconn *conn = PQconnectdbParams(keywords, values, true);
/* Check to see that the backend connection was successfully made */
if ((PQstatus(conn) != CONNECTION_OK))
{
log_err(_("Connection to database failed: %s\n"),
PQerrorMessage(conn));
if (exit_on_error)
{
PQfinish(conn);
exit(ERR_DB_CON);
}
}
return conn;
}
bool
is_standby(PGconn *conn)
{
PGresult *res;
bool result;
PGresult *res;
bool result = false;
res = PQexec(conn, "SELECT pg_is_in_recovery()");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "Can't query server mode: %s", PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}
res = PQexec(conn, "SELECT pg_is_in_recovery()");
if (strcmp(PQgetvalue(res, 0, 0), "f") == 0)
result = false;
else
result = true;
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_err(_("Can't query server mode: %s"),
PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(ERR_DB_QUERY);
}
if (PQntuples(res) == 1 && strcmp(PQgetvalue(res, 0, 0), "t") == 0)
result = true;
PQclear(res);
return result;
}
/*
bool
is_witness(PGconn *conn, char *schema, char *cluster, int node_id)
{
PGresult *res;
bool result = false;
char sqlquery[QUERY_STR_LEN];
sqlquery_snprintf(sqlquery, "SELECT witness from %s.repl_nodes where cluster = '%s' and id = %d",
schema, cluster, node_id);
res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_err(_("Can't query server mode: %s"), PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(ERR_DB_QUERY);
}
if (PQntuples(res) == 1 && strcmp(PQgetvalue(res, 0, 0), "t") == 0)
result = true;
PQclear(res);
return result;
}
/* check the PQStatus and try to 'select 1' to confirm good connection */
bool
is_pgup(PGconn *conn, int timeout)
{
char sqlquery[QUERY_STR_LEN];
/* Check the connection status twice in case it changes after reset */
bool twice = false;
/* Check the connection status twice in case it changes after reset */
for (;;)
{
if (PQstatus(conn) != CONNECTION_OK)
{
if (twice)
return false;
PQreset(conn); // reconnect
twice = true;
}
else
{
/*
* Send a SELECT 1 just to check if the connection is OK
*/
if (!CancelQuery(conn, timeout))
goto failed;
if (wait_connection_availability(conn, timeout) != 1)
goto failed;
sqlquery_snprintf(sqlquery, "SELECT 1");
if (PQsendQuery(conn, sqlquery) == 0)
{
log_warning(_("PQsendQuery: Query could not be sent to primary. %s\n"),
PQerrorMessage(conn));
goto failed;
}
if (wait_connection_availability(conn, timeout) != 1)
goto failed;
break;
failed:
// we need to retry, because we might just have loose the connection once
if (twice)
return false;
PQreset(conn); // reconnect
twice = true;
}
}
return true;
}
/*
* If postgreSQL version is 9 or superior returns the major version
* if 8 or inferior returns an empty string
*/
char *
pg_version(PGconn *conn)
pg_version(PGconn *conn, char* major_version)
{
PGresult *res;
char *major_version;
int major_version1;
char *major_version2;
int major_version1;
char *major_version2;
res = PQexec(conn, "WITH pg_version(ver) AS (SELECT split_part(version(), ' ', 2)) "
"SELECT split_part(ver, '.', 1), split_part(ver, '.', 2) FROM pg_version");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "PQexec failed: %s", PQerrorMessage(conn));
PQclear(res);
res = PQexec(conn,
"WITH pg_version(ver) AS "
"(SELECT split_part(version(), ' ', 2)) "
"SELECT split_part(ver, '.', 1), split_part(ver, '.', 2) "
"FROM pg_version");
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_err(_("Version check PQexec failed: %s"),
PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}
major_version1 = atoi(PQgetvalue(res, 0, 0));
major_version2 = PQgetvalue(res, 0, 1);
PQclear(res);
exit(ERR_DB_QUERY);
}
major_version1 = atoi(PQgetvalue(res, 0, 0));
major_version2 = PQgetvalue(res, 0, 1);
major_version = malloc(10);
if (major_version1 >= 9)
{
/* form a major version string */
sprintf(major_version, "%d.%s", major_version1, major_version2);
xsnprintf(major_version, MAXVERSIONSTR, "%d.%s", major_version1,
major_version2);
}
else
strcpy(major_version, "");
PQclear(res);
return major_version;
}
bool
guc_setted(PGconn *conn, const char *parameter, const char *op, const char *value)
guc_setted(PGconn *conn, const char *parameter, const char *op,
const char *value)
{
PGresult *res;
char sqlquery[8192];
char sqlquery[QUERY_STR_LEN];
sprintf(sqlquery, "SELECT true FROM pg_settings "
" WHERE name = '%s' AND setting %s '%s'",
parameter, op, value);
sqlquery_snprintf(sqlquery, "SELECT true FROM pg_settings "
" WHERE name = '%s' AND setting %s '%s'",
parameter, op, value);
res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "PQexec failed: %s", PQerrorMessage(conn));
PQclear(res);
res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_err(_("GUC setting check PQexec failed: %s"),
PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}
exit(ERR_DB_QUERY);
}
if (PQntuples(res) == 0)
{
PQclear(res);
return false;
return false;
}
PQclear(res);
return true;
}
/**
* Just like guc_setted except with an extra parameter containing the name of
* the pg datatype so that the comparison can be done properly.
*/
bool
guc_setted_typed(PGconn *conn, const char *parameter, const char *op,
const char *value, const char *datatype)
{
PGresult *res;
char sqlquery[QUERY_STR_LEN];
sqlquery_snprintf(sqlquery, "SELECT true FROM pg_settings "
" WHERE name = '%s' AND setting::%s %s '%s'::%s",
parameter, datatype, op, value, datatype);
res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_err(_("GUC setting check PQexec failed: %s"),
PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(ERR_DB_QUERY);
}
if (PQntuples(res) == 0)
{
PQclear(res);
return false;
}
PQclear(res);
@@ -128,75 +289,115 @@ const char *
get_cluster_size(PGconn *conn)
{
PGresult *res;
const char *size;
char sqlquery[8192];
const char *size;
char sqlquery[QUERY_STR_LEN];
sprintf(sqlquery, "SELECT pg_size_pretty(SUM(pg_database_size(oid))::bigint) "
" FROM pg_database ");
sqlquery_snprintf(
sqlquery,
"SELECT pg_size_pretty(SUM(pg_database_size(oid))::bigint) "
" FROM pg_database ");
res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
fprintf(stderr, "PQexec failed: %s", PQerrorMessage(conn));
PQclear(res);
res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
{
log_err(_("Get cluster size PQexec failed: %s"),
PQerrorMessage(conn));
PQclear(res);
PQfinish(conn);
exit(1);
}
size = PQgetvalue(res, 0, 0);
exit(ERR_DB_QUERY);
}
size = PQgetvalue(res, 0, 0);
PQclear(res);
return size;
}
/*
* get a connection to master by reading repl_nodes, creating a connection
* get a connection to master by reading repl_nodes, creating a connection
* to each node (one at a time) and finding if it is a master or a standby
*
* NB: If master_conninfo_out may be NULL. If it is non-null, it is assumed to
* point to allocated memory of MAXCONNINFO in length, and the master server
* connection string is placed there.
*/
PGconn *
getMasterConnection(PGconn *standby_conn, int id, char *cluster, int *master_id)
getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
int *master_id, char *master_conninfo_out)
{
PGconn *master_conn = NULL;
PGresult *res1;
PGresult *res2;
char sqlquery[8192];
char master_conninfo[8192];
PGconn *master_conn = NULL;
PGresult *res1;
PGresult *res2;
char sqlquery[QUERY_STR_LEN];
char master_conninfo_stack[MAXCONNINFO];
char *master_conninfo = &*master_conninfo_stack;
char schema_quoted[MAXLEN];
int i;
/* find all nodes belonging to this cluster */
sprintf(sqlquery, "SELECT * FROM repmgr_%s.repl_nodes "
" WHERE cluster = '%s' and id <> %d",
cluster, cluster, id);
/*
* If the caller wanted to get a copy of the connection info string, sub
* out the local stack pointer for the pointer passed by the caller.
*/
if (master_conninfo_out != NULL)
master_conninfo = master_conninfo_out;
res1 = PQexec(standby_conn, sqlquery);
if (PQresultStatus(res1) != PGRES_TUPLES_OK)
{
fprintf(stderr, "Can't get nodes info: %s\n", PQerrorMessage(standby_conn));
PQclear(res1);
/*
* XXX: This is copied in at least two other procedures
*
* Assemble the unquoted schema name
*/
{
char *identifier = PQescapeIdentifier(standby_conn, schema,
strlen(schema));
maxlen_snprintf(schema_quoted, "%s", identifier);
PQfreemem(identifier);
}
/* find all nodes belonging to this cluster */
log_info(_("finding node list for cluster '%s'\n"),
cluster);
sqlquery_snprintf(sqlquery, "SELECT id, conninfo FROM %s.repl_nodes "
" WHERE cluster = '%s' and not witness",
schema_quoted, cluster);
res1 = PQexec(standby_conn, sqlquery);
if (PQresultStatus(res1) != PGRES_TUPLES_OK)
{
log_err(_("Can't get nodes info: %s\n"),
PQerrorMessage(standby_conn));
PQclear(res1);
PQfinish(standby_conn);
exit(1);
}
exit(ERR_DB_QUERY);
}
for (i = 0; i < PQntuples(res1); i++)
{
{
/* initialize with the values of the current node being processed */
*master_id = atoi(PQgetvalue(res1, i, 0));
strcpy(master_conninfo, PQgetvalue(res1, i, 2));
strncpy(master_conninfo, PQgetvalue(res1, i, 1), MAXCONNINFO);
log_info(_("checking role of cluster node '%s'\n"),
master_conninfo);
master_conn = establishDBConnection(master_conninfo, false);
if (PQstatus(master_conn) != CONNECTION_OK)
continue;
/*
* I can't use the is_standby() function here because on error that
* function closes the connection i pass and exit, but i still need to close
* standby_conn
/*
* Can't use the is_standby() function here because on error that
* function closes the connection passed and exits. This still
* needs to close master_conn first.
*/
res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()");
if (PQresultStatus(res2) != PGRES_TUPLES_OK)
{
fprintf(stderr, "Can't get recovery state from this node: %s\n", PQerrorMessage(master_conn));
PQclear(res2);
res2 = PQexec(master_conn, "SELECT pg_is_in_recovery()");
if (PQresultStatus(res2) != PGRES_TUPLES_OK)
{
log_err(_("Can't get recovery state from this node: %s\n"),
PQerrorMessage(master_conn));
PQclear(res2);
PQfinish(master_conn);
continue;
}
}
/* if false, this is the master */
if (strcmp(PQgetvalue(res2, 0, 0), "f") == 0)
@@ -212,17 +413,86 @@ getMasterConnection(PGconn *standby_conn, int id, char *cluster, int *master_id)
PQfinish(master_conn);
*master_id = -1;
}
}
}
/* If we finish this loop without finding a master then
* we doesn't have the info or the master has failed (or we
* reached max_connections or superuser_reserved_connections,
* anything else i'm missing?),
* Probably we will need to check the error to know if we need
* to start failover procedure or just fix some situation on the
* standby.
*/
* we doesn't have the info or the master has failed (or we
* reached max_connections or superuser_reserved_connections,
* anything else I'm missing?).
*
* Probably we will need to check the error to know if we need
* to start failover procedure or just fix some situation on the
* standby.
*/
PQclear(res1);
return NULL;
}
/*
* wait until current query finishes ignoring any results, this could be an async command
* or a cancelation of a query
* return 1 if Ok; 0 if any error ocurred; -1 if timeout reached
*/
int
wait_connection_availability(PGconn *conn, int timeout)
{
PGresult *res;
while(timeout-- >= 0)
{
if (PQconsumeInput(conn) == 0)
{
log_warning(_("wait_connection_availability: could not receive data from master. %s\n"),
PQerrorMessage(conn));
return 0;
}
if (PQisBusy(conn) == 0)
{
res = PQgetResult(conn);
if (res == NULL)
break;
PQclear(res);
}
sleep(1);
}
if (timeout >= 0)
return 1;
else {
log_warning(_("wait_connection_availability: timeout reached"));
return -1;
}
}
bool
CancelQuery(PGconn *conn, int timeout)
{
char errbuf[ERRBUFF_SIZE];
PGcancel *pgcancel;
if (wait_connection_availability(conn, timeout) != 1)
return false;
pgcancel = PQgetCancel(conn);
if (pgcancel == NULL)
return false;
/*
* PQcancel can only return 0 if socket()/connect()/send()
* fails, in any of those cases we can assume something
* bad happened to the connection
*/
if (PQcancel(pgcancel, errbuf, ERRBUFF_SIZE) == 0)
{
log_warning(_("Can't stop current query: %s\n"), errbuf);
PQfreeCancel(pgcancel);
return false;
}
PQfreeCancel(pgcancel);
return true;
}

View File

@@ -1,12 +1,43 @@
/*
* dbutils.h
* Copyright (c) 2ndQuadrant, 2010
* Copyright (c) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _REPMGR_DBUTILS_H_
#define _REPMGR_DBUTILS_H_
#include "strutil.h"
PGconn *establishDBConnection(const char *conninfo, const bool exit_on_error);
PGconn *establishDBConnectionByParams(const char *keywords[],
const char *values[],
const bool exit_on_error);
bool is_standby(PGconn *conn);
char *pg_version(PGconn *conn);
bool guc_setted(PGconn *conn, const char *parameter, const char *op, const char *value);
const char *get_cluster_size(PGconn *conn);
PGconn * getMasterConnection(PGconn *standby_conn, int id, char *cluster, int *master_id);
bool is_witness(PGconn *conn, char *schema, char *cluster, int node_id);
bool is_pgup(PGconn *conn, int timeout);
char *pg_version(PGconn *conn, char* major_version);
bool guc_setted(PGconn *conn, const char *parameter, const char *op,
const char *value);
bool guc_setted_typed(PGconn *conn, const char *parameter, const char *op,
const char *value, const char *datatype);
const char *get_cluster_size(PGconn *conn);
PGconn *getMasterConnection(PGconn *standby_conn, char *schema, char *cluster,
int *master_id, char *master_conninfo_out);
int wait_connection_availability(PGconn *conn, int timeout);
bool CancelQuery(PGconn *conn, int timeout);
#endif

9
debian/DEBIAN/control vendored Normal file
View File

@@ -0,0 +1,9 @@
Package: repmgr-auto
Version: 2.0beta2
Section: database
Priority: optional
Architecture: all
Depends: rsync, postgresql-9.0 | postgresql-9.1 | postgresql-9.2 | postgresql-9.3
Maintainer: Jaime Casanova <jaime@2ndQuadrant.com>
Description: PostgreSQL replication setup, magament and monitoring
has two main executables

14
debian/repmgr.repmgrd.default vendored Normal file
View File

@@ -0,0 +1,14 @@
#!/bin/sh
# default settings for repmgrd. This file is source by /bin/sh from
# /etc/init.d/repmgrd
# Options for repmgrd
REPMGRD_OPTS=""
# repmgrd binary
REPMGR_BIN="/usr/bin/repmgr"
# pid file
REPMGR_PIDFILE="/var/run/repmgrd.pid"

48
debian/repmgr.repmgrd.init vendored Normal file
View File

@@ -0,0 +1,48 @@
#!/bin/sh
### 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
# Should-Start: $syslog $postgresql
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop repmgrd
### END INIT INFO
set -e
if test -f /etc/default/repmgrd; then
. /etc/default/repmgrd
fi
if [ -z "$REPMGRD_BIN" ]; then
REPMGRD_BIN="/usr/bin/repmgrd"
fi
if [ -z "$REPMGRD_PIDFILE" ]; then
REPMGRD_PIDFILE="/var/run/repmgrd.pid"
fi
test -x $REPMGRD_BIN || exit 0
case "$1" in
start)
start-stop-daemon --start --quiet --make-pidfile --pidfile $REPMGRD_PIDFILE --exec $REPMGRD_BIN $REPMGRD_OPTS
;;
stop)
start-stop-daemon --stop --oknodo --quiet --pidfile $REPMGRD_PIDFILE
;;
restart)
$0 stop && $0 start || exit 1
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
;;
esac
exit 0

39
errcode.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* errcode.h
* Copyright (C) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _ERRCODE_H_
#define _ERRCODE_H_
/* Exit return code */
#define SUCCESS 0
#define ERR_BAD_CONFIG 1
#define ERR_BAD_RSYNC 2
#define ERR_STOP_BACKUP 3
#define ERR_NO_RESTART 4
#define ERR_NEEDS_XLOG 5
#define ERR_DB_CON 6
#define ERR_DB_QUERY 7
#define ERR_PROMOTED 8
#define ERR_BAD_PASSWORD 9
#define ERR_STR_OVERFLOW 10
#define ERR_FAILOVER_FAIL 11
#define ERR_BAD_SSH 12
#endif /* _ERRCODE_H_ */

238
log.c Normal file
View File

@@ -0,0 +1,238 @@
/*
* log.c - Logging methods
* Copyright (C) 2ndQuadrant, 2010-2012
*
* This module is a set of methods for logging (currently only syslog)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "repmgr.h"
#include <stdlib.h>
#ifdef HAVE_SYSLOG
#include <syslog.h>
#endif
#include <stdarg.h>
#include <time.h>
#include "log.h"
#define DEFAULT_IDENT "repmgr"
#ifdef HAVE_SYSLOG
#define DEFAULT_SYSLOG_FACILITY LOG_LOCAL0
#endif
/* #define REPMGR_DEBUG */
void 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;
struct tm *tm;
char buff[100];
va_list ap;
if(log_level >= level) {
time(&t);
tm = localtime(&t);
va_start(ap, fmt);
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);
}
}
static int detect_log_level(const char* level);
static int detect_log_facility(const char* facility);
int log_type = REPMGR_STDERR;
int log_level = LOG_NOTICE;
bool logger_init(const char* ident, const char* level, const char* facility)
{
int l;
int f;
#ifdef HAVE_SYSLOG
int syslog_facility = DEFAULT_SYSLOG_FACILITY;
#endif
#ifdef REPMGR_DEBUG
printf("Logger initialisation (Level: %s, Facility: %s)\n", level, facility);
#endif
if (!ident)
{
ident = DEFAULT_IDENT;
}
if (level && *level)
{
l = detect_log_level(level);
#ifdef REPMGR_DEBUG
printf("Assigned level for logger: %d\n", l);
#endif
if (l > 0)
log_level = l;
else
stderr_log_warning(_("Cannot detect log level %s (use any of DEBUG, INFO, NOTICE, WARNING, ERR, ALERT, CRIT or EMERG)\n"), level);
}
if (facility && *facility)
{
f = detect_log_facility(facility);
#ifdef REPMGR_DEBUG
printf("Assigned facility for logger: %d\n", f);
#endif
if (f == 0)
{
/* No syslog requested, just stderr */
#ifdef REPMGR_DEBUG
printf(_("Use stderr for logging\n"));
#endif
}
else if (f == -1)
{
stderr_log_warning(_("Cannot detect log facility %s (use any of LOCAL0, LOCAL1, ..., LOCAL7, USER or STDERR)\n"), facility);
}
#ifdef HAVE_SYSLOG
else
{
syslog_facility = f;
log_type = REPMGR_SYSLOG;
}
#endif
}
#ifdef HAVE_SYSLOG
if (log_type == REPMGR_SYSLOG)
{
setlogmask (LOG_UPTO (log_level));
openlog (ident, LOG_CONS | LOG_PID | LOG_NDELAY, syslog_facility);
stderr_log_notice(_("Setup syslog (level: %s, facility: %s)\n"), level, facility);
}
#endif
return true;
}
bool logger_shutdown(void)
{
#ifdef HAVE_SYSLOG
if (log_type == REPMGR_SYSLOG)
closelog();
#endif
return true;
}
/*
* Set a minimum logging level. Intended for command line verbosity
* options, which might increase requested logging over what's specified
* in the regular configuration file.
*/
void logger_min_verbose(int minimum)
{
if (log_level < minimum)
log_level = minimum;
}
int detect_log_level(const char* level)
{
if (!strcmp(level, "DEBUG"))
return LOG_DEBUG;
if (!strcmp(level, "INFO"))
return LOG_INFO;
if (!strcmp(level, "NOTICE"))
return LOG_NOTICE;
if (!strcmp(level, "WARNING"))
return LOG_WARNING;
if (!strcmp(level, "ERR"))
return LOG_ERR;
if (!strcmp(level, "ALERT"))
return LOG_ALERT;
if (!strcmp(level, "CRIT"))
return LOG_CRIT;
if (!strcmp(level, "EMERG"))
return LOG_EMERG;
return 0;
}
int detect_log_facility(const char* facility)
{
int local = 0;
if (!strncmp(facility, "LOCAL", 5) && strlen(facility) == 6)
{
local = atoi (&facility[5]);
switch (local)
{
case 0:
return LOG_LOCAL0;
break;
case 1:
return LOG_LOCAL1;
break;
case 2:
return LOG_LOCAL2;
break;
case 3:
return LOG_LOCAL3;
break;
case 4:
return LOG_LOCAL4;
break;
case 5:
return LOG_LOCAL5;
break;
case 6:
return LOG_LOCAL6;
break;
case 7:
return LOG_LOCAL7;
break;
}
}
else if (!strcmp(facility, "USER"))
{
return LOG_USER;
}
else if (!strcmp(facility, "STDERR"))
{
return 0;
}
return -1;
}

123
log.h Normal file
View File

@@ -0,0 +1,123 @@
/*
* log.h
* Copyright (c) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _REPMGR_LOG_H_
#define _REPMGR_LOG_H_
#include "repmgr.h"
#define REPMGR_SYSLOG 1
#define REPMGR_STDERR 2
void stderr_log_with_level(const char *level_name, int level, const char *fmt, ...);
/* Standard error logging */
#define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__)
#define stderr_log_info(...) stderr_log_with_level("INFO", LOG_INFO, __VA_ARGS__)
#define stderr_log_notice(...) stderr_log_with_level("NOTICE", LOG_NOTICE, __VA_ARGS__)
#define stderr_log_warning(...) stderr_log_with_level("WARNING", LOG_WARNING, __VA_ARGS__)
#define stderr_log_err(...) stderr_log_with_level("ERROR", LOG_ERR, __VA_ARGS__)
#define stderr_log_crit(...) stderr_log_with_level("CRITICAL", LOG_CRIT, __VA_ARGS__)
#define stderr_log_alert(...) stderr_log_with_level("ALERT", LOG_ALERT, __VA_ARGS__)
#define stderr_log_emerg(...) stderr_log_with_level("EMERGENCY", LOG_EMERG, __VA_ARGS__)
#ifdef HAVE_SYSLOG
#include <syslog.h>
#define log_debug(...) \
if (log_type == REPMGR_SYSLOG) \
syslog(LOG_DEBUG, __VA_ARGS__); \
else \
stderr_log_debug(__VA_ARGS__);
#define log_info(...) \
{ \
if (log_type == REPMGR_SYSLOG) syslog(LOG_INFO, __VA_ARGS__); \
else stderr_log_info(__VA_ARGS__); \
}
#define log_notice(...) \
{ \
if (log_type == REPMGR_SYSLOG) syslog(LOG_NOTICE, __VA_ARGS__); \
else stderr_log_notice(__VA_ARGS__); \
}
#define log_warning(...) \
{ \
if (log_type == REPMGR_SYSLOG) syslog(LOG_WARNING, __VA_ARGS__); \
else stderr_log_warning(__VA_ARGS__); \
}
#define log_err(...) \
{ \
if (log_type == REPMGR_SYSLOG) syslog(LOG_ERR, __VA_ARGS__); \
else stderr_log_err(__VA_ARGS__); \
}
#define log_crit(...) \
{ \
if (log_type == REPMGR_SYSLOG) syslog(LOG_CRIT, __VA_ARGS__); \
else stderr_log_crit(__VA_ARGS__); \
}
#define log_alert(...) \
{ \
if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \
else stderr_log_alert(__VA_ARGS__); \
}
#define log_emerg(...) \
{ \
if (log_type == REPMGR_SYSLOG) syslog(LOG_ALERT, __VA_ARGS__); \
else stderr_log_alert(__VA_ARGS__); \
}
#else
#define LOG_EMERG 0 /* system is unusable */
#define LOG_ALERT 1 /* action must be taken immediately */
#define LOG_CRIT 2 /* critical conditions */
#define LOG_ERR 3 /* error conditions */
#define LOG_WARNING 4 /* warning conditions */
#define LOG_NOTICE 5 /* normal but significant condition */
#define LOG_INFO 6 /* informational */
#define LOG_DEBUG 7 /* debug-level messages */
#define log_debug(...) stderr_log_debug(__VA_ARGS__)
#define log_info(...) stderr_log_info(__VA_ARGS__)
#define log_notice(...) stderr_log_notice(__VA_ARGS__)
#define log_warning(...) stderr_log_warning(__VA_ARGS__)
#define log_err(...) stderr_log_err(__VA_ARGS__)
#define log_crit(...) stderr_log_crit(__VA_ARGS__)
#define log_alert(...) stderr_log_alert(__VA_ARGS__)
#define log_emerg(...) stderr_log_emerg(__VA_ARGS__)
#endif
/* Logger initialisation and shutdown */
bool logger_shutdown(void);
bool logger_init(const char* ident, const char* level, const char* facility);
void logger_min_verbose(int minimum);
extern int log_type;
extern int log_level;
#endif

2625
repmgr.c

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
cluster=test
node=2
conninfo='host=192.168.204.104'

36
repmgr.conf.sample Normal file
View File

@@ -0,0 +1,36 @@
###################################################
# Replication Manager configuration file
###################################################
# Cluster name
cluster=test
# Node ID
node=2
node_name=standby2
# Connection information
conninfo='host=192.168.204.104'
rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\""
ssh_options=-o "StrictHostKeyChecking no"
# How many seconds we wait for master response before declaring master failure
master_response_timeout=60
# How many time we try to reconnect to master before starting failover procedure
reconnect_attempts=6
reconnect_interval=10
# Autofailover options
failover=automatic
priority=-1
promote_command='repmgr standby promote -f /path/to/repmgr.conf'
follow_command='repmgr standby follow -f /path/to/repmgr.conf -W'
# Log level: possible values are DEBUG, INFO, NOTICE, WARNING, ERR, ALERT, CRIT or EMERG
# Default: NOTICE
loglevel=NOTICE
# Logging facility: possible values are STDERR or - for Syslog integration - one of LOCAL0, LOCAL1, ..., LOCAL7, USER
# Default: STDERR
logfacility=STDERR

View File

@@ -1,6 +1,19 @@
/*
* dbutils.h
* Copyright (c) 2ndQuadrant, 2010
* repmgr.h
* Copyright (c) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
@@ -11,14 +24,51 @@
#include "getopt_long.h"
#include "libpq-fe.h"
#include "strutil.h"
#include "dbutils.h"
#include "config.h"
#include "errcode.h"
#define PRIMARY_MODE 0
#define STANDBY_MODE 1
#define WITNESS_MODE 2
#define MAXLEN 80
#define CONFIG_FILE "repmgr.conf"
#include "config.h"
#define MAXFILENAME 1024
#define ERRBUFF_SIZE 512
#define DEFAULT_CONFIG_FILE "./repmgr.conf"
#define DEFAULT_WAL_KEEP_SEGMENTS "5000"
#define DEFAULT_DEST_DIR "."
#define DEFAULT_MASTER_PORT "5432"
#define DEFAULT_DBNAME "postgres"
#define DEFAULT_REPMGR_SCHEMA_PREFIX "repmgr_"
#define MANUAL_FAILOVER 0
#define AUTOMATIC_FAILOVER 1
/* Run time options type */
typedef struct
{
char dbname[MAXLEN];
char host[MAXLEN];
char username[MAXLEN];
char dest_dir[MAXFILENAME];
char config_file[MAXFILENAME];
char remote_user[MAXLEN];
char wal_keep_segments[MAXLEN];
bool verbose;
bool force;
bool wait_for_master;
bool ignore_rsync_warn;
char masterport[MAXLEN];
char localport[MAXLEN];
/* parameter used by CLUSTER CLEANUP */
int keep_history;
} t_runtime_options;
#define SLEEP_MONITOR 2
#endif

View File

@@ -1,3 +1,10 @@
/*
* repmgr.sql
*
* Copyright (C) 2ndQuadrant, 2010-2012
*
*/
CREATE USER repmgr;
CREATE SCHEMA repmgr;
@@ -5,51 +12,50 @@ CREATE SCHEMA repmgr;
* The table repl_nodes keeps information about all machines in
* a cluster
*/
drop table if exists repl_nodes cascade;
CREATE TABLE repl_nodes (
id integer primary key,
cluster text not null, -- Name to identify the cluster
conninfo text not null
id integer primary key,
cluster text not null, -- Name to identify the cluster
name text not null,
conninfo text not null,
priority integer not null,
witness boolean not null default false
);
ALTER TABLE repl_nodes OWNER TO repmgr;
/*
* Keeps monitor info about every node and their relative "position"
* Keeps monitor info about every node and their relative "position"
* to primary
*/
drop table if exists repl_monitor cascade;
CREATE TABLE repl_monitor (
primary_node INTEGER NOT NULL,
standby_node INTEGER NOT NULL,
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
last_wal_primary_location TEXT NOT NULL,
last_wal_standby_location TEXT NOT NULL,
replication_lag BIGINT NOT NULL,
apply_lag BIGINT NOT NULL
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
last_wal_primary_location TEXT NOT NULL,
last_wal_standby_location TEXT, -- In case of a witness server this will be NULL
replication_lag BIGINT NOT NULL,
apply_lag BIGINT NOT NULL
);
ALTER TABLE repl_monitor OWNER TO repmgr;
/*
* This view shows the latest monitor info about every node.
* Interesting thing to see:
* replication_lag: in bytes (this is how far the latest xlog record
* replication_lag: in bytes (this is how far the latest xlog record
* we have received is from master)
* apply_lag: in bytes (this is how far the latest xlog record
* we have applied is from the latest record we
* we have applied is from the latest record we
* have received)
* time_lag: how many seconds are we from being up-to-date with master
*/
drop view if exists repl_status;
CREATE VIEW repl_status AS
WITH monitor_info AS (SELECT *, ROW_NUMBER() OVER (PARTITION BY primary_node, standby_node
ORDER BY last_monitor_time desc)
FROM repl_monitor)
SELECT primary_node, standby_node, last_monitor_time, last_wal_primary_location,
last_wal_standby_location, pg_size_pretty(replication_lag) replication_lag,
pg_size_pretty(apply_lag) apply_lag,
SELECT primary_node, standby_node, name AS standby_name, last_monitor_time, last_wal_primary_location,
last_wal_standby_location, pg_size_pretty(replication_lag) replication_lag,
pg_size_pretty(apply_lag) apply_lag,
age(now(), last_monitor_time) AS time_lag
FROM monitor_info a
WHERE row_number = 1;
FROM repl_monitor JOIN repl_nodes ON standby_node = id
WHERE (standby_node, last_monitor_time) IN (SELECT standby_node, MAX(last_monitor_time)
FROM repl_monitor GROUP BY 1);
ALTER VIEW repl_status OWNER TO repmgr;
CREATE INDEX idx_repl_status_sort ON repl_monitor(last_monitor_time, standby_node);

1213
repmgrd.c

File diff suppressed because it is too large Load Diff

19
sql/Makefile Normal file
View File

@@ -0,0 +1,19 @@
#
# Makefile
# Copyright (c) 2ndQuadrant, 2010
#
MODULE_big = repmgr_funcs
DATA_built=repmgr_funcs.sql
DATA=uninstall_repmgr_funcs.sql
OBJS=repmgr_funcs.o
ifdef USE_PGXS
PGXS := $(shell pg_config --pgxs)
include $(PGXS)
else
subdir = contrib/repmgr/sql
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
include $(top_srcdir)/contrib/contrib-global.mk
endif

189
sql/repmgr_funcs.c Normal file
View File

@@ -0,0 +1,189 @@
/*
* repmgr_funcs.c
* Copyright (c) 2ndQuadrant, 2010
*
* Shared memory state management and some backend functions in SQL
*/
#include "postgres.h"
#include "fmgr.h"
#include "access/xlog.h"
#include "miscadmin.h"
#include "storage/ipc.h"
#include "storage/lwlock.h"
#include "storage/procarray.h"
#include "storage/shmem.h"
#include "storage/spin.h"
#include "utils/builtins.h"
/* same definition as the one in xlog_internal.h */
#define MAXFNAMELEN 64
PG_MODULE_MAGIC;
/*
* Global shared state
*/
typedef struct repmgrSharedState
{
LWLockId lock; /* protects search/modification */
char location[MAXFNAMELEN]; /* last known xlog location */
} repmgrSharedState;
/* Links to shared memory state */
static repmgrSharedState *shared_state = NULL;
static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
void _PG_init(void);
void _PG_fini(void);
static void repmgr_shmem_startup(void);
static Size repmgr_memsize(void);
static bool repmgr_set_standby_location(char *locationstr);
Datum repmgr_update_standby_location(PG_FUNCTION_ARGS);
Datum repmgr_get_last_standby_location(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(repmgr_update_standby_location);
PG_FUNCTION_INFO_V1(repmgr_get_last_standby_location);
/*
* Module load callback
*/
void
_PG_init(void)
{
/*
* 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
* 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 active. The functions must protect themselves against
* being called then, however.)
*/
if (!process_shared_preload_libraries_in_progress)
return;
/*
* Request additional shared resources. (These are no-ops if we're not in
* the postmaster process.) We'll allocate or attach to the shared
* resources in repmgr_shmem_startup().
*/
RequestAddinShmemSpace(repmgr_memsize());
RequestAddinLWLocks(1);
/*
* Install hooks.
*/
prev_shmem_startup_hook = shmem_startup_hook;
shmem_startup_hook = repmgr_shmem_startup;
}
/*
* Module unload callback
*/
void
_PG_fini(void)
{
/* Uninstall hooks. */
shmem_startup_hook = prev_shmem_startup_hook;
}
/*
* shmem_startup hook: allocate or attach to shared memory,
*/
static void
repmgr_shmem_startup(void)
{
bool found;
if (prev_shmem_startup_hook)
prev_shmem_startup_hook();
/* reset in case this is a restart within the postmaster */
shared_state = NULL;
/*
* Create or attach to the shared memory state, including hash table
*/
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
shared_state = ShmemInitStruct("repmgr shared state",
sizeof(repmgrSharedState),
&found);
if (!found)
{
/* First time through ... */
shared_state->lock = LWLockAssign();
snprintf(shared_state->location,
sizeof(shared_state->location), "%X/%X", 0, 0);
}
LWLockRelease(AddinShmemInitLock);
}
/*
* Estimate shared memory space needed.
*/
static Size
repmgr_memsize(void)
{
return MAXALIGN(sizeof(repmgrSharedState));
}
static bool
repmgr_set_standby_location(char *locationstr)
{
/* Safety check... */
if (!shared_state)
return false;
LWLockAcquire(shared_state->lock, LW_EXCLUSIVE);
strncpy(shared_state->location, locationstr, MAXFNAMELEN);
LWLockRelease(shared_state->lock);
return true;
}
/* SQL Functions */
/* Read last xlog location reported by this standby from shared memory */
Datum
repmgr_get_last_standby_location(PG_FUNCTION_ARGS)
{
char location[MAXFNAMELEN];
/* Safety check... */
if (!shared_state)
PG_RETURN_NULL();
LWLockAcquire(shared_state->lock, LW_SHARED);
strncpy(location, shared_state->location, MAXFNAMELEN);
LWLockRelease(shared_state->lock);
PG_RETURN_TEXT_P(cstring_to_text(location));
}
/* Set update last xlog location reported by this standby to shared memory */
Datum
repmgr_update_standby_location(PG_FUNCTION_ARGS)
{
text *location = PG_GETARG_TEXT_P(0);
char *locationstr;
/* Safety check... */
if (!shared_state)
PG_RETURN_BOOL(false);
locationstr = text_to_cstring(location);
PG_RETURN_BOOL(repmgr_set_standby_location(locationstr));
}

15
sql/repmgr_funcs.sql.in Normal file
View File

@@ -0,0 +1,15 @@
/*
* repmgr_function.sql
* Copyright (c) 2ndQuadrant, 2010
*
*/
-- SET SEARCH_PATH TO 'repmgr';
CREATE FUNCTION repmgr_update_standby_location(text) RETURNS boolean
AS 'MODULE_PATHNAME', 'repmgr_update_standby_location'
LANGUAGE C STRICT;
CREATE FUNCTION repmgr_get_last_standby_location() RETURNS text
AS 'MODULE_PATHNAME', 'repmgr_get_last_standby_location'
LANGUAGE C STRICT;

View File

@@ -0,0 +1,2 @@
DROP FUNCTION repmgr_update_standby_location(text);
DROP FUNCTION repmgr_get_last_standby_location();

96
strutil.c Normal file
View File

@@ -0,0 +1,96 @@
/*
* strutil.c
*
* Copyright (C) 2ndQuadrant, 2010-2012
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "log.h"
#include "strutil.h"
static int xvsnprintf(char *str, size_t size, const char *format, va_list ap);
/* 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
xvsnprintf(char *str, size_t size, const char *format, va_list ap)
{
int retval;
retval = vsnprintf(str, size, format, ap);
if (retval >= size)
{
log_err(_("Buffer of size not large enough to format entire string '%s'\n"),
str);
exit(ERR_STR_OVERFLOW);
}
return retval;
}
int
xsnprintf(char *str, size_t size, const char *format, ...)
{
va_list arglist;
int retval;
va_start(arglist, format);
retval = xvsnprintf(str, size, format, arglist);
va_end(arglist);
return retval;
}
int
sqlquery_snprintf(char *str, const char *format, ...)
{
va_list arglist;
int retval;
va_start(arglist, format);
retval = xvsnprintf(str, QUERY_STR_LEN, format, arglist);
va_end(arglist);
return retval;
}
int maxlen_snprintf(char *str, const char *format, ...)
{
va_list arglist;
int retval;
va_start(arglist, format);
retval = xvsnprintf(str, MAXLEN, format, arglist);
va_end(arglist);
return retval;
}

43
strutil.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* strutil.h
* Copyright (C) 2ndQuadrant, 2010-2012
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _STRUTIL_H_
#define _STRUTIL_H_
#include <stdlib.h>
#include <errcode.h>
#define QUERY_STR_LEN 8192
#define MAXLEN 1024
#define MAXLINELENGTH 4096
#define MAXVERSIONSTR 16
#define MAXCONNINFO 1024
extern int xsnprintf(char *str, size_t size, const char *format, ...);
extern int sqlquery_snprintf(char *str, const char *format, ...);
extern int maxlen_snprintf(char *str, const char *format, ...);
/* Add strnlen on platforms that don't have it, like OS X */
#ifndef strnlen
extern size_t strnlen(const char *s, size_t n);
#endif
#endif /* _STRUTIL_H_ */

13
uninstall_repmgr.sql Normal file
View File

@@ -0,0 +1,13 @@
/*
* uninstall_repmgr.sql
*
* Copyright (C) 2ndQuadrant, 2010-2012
*
*/
DROP TABLE IF EXISTS repl_nodes;
DROP TABLE IF EXISTS repl_monitor;
DROP VIEW IF EXISTS repl_status;
DROP SCHEMA repmgr;
DROP USER repmgr;

4
version.h Normal file
View File

@@ -0,0 +1,4 @@
#ifndef _VERSION_H_
#define _VERSION_H_
#define REPMGR_VERSION "2.0beta1"
#endif