d21a851e1892724009277d5de14a3c4df6e5951a
angie
  Mon Jun 3 12:40:16 2013 -0700
oops, forgot to clean up qLm -- added now.  for #6152
diff --git src/lib/annoGrator.c src/lib/annoGrator.c
index 74bffda..5291628 100644
--- src/lib/annoGrator.c
+++ src/lib/annoGrator.c
@@ -35,30 +35,31 @@
 	if (prevQRow == NULL)
 	    self->qHead = qRow->next;
 	else
 	    prevQRow->next = qRow->next;
 	if (self->qTail == qRow)
 	    self->qTail = prevQRow;
 	}
     else
 	prevQRow = qRow;
     }
 if (self->qHead == NULL)
     {
     // Queue is empty - clean up lm
     lmCleanup(&(self->qLm));
     self->qLm = lmInit(0);
+    self->qSkippedCount = 0;
     }
 }
 
 INLINE void agCheckInternalSorting(struct annoGrator *self, struct annoRow *newRow)
 /* Die if newRow precedes qTail. */
 {
 if (self->qTail != NULL)
     {
     int cDifNewTail = strcmp(newRow->chrom, self->qTail->chrom);
     if (cDifNewTail < 0)
 	errAbort("annoGrator %s: Unsorted input from internal source %s (%s < %s)",
 		 self->streamer.name, self->mySource->name, newRow->chrom, self->qTail->chrom);
     else if (cDifNewTail == 0 && newRow->start < self->qTail->start)
 	errAbort("annoGrator %s: Unsorted input from internal source %s (%s, %u < %u)",
 		 self->streamer.name, self->mySource->name,
@@ -87,30 +88,41 @@
 		{
 		if (self->qHead != NULL)
 		    errAbort("annoGrator %s: qTail is NULL but qHead is non-NULL",
 			     self->streamer.name);
 		self->qHead = self->qTail = newRow;
 		}
 	    else
 		{
 		self->qTail->next = newRow;
 		self->qTail = newRow;
 		}
 	    if (cDifNewP > 0)
 		// newRow->chrom comes after chrom; we're done for now
 		break;
 	    }
+	// If we're skipping past large regions, keep qLm size under control:
+	else
+	    {
+	    self->qSkippedCount++;
+	    if (self->qSkippedCount > 1024 && self->qHead == NULL && self->qTail == NULL)
+		{
+		lmCleanup(&(self->qLm));
+		self->qLm = lmInit(0);
+		self->qSkippedCount = 0;
+		}
+	    }
 	}
     }
 }
 
 struct annoRow *annoGratorIntegrate(struct annoGrator *self, struct annoStreamRows *primaryData,
 				    boolean *retRJFilterFailed, struct lm *callerLm)
 /* Given a single row from the primary source, get all overlapping rows from internal
  * source, and produce joined output rows.
  * If retRJFilterFailed is non-NULL:
  * - any overlapping row has a rightJoin filter failure (see annoFilter.h), or
  * - overlap rule is agoMustOverlap and no rows overlap, or
  * - overlap rule is agoMustNotOverlap and any overlapping row is found,
  * then set retRJFilterFailed and stop. */
 {
 struct annoRow *primaryRow = primaryData->rowList;
@@ -166,30 +178,31 @@
 {
 errAbort("annoGrator %s: nextRow() called, but integrate() should be called instead",
 	 self->name);
 return NULL;
 }
 
 static void agReset(struct annoGrator *self)
 /* Reset all state associated with position */
 {
 freez(&(self->prevPChrom));
 self->prevPStart = 0;
 self->eof = FALSE;
 lmCleanup(&(self->qLm));
 self->qLm = lmInit(0);
 self->qHead = self->qTail = NULL;
+self->qSkippedCount = 0;
 }
 
 static boolean filtersHaveRJInclude(struct annoFilter *filters)
 /* Return TRUE if filters have at least one active filter with !isExclude && rightJoin. */
 {
 struct annoFilter *filter;
 for (filter = filters;  filter != NULL;  filter = filter->next)
     if (filter->op != afNoFilter && !filter->isExclude && filter->rightJoin)
 	return TRUE;
 return FALSE;
 }
 
 static void agSetFilters(struct annoStreamer *vSelf, struct annoFilter *newFilters)
 /* Update filters and re-evaluate self->haveRJIncludeFilter */
 {