Re: [PATCHES] Writing WAL for relcache invalidation: pg_internal.init

2006-11-01 Thread Tom Lane
Simon Riggs [EMAIL PROTECTED] writes:
 Enclose a patch for new WAL records for relcache invalidation.

I don't think this works.  RelationCacheInitFileInvalidate is executed
post-commit, which means that there's a window between commit and where
you propose to write the WAL entry.  A crash and restart in that
interval would leave the catalog changes committed, but not reflected
into pg_internal.init.

I think we're probably better off to just forcibly remove the init file
during post-recovery cleanup.  The easiest place to do this might be
BuildFlatFiles, which has to scan pg_database anyway ...

regards, tom lane

---(end of broadcast)---
TIP 1: if posting/reading through Usenet, please send an appropriate
   subscribe-nomail command to [EMAIL PROTECTED] so that your
   message can get through to the mailing list cleanly


[PATCHES] Writing WAL for relcache invalidation: pg_internal.init

2006-10-27 Thread Simon Riggs
Enclose a patch for new WAL records for relcache invalidation.

Not conclusively tested, but seems to work fine, so please regard this
as a prototype-needs-review.

We definitely need a regr test framework to support this type of patch.

-- 
  Simon Riggs 
  EnterpriseDB   http://www.enterprisedb.com

Index: src/backend/access/transam/rmgr.c
===
RCS file: /projects/cvsroot/pgsql/src/backend/access/transam/rmgr.c,v
retrieving revision 1.24
diff -c -r1.24 rmgr.c
*** src/backend/access/transam/rmgr.c	7 Aug 2006 16:57:56 -	1.24
--- src/backend/access/transam/rmgr.c	27 Oct 2006 20:36:09 -
***
*** 20,25 
--- 20,26 
  #include commands/sequence.h
  #include commands/tablespace.h
  #include storage/smgr.h
+ #include utils/relcache.h
  
  
  const RmgrData RmgrTable[RM_MAX_ID + 1] = {
***
*** 30,36 
  	{Database, dbase_redo, dbase_desc, NULL, NULL, NULL},
  	{Tablespace, tblspc_redo, tblspc_desc, NULL, NULL, NULL},
  	{MultiXact, multixact_redo, multixact_desc, NULL, NULL, NULL},
! 	{Reserved 7, NULL, NULL, NULL, NULL, NULL},
  	{Reserved 8, NULL, NULL, NULL, NULL, NULL},
  	{Reserved 9, NULL, NULL, NULL, NULL, NULL},
  	{Heap, heap_redo, heap_desc, NULL, NULL, NULL},
--- 31,37 
  	{Database, dbase_redo, dbase_desc, NULL, NULL, NULL},
  	{Tablespace, tblspc_redo, tblspc_desc, NULL, NULL, NULL},
  	{MultiXact, multixact_redo, multixact_desc, NULL, NULL, NULL},
! 	{Cache, cache_redo, cache_desc, NULL, NULL, NULL},
  	{Reserved 8, NULL, NULL, NULL, NULL, NULL},
  	{Reserved 9, NULL, NULL, NULL, NULL, NULL},
  	{Heap, heap_redo, heap_desc, NULL, NULL, NULL},
Index: src/backend/access/transam/xlog.c
===
RCS file: /projects/cvsroot/pgsql/src/backend/access/transam/xlog.c,v
retrieving revision 1.252
diff -c -r1.252 xlog.c
*** src/backend/access/transam/xlog.c	18 Oct 2006 22:44:11 -	1.252
--- src/backend/access/transam/xlog.c	27 Oct 2006 20:36:19 -
***
*** 46,51 
--- 46,52 
  #include utils/builtins.h
  #include utils/nabstime.h
  #include utils/pg_locale.h
+ #include utils/relcache.h
  
  
  /*
Index: src/backend/utils/cache/relcache.c
===
RCS file: /projects/cvsroot/pgsql/src/backend/utils/cache/relcache.c,v
retrieving revision 1.249
diff -c -r1.249 relcache.c
*** src/backend/utils/cache/relcache.c	4 Oct 2006 00:30:00 -	1.249
--- src/backend/utils/cache/relcache.c	27 Oct 2006 20:36:24 -
***
*** 3568,3575 
  
  	if (beforeSend)
  	{
  		/* no interlock needed here */
! 		unlink(initfilename);
  	}
  	else
  	{
--- 3568,3599 
  
  	if (beforeSend)
  	{
+ 		/*
+ 		 * Make a non-transactional XLOG entry showing the file removal
+ 		 * It's non-transactional because we should replay it whether the
+ 		 * transaction commits or not; the underlying file change is certainly
+ 		 * not reversible. We do this *once* because we don't need to process
+  * invalidation messages during WAL reply, so even though the file
+  * is unlinked twice during normal invalidation sequence we need only
+  * do this once during WAL replay and so need only write WAL once.
+ 		 */
+ 		XLogRecPtr	lsn;
+ 		XLogRecData rdata;
+ 		xl_cache_init_file_inval xlrec;
+ 
+ xlrec.dbOid = MyDatabaseId;
+ xlrec.dbTableSpaceOid = MyDatabaseTableSpace;
+ 
+ 		rdata.data = (char *) xlrec;
+ 		rdata.len = sizeof(xlrec);
+ 		rdata.buffer = InvalidBuffer;
+ 		rdata.next = NULL;
+ 
+ 		lsn = XLogInsert(RM_CACHE_ID, XLOG_CACHE_INIT_FILE_INVAL | XLOG_NO_TRAN,
+ 		 rdata);
+ 
  		/* no interlock needed here */
! unlink(initfilename);
  	}
  	else
  	{
***
*** 3582,3588 
  		 * that we will execute second and successfully unlink the file.
  		 */
  		LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
! 		unlink(initfilename);
  		LWLockRelease(RelCacheInitLock);
  	}
  }
--- 3606,3651 
  		 * that we will execute second and successfully unlink the file.
  		 */
  		LWLockAcquire(RelCacheInitLock, LW_EXCLUSIVE);
! unlink(initfilename);
  		LWLockRelease(RelCacheInitLock);
  	}
+
+ }
+ 
+ void
+ cache_redo(XLogRecPtr lsn, XLogRecord *record)
+ {
+ 	uint8		info = record-xl_info  ~XLR_INFO_MASK;
+ 
+ if (info == XLOG_CACHE_INIT_FILE_INVAL)
+ {
+ 		xl_cache_init_file_inval *xlrec = (xl_cache_init_file_inval *) XLogRecGetData(record);
+ 		char *dbpath = GetDatabasePath((int) xlrec-dbOid, (int) xlrec-dbTableSpaceOid);
+ 	char initfilename[MAXPGPATH];
+ 
+ 	snprintf(initfilename, sizeof(initfilename), %s/%s,
+ 			 dbpath, RELCACHE_INIT_FILENAME);
+ 
+ unlink(initfilename);
+ 		pfree(dbpath);
+ }
+ 	else
+ 		elog(PANIC, cache_redo: unknown op code %u, info);
+ }
+ 
+ void
+ cache_desc(StringInfo buf, uint8 xl_info, char *rec)
+ {
+ 	uint8		info = xl_info  ~XLR_INFO_MASK;
+