I attach a small patch that slightly refactors some code in
storage/smgr/smgr.c. Regression test pass. There's no change in
functionality, only code reordering. (Well, it changes an ad-hoc linked
list into a proper List).
Please review and if Ok, apply.
--
Alvaro Herrera (<alvherre[a]dcc.uchile.cl>)
"At least to kernel hackers, who really are human, despite occasional
rumors to the contrary" (LWN.net)
diff -cr --exclude=CVS 01trivial/src/backend/access/transam/xact.c
02smgr/src/backend/access/transam/xact.c
*** 01trivial/src/backend/access/transam/xact.c 2004-01-15 23:34:42.000000000 -0300
--- 02smgr/src/backend/access/transam/xact.c 2004-01-19 19:37:54.000000000 -0300
***************
*** 865,870 ****
--- 865,875 ----
DeferredTriggerBeginXact();
/*
+ * Initialize the smgr subsystem
+ */
+ PendingDeletesBeginXact();
+
+ /*
* done with start processing, set current transaction state to "in
* progress"
*/
diff -cr --exclude=CVS 01trivial/src/backend/storage/smgr/smgr.c
02smgr/src/backend/storage/smgr/smgr.c
*** 01trivial/src/backend/storage/smgr/smgr.c 2004-01-15 23:33:55.000000000 -0300
--- 02smgr/src/backend/storage/smgr/smgr.c 2004-01-19 19:37:54.000000000 -0300
***************
*** 97,105 ****
* executed immediately, but is just entered in the list. When and if
* the transaction commits, we can delete the physical file.
*
! * NOTE: the list is kept in TopMemoryContext to be sure it won't disappear
! * unbetimes. It'd probably be OK to keep it in TopTransactionContext,
! * but I'm being paranoid.
*/
typedef struct PendingRelDelete
--- 97,104 ----
* executed immediately, but is just entered in the list. When and if
* the transaction commits, we can delete the physical file.
*
! * NOTE: the list is kept in TopTransactionContext, so the items will
! * automatically disappear when the transaction ends.
*/
typedef struct PendingRelDelete
***************
*** 108,118 ****
int16 which; /* which storage manager? */
bool isTemp; /* is it a temporary relation? */
bool atCommit; /* T=delete at commit; F=delete at
abort */
- struct PendingRelDelete *next; /* linked-list link */
} PendingRelDelete;
! static PendingRelDelete *pendingDeletes = NULL; /* head of linked list */
/*
* smgrinit(), smgrshutdown() -- Initialize or shut down all storage
--- 107,118 ----
int16 which; /* which storage manager? */
bool isTemp; /* is it a temporary relation? */
bool atCommit; /* T=delete at commit; F=delete at
abort */
} PendingRelDelete;
! static List *pendingDeletes;
+ static void smgrDeleteItem(PendingRelDelete *pending);
+ static void addPendingDelete(int16 which, Relation reln, bool atCommit);
/*
* smgrinit(), smgrshutdown() -- Initialize or shut down all storage
***************
*** 168,174 ****
smgrcreate(int16 which, Relation reln)
{
int fd;
- PendingRelDelete *pending;
if ((fd = (*(smgrsw[which].smgr_create)) (reln)) < 0)
ereport(ERROR,
--- 168,173 ----
***************
*** 177,190 ****
RelationGetRelationName(reln))));
/* Add the relation to the list of stuff to delete at abort */
! pending = (PendingRelDelete *)
! MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
! pending->relnode = reln->rd_node;
! pending->which = which;
! pending->isTemp = reln->rd_istemp;
! pending->atCommit = false; /* delete if abort */
! pending->next = pendingDeletes;
! pendingDeletes = pending;
return fd;
}
--- 176,182 ----
RelationGetRelationName(reln))));
/* Add the relation to the list of stuff to delete at abort */
! addPendingDelete(which, reln, false);
return fd;
}
***************
*** 198,218 ****
int
smgrunlink(int16 which, Relation reln)
{
- PendingRelDelete *pending;
/* Make sure the file is closed */
if (reln->rd_fd >= 0)
smgrclose(which, reln);
/* Add the relation to the list of stuff to delete at commit */
! pending = (PendingRelDelete *)
! MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
! pending->relnode = reln->rd_node;
! pending->which = which;
! pending->isTemp = reln->rd_istemp;
! pending->atCommit = true; /* delete if commit */
! pending->next = pendingDeletes;
! pendingDeletes = pending;
/*
* NOTE: if the relation was created in this transaction, it will now
--- 190,202 ----
int
smgrunlink(int16 which, Relation reln)
{
/* Make sure the file is closed */
if (reln->rd_fd >= 0)
smgrclose(which, reln);
/* Add the relation to the list of stuff to delete at commit */
! addPendingDelete(which, reln, true);
/*
* NOTE: if the relation was created in this transaction, it will now
***************
*** 444,496 ****
}
/*
* smgrDoPendingDeletes() -- Take care of relation deletes at end of xact.
*/
int
smgrDoPendingDeletes(bool isCommit)
{
! while (pendingDeletes != NULL)
{
! PendingRelDelete *pending = pendingDeletes;
- pendingDeletes = pending->next;
if (pending->atCommit == isCommit)
! {
! /*
! * Get rid of any leftover buffers for the rel (shouldn't be
! * any in the commit case, but there can be in the abort
! * case).
! */
! DropRelFileNodeBuffers(pending->relnode, pending->isTemp);
!
! /*
! * Tell the free space map to forget this relation. It won't
! * be accessed any more anyway, but we may as well recycle the
! * map space quickly.
! */
! FreeSpaceMapForgetRel(&pending->relnode);
!
! /*
! * And delete the physical files.
! *
! * Note: we treat deletion failure as a WARNING, not an error,
! * because we've already decided to commit or abort the
! * current xact.
! */
! if ((*(smgrsw[pending->which].smgr_unlink)) (pending->relnode)
== SM_FAIL)
! ereport(WARNING,
! (errcode_for_file_access(),
! errmsg("could not unlink %u/%u: %m",
!
pending->relnode.tblNode,
!
pending->relnode.relNode)));
! }
! pfree(pending);
}
return SM_SUCCESS;
}
/*
* smgrcommit() -- Prepare to commit changes made during the current
* transaction.
*
--- 428,519 ----
}
/*
+ * Add a relation to delete at transaction end.
+ */
+ void
+ addPendingDelete(int16 which, Relation reln, bool atCommit)
+ {
+ MemoryContext old_cxt = MemoryContextSwitchTo(TopTransactionContext);
+ PendingRelDelete *pending = (PendingRelDelete *)
palloc(sizeof(PendingRelDelete));
+
+ pending->relnode = reln->rd_node;
+ pending->which = which;
+ pending->isTemp = reln->rd_istemp;
+ pending->atCommit = atCommit;
+ pendingDeletes = lcons(pending, pendingDeletes);
+
+ MemoryContextSwitchTo(old_cxt);
+ }
+
+ /*
+ * Delete a pending relation.
+ */
+ void
+ smgrDeleteItem(PendingRelDelete *pending)
+ {
+ /*
+ * Get rid of any leftover buffers for the rel (shouldn't be
+ * any in the commit case, but there can be in the abort
+ * case).
+ */
+ DropRelFileNodeBuffers(pending->relnode, pending->isTemp);
+
+ /*
+ * Tell the free space map to forget this relation. It won't
+ * be accessed any more anyway, but we may as well recycle the
+ * map space quickly.
+ */
+ FreeSpaceMapForgetRel(&pending->relnode);
+
+ /*
+ * And delete the physical files.
+ *
+ * Note: we treat deletion failure as a WARNING, not an error,
+ * because we've already decided to commit or abort the
+ * current xact.
+ */
+ if ((*(smgrsw[pending->which].smgr_unlink)) (pending->relnode) == SM_FAIL)
+ ereport(WARNING,
+ (errcode_for_file_access(),
+ errmsg("could not unlink %u/%u: %m",
+ pending->relnode.tblNode,
+ pending->relnode.relNode)));
+ }
+
+ /*
* smgrDoPendingDeletes() -- Take care of relation deletes at end of xact.
*/
int
smgrDoPendingDeletes(bool isCommit)
{
! List *p;
! foreach (p, pendingDeletes)
{
! PendingRelDelete *pending = (PendingRelDelete *)lfirst(p);
if (pending->atCommit == isCommit)
! smgrDeleteItem(pending);
!
! /*
! * The structs will be freed at the end of the transaction,
! * no need to free them individually.
! */
}
+ pendingDeletes = NIL;
return SM_SUCCESS;
}
/*
+ * Initializes the smgr pending deletes queue.
+ */
+ void
+ PendingDeletesBeginXact(void)
+ {
+ pendingDeletes = NIL;
+ }
+
+ /*
* smgrcommit() -- Prepare to commit changes made during the current
* transaction.
*
diff -cr --exclude=CVS 01trivial/src/include/storage/smgr.h
02smgr/src/include/storage/smgr.h
*** 01trivial/src/include/storage/smgr.h 2004-01-15 23:34:12.000000000 -0300
--- 02smgr/src/include/storage/smgr.h 2004-01-19 19:37:54.000000000 -0300
***************
*** 43,48 ****
--- 43,50 ----
extern BlockNumber smgrtruncate(int16 which, Relation reln,
BlockNumber nblocks);
extern int smgrDoPendingDeletes(bool isCommit);
+ extern void PendingDeletesBeginXact(void);
+
extern int smgrcommit(void);
extern int smgrabort(void);
extern int smgrsync(void);
---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to [EMAIL PROTECTED])