Reduce amount of memory used per tuple for after-event triggers. This
is still a memory leak, but a little less bad than it was.
This commit is contained in:
parent
c9f26d7af6
commit
7fdaf78ed0
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.87 2001/03/12 23:02:00 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.88 2001/03/14 21:50:32 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1153,15 +1153,18 @@ static List *deftrig_trigstates;
|
|||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* The list of events during the entire transaction. deftrig_events
|
* The list of events during the entire transaction. deftrig_events
|
||||||
* is the head, deftrig_event_tail is the last entry.
|
* is the head, deftrig_event_tail is the last entry. Because this can
|
||||||
|
* grow pretty large, we don't use separate List nodes, but instead thread
|
||||||
|
* the list through the dte_next fields of the member nodes. Saves just a
|
||||||
|
* few bytes per entry, but that adds up.
|
||||||
*
|
*
|
||||||
* XXX Need to be able to shove this data out to a file if it grows too
|
* XXX Need to be able to shove this data out to a file if it grows too
|
||||||
* large...
|
* large...
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
static int deftrig_n_events;
|
static int deftrig_n_events;
|
||||||
static List *deftrig_events;
|
static DeferredTriggerEvent deftrig_events;
|
||||||
static List *deftrig_event_tail;
|
static DeferredTriggerEvent deftrig_event_tail;
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
@ -1242,16 +1245,17 @@ deferredTriggerAddEvent(DeferredTriggerEvent event)
|
|||||||
* list tail and append there, rather than just doing a stupid "lappend".
|
* list tail and append there, rather than just doing a stupid "lappend".
|
||||||
* This avoids O(N^2) behavior for large numbers of events.
|
* This avoids O(N^2) behavior for large numbers of events.
|
||||||
*/
|
*/
|
||||||
if (deftrig_event_tail == NIL)
|
event->dte_next = NULL;
|
||||||
|
if (deftrig_event_tail == NULL)
|
||||||
{
|
{
|
||||||
/* first list entry */
|
/* first list entry */
|
||||||
deftrig_events = makeList1(event);
|
deftrig_events = event;
|
||||||
deftrig_event_tail = deftrig_events;
|
deftrig_event_tail = event;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
lnext(deftrig_event_tail) = makeList1(event);
|
deftrig_event_tail->dte_next = event;
|
||||||
deftrig_event_tail = lnext(deftrig_event_tail);
|
deftrig_event_tail = event;
|
||||||
}
|
}
|
||||||
deftrig_n_events++;
|
deftrig_n_events++;
|
||||||
}
|
}
|
||||||
@ -1268,13 +1272,11 @@ static DeferredTriggerEvent
|
|||||||
deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
|
deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
|
||||||
{
|
{
|
||||||
DeferredTriggerEvent previous = NULL;
|
DeferredTriggerEvent previous = NULL;
|
||||||
List *dtev;
|
DeferredTriggerEvent prev;
|
||||||
|
|
||||||
/* Search the list to find the last event affecting this tuple */
|
/* Search the list to find the last event affecting this tuple */
|
||||||
foreach(dtev, deftrig_events)
|
for (prev = deftrig_events; prev != NULL; prev = prev->dte_next)
|
||||||
{
|
{
|
||||||
DeferredTriggerEvent prev = (DeferredTriggerEvent) lfirst(dtev);
|
|
||||||
|
|
||||||
if (prev->dte_relid != relid)
|
if (prev->dte_relid != relid)
|
||||||
continue;
|
continue;
|
||||||
if (prev->dte_event & TRIGGER_DEFERRED_CANCELED)
|
if (prev->dte_event & TRIGGER_DEFERRED_CANCELED)
|
||||||
@ -1411,7 +1413,6 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno,
|
|||||||
static void
|
static void
|
||||||
deferredTriggerInvokeEvents(bool immediate_only)
|
deferredTriggerInvokeEvents(bool immediate_only)
|
||||||
{
|
{
|
||||||
List *el;
|
|
||||||
DeferredTriggerEvent event;
|
DeferredTriggerEvent event;
|
||||||
int still_deferred_ones;
|
int still_deferred_ones;
|
||||||
int i;
|
int i;
|
||||||
@ -1435,19 +1436,18 @@ deferredTriggerInvokeEvents(bool immediate_only)
|
|||||||
ALLOCSET_DEFAULT_INITSIZE,
|
ALLOCSET_DEFAULT_INITSIZE,
|
||||||
ALLOCSET_DEFAULT_MAXSIZE);
|
ALLOCSET_DEFAULT_MAXSIZE);
|
||||||
|
|
||||||
foreach(el, deftrig_events)
|
for (event = deftrig_events; event != NULL; event = event->dte_next)
|
||||||
{
|
{
|
||||||
MemoryContextReset(per_tuple_context);
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Get the event and check if it is completely done.
|
* Check if event is completely done.
|
||||||
* ----------
|
* ----------
|
||||||
*/
|
*/
|
||||||
event = (DeferredTriggerEvent) lfirst(el);
|
|
||||||
if (event->dte_event & (TRIGGER_DEFERRED_DONE |
|
if (event->dte_event & (TRIGGER_DEFERRED_DONE |
|
||||||
TRIGGER_DEFERRED_CANCELED))
|
TRIGGER_DEFERRED_CANCELED))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
MemoryContextReset(per_tuple_context);
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* Check each trigger item in the event.
|
* Check each trigger item in the event.
|
||||||
* ----------
|
* ----------
|
||||||
@ -1561,8 +1561,8 @@ DeferredTriggerBeginXact(void)
|
|||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
deftrig_n_events = 0;
|
deftrig_n_events = 0;
|
||||||
deftrig_events = NIL;
|
deftrig_events = NULL;
|
||||||
deftrig_event_tail = NIL;
|
deftrig_event_tail = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1957,16 +1957,16 @@ DeferredTriggerSaveEvent(Relation rel, int event,
|
|||||||
|
|
||||||
ntriggers = rel->trigdesc->n_after_row[event];
|
ntriggers = rel->trigdesc->n_after_row[event];
|
||||||
triggers = rel->trigdesc->tg_after_row[event];
|
triggers = rel->trigdesc->tg_after_row[event];
|
||||||
new_size = sizeof(DeferredTriggerEventData) +
|
new_size = offsetof(DeferredTriggerEventData, dte_item[0]) +
|
||||||
ntriggers * sizeof(DeferredTriggerEventItem);
|
ntriggers * sizeof(DeferredTriggerEventItem);
|
||||||
|
|
||||||
new_event = (DeferredTriggerEvent) palloc(new_size);
|
new_event = (DeferredTriggerEvent) palloc(new_size);
|
||||||
|
new_event->dte_next = NULL;
|
||||||
new_event->dte_event = event & TRIGGER_EVENT_OPMASK;
|
new_event->dte_event = event & TRIGGER_EVENT_OPMASK;
|
||||||
new_event->dte_relid = rel->rd_id;
|
new_event->dte_relid = rel->rd_id;
|
||||||
ItemPointerCopy(&oldctid, &(new_event->dte_oldctid));
|
ItemPointerCopy(&oldctid, &(new_event->dte_oldctid));
|
||||||
ItemPointerCopy(&newctid, &(new_event->dte_newctid));
|
ItemPointerCopy(&newctid, &(new_event->dte_newctid));
|
||||||
new_event->dte_n_items = ntriggers;
|
new_event->dte_n_items = ntriggers;
|
||||||
new_event->dte_item[ntriggers].dti_state = new_size;
|
|
||||||
for (i = 0; i < ntriggers; i++)
|
for (i = 0; i < ntriggers; i++)
|
||||||
{
|
{
|
||||||
new_event->dte_item[i].dti_tgoid = triggers[i]->tgoid;
|
new_event->dte_item[i].dti_tgoid = triggers[i]->tgoid;
|
||||||
@ -1978,6 +1978,7 @@ DeferredTriggerSaveEvent(Relation rel, int event,
|
|||||||
((rel->trigdesc->n_before_row[event] > 0) ?
|
((rel->trigdesc->n_before_row[event] > 0) ?
|
||||||
TRIGGER_DEFERRED_HAS_BEFORE : 0);
|
TRIGGER_DEFERRED_HAS_BEFORE : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
switch (event & TRIGGER_EVENT_OPMASK)
|
switch (event & TRIGGER_EVENT_OPMASK)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2001, 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: trigger.h,v 1.24 2001/01/24 19:43:23 momjian Exp $
|
* $Id: trigger.h,v 1.25 2001/03/14 21:50:32 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -110,6 +110,7 @@ typedef struct DeferredTriggerStatusData
|
|||||||
Oid dts_tgoid;
|
Oid dts_tgoid;
|
||||||
bool dts_tgisdeferred;
|
bool dts_tgisdeferred;
|
||||||
} DeferredTriggerStatusData;
|
} DeferredTriggerStatusData;
|
||||||
|
|
||||||
typedef struct DeferredTriggerStatusData *DeferredTriggerStatus;
|
typedef struct DeferredTriggerStatusData *DeferredTriggerStatus;
|
||||||
|
|
||||||
|
|
||||||
@ -120,16 +121,19 @@ typedef struct DeferredTriggerEventItem
|
|||||||
} DeferredTriggerEventItem;
|
} DeferredTriggerEventItem;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct DeferredTriggerEventData *DeferredTriggerEvent;
|
||||||
|
|
||||||
typedef struct DeferredTriggerEventData
|
typedef struct DeferredTriggerEventData
|
||||||
{
|
{
|
||||||
|
DeferredTriggerEvent dte_next; /* list link */
|
||||||
int32 dte_event;
|
int32 dte_event;
|
||||||
Oid dte_relid;
|
Oid dte_relid;
|
||||||
ItemPointerData dte_oldctid;
|
ItemPointerData dte_oldctid;
|
||||||
ItemPointerData dte_newctid;
|
ItemPointerData dte_newctid;
|
||||||
int32 dte_n_items;
|
int32 dte_n_items;
|
||||||
|
/* dte_item is actually a variable-size array, of length dte_n_items */
|
||||||
DeferredTriggerEventItem dte_item[1];
|
DeferredTriggerEventItem dte_item[1];
|
||||||
} DeferredTriggerEventData;
|
} DeferredTriggerEventData;
|
||||||
typedef struct DeferredTriggerEventData *DeferredTriggerEvent;
|
|
||||||
|
|
||||||
|
|
||||||
extern void DeferredTriggerInit(void);
|
extern void DeferredTriggerInit(void);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user