OSDN Git Service

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 7a013c0..4a6ddef 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 613a155..86387b0 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);