summaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/inval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/inval.c')
-rw-r--r--src/backend/utils/cache/inval.c101
1 files changed, 100 insertions, 1 deletions
diff --git a/src/backend/utils/cache/inval.c b/src/backend/utils/cache/inval.c
index 61b7522f8c9..da0ffad16b2 100644
--- a/src/backend/utils/cache/inval.c
+++ b/src/backend/utils/cache/inval.c
@@ -80,12 +80,13 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.71 2005/04/14 01:38:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/cache/inval.c,v 1.72 2005/06/17 22:32:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "access/twophase_rmgr.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "miscadmin.h"
@@ -171,6 +172,13 @@ static struct CACHECALLBACK
static int cache_callback_count = 0;
+/* info values for 2PC callback */
+#define TWOPHASE_INFO_MSG 0 /* SharedInvalidationMessage */
+#define TWOPHASE_INFO_FILE_BEFORE 1 /* relcache file inval */
+#define TWOPHASE_INFO_FILE_AFTER 2 /* relcache file inval */
+
+static void PersistInvalidationMessage(SharedInvalidationMessage *msg);
+
/* ----------------------------------------------------------------
* Invalidation list support functions
@@ -637,6 +645,56 @@ AtStart_Inval(void)
}
/*
+ * AtPrepare_Inval
+ * Save the inval lists state at 2PC transaction prepare.
+ *
+ * In this phase we just generate 2PC records for all the pending invalidation
+ * work.
+ */
+void
+AtPrepare_Inval(void)
+{
+ /* Must be at top of stack */
+ Assert(transInvalInfo != NULL && transInvalInfo->parent == NULL);
+
+ /*
+ * Relcache init file invalidation requires processing both before
+ * and after we send the SI messages.
+ */
+ if (transInvalInfo->RelcacheInitFileInval)
+ RegisterTwoPhaseRecord(TWOPHASE_RM_INVAL_ID, TWOPHASE_INFO_FILE_BEFORE,
+ NULL, 0);
+
+ AppendInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs,
+ &transInvalInfo->CurrentCmdInvalidMsgs);
+
+ ProcessInvalidationMessages(&transInvalInfo->PriorCmdInvalidMsgs,
+ PersistInvalidationMessage);
+
+ if (transInvalInfo->RelcacheInitFileInval)
+ RegisterTwoPhaseRecord(TWOPHASE_RM_INVAL_ID, TWOPHASE_INFO_FILE_AFTER,
+ NULL, 0);
+}
+
+/*
+ * PostPrepare_Inval
+ * Clean up after successful PREPARE.
+ *
+ * Here, we want to act as though the transaction aborted, so that we will
+ * undo any syscache changes it made, thereby bringing us into sync with the
+ * outside world, which doesn't believe the transaction committed yet.
+ *
+ * If the prepared transaction is later aborted, there is nothing more to
+ * do; if it commits, we will receive the consequent inval messages just
+ * like everyone else.
+ */
+void
+PostPrepare_Inval(void)
+{
+ AtEOXact_Inval(false);
+}
+
+/*
* AtSubStart_Inval
* Initialize inval lists at start of a subtransaction.
*/
@@ -655,6 +713,47 @@ AtSubStart_Inval(void)
}
/*
+ * PersistInvalidationMessage
+ * Write an invalidation message to the 2PC state file.
+ */
+static void
+PersistInvalidationMessage(SharedInvalidationMessage *msg)
+{
+ RegisterTwoPhaseRecord(TWOPHASE_RM_INVAL_ID, TWOPHASE_INFO_MSG,
+ msg, sizeof(SharedInvalidationMessage));
+}
+
+/*
+ * inval_twophase_postcommit
+ * Process an invalidation message from the 2PC state file.
+ */
+void
+inval_twophase_postcommit(TransactionId xid, uint16 info,
+ void *recdata, uint32 len)
+{
+ SharedInvalidationMessage *msg;
+
+ switch (info)
+ {
+ case TWOPHASE_INFO_MSG:
+ msg = (SharedInvalidationMessage *) recdata;
+ Assert(len == sizeof(SharedInvalidationMessage));
+ SendSharedInvalidMessage(msg);
+ break;
+ case TWOPHASE_INFO_FILE_BEFORE:
+ RelationCacheInitFileInvalidate(true);
+ break;
+ case TWOPHASE_INFO_FILE_AFTER:
+ RelationCacheInitFileInvalidate(false);
+ break;
+ default:
+ Assert(false);
+ break;
+ }
+}
+
+
+/*
* AtEOXact_Inval
* Process queued-up invalidation messages at end of main transaction.
*