Reduce amount of memory used per tuple for after-event triggers. This
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 14 Mar 2001 21:50:32 +0000 (21:50 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 14 Mar 2001 21:50:32 +0000 (21:50 +0000)
is still a memory leak, but a little less bad than it was.

src/backend/commands/trigger.c
src/include/commands/trigger.h

index 7a013c076bdcfa0c5ca405c25756ae609f263dbd..4a6ddef9283484b49f7c85b9bcbee66a04613b80 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * 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
- * 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
  *    large...
  * ----------
  */
 static int deftrig_n_events;
-static List *deftrig_events;
-static List *deftrig_event_tail;
+static DeferredTriggerEvent deftrig_events;
+static DeferredTriggerEvent deftrig_event_tail;
 
 
 /* ----------
@@ -1242,16 +1245,17 @@ deferredTriggerAddEvent(DeferredTriggerEvent event)
     * list tail and append there, rather than just doing a stupid "lappend".
     * 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 */
-       deftrig_events = makeList1(event);
-       deftrig_event_tail = deftrig_events;
+       deftrig_events = event;
+       deftrig_event_tail = event;
    }
    else
    {
-       lnext(deftrig_event_tail) = makeList1(event);
-       deftrig_event_tail = lnext(deftrig_event_tail);
+       deftrig_event_tail->dte_next = event;
+       deftrig_event_tail = event;
    }
    deftrig_n_events++;
 }
@@ -1268,13 +1272,11 @@ static DeferredTriggerEvent
 deferredTriggerGetPreviousEvent(Oid relid, ItemPointer ctid)
 {
    DeferredTriggerEvent previous = NULL;
-   List   *dtev;
+   DeferredTriggerEvent prev;
 
    /* 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)
            continue;
        if (prev->dte_event & TRIGGER_DEFERRED_CANCELED)
@@ -1411,7 +1413,6 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno,
 static void
 deferredTriggerInvokeEvents(bool immediate_only)
 {
-   List       *el;
    DeferredTriggerEvent event;
    int         still_deferred_ones;
    int         i;
@@ -1435,19 +1436,18 @@ deferredTriggerInvokeEvents(bool immediate_only)
                              ALLOCSET_DEFAULT_INITSIZE,
                              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 |
                                TRIGGER_DEFERRED_CANCELED))
            continue;
 
+       MemoryContextReset(per_tuple_context);
+
        /* ----------
         * Check each trigger item in the event.
         * ----------
@@ -1561,8 +1561,8 @@ DeferredTriggerBeginXact(void)
    MemoryContextSwitchTo(oldcxt);
 
    deftrig_n_events = 0;
-   deftrig_events = NIL;
-   deftrig_event_tail = NIL;
+   deftrig_events = NULL;
+   deftrig_event_tail = NULL;
 }
 
 
@@ -1957,16 +1957,16 @@ DeferredTriggerSaveEvent(Relation rel, int event,
 
    ntriggers = rel->trigdesc->n_after_row[event];
    triggers = rel->trigdesc->tg_after_row[event];
-   new_size = sizeof(DeferredTriggerEventData) +
+   new_size = offsetof(DeferredTriggerEventData, dte_item[0]) +
        ntriggers * sizeof(DeferredTriggerEventItem);
 
    new_event = (DeferredTriggerEvent) palloc(new_size);
+   new_event->dte_next = NULL;
    new_event->dte_event = event & TRIGGER_EVENT_OPMASK;
    new_event->dte_relid = rel->rd_id;
    ItemPointerCopy(&oldctid, &(new_event->dte_oldctid));
    ItemPointerCopy(&newctid, &(new_event->dte_newctid));
    new_event->dte_n_items = ntriggers;
-   new_event->dte_item[ntriggers].dti_state = new_size;
    for (i = 0; i < ntriggers; i++)
    {
        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) ?
             TRIGGER_DEFERRED_HAS_BEFORE : 0);
    }
+
    MemoryContextSwitchTo(oldcxt);
 
    switch (event & TRIGGER_EVENT_OPMASK)
index 613a155cd6c54522d7f9a73c782575d84ed03ba3..86387b0a6f6101396e2f5a23cb8a678b512ca3a9 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * 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;
    bool        dts_tgisdeferred;
 } DeferredTriggerStatusData;
+
 typedef struct DeferredTriggerStatusData *DeferredTriggerStatus;
 
 
@@ -120,16 +121,19 @@ typedef struct DeferredTriggerEventItem
 } DeferredTriggerEventItem;
 
 
+typedef struct DeferredTriggerEventData *DeferredTriggerEvent;
+
 typedef struct DeferredTriggerEventData
 {
+   DeferredTriggerEvent dte_next; /* list link */
    int32       dte_event;
    Oid         dte_relid;
    ItemPointerData dte_oldctid;
    ItemPointerData dte_newctid;
    int32       dte_n_items;
+   /* dte_item is actually a variable-size array, of length dte_n_items */
    DeferredTriggerEventItem dte_item[1];
 } DeferredTriggerEventData;
-typedef struct DeferredTriggerEventData *DeferredTriggerEvent;
 
 
 extern void DeferredTriggerInit(void);