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 -0000 1.24 --- src/backend/access/transam/rmgr.c 27 Oct 2006 20:36:09 -0000 *************** *** 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 -0000 1.252 --- src/backend/access/transam/xlog.c 27 Oct 2006 20:36:19 -0000 *************** *** 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 -0000 1.249 --- src/backend/utils/cache/relcache.c 27 Oct 2006 20:36:24 -0000 *************** *** 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; + + if (info == XLOG_CACHE_INIT_FILE_INVAL) + { + xl_cache_init_file_inval *xlrec = (xl_cache_init_file_inval *) rec; + + appendStringInfo(buf, "cache: relcache init file invalidation; "); + appendStringInfo(buf, "database %u; tablespace %u", + (int) &xlrec->dbOid, (int) &xlrec->dbTableSpaceOid); + } + else + appendStringInfo(buf, "UNKNOWN"); } Index: src/include/access/rmgr.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/access/rmgr.h,v retrieving revision 1.16 diff -c -r1.16 rmgr.h *** src/include/access/rmgr.h 2 May 2006 11:28:55 -0000 1.16 --- src/include/access/rmgr.h 27 Oct 2006 20:36:25 -0000 *************** *** 20,25 **** --- 20,26 ---- #define RM_DBASE_ID 4 #define RM_TBLSPC_ID 5 #define RM_MULTIXACT_ID 6 + #define RM_CACHE_ID 7 #define RM_HEAP_ID 10 #define RM_BTREE_ID 11 #define RM_HASH_ID 12 Index: src/include/utils/relcache.h =================================================================== RCS file: /projects/cvsroot/pgsql/src/include/utils/relcache.h,v retrieving revision 1.55 diff -c -r1.55 relcache.h *** src/include/utils/relcache.h 31 Jul 2006 20:09:10 -0000 1.55 --- src/include/utils/relcache.h 27 Oct 2006 20:36:26 -0000 *************** *** 64,69 **** --- 64,84 ---- extern void AtEOSubXact_RelationCache(bool isCommit, SubTransactionId mySubid, SubTransactionId parentSubid); + /* + * xlog support for cache invalidation + */ + extern void cache_redo(XLogRecPtr lsn, XLogRecord *record); + extern void cache_desc(StringInfo buf, uint8 xl_info, char *rec); + + typedef struct xl_cache_init_file_inval + { + Oid dbOid; + Oid dbTableSpaceOid; + } xl_cache_init_file_inval; + + #define XLOG_CACHE_INIT_FILE_INVAL 0x00 + + /* * Routines to help manage rebuilding of relcache init file */
---------------------------(end of broadcast)--------------------------- TIP 5: don't forget to increase your free space map settings