|
16 | 16 | */
|
17 | 17 | #include"postgres.h"
|
18 | 18 |
|
| 19 | +#include<unistd.h> |
| 20 | + |
19 | 21 | #include"access/htup_details.h"
|
20 | 22 | #include"access/xlog.h"
|
21 | 23 | #include"access/xlog_internal.h"
|
22 | 24 | #include"access/xlogutils.h"
|
23 | 25 | #include"catalog/pg_type.h"
|
24 | 26 | #include"funcapi.h"
|
25 | 27 | #include"miscadmin.h"
|
| 28 | +#include"pgstat.h" |
26 | 29 | #include"replication/walreceiver.h"
|
27 | 30 | #include"storage/smgr.h"
|
28 | 31 | #include"utils/builtins.h"
|
@@ -697,3 +700,77 @@ pg_backup_start_time(PG_FUNCTION_ARGS)
|
697 | 700 |
|
698 | 701 | PG_RETURN_DATUM(xtime);
|
699 | 702 | }
|
| 703 | + |
| 704 | +/* |
| 705 | + * Promotes a standby server. |
| 706 | + * |
| 707 | + * A result of "true" means that promotion has been completed if "wait" is |
| 708 | + * "true", or initiated if "wait" is false. |
| 709 | + */ |
| 710 | +Datum |
| 711 | +pg_promote(PG_FUNCTION_ARGS) |
| 712 | +{ |
| 713 | +boolwait=PG_GETARG_BOOL(0); |
| 714 | +intwait_seconds=PG_GETARG_INT32(1); |
| 715 | +FILE*promote_file; |
| 716 | +inti; |
| 717 | + |
| 718 | +if (!RecoveryInProgress()) |
| 719 | +ereport(ERROR, |
| 720 | +(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
| 721 | +errmsg("recovery is not in progress"), |
| 722 | +errhint("Recovery control functions can only be executed during recovery."))); |
| 723 | + |
| 724 | +if (wait_seconds <=0) |
| 725 | +ereport(ERROR, |
| 726 | +(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), |
| 727 | +errmsg("\"wait_seconds\" cannot be negative or equal zero"))); |
| 728 | + |
| 729 | +/* create the promote signal file */ |
| 730 | +promote_file=AllocateFile(PROMOTE_SIGNAL_FILE,"w"); |
| 731 | +if (!promote_file) |
| 732 | +ereport(ERROR, |
| 733 | +(errcode_for_file_access(), |
| 734 | +errmsg("could not create file \"%s\": %m", |
| 735 | +PROMOTE_SIGNAL_FILE))); |
| 736 | + |
| 737 | +if (FreeFile(promote_file)) |
| 738 | +ereport(ERROR, |
| 739 | +(errcode_for_file_access(), |
| 740 | +errmsg("could not write file \"%s\": %m", |
| 741 | +PROMOTE_SIGNAL_FILE))); |
| 742 | + |
| 743 | +/* signal the postmaster */ |
| 744 | +if (kill(PostmasterPid,SIGUSR1)!=0) |
| 745 | +{ |
| 746 | +ereport(WARNING, |
| 747 | +(errmsg("failed to send signal to postmaster: %m"))); |
| 748 | +(void)unlink(PROMOTE_SIGNAL_FILE); |
| 749 | +PG_RETURN_BOOL(false); |
| 750 | +} |
| 751 | + |
| 752 | +/* return immediately if waiting was not requested */ |
| 753 | +if (!wait) |
| 754 | +PG_RETURN_BOOL(true); |
| 755 | + |
| 756 | +/* wait for the amount of time wanted until promotion */ |
| 757 | +#defineWAITS_PER_SECOND 10 |
| 758 | +for (i=0;i<WAITS_PER_SECOND*wait_seconds;i++) |
| 759 | +{ |
| 760 | +ResetLatch(MyLatch); |
| 761 | + |
| 762 | +if (!RecoveryInProgress()) |
| 763 | +PG_RETURN_BOOL(true); |
| 764 | + |
| 765 | +CHECK_FOR_INTERRUPTS(); |
| 766 | + |
| 767 | +WaitLatch(MyLatch, |
| 768 | +WL_LATCH_SET |WL_TIMEOUT |WL_POSTMASTER_DEATH, |
| 769 | +1000L /WAITS_PER_SECOND, |
| 770 | +WAIT_EVENT_PROMOTE); |
| 771 | +} |
| 772 | + |
| 773 | +ereport(WARNING, |
| 774 | +(errmsg("server did not promote within %d seconds",wait_seconds))); |
| 775 | +PG_RETURN_BOOL(false); |
| 776 | +} |