Commit 89347900 authored by Tom Lane's avatar Tom Lane

Add a mechanism to let dynamically loaded modules register post-commit/

post-abort cleanup hooks.  I'm surprised that we have not needed this
already, but I need it now to fix a plpgsql problem, and the usefulness
for other dynamically loaded modules seems obvious.
parent a15207f8
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.154 2003/09/25 06:57:57 petere Exp $ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.155 2003/09/28 23:26:20 tgl Exp $
* *
* NOTES * NOTES
* Transaction aborts can now occur two ways: * Transaction aborts can now occur two ways:
...@@ -183,6 +183,7 @@ static void AtCommit_Memory(void); ...@@ -183,6 +183,7 @@ static void AtCommit_Memory(void);
static void AtStart_Cache(void); static void AtStart_Cache(void);
static void AtStart_Locks(void); static void AtStart_Locks(void);
static void AtStart_Memory(void); static void AtStart_Memory(void);
static void CallEOXactCallbacks(bool isCommit);
static void CleanupTransaction(void); static void CleanupTransaction(void);
static void CommitTransaction(void); static void CommitTransaction(void);
static void RecordTransactionAbort(void); static void RecordTransactionAbort(void);
...@@ -217,6 +218,18 @@ int CommitSiblings = 5; /* number of concurrent xacts needed to ...@@ -217,6 +218,18 @@ int CommitSiblings = 5; /* number of concurrent xacts needed to
* sleep */ * sleep */
/*
* List of add-on end-of-xact callbacks
*/
typedef struct EOXactCallbackItem
{
struct EOXactCallbackItem *next;
EOXactCallback callback;
void *arg;
} EOXactCallbackItem;
static EOXactCallbackItem *EOXact_callbacks = NULL;
static void (*_RollbackFunc) (void *) = NULL; static void (*_RollbackFunc) (void *) = NULL;
static void *_RollbackData = NULL; static void *_RollbackData = NULL;
...@@ -964,6 +977,7 @@ CommitTransaction(void) ...@@ -964,6 +977,7 @@ CommitTransaction(void)
AtCommit_Locks(); AtCommit_Locks();
CallEOXactCallbacks(true);
AtEOXact_GUC(true); AtEOXact_GUC(true);
AtEOXact_SPI(); AtEOXact_SPI();
AtEOXact_gist(); AtEOXact_gist();
...@@ -1073,6 +1087,7 @@ AbortTransaction(void) ...@@ -1073,6 +1087,7 @@ AbortTransaction(void)
AtAbort_Locks(); AtAbort_Locks();
CallEOXactCallbacks(false);
AtEOXact_GUC(false); AtEOXact_GUC(false);
AtEOXact_SPI(); AtEOXact_SPI();
AtEOXact_gist(); AtEOXact_gist();
...@@ -1430,6 +1445,62 @@ RequireTransactionChain(void *stmtNode, const char *stmtType) ...@@ -1430,6 +1445,62 @@ RequireTransactionChain(void *stmtNode, const char *stmtType)
} }
/*
* Register or deregister callback functions for end-of-xact cleanup
*
* These functions are intended for use by dynamically loaded modules.
* For built-in modules we generally just hardwire the appropriate calls
* (mainly because it's easier to control the order that way, where needed).
*
* Note that the callback occurs post-commit or post-abort, so the callback
* functions can only do noncritical cleanup.
*/
void
RegisterEOXactCallback(EOXactCallback callback, void *arg)
{
EOXactCallbackItem *item;
item = (EOXactCallbackItem *)
MemoryContextAlloc(TopMemoryContext, sizeof(EOXactCallbackItem));
item->callback = callback;
item->arg = arg;
item->next = EOXact_callbacks;
EOXact_callbacks = item;
}
void
UnregisterEOXactCallback(EOXactCallback callback, void *arg)
{
EOXactCallbackItem *item;
EOXactCallbackItem *prev;
prev = NULL;
for (item = EOXact_callbacks; item; prev = item, item = item->next)
{
if (item->callback == callback && item->arg == arg)
{
if (prev)
prev->next = item->next;
else
EOXact_callbacks = item->next;
pfree(item);
break;
}
}
}
static void
CallEOXactCallbacks(bool isCommit)
{
EOXactCallbackItem *item;
for (item = EOXact_callbacks; item; item = item->next)
{
(*item->callback) (isCommit, item->arg);
}
}
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* transaction block support * transaction block support
* ---------------------------------------------------------------- * ----------------------------------------------------------------
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: xact.h,v 1.55 2003/08/08 21:42:32 momjian Exp $ * $Id: xact.h,v 1.56 2003/09/28 23:26:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -59,9 +59,13 @@ typedef enum TBlockState ...@@ -59,9 +59,13 @@ typedef enum TBlockState
TBLOCK_ENDABORT TBLOCK_ENDABORT
} TBlockState; } TBlockState;
/* ---------------- /*
* end-of-transaction cleanup callbacks for dynamically loaded modules
*/
typedef void (*EOXactCallback) (bool isCommit, void *arg);
/*
* transaction state structure * transaction state structure
* ----------------
*/ */
typedef struct TransactionStateData typedef struct TransactionStateData
{ {
...@@ -130,6 +134,8 @@ extern void UserAbortTransactionBlock(void); ...@@ -130,6 +134,8 @@ extern void UserAbortTransactionBlock(void);
extern void AbortOutOfAnyTransaction(void); extern void AbortOutOfAnyTransaction(void);
extern void PreventTransactionChain(void *stmtNode, const char *stmtType); extern void PreventTransactionChain(void *stmtNode, const char *stmtType);
extern void RequireTransactionChain(void *stmtNode, const char *stmtType); extern void RequireTransactionChain(void *stmtNode, const char *stmtType);
extern void RegisterEOXactCallback(EOXactCallback callback, void *arg);
extern void UnregisterEOXactCallback(EOXactCallback callback, void *arg);
extern void RecordTransactionCommit(void); extern void RecordTransactionCommit(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment