*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 1775,1780 **** include 'filename'
--- 1775,1836 ----
        </listitem>
       </varlistentry>
  
+      <varlistentry id="guc-enable_standalone_master" xreflabel="enable_standalone_master">
+       <term><varname>enable_standalone_master</varname> (<type>boolean</type>)</term>
+       <indexterm>
+        <primary><varname>enable_standalone_master</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+        Specifies how the master behaves when <xref linkend="guc-synchronous-commit">
+ 	is set to <literal>on</> and <xref linkend="guc-synchronous-standby-names"> is configured but no
+ 	 appropriate standby servers are currently connected. If enabled, the master will
+ 	 continue processing transactions alone. If disabled, all the transactions on the
+ 	 master are blocked until a synchronous standby has appeared.  The default is disabled.
+        </para>
+       </listitem>
+      </varlistentry>     
+ 	 
+      <varlistentry id="guc-master_to_standalone_cmd" xreflabel="master_to_standalone_cmd">
+       <term><varname>master_to_standalone_cmd</varname> (<type>enum</type>)</term>
+       <indexterm>
+        <primary><varname>master_to_standalone_cmd</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         This command is executed before master switches from sync mode to standalone
+ 		mode, this command is executed and if this command execution returns zero(i.e. success), 
+ 		then only master can switch to standalone mode. Incase of failure of the given 
+ 		command execution, the master mode remains same i.e. it remains in sync mode.
+ 	   </para>
+ 	   <para>
+ 	    The user should provide some command, which does some operation, which DBA can 
+ 		check later to determine the master mode. E.g. a command can be given which can
+ 		create some files to indicate that master has got switched to standalone mode.
+        </para>
+       </listitem>
+      </varlistentry>	
+ 
+     <varlistentry id="guc-master_to_sync_cmd" xreflabel="master_to_sync_cmd">
+       <term><varname>master_to_sync_cmd</varname> (<type>enum</type>)</term>
+       <indexterm>
+        <primary><varname>master_to_sync_cmd</> configuration parameter</primary>
+       </indexterm>
+       <listitem>
+        <para>
+         This command is executed before master switches from standalone mode to sync mode
+ 		mode, this command is executed and if this command execution returns zero(i.e. success), 
+ 		then only master can switch to sync mode. Incase of failure of the given 
+ 		command execution, the master mode remains same i.e. it remains in standalone mode.
+ 	   </para>
+ 	   <para>
+ 	    The user should provide command reverse to <varname>master_to_standalone_cmd</>, so that
+ 		it can undo the changes made. This will help DBA to determine that the master is running in
+ 		sync mode.
+        </para>
+       </listitem>
+      </varlistentry>	      
+ 
       <varlistentry id="guc-wal-sync-method" xreflabel="wal_sync_method">
        <term><varname>wal_sync_method</varname> (<type>enum</type>)</term>
        <indexterm>
*** a/src/backend/postmaster/checkpointer.c
--- b/src/backend/postmaster/checkpointer.c
***************
*** 1354,1359 **** UpdateSharedMemoryConfig(void)
--- 1354,1360 ----
  {
  	/* update global shmem state for sync rep */
  	SyncRepUpdateSyncStandbysDefined();
+ 	SyncRepUpdateSyncStandaloneMasterAllowed();
  
  	/*
  	 * If full_page_writes has been changed by SIGHUP, we update it in shared
*** a/src/backend/replication/syncrep.c
--- b/src/backend/replication/syncrep.c
***************
*** 60,65 ****
--- 60,76 ----
  /* User-settable parameters for sync rep */
  char	   *SyncRepStandbyNames;
  
+ /* Commands to be executed to indicate change in sync mode*/
+ char    *master_to_standalone_cmd; /* Master switch to standalone mode*/
+ char    *master_to_sync_cmd;		    /* Master switch to sync mode*/	
+ 
+ /* 
+  * To control whether a master configured with synchronous_commit = on is
+  * allowed to stop waiting for standby WAL sync when all synchronous
+  * standby WAL senders are disconnected.
+  */
+ bool    enable_standalone_master = false;
+ 
  #define SyncStandbysDefined() \
  	(SyncRepStandbyNames != NULL && SyncRepStandbyNames[0] != '\0')
  
***************
*** 127,132 **** SyncRepWaitForLSN(XLogRecPtr XactCommitLSN)
--- 138,153 ----
  		return;
  	}
  
+   	/*
+  	 * Return without waiting for LSN if there is no synchronous standbys
+  	 * connected
+  	 */
+  	if (WalSndCtl->sync_master_in_standalone_mode)
+  	{
+  		LWLockRelease(SyncRepLock);
+  		return;		
+ 	}	
+ 
  	/*
  	 * Set our waitLSN so WALSender will know when to wake us, and add
  	 * ourselves to the queue.
***************
*** 350,355 **** SyncRepInitConfig(void)
--- 371,384 ----
  	{
  		LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
  		MyWalSnd->sync_standby_priority = priority;
+ 
+  
+  		/*
+  		 * Synchronous standby is starting, so we should change the standalone
+  		 * sync_master_in_standalone_mode, if required.
+  		 */
+  		SyncRepCheckSyncStdbyAlive();
+ 
  		LWLockRelease(SyncRepLock);
  		ereport(DEBUG1,
  			(errmsg("standby \"%s\" now has synchronous standby priority %u",
***************
*** 710,712 **** assign_synchronous_commit(int newval, void *extra)
--- 739,874 ----
  			break;
  	}
  }
+ 
+ /*
+  * The checkpointer calls this as needed to update the shared
+  * sync_standbalone_master_allowed flag, so that backends don't remain 
+  * permanently wedged if sync_standbalone_master_allowed is unset.  
+  * It's safe to check the current value
+  * without the lock, because it's only ever updated by one process.  But we
+  * must take the lock to change it.
+  */
+ void
+ SyncRepUpdateSyncStandaloneMasterAllowed()
+ {
+ 	/* 
+ 	 * Check if new value of parameter is same as earlier, 
+ 	 * if not then change in shared memory. Since here were enabling this 
+ 	 * parameter now only, so it may happen that there were no synchronous 
+ 	 * standby but master has not gone in stand-alone mode because it was 
+ 	 * not configured to do so.
+ 	 */
+ 	if (enable_standalone_master != WalSndCtl->sync_standbalone_master_allowed)
+ 	{
+ 		LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);
+ 		
+ 		WalSndCtl->sync_standbalone_master_allowed = enable_standalone_master;
+ 		(void)SyncRepCheckSyncStdbyAlive();
+ 
+ 		LWLockRelease(SyncRepLock);
+ 	}
+ }
+ 
+ /*
+  * Loop through all sender task and check if there is any
+  * synchronous standby is alive. If alive then master needs
+  * to continue to wait for synchronous standby otherwise,
+  * it does not have to and it can switch to standalone mode.
+  * Whenever mode is changing from one to another then
+  * log the appropriate log message, which will be used by
+  * DBA.
+  */
+ void
+ SyncRepCheckSyncStdbyAlive()
+ {
+ 	bool sync_standby_connected = false;
+ 	int   loop = 0;
+ 
+ 	/* 
+ 	 * If it is in recovery mode (i.e. standby) then no need to check for 
+ 	 * synchronous standbys
+ 	 */
+ 	if (RecoveryInProgress())
+ 	{
+ 		WalSndCtl->sync_master_in_standalone_mode = false;
+ 		return;		
+ 	}
+ 	
+ 	if (!SyncRepRequested() || !SyncStandbysDefined())
+ 	{
+ 		WalSndCtl->sync_master_in_standalone_mode = false;
+ 		return;
+ 	}
+ 
+ 	if ( !(WalSndCtl->sync_standbalone_master_allowed))
+ 	{
+ 		/* 
+ 		 * May be synchronous_standalone_allowed is changed to disable, then
+ 		 * master should run in sync mode.
+ 		 */
+ 		if (WalSndCtl->sync_master_in_standalone_mode && !system(master_to_sync_cmd)) 
+ 		{
+ 			ereport(LOG,
+ 				(errmsg("Master switched to sync mode: "
+ 						"Waiting for standby synchronisation")));
+ 			WalSndCtl->sync_master_in_standalone_mode = false;
+ 		}
+ 		
+ 		return;
+ 	}
+ 
+ 	for (loop = 0; loop < max_wal_senders; loop++)
+ 	{
+ 		volatile WalSnd *walsnd = &WalSndCtl->walsnds[loop];
+ 
+ 		/* 
+ 		 * Check if this synchronous standby and its pid is not zero i.e. synchronous 
+ 		 * standby is alive.
+ 		 */
+ 		if (walsnd->sync_standby_priority && walsnd->pid != 0)
+ 		{
+ 			sync_standby_connected = true;
+ 			if (WalSndCtl->sync_master_in_standalone_mode  && !system(master_to_sync_cmd))
+ 			{
+ 				/* 
+ 				 * This log should be used by DBA to check if master 
+ 				 * was running in synchronoisation mode
+ 				 */				 
+ 				ereport(LOG,
+ 					(errmsg("Master switched to sync mode: "
+ 							"Waiting for standby synchronisation")));
+ 				WalSndCtl->sync_master_in_standalone_mode = false;
+ 			}
+ 			
+ 			return;
+ 		}		
+ 	}
+ 
+ 	if (!sync_standby_connected)
+ 	{
+ 		if (!(WalSndCtl->sync_master_in_standalone_mode) && !system(master_to_standalone_cmd))
+ 		{
+ 			/* 
+ 			 * This log should be used by DBA to check if master 
+ 			 * was running in standalone mode
+ 			 */
+ 			ereport(LOG,	
+ 				(errmsg("Master switched to standalone mode: "
+ 						"Not waiting for standby synchronisation")));
+ 			
+ 			WalSndCtl->sync_master_in_standalone_mode = true;
+ 
+ 			/* 
+ 			 * If there is any waiting sender, then wake-up them as
+ 			 * master has switched to standalone mode
+ 			 */
+ 			for (loop = 0; loop < NUM_SYNC_REP_WAIT_MODE; loop++)
+ 			{
+ 				SyncRepWakeQueue(true, loop);
+ 			} 
+ 		}
+ 	}
+ 
+ 	return;
+ }
+ 
*** a/src/backend/replication/walsender.c
--- b/src/backend/replication/walsender.c
***************
*** 1187,1196 **** InitWalSenderSlot(void)
  		{
  			/*
  			 * Found a free slot. Reserve it for us.
! 			 */
  			walsnd->pid = MyProcPid;
  			walsnd->sentPtr = InvalidXLogRecPtr;
  			walsnd->state = WALSNDSTATE_STARTUP;
  			SpinLockRelease(&walsnd->mutex);
  			/* don't need the lock anymore */
  			OwnLatch((Latch *) &walsnd->latch);
--- 1187,1198 ----
  		{
  			/*
  			 * Found a free slot. Reserve it for us.
! 			 */ 
!  						
  			walsnd->pid = MyProcPid;
  			walsnd->sentPtr = InvalidXLogRecPtr;
  			walsnd->state = WALSNDSTATE_STARTUP;
+ 			walsnd->sync_standby_priority = 0;
  			SpinLockRelease(&walsnd->mutex);
  			/* don't need the lock anymore */
  			OwnLatch((Latch *) &walsnd->latch);
***************
*** 1223,1228 **** WalSndKill(int code, Datum arg)
--- 1225,1241 ----
  	MyWalSnd->pid = 0;
  	DisownLatch(&MyWalSnd->latch);
  
+  	/*
+  	 * Here one standby is going down, then check if it was synchronous
+  	 * standby and also there is no more synchronous standby, if yes
+  	 * then wake all waiting transaction and also change the master
+  	 * mode to standalone
+  	 */
+  	LWLockAcquire(SyncRepLock, LW_EXCLUSIVE);  
+  	SyncRepCheckSyncStdbyAlive();
+  	LWLockRelease(SyncRepLock);	
+  	
+ 
  	/* WalSnd struct isn't mine anymore */
  	MyWalSnd = NULL;
  }
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 1470,1475 **** static struct config_bool ConfigureNamesBool[] =
--- 1470,1486 ----
  		NULL, NULL, NULL
  	},
  
+  	{
+  		{"enable_standalone_master", PGC_SIGHUP, REPLICATION_MASTER,
+  			gettext_noop("Enable master to continue as standbalone on sync standbys failure."),
+  			NULL,
+  		},
+  		&enable_standalone_master,
+  		false,
+  		NULL, NULL, NULL
+  	},
+  		
+ 
  	/* End-of-list marker */
  	{
  		{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
***************
*** 3151,3156 **** static struct config_string ConfigureNamesString[] =
--- 3162,3190 ----
  		check_application_name, assign_application_name, NULL
  	},
  
+ 	{
+ 		{"master_to_standalone_cmd", PGC_SIGHUP, REPLICATION_MASTER,
+ 			gettext_noop("Cmd to be executed to indicate DBA, master switched to standalone mode"),
+ 			NULL,
+ 			GUC_LIST_INPUT
+ 		},
+ 		&master_to_standalone_cmd,
+ 		"",
+ 		NULL, NULL, NULL
+ 	},		
+ 
+ 	{
+ 		{"master_to_sync_cmd", PGC_SIGHUP, REPLICATION_MASTER,
+ 			gettext_noop("Cmd to be executed to indicate DBA, master switched to sync mode"),
+ 			NULL,
+ 			GUC_LIST_INPUT
+ 		},
+ 		&master_to_sync_cmd,
+ 		"",
+ 		NULL, NULL, NULL
+ 	},		
+ 
+ 
  	/* End-of-list marker */
  	{
  		{NULL, 0, 0, NULL, NULL}, NULL, NULL, NULL, NULL, NULL
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 227,232 ****
--- 227,242 ----
  #synchronous_standby_names = ''	# standby servers that provide sync rep
  				# comma-separated list of application_name
  				# from standby(s); '*' = all
+ 
+ #enable_standalone_master = off	#Whether master is allowed to continue
+ 				#as standbalone after sync standby failure
+ 
+ #master_to_standalone_cmd = ''	#Execute this command to indicate DBA that
+ 				# master node has switched to standalone mode.	
+ 
+ #master_to_sync_cmd	= ''	#Execute this command to indicate DBA that
+ 				# master node has switched to sync mode.	
+ 
  #vacuum_defer_cleanup_age = 0	# number of xacts by which cleanup is delayed
  
  # - Standby Servers -
*** a/src/include/replication/syncrep.h
--- b/src/include/replication/syncrep.h
***************
*** 33,38 ****
--- 33,41 ----
  
  /* user-settable parameters for synchronous replication */
  extern char *SyncRepStandbyNames;
+ extern char *master_to_standalone_cmd;
+ extern char *master_to_sync_cmd;
+ extern bool    enable_standalone_master;
  
  /* called by user backend */
  extern void SyncRepWaitForLSN(XLogRecPtr XactCommitLSN);
***************
*** 53,56 **** extern int	SyncRepWakeQueue(bool all, int mode);
--- 56,66 ----
  extern bool check_synchronous_standby_names(char **newval, void **extra, GucSource source);
  extern void assign_synchronous_commit(int newval, void *extra);
  
+ /* called to set the shared memory values*/
+ void SyncRepUpdateSyncStandaloneMasterAllowed(void);
+  
+ /* called to check if any synchronous standby is alive*/
+ void SyncRepCheckSyncStdbyAlive(void);
+  
+ 
  #endif   /* _SYNCREP_H */
*** a/src/include/replication/walsender_private.h
--- b/src/include/replication/walsender_private.h
***************
*** 88,93 **** typedef struct
--- 88,107 ----
  	 */
  	bool		sync_standbys_defined;
  
+  	/* 
+  	 * Indicates the current running mode of master node. If it is true means
+  	 * there is no synchronous standby available so it is running in standalone
+  	 * mode.
+  	 */  
+  	bool 		sync_master_in_standalone_mode;
+  
+ 	/* 
+ 	 * Whether master is allowed to switch to standalone if no synchronous
+ 	 * standbys are available. This is a copy of GUC variable.
+ 	 */
+  	bool			sync_standbalone_master_allowed;
+  	
+ 
  	WalSnd		walsnds[1];		/* VARIABLE LENGTH ARRAY */
  } WalSndCtlData;
  
