diff -cprN head/src/backend/access/transam/twophase.c dblink2/src/backend/access/transam/twophase.c
*** head/src/backend/access/transam/twophase.c	2009-06-26 04:05:52.000000000 +0900
--- dblink2/src/backend/access/transam/twophase.c	2009-08-20 11:18:35.852151624 +0900
*************** typedef struct TwoPhaseStateData
*** 138,143 ****
--- 138,155 ----
  
  static TwoPhaseStateData *TwoPhaseState;
  
+ /*
+  * List of add-on for twophase commit callbacks
+  */
+ typedef struct TwoPhaseCallbackItem
+ {
+ 	struct TwoPhaseCallbackItem *next;
+ 	TwoPhaseEventCallback callback;
+ 	void	   *arg;
+ } TwoPhaseCallbackItem;
+ 
+ static TwoPhaseCallbackItem *TwoPhase_callbacks = NULL;
+ 
  
  static void RecordTransactionCommitPrepared(TransactionId xid,
  								int nchildren,
*************** EndPrepare(GlobalTransaction gxact)
*** 944,949 ****
--- 956,964 ----
  				 errmsg("could not seek in two-phase state file: %m")));
  	}
  
+ 	/* Fire pre-commit callbacks */
+ 	CallTwoPhaseCallbacks(TWOPHASE_EVENT_PRE_COMMIT, gxact);
+ 
  	/*
  	 * The state file isn't valid yet, because we haven't written the correct
  	 * CRC yet.  Before we do that, insert entry in WAL and flush it to disk.
*************** FinishPreparedTransaction(const char *gi
*** 1248,1256 ****
--- 1263,1277 ----
  
  	/* And now do the callbacks */
  	if (isCommit)
+ 	{
  		ProcessRecords(bufptr, xid, twophase_postcommit_callbacks);
+ 		CallTwoPhaseCallbacks(TWOPHASE_EVENT_POST_COMMIT, gxact);
+ 	}
  	else
+ 	{
  		ProcessRecords(bufptr, xid, twophase_postabort_callbacks);
+ 		CallTwoPhaseCallbacks(TWOPHASE_EVENT_POST_ABORT, gxact);
+ 	}
  
  	/* Count the prepared xact as committed or aborted */
  	AtEOXact_PgStat(isCommit);
*************** RecoverPreparedTransactions(void)
*** 1687,1692 ****
--- 1708,1714 ----
  			 * Recover other state (notably locks) using resource managers
  			 */
  			ProcessRecords(bufptr, xid, twophase_recover_callbacks);
+ 			CallTwoPhaseCallbacks(TWOPHASE_EVENT_RECOVER, gxact);
  
  			pfree(buf);
  		}
*************** RecordTransactionAbortPrepared(Transacti
*** 1839,1841 ****
--- 1861,1906 ----
  
  	END_CRIT_SECTION();
  }
+ 
+ void
+ RegisterTwoPhaseCallback(TwoPhaseEventCallback callback, void *arg)
+ {
+ 	TwoPhaseCallbackItem *item;
+ 
+ 	item = (TwoPhaseCallbackItem *)
+ 		MemoryContextAlloc(TopMemoryContext, sizeof(TwoPhaseCallbackItem));
+ 	item->callback = callback;
+ 	item->arg = arg;
+ 	item->next = TwoPhase_callbacks;
+ 	TwoPhase_callbacks = item;
+ }
+ 
+ void
+ UnregisterTwoPhaseCallback(TwoPhaseEventCallback callback, void *arg)
+ {
+ 	TwoPhaseCallbackItem *item;
+ 	TwoPhaseCallbackItem *prev;
+ 
+ 	prev = NULL;
+ 	for (item = TwoPhase_callbacks; item; prev = item, item = item->next)
+ 	{
+ 		if (item->callback == callback && item->arg == arg)
+ 		{
+ 			if (prev)
+ 				prev->next = item->next;
+ 			else
+ 				TwoPhase_callbacks = item->next;
+ 			pfree(item);
+ 			break;
+ 		}
+ 	}
+ }
+ 
+ void
+ CallTwoPhaseCallbacks(TwoPhaseEvent event, GlobalTransaction gxact)
+ {
+ 	TwoPhaseCallbackItem *item;
+ 
+ 	for (item = TwoPhase_callbacks; item; item = item->next)
+ 		(*item->callback) (event, gxact, item->arg);
+ }
diff -cprN head/src/backend/access/transam/xact.c dblink2/src/backend/access/transam/xact.c
*** head/src/backend/access/transam/xact.c	2009-06-11 23:48:54.000000000 +0900
--- dblink2/src/backend/access/transam/xact.c	2009-08-20 11:14:22.576185055 +0900
*************** CommitTransaction(void)
*** 1593,1598 ****
--- 1593,1601 ----
  	/* Now we can shut down the deferred-trigger manager */
  	AfterTriggerEndXact(true);
  
+ 	/* Fire pre-commit callbacks */
+ 	CallTwoPhaseCallbacks(TWOPHASE_EVENT_PRE_COMMIT, NULL);
+ 
  	/* Close any open regular cursors */
  	AtCommit_Portals();
  
diff -cprN head/src/include/access/twophase.h dblink2/src/include/access/twophase.h
*** head/src/include/access/twophase.h	2009-01-02 02:23:56.000000000 +0900
--- dblink2/src/include/access/twophase.h	2009-08-20 11:06:06.572168421 +0900
***************
*** 24,29 ****
--- 24,40 ----
   */
  typedef struct GlobalTransactionData *GlobalTransaction;
  
+ typedef enum
+ {
+ 	TWOPHASE_EVENT_PRE_COMMIT,
+ 	TWOPHASE_EVENT_POST_COMMIT,
+ 	TWOPHASE_EVENT_POST_ABORT,
+ 	TWOPHASE_EVENT_RECOVER,
+ } TwoPhaseEvent;
+ 
+ typedef void (*TwoPhaseEventCallback) (TwoPhaseEvent event,
+ 									   GlobalTransaction gxact, void *arg);
+ 
  /* GUC variable */
  extern int	max_prepared_xacts;
  
*************** extern void CheckPointTwoPhase(XLogRecPt
*** 49,52 ****
--- 60,67 ----
  
  extern void FinishPreparedTransaction(const char *gid, bool isCommit);
  
+ extern void RegisterTwoPhaseCallback(TwoPhaseEventCallback callback, void *arg);
+ extern void UnregisterTwoPhaseCallback(TwoPhaseEventCallback callback, void *arg);
+ extern void CallTwoPhaseCallbacks(TwoPhaseEvent event, GlobalTransaction gxact);
+ 
  #endif   /* TWOPHASE_H */