*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 13602,13607 **** postgres=# SELECT * FROM pg_xlogfile_name_offset(pg_stop_backup());
--- 13602,13622 ----
          the function returns NULL.
         </entry>
        </row>
+       <row>
+        <entry>
+         <literal><function>pg_trigger_failover()</function></literal>
+         </entry>
+        <entry><type>bool</type></entry>
+        <entry>Request the standby to end recovery and become the master.
+         Even if <xref linkend="trigger-file"> is not specified, this triggers
+         failover. But it's important to specify <varname>trigger_file</>
+         to enable failover even when the server is not in Hot Standby mode and
+         the function is not allowed to run. Superuser permission is required
+         to trigger failover. This function returns <literal>false</> if the
+         server is not running recovery, <literal>true</> otherwise. Note that
+         this cannot bring up the standby which uses <application>pg_standby</>.
+        </entry>
+       </row>
       </tbody>
      </tgroup>
     </table>
*** a/doc/src/sgml/high-availability.sgml
--- b/doc/src/sgml/high-availability.sgml
***************
*** 610,621 **** protocol to make nodes agree on a serializable transactional order.
      later disconnected, the standby goes back to step 1 and tries to
      restore the file from the archive again. This loop of retries from the
      archive, <filename>pg_xlog</>, and via streaming replication goes on until the server
!     is stopped or failover is triggered by a trigger file.
     </para>
  
     <para>
      Standby mode is exited and the server switches to normal operation,
!     when a trigger file is found (<varname>trigger_file</>). Before failover,
      any WAL immediately available in the archive or in <filename>pg_xlog</> will be
      restored, but no attempt is made to connect to the master.
     </para>
--- 610,623 ----
      later disconnected, the standby goes back to step 1 and tries to
      restore the file from the archive again. This loop of retries from the
      archive, <filename>pg_xlog</>, and via streaming replication goes on until the server
!     is stopped or failover is triggered by a trigger file or
!     <function>pg_trigger_failover</>.
     </para>
  
     <para>
      Standby mode is exited and the server switches to normal operation,
!     when a trigger file is found (<varname>trigger_file</>) or
!     <function>pg_trigger_failover</> is called. Before failover,
      any WAL immediately available in the archive or in <filename>pg_xlog</> will be
      restored, but no attempt is made to connect to the master.
     </para>
***************
*** 694,699 **** protocol to make nodes agree on a serializable transactional order.
--- 696,706 ----
      If you're setting up the standby server for reporting
      purposes, with no plans to fail over to it, <varname>trigger_file</>
      is not required.
+     Even if <varname>trigger_file</> is not specified, you can trigger
+     failover by using <function>pg_trigger_failover</>. But it's important
+     to specify <varname>trigger_file</> to enable failover even when
+     the server is not in Hot Standby mode and the function is not allowed
+     to run.
     </para>
  
     <para>
***************
*** 927,934 **** primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
     <para>
      To trigger failover of a log-shipping standby server, create a trigger
      file with the filename and path specified by the <varname>trigger_file</>
!     setting in <filename>recovery.conf</>. If <varname>trigger_file</> is
!     not given, there is no way to exit recovery in the standby and promote
      it to a master. That can be useful for e.g reporting servers that are
      only used to offload read-only queries from the primary, not for high
      availability purposes.
--- 934,942 ----
     <para>
      To trigger failover of a log-shipping standby server, create a trigger
      file with the filename and path specified by the <varname>trigger_file</>
!     setting in <filename>recovery.conf</> or call <function>pg_trigger_failover</>.
!     If <varname>trigger_file</> is not given and <varname>hot_standby</> is not
!     enabled, there is no way to exit recovery in the standby and promote
      it to a master. That can be useful for e.g reporting servers that are
      only used to offload read-only queries from the primary, not for high
      availability purposes.
*** a/doc/src/sgml/recovery-config.sgml
--- b/doc/src/sgml/recovery-config.sgml
***************
*** 288,295 **** restore_command = 'copy "C:\\server\\archivedir\\%f" "%p"'  # Windows
          <listitem>
           <para>
            Specifies a trigger file whose presence ends recovery in the
!           standby. If no trigger file is specified, the standby never exits
!           recovery.
            This setting has no effect if <varname>standby_mode</> is <literal>off</>.
           </para>
          </listitem>
--- 288,296 ----
          <listitem>
           <para>
            Specifies a trigger file whose presence ends recovery in the
!           standby. Even if no trigger file is specified, you can request the standby
!           to exit recovery by using <function>pg_trigger_failover</> if hot standby
!           is enabled.
            This setting has no effect if <varname>standby_mode</> is <literal>off</>.
           </para>
          </listitem>
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 416,421 **** typedef struct XLogCtlData
--- 416,427 ----
  	/* timestamp of last COMMIT/ABORT record replayed (or being replayed) */
  	TimestampTz recoveryLastXTime;
  
+ 	/*
+ 	 * failoverRequested indicates if failover has been requested via
+ 	 * pg_trigger_failover.	Protected by info_lck.
+ 	 */
+ 	bool		failoverRequested;
+ 
  	slock_t		info_lck;		/* locks shared variables shown above */
  } XLogCtlData;
  
***************
*** 8869,8874 **** pg_last_xlog_replay_location(PG_FUNCTION_ARGS)
--- 8875,8914 ----
  }
  
  /*
+  * Promote the standby to the master by requesting startup process to
+  * end recovery.
+  *
+  * Even if trigger_file parameter is not specified in recovery.conf,
+  * this function triggers failover.
+  *
+  * Returns FALSE if there is no startup process that we request to
+  * end recovery, TRUE otherwise.
+  *
+  * XXX: Should this return FALSE if standby mode is not enabled too?
+  */
+ Datum
+ pg_trigger_failover(PG_FUNCTION_ARGS)
+ {
+ 	/* use volatile pointer to prevent code rearrangement */
+ 	volatile XLogCtlData *xlogctl = XLogCtl;
+ 
+ 	if (!superuser())
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 			 (errmsg("must be superuser to trigger failover"))));
+ 
+ 	if (!RecoveryInProgress())
+ 		PG_RETURN_BOOL(false);
+ 
+ 	SpinLockAcquire(&xlogctl->info_lck);
+ 	xlogctl->failoverRequested = true;
+ 	SpinLockRelease(&xlogctl->info_lck);
+ 
+ 	WakeupRecovery();
+ 	PG_RETURN_BOOL(true);
+ }
+ 
+ /*
   * Compute an xlog file name and decimal byte offset given a WAL location,
   * such as is returned by pg_stop_backup() or pg_xlog_switch().
   *
***************
*** 9516,9524 **** retry:
  					failedSources |= sources;
  
  					/*
! 					 * Check to see if the trigger file exists. Note that we
! 					 * do this only after failure, so when you create the
! 					 * trigger file, we still finish replaying as much as we
  					 * can from archive and pg_xlog before failover.
  					 */
  					if (CheckForStandbyTrigger())
--- 9556,9564 ----
  					failedSources |= sources;
  
  					/*
! 					 * Check to see if failover has been requested. Note that
! 					 * we do this only after failure, so when you request
! 					 * failover, we still finish replaying as much as we
  					 * can from archive and pg_xlog before failover.
  					 */
  					if (CheckForStandbyTrigger())
***************
*** 9690,9704 **** emode_for_corrupt_record(int emode, XLogRecPtr RecPtr)
  }
  
  /*
!  * Check to see if the trigger file exists. If it does, request postmaster
!  * to shut down walreceiver, wait for it to exit, remove the trigger
!  * file, and return true.
   */
  static bool
  CheckForStandbyTrigger(void)
  {
  	struct stat stat_buf;
  
  	if (TriggerFile == NULL)
  		return false;
  
--- 9730,9764 ----
  }
  
  /*
!  * Check to see if failover has been requested. If it's been done,
!  * request postmaster to shut down walreceiver, wait for it to exit,
!  * remove the trigger file if the request has come via it,
!  * and return true.
   */
  static bool
  CheckForStandbyTrigger(void)
  {
+ 	/* use volatile pointer to prevent code rearrangement */
+ 	volatile XLogCtlData *xlogctl = XLogCtl;
+ 	bool		failoverRequested = false;
  	struct stat stat_buf;
  
+ 	SpinLockAcquire(&xlogctl->info_lck);
+ 	failoverRequested = xlogctl->failoverRequested;
+ 
+ 	/*
+ 	 * It's not strictly necessary to reset the flag since we will not re-enter
+ 	 * the standby mode after failover, but let's do it for the sake of tidiness.
+ 	 */
+ 	xlogctl->failoverRequested = false;
+ 	SpinLockRelease(&xlogctl->info_lck);
+ 
+ 	if (failoverRequested)
+ 	{
+ 		ShutdownWalRcv();
+ 		return true;
+ 	}
+ 
  	if (TriggerFile == NULL)
  		return false;
  
*** a/src/include/access/xlog_internal.h
--- b/src/include/access/xlog_internal.h
***************
*** 271,276 **** extern Datum pg_current_xlog_location(PG_FUNCTION_ARGS);
--- 271,277 ----
  extern Datum pg_current_xlog_insert_location(PG_FUNCTION_ARGS);
  extern Datum pg_last_xlog_receive_location(PG_FUNCTION_ARGS);
  extern Datum pg_last_xlog_replay_location(PG_FUNCTION_ARGS);
+ extern Datum pg_trigger_failover(PG_FUNCTION_ARGS);
  extern Datum pg_xlogfile_name_offset(PG_FUNCTION_ARGS);
  extern Datum pg_xlogfile_name(PG_FUNCTION_ARGS);
  extern Datum pg_is_in_recovery(PG_FUNCTION_ARGS);
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 3380,3385 **** DATA(insert OID = 3820 ( pg_last_xlog_receive_location	PGNSP PGUID 12 1 0 0 f f
--- 3380,3387 ----
  DESCR("current xlog flush location");
  DATA(insert OID = 3821 ( pg_last_xlog_replay_location	PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ pg_last_xlog_replay_location _null_ _null_ _null_ ));
  DESCR("last xlog replay location");
+ DATA(insert OID = 3819 ( pg_trigger_failover	PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pg_trigger_failover _null_ _null_ _null_ ));
+ DESCR("trigger failover");
  
  DATA(insert OID = 2621 ( pg_reload_conf			PGNSP PGUID 12 1 0 0 f f f t f v 0 0 16 "" _null_ _null_ _null_ _null_ pg_reload_conf _null_ _null_ _null_ ));
  DESCR("reload configuration files");
