Latest version of rmgr hooks patch for later review in current
commitfest.

(Minor update to CVS HEAD).

-- 
 Simon Riggs           www.2ndQuadrant.com
 PostgreSQL Training, Services and Support
Index: src/backend/access/transam/rmgr.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/rmgr.c,v
retrieving revision 1.27
diff -c -r1.27 rmgr.c
*** src/backend/access/transam/rmgr.c	19 Nov 2008 10:34:50 -0000	1.27
--- src/backend/access/transam/rmgr.c	17 Dec 2008 19:05:51 -0000
***************
*** 7,12 ****
--- 7,13 ----
   */
  #include "postgres.h"
  
+ #include "miscadmin.h"
  #include "access/clog.h"
  #include "access/gin.h"
  #include "access/gist_private.h"
***************
*** 16,21 ****
--- 17,23 ----
  #include "access/nbtree.h"
  #include "access/xact.h"
  #include "access/xlog_internal.h"
+ #include "nodes/bitmapset.h"
  #include "catalog/storage.h"
  #include "commands/dbcommands.h"
  #include "commands/sequence.h"
***************
*** 23,29 ****
  #include "storage/freespace.h"
  
  
! const RmgrData RmgrTable[RM_MAX_ID + 1] = {
  	{"XLOG", xlog_redo, xlog_desc, NULL, NULL, NULL},
  	{"Transaction", xact_redo, xact_desc, NULL, NULL, NULL},
  	{"Storage", smgr_redo, smgr_desc, NULL, NULL, NULL},
--- 25,31 ----
  #include "storage/freespace.h"
  
  
! const RmgrData FixedRmgrTable[RM_MAX_FIXED_ID + 1] = {
  	{"XLOG", xlog_redo, xlog_desc, NULL, NULL, NULL},
  	{"Transaction", xact_redo, xact_desc, NULL, NULL, NULL},
  	{"Storage", smgr_redo, smgr_desc, NULL, NULL, NULL},
***************
*** 41,43 ****
--- 43,366 ----
  	{"Gist", gist_redo, gist_desc, gist_xlog_startup, gist_xlog_cleanup, gist_safe_restartpoint},
  	{"Sequence", seq_redo, seq_desc, NULL, NULL, NULL}
  };
+ 
+ /* Main table of Resource Managers */
+ RmgrData *RmgrTable;
+ 
+ /* Hook for plugins to get control in RmgrInitialize() */
+ rmgr_hook_type rmgr_hook = NULL;
+ 
+ #define MAX_NUM_RMGRS			255
+ #define RMGR_BITS_PER_WORD		32
+ #define	RMGR_BITMAP_WORDS		((MAX_NUM_RMGRS + 1) / RMGR_BITS_PER_WORD)
+ typedef struct RmgrCtlData
+ {
+ 	uint32	RmgrBitmap[RMGR_BITMAP_WORDS];		/* fixed size bitmapset */
+ } RmgrCtlData;
+ 
+ static RmgrCtlData *RmgrCtl = NULL;
+ 
+ /*
+  * Initialization of shared memory for Rmgrs
+  */
+ Size
+ RmgrShmemSize(void)
+ {
+ 	return sizeof(RmgrCtlData);
+ }
+ 
+ void
+ RmgrShmemInit(void)
+ {
+ 	bool		foundRmgr;
+ 
+ 	RmgrCtl = (RmgrCtlData *)
+ 		ShmemInitStruct("Rmgr Ctl", RmgrShmemSize(), &foundRmgr);
+ 
+ 	if (foundRmgr)
+ 		return;
+ 
+ 	memset(RmgrCtl, 0, sizeof(RmgrCtlData));
+ }
+ 
+ /*
+  * RmgrInitialize()
+  *
+  * Create RmgrTable, populate RmgrTable with fixed Rmgrs, call plugin
+  * and then initialize shared list of current resource managers.
+  *
+  * RmgrInitialize must run before any other Rmgr function. Normally,
+  * it runs only in the Startup process (once), ensuring that the RmgrTable
+  * and its functions cannot be accessed by normal backends.
+  *
+  * If we have WAL_DEBUG set then the plugin will be called multiple
+  * times and so must be designed to return same answer every time.
+  */
+ void
+ RmgrInitialize(void)
+ {
+ 	int rmid;
+ 	int	num_rmgrs = 0;
+ 
+ 	if (RmgrTable)
+ 		return;
+ 
+ 	/*
+ 	 * Create local copy of RmgrTable. Memory is never freed.
+ 	 */
+ 	RmgrTable = malloc(sizeof(RmgrData) * (MAX_NUM_RMGRS + 1));
+ 
+ 	for (rmid = 0; rmid <= MAX_NUM_RMGRS; rmid++)
+ 	{
+ 		if (rmid <= RM_MAX_FIXED_ID)
+ 		{
+ 			RmgrTable[rmid].rm_name = FixedRmgrTable[rmid].rm_name;
+ 			RmgrTable[rmid].rm_redo = FixedRmgrTable[rmid].rm_redo;
+ 			RmgrTable[rmid].rm_desc = FixedRmgrTable[rmid].rm_desc;
+ 			RmgrTable[rmid].rm_startup = FixedRmgrTable[rmid].rm_startup;
+ 			RmgrTable[rmid].rm_cleanup = FixedRmgrTable[rmid].rm_cleanup;
+ 			RmgrTable[rmid].rm_safe_restartpoint = 
+ 									FixedRmgrTable[rmid].rm_safe_restartpoint;
+ 		}
+ 		else
+ 		{
+ 			RmgrTable[rmid].rm_name = NULL;
+ 			RmgrTable[rmid].rm_redo = NULL;
+ 			RmgrTable[rmid].rm_desc = NULL;
+ 			RmgrTable[rmid].rm_startup = NULL;
+ 			RmgrTable[rmid].rm_cleanup = NULL;
+ 			RmgrTable[rmid].rm_safe_restartpoint = NULL; 
+ 		}
+ 	}
+ 
+ 	/* 
+ 	 * Call plugin, if present and output log message to assist with
+ 	 * diagnosis of recovery issues.
+ 	 *
+ 	 * What is the plugin allowed to do?
+ 	 * All RMs are assigned to a single RmgrId. All RM functions are 
+ 	 * optional, though we will only allow WAL inserts for RmgrIds that 
+ 	 * have a defined rm_redo function. The fixed RMs can be overridden
+ 	 * by providing new routines that do similar, yet slightly different
+ 	 * actions such as filters. There is no direct connection between
+ 	 * an RM and and entry in pg_am, so it is possible to create a new
+ 	 * index type but then not be able to insert into that index, iff
+ 	 * the new index code issues any WAL inserts. That error is quickly
+ 	 * discovered in practice, even if the docs are ignored. That sounds
+ 	 * a little strange, but then pg_am is not readable at the time we 
+ 	 * need to know which RM functions to use for recovery.
+ 	 *
+ 	 * XXX we cannot yet issue an index rebuild from rm_cleanup()
+ 	 * though that feature is expected to be achieved one day
+ 	 */
+ 	if (rmgr_hook)
+ 	{
+ 		elog(LOG, "Executing Rmgr hook to extend and/or modify resource managers");
+ 		(*rmgr_hook) (RmgrTable);
+ 	}
+ 
+ 	/*
+ 	 * Now create data structure to allow checking of RmgrId in each backend.
+ 	 */
+ 	for (rmid = 0; rmid <= MAX_NUM_RMGRS; rmid++)
+ 	{
+ 		if (RmgrTable[rmid].rm_redo != NULL)
+ 		{
+ 			int wordnum = rmid / RMGR_BITS_PER_WORD;
+ 			int bitnum = rmid % RMGR_BITS_PER_WORD;
+ 			RmgrCtl->RmgrBitmap[wordnum] |= ((uint32) 1 << bitnum);
+ 
+ 			num_rmgrs++;
+ 
+ 			/*
+ 			 * Keep track of new or modified RMs for diagnostic purposes
+ 			 */
+ 			if (rmid <= RM_MAX_FIXED_ID)
+ 			{
+ 				if	(RmgrTable[rmid].rm_name != FixedRmgrTable[rmid].rm_name ||
+ 				 	 RmgrTable[rmid].rm_redo != FixedRmgrTable[rmid].rm_redo ||
+ 				 	 RmgrTable[rmid].rm_startup != FixedRmgrTable[rmid].rm_startup ||
+ 				 	 RmgrTable[rmid].rm_cleanup != FixedRmgrTable[rmid].rm_cleanup ||
+ 				 	 RmgrTable[rmid].rm_safe_restartpoint != 
+ 									FixedRmgrTable[rmid].rm_safe_restartpoint)
+ 				elog(LOG, "Rmgr (%d) %s has been modified", rmid, 
+ 						FixedRmgrTable[rmid].rm_name);
+ 			}
+ 			else
+ 				elog(LOG, "Rmgr (%d) %s defined", rmid, 
+ 						(RmgrTable[rmid].rm_name != NULL ? 
+ 								RmgrTable[rmid].rm_name : "<Unnamed>"));
+ 		}
+ 	}
+ 
+ 	if (num_rmgrs == 0)
+ 		elog(FATAL, "No valid resource managers defined");
+ }
+ 
+ 
+ /*
+  * RmgrStartup()
+  *
+  * Allow resource managers to do any required startup.
+  * Run RM startup functions once, only ever runs in Startup process.
+  */
+ void
+ RmgrStartup(void)
+ {
+ 	int rmid;
+ 
+ 	Assert(RmgrTable);
+ 	for (rmid = 0; rmid <= MAX_NUM_RMGRS; rmid++)
+ 	{
+ 		if (RmgrTable[rmid].rm_startup != NULL)
+ 		{
+ 			elog(DEBUG2, "RmgrStartup (%d) %s", rmid, RmgrTable[rmid].rm_name);
+ 			RmgrTable[rmid].rm_startup();
+ 		}
+ 	}
+ }
+ 
+ /*
+  * RmgrCleanup()
+  *
+  * Allow resource managers to do any required cleanup.
+  * Run RM cleanup functions once, only ever runs in Startup process.
+  *
+  * Called once prior to start of normal running
+  */
+ void
+ RmgrCleanup(void)
+ {
+ 	int			rmid;
+ 
+ 	Assert(RmgrTable);
+ 	for (rmid = 0; rmid <= MAX_NUM_RMGRS; rmid++)
+ 	{
+ 		if (RmgrTable[rmid].rm_cleanup != NULL)
+ 		{
+ 			elog(DEBUG2, "RmgrCleanup (%d) %s", rmid, RmgrTable[rmid].rm_name);
+ 			RmgrTable[rmid].rm_cleanup();
+ 		}
+ 	}
+ }
+ 
+ /*
+  * RmgrSafeRestartpoint()
+  *
+  * Is it safe to mark a restartpoint?  We must ask each of the resource 
+  * managers whether they have any partial state information that might
+  * prevent a correct restart from the supplied LSN.
+  *
+  * Called once every 5 minutes with default settings, sometimes more
+  * frequently if last call returned false.
+  */
+ bool
+ RmgrSafeRestartpoint(XLogRecPtr checkPointRedo)
+ {
+ 	int rmid;
+ 
+ 	Assert(RmgrTable);
+ 	for (rmid = 0; rmid <= MAX_NUM_RMGRS; rmid++)
+ 	{
+ 		if (RmgrTable[rmid].rm_safe_restartpoint != NULL)
+ 			if (!(RmgrTable[rmid].rm_safe_restartpoint()))
+ 			{
+ 				elog(DEBUG2, "RM (%d) %s not safe to record restart point at %X/%X",
+ 					 rmid,
+ 					 RmgrTable[rmid].rm_name,
+ 					 checkPointRedo.xlogid,
+ 					 checkPointRedo.xrecoff);
+ 				return false;
+ 			}
+ 	}
+ 
+ 	return true;
+ }
+ 
+ /*
+  * RmgrRedo
+  *
+  * Call the RM's redo function to apply WAL records. The RmgrId should
+  * previously have been checked using RmgrIdIsValid().
+  */
+ void
+ RmgrRedo(XLogRecPtr lsn, XLogRecord *rptr)
+ {
+ 	RmgrTable[rptr->xl_rmid].rm_redo(lsn, rptr);
+ }
+ 
+ /*
+  * Error context callback for errors occurring during rm_redo().
+  */
+ void
+ rm_redo_error_callback(void *arg)
+ {
+ 	XLogRecord *record = (XLogRecord *) arg;
+ 	StringInfoData buf;
+ 
+ 	initStringInfo(&buf)	;
+ 	Assert(RmgrTable);
+ 	if (RmgrTable[record->xl_rmid].rm_desc != NULL)
+ 		RmgrTable[record->xl_rmid].rm_desc(&buf,
+ 									   record->xl_info,
+ 									   XLogRecGetData(record));
+ 
+ 	/* don't bother emitting empty description */
+ 	if (buf.len > 0)
+ 		errcontext("xlog redo %s", buf.data);
+ 
+ 	pfree(buf.data);
+ }
+ 
+ /*
+  * RmgrDesc
+  *
+  * Call the RM's desc function to print details of WAL records
+  * during error handling or when WAL_DEBUG is set
+  */
+ void
+ RmgrDesc(StringInfo buf, XLogRecord *rptr, char *rec)
+ {
+ 	if (RmgrTable[rptr->xl_rmid].rm_desc != NULL)
+ 		RmgrTable[rptr->xl_rmid].rm_desc(buf, rptr->xl_info, rec);
+ }
+ 
+ /*
+  * RmgrName
+  *
+  * Get the RM's namefor use when WAL_DEBUG is set
+  */
+ const char *
+ RmgrName(RmgrId rmid)
+ {
+ 	Assert(RmgrTable);
+ 	return RmgrTable[rmid].rm_name;
+ }
+ 
+ /*
+  * RmgrIsIsValid
+  *
+  * Check whether the RmgrId has a valid rm_redo function currently
+  * Caller throws any error, not here.
+  */
+ bool
+ RmgrIdIsValid(RmgrId rmid)
+ {
+ 	int		wordnum = rmid / RMGR_BITS_PER_WORD;
+ 	int		bitnum = rmid % RMGR_BITS_PER_WORD;
+ 
+ 	/*
+ 	 * If not already done so, get set of valid RmgrIds as a bms
+ 	 */
+ 	if (!RmgrCtl)
+ 		RmgrShmemInit();
+ 
+ 	/*
+ 	 * Check validity
+ 	 */
+ 	if ((RmgrCtl->RmgrBitmap[wordnum] & ((bitmapword) 1 << bitnum)) != 0)
+ 		return true;
+ 
+ 	return false;
+ }
+ 
Index: src/backend/access/transam/xlog.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/access/transam/xlog.c,v
retrieving revision 1.323
diff -c -r1.323 xlog.c
*** src/backend/access/transam/xlog.c	3 Dec 2008 08:20:11 -0000	1.323
--- src/backend/access/transam/xlog.c	17 Dec 2008 19:04:34 -0000
***************
*** 437,443 ****
  static void pg_start_backup_callback(int code, Datum arg);
  static bool read_backup_label(XLogRecPtr *checkPointLoc,
  				  XLogRecPtr *minRecoveryLoc);
- static void rm_redo_error_callback(void *arg);
  static int get_sync_bit(int method);
  
  
--- 437,442 ----
***************
*** 498,503 ****
--- 497,513 ----
  	}
  
  	/*
+ 	 * Check that we are writing a currently valid RmgrId. If not, then
+ 	 * we cannot allow this to be written to WAL otherwise we would be 
+ 	 * unable to recover correctly from crash and could lose data written
+ 	 * after an invalid WAL record.
+ 	 */
+ 	if (!RmgrIdIsValid(rmid))
+ 		ereport(ERROR,
+ 				(errmsg("invalid resource manager ID %u", rmid),
+ 				 errhint("You must configure resource manager at startup.")));
+ 
+ 	/*
  	 * Here we scan the rdata chain, determine which buffers must be backed
  	 * up, and compute the CRC values for the data.  Note that the record
  	 * header isn't added into the CRC initially since we don't know the final
***************
*** 829,834 ****
--- 839,846 ----
  	{
  		StringInfoData buf;
  
+ 		RmgrInitialize();
+ 
  		initStringInfo(&buf);
  		appendStringInfo(&buf, "INSERT @ %X/%X: ",
  						 RecPtr.xlogid, RecPtr.xrecoff);
***************
*** 836,842 ****
  		if (rdata->data != NULL)
  		{
  			appendStringInfo(&buf, " - ");
! 			RmgrTable[record->xl_rmid].rm_desc(&buf, record->xl_info, rdata->data);
  		}
  		elog(LOG, "%s", buf.data);
  		pfree(buf.data);
--- 848,854 ----
  		if (rdata->data != NULL)
  		{
  			appendStringInfo(&buf, " - ");
! 			RmgrDesc(&buf, record, rdata->data);
  		}
  		elog(LOG, "%s", buf.data);
  		pfree(buf.data);
***************
*** 3235,3244 ****
  						RecPtr->xlogid, RecPtr->xrecoff)));
  		goto next_record_is_invalid;
  	}
! 	if (record->xl_rmid > RM_MAX_ID)
  	{
  		ereport(emode,
! 				(errmsg("invalid resource manager ID %u at %X/%X",
  						record->xl_rmid, RecPtr->xlogid, RecPtr->xrecoff)));
  		goto next_record_is_invalid;
  	}
--- 3247,3256 ----
  						RecPtr->xlogid, RecPtr->xrecoff)));
  		goto next_record_is_invalid;
  	}
! 	if (!RmgrIdIsValid(record->xl_rmid))
  	{
  		ereport(emode,
! 				(errmsg("invalid resource manager ID %u" " at %X/%X",
  						record->xl_rmid, RecPtr->xlogid, RecPtr->xrecoff)));
  		goto next_record_is_invalid;
  	}
***************
*** 4945,4950 ****
--- 4957,4971 ----
  	 */
  	readRecoveryCommandFile();
  
+ 	/*
+ 	 * Initialize RMs. Startup functions are *not* called unless we
+ 	 * are InRecovery. We do this in two steps so that we know what 
+ 	 * RMs are currently valid for when we call XLogInsert(). We
+ 	 * specifically do not write the list of RMs to the ControlFile,
+ 	 * to allow more flexibility in adding/removing RMs.
+ 	 */
+ 	RmgrInitialize();
+ 
  	/* Now we can determine the list of expected TLIs */
  	expectedTLIs = readTimeLineHistory(recoveryTargetTLI);
  
***************
*** 5074,5081 ****
  	/* REDO */
  	if (InRecovery)
  	{
- 		int			rmid;
- 
  		/*
  		 * Update pg_control to show that we are recovering and to show the
  		 * selected checkpoint as the place we are starting from. We also mark
--- 5095,5100 ----
***************
*** 5121,5132 ****
  								BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
  		}
  
! 		/* Initialize resource managers */
! 		for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
! 		{
! 			if (RmgrTable[rmid].rm_startup != NULL)
! 				RmgrTable[rmid].rm_startup();
! 		}
  
  		/*
  		 * Find the first record that logically follows the checkpoint --- it
--- 5140,5149 ----
  								BACKUP_LABEL_FILE, BACKUP_LABEL_OLD)));
  		}
  
! 		/*
! 		 * Startup Resource Managers
! 		 */
! 		RmgrStartup();
  
  		/*
  		 * Find the first record that logically follows the checkpoint --- it
***************
*** 5170,5178 ****
  									 EndRecPtr.xlogid, EndRecPtr.xrecoff);
  					xlog_outrec(&buf, record);
  					appendStringInfo(&buf, " - ");
! 					RmgrTable[record->xl_rmid].rm_desc(&buf,
! 													   record->xl_info,
! 													 XLogRecGetData(record));
  					elog(LOG, "%s", buf.data);
  					pfree(buf.data);
  				}
--- 5187,5193 ----
  									 EndRecPtr.xlogid, EndRecPtr.xrecoff);
  					xlog_outrec(&buf, record);
  					appendStringInfo(&buf, " - ");
! 					RmgrDesc(&buf, record, XLogRecGetData(record));
  					elog(LOG, "%s", buf.data);
  					pfree(buf.data);
  				}
***************
*** 5190,5196 ****
  				}
  
  				/* Setup error traceback support for ereport() */
! 				errcontext.callback = rm_redo_error_callback;
  				errcontext.arg = (void *) record;
  				errcontext.previous = error_context_stack;
  				error_context_stack = &errcontext;
--- 5205,5211 ----
  				}
  
  				/* Setup error traceback support for ereport() */
! 				errcontext.callback = rm_redo_error_callback; /* see rmgr.c */
  				errcontext.arg = (void *) record;
  				errcontext.previous = error_context_stack;
  				error_context_stack = &errcontext;
***************
*** 5206,5212 ****
  				if (record->xl_info & XLR_BKP_BLOCK_MASK)
  					RestoreBkpBlocks(record, EndRecPtr);
  
! 				RmgrTable[record->xl_rmid].rm_redo(EndRecPtr, record);
  
  				/* Pop the error context stack */
  				error_context_stack = errcontext.previous;
--- 5221,5227 ----
  				if (record->xl_info & XLR_BKP_BLOCK_MASK)
  					RestoreBkpBlocks(record, EndRecPtr);
  
! 				RmgrRedo(EndRecPtr, record);
  
  				/* Pop the error context stack */
  				error_context_stack = errcontext.previous;
***************
*** 5353,5368 ****
  
  	if (InRecovery)
  	{
! 		int			rmid;
! 
! 		/*
! 		 * Allow resource managers to do any required cleanup.
! 		 */
! 		for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
! 		{
! 			if (RmgrTable[rmid].rm_cleanup != NULL)
! 				RmgrTable[rmid].rm_cleanup();
! 		}
  
  		/*
  		 * Check to see if the XLOG sequence contained any unresolved
--- 5368,5374 ----
  
  	if (InRecovery)
  	{
! 		RmgrCleanup();
  
  		/*
  		 * Check to see if the XLOG sequence contained any unresolved
***************
*** 6102,6108 ****
  RecoveryRestartPoint(const CheckPoint *checkPoint)
  {
  	int			elapsed_secs;
- 	int			rmid;
  
  	/*
  	 * Do nothing if the elapsed time since the last restartpoint is less than
--- 6108,6113 ----
***************
*** 6118,6140 ****
  		return;
  
  	/*
! 	 * Is it safe to checkpoint?  We must ask each of the resource managers
! 	 * whether they have any partial state information that might prevent a
! 	 * correct restart from this point.  If so, we skip this opportunity, but
  	 * return at the next checkpoint record for another try.
  	 */
! 	for (rmid = 0; rmid <= RM_MAX_ID; rmid++)
! 	{
! 		if (RmgrTable[rmid].rm_safe_restartpoint != NULL)
! 			if (!(RmgrTable[rmid].rm_safe_restartpoint()))
! 			{
! 				elog(DEBUG2, "RM %d not safe to record restart point at %X/%X",
! 					 rmid,
! 					 checkPoint->redo.xlogid,
! 					 checkPoint->redo.xrecoff);
! 				return;
! 			}
! 	}
  
  	/*
  	 * OK, force data out to disk
--- 6123,6133 ----
  		return;
  
  	/*
! 	 * Is it safe to restart from here? If not, we skip this opportunity, but
  	 * return at the next checkpoint record for another try.
  	 */
! 	if (!RmgrSafeRestartpoint(checkPoint->redo))
! 		return;
  
  	/*
  	 * OK, force data out to disk
***************
*** 6369,6375 ****
  			appendStringInfo(buf, "; bkpb%d", i + 1);
  	}
  
! 	appendStringInfo(buf, ": %s", RmgrTable[record->xl_rmid].rm_name);
  }
  #endif   /* WAL_DEBUG */
  
--- 6362,6368 ----
  			appendStringInfo(buf, "; bkpb%d", i + 1);
  	}
  
! 	appendStringInfo(buf, ": %s", RmgrName(record->xl_rmid));
  }
  #endif   /* WAL_DEBUG */
  
***************
*** 7141,7167 ****
  }
  
  /*
-  * Error context callback for errors occurring during rm_redo().
-  */
- static void
- rm_redo_error_callback(void *arg)
- {
- 	XLogRecord *record = (XLogRecord *) arg;
- 	StringInfoData buf;
- 
- 	initStringInfo(&buf);
- 	RmgrTable[record->xl_rmid].rm_desc(&buf,
- 									   record->xl_info,
- 									   XLogRecGetData(record));
- 
- 	/* don't bother emitting empty description */
- 	if (buf.len > 0)
- 		errcontext("xlog redo %s", buf.data);
- 
- 	pfree(buf.data);
- }
- 
- /*
   * BackupInProgress: check if online backup mode is active
   *
   * This is done by checking for existence of the "backup_label" file.
--- 7134,7139 ----
Index: src/backend/storage/ipc/ipci.c
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/storage/ipc/ipci.c,v
retrieving revision 1.97
diff -c -r1.97 ipci.c
*** src/backend/storage/ipc/ipci.c	30 Sep 2008 10:52:13 -0000	1.97
--- src/backend/storage/ipc/ipci.c	17 Dec 2008 19:04:34 -0000
***************
*** 18,23 ****
--- 18,24 ----
  #include "access/heapam.h"
  #include "access/multixact.h"
  #include "access/nbtree.h"
+ #include "access/rmgr.h"
  #include "access/subtrans.h"
  #include "access/twophase.h"
  #include "miscadmin.h"
***************
*** 101,106 ****
--- 102,108 ----
  		size = add_size(size, LockShmemSize());
  		size = add_size(size, ProcGlobalShmemSize());
  		size = add_size(size, XLOGShmemSize());
+ 		size = add_size(size, RmgrShmemSize());
  		size = add_size(size, CLOGShmemSize());
  		size = add_size(size, SUBTRANSShmemSize());
  		size = add_size(size, TwoPhaseShmemSize());
***************
*** 174,182 ****
  	InitShmemIndex();
  
  	/*
! 	 * Set up xlog, clog, and buffers
  	 */
  	XLOGShmemInit();
  	CLOGShmemInit();
  	SUBTRANSShmemInit();
  	TwoPhaseShmemInit();
--- 176,185 ----
  	InitShmemIndex();
  
  	/*
! 	 * Set up xlog, rmgr, clog, and buffers
  	 */
  	XLOGShmemInit();
+ 	RmgrShmemInit();
  	CLOGShmemInit();
  	SUBTRANSShmemInit();
  	TwoPhaseShmemInit();
Index: src/include/access/rmgr.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/access/rmgr.h,v
retrieving revision 1.19
diff -c -r1.19 rmgr.h
*** src/include/access/rmgr.h	19 Nov 2008 10:34:52 -0000	1.19
--- src/include/access/rmgr.h	17 Dec 2008 19:04:34 -0000
***************
*** 10,15 ****
--- 10,18 ----
  
  typedef uint8 RmgrId;
  
+ extern Size RmgrShmemSize(void);
+ extern void RmgrShmemInit(void);
+ 
  /*
   * Built-in resource managers
   *
***************
*** 23,28 ****
--- 26,33 ----
  #define RM_DBASE_ID				4
  #define RM_TBLSPC_ID			5
  #define RM_MULTIXACT_ID			6
+ /* RmgrId 7 is currently unused */
+ /* RmgrId 8 is currently unused */
  #define RM_HEAP2_ID				9
  #define RM_HEAP_ID				10
  #define RM_BTREE_ID				11
***************
*** 30,35 ****
  #define RM_GIN_ID				13
  #define RM_GIST_ID				14
  #define RM_SEQ_ID				15
! #define RM_MAX_ID				RM_SEQ_ID
  
  #endif   /* RMGR_H */
--- 35,49 ----
  #define RM_GIN_ID				13
  #define RM_GIST_ID				14
  #define RM_SEQ_ID				15
! #define RM_MAX_FIXED_ID			RM_SEQ_ID
! 
! /* 
!  * RmgrId Reservation
!  *
!  * RmgrIds up to 31 are reserved for PostgreSQL Core use only 
!  * RmgrIds between 32 and 127 are available for registration by
!  *		PostgreSQL-related projects
!  * RmgrIds of 128 and above are always designed for each site
!  */
  
  #endif   /* RMGR_H */
Index: src/include/access/xlog_internal.h
===================================================================
RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/access/xlog_internal.h,v
retrieving revision 1.24
diff -c -r1.24 xlog_internal.h
*** src/include/access/xlog_internal.h	11 Aug 2008 11:05:11 -0000	1.24
--- src/include/access/xlog_internal.h	17 Dec 2008 19:04:34 -0000
***************
*** 229,235 ****
   */
  typedef struct RmgrData
  {
! 	const char *rm_name;
  	void		(*rm_redo) (XLogRecPtr lsn, XLogRecord *rptr);
  	void		(*rm_desc) (StringInfo buf, uint8 xl_info, char *rec);
  	void		(*rm_startup) (void);
--- 229,235 ----
   */
  typedef struct RmgrData
  {
! 	char *rm_name;
  	void		(*rm_redo) (XLogRecPtr lsn, XLogRecord *rptr);
  	void		(*rm_desc) (StringInfo buf, uint8 xl_info, char *rec);
  	void		(*rm_startup) (void);
***************
*** 237,243 ****
  	bool		(*rm_safe_restartpoint) (void);
  } RmgrData;
  
! extern const RmgrData RmgrTable[];
  
  /*
   * Exported to support xlog switching from bgwriter
--- 237,254 ----
  	bool		(*rm_safe_restartpoint) (void);
  } RmgrData;
  
! typedef void (*rmgr_hook_type) (RmgrData *);
! extern PGDLLIMPORT rmgr_hook_type rmgr_hook;
! 
! extern void RmgrInitialize(void);
! extern void RmgrStartup(void);
! extern void RmgrCleanup(void);
! extern bool RmgrSafeRestartpoint(XLogRecPtr checkPointRedo);
! extern void RmgrRedo(XLogRecPtr lsn, XLogRecord *rptr);
! extern void RmgrDesc(StringInfo buf, XLogRecord *rptr, char *rec);
! extern void rm_redo_error_callback(void *arg);
! extern const char *RmgrName(RmgrId rmid);
! extern bool RmgrIdIsValid(RmgrId rmid);
  
  /*
   * Exported to support xlog switching from bgwriter

Attachment: rmgr_hook_contrib.v1.tar
Description: Unix tar archive

-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to