--------------------- PatchSet 463 Date: 2002/12/23 23:17:49 Author: rbcollins Branch: esi Tag: (none) Log: esi segments are now refcounted, and no known mem leaks Members: src/ESI.cc:1.1.2.73->1.1.2.74 src/ESIContext.h:1.1.2.3->1.1.2.4 src/ESIElement.h:1.1.2.8->1.1.2.9 src/ESISegment.cc:1.1.2.5->1.1.2.6 src/ESISegment.h:1.1.2.5->1.1.2.6 Index: squid3/src/ESI.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESI.cc,v retrieving revision 1.1.2.73 retrieving revision 1.1.2.74 diff -u -r1.1.2.73 -r1.1.2.74 --- squid3/src/ESI.cc 22 Dec 2002 07:41:16 -0000 1.1.2.73 +++ squid3/src/ESI.cc 23 Dec 2002 23:17:49 -0000 1.1.2.74 @@ -1,6 +1,6 @@ /* - * $Id: ESI.cc,v 1.1.2.73 2002/12/22 07:41:16 rbcollins Exp $ + * $Id: ESI.cc,v 1.1.2.74 2002/12/23 23:17:49 rbcollins Exp $ * * DEBUG: section 86 ESI processing * AUTHOR: Robert Collins @@ -97,7 +97,7 @@ /* Recursive uses are not supported by design */ struct _query_elem{char *var, *val;}; struct esiVarState { - ESISegment *extractList(); + ESISegment::Pointer extractList(); char *extractChar(); void feedData (const char *buf, size_t len); void buildVary (HttpReply *rep); @@ -110,8 +110,8 @@ private: char *getProductVersion (char const *s); - ESISegment *input; - ESISegment *output; + ESISegment::Pointer input; + ESISegment::Pointer output; HttpHeader hdr; struct _query_elem *query; size_t query_sz; @@ -189,7 +189,7 @@ esiComment(); Pointer makeCacheable() const; - void render(ESISegment *); + void render(ESISegment::Pointer); void finish(); private: static MemPool *pool; @@ -202,15 +202,15 @@ void operator delete (void *address); void deleteSelf() const; - esiLiteral(ESISegment *); + esiLiteral(ESISegment::Pointer); esiLiteral(ESIContext *, const XML_Char *s, int len); ~esiLiteral(); - void render(ESISegment *); + void render(ESISegment::Pointer); esiProcessResult_t process (int dovars); Pointer makeCacheable() const; /* optimise copies away later */ - ESISegment *buffer; + ESISegment::Pointer buffer; struct { int donevars:1; } flags; @@ -232,10 +232,10 @@ esiSequence(esiTreeParentPtr, bool = false); ~esiSequence(); - void render(ESISegment *); + void render(ESISegment::Pointer); bool addElement (ESIElement::Pointer); esiProcessResult_t process (int dovars); - void provideData (ESISegment *, ESIElement*); + void provideData (ESISegment::Pointer, ESIElement*); bool mayFail () const; void wontFail(); void fail(ESIElement *); @@ -273,7 +273,7 @@ esiInclude(esiTreeParentPtr, int attributes, const char **attr, ESIContext *); ~esiInclude(); - void render(ESISegment *); + void render(ESISegment::Pointer); esiProcessResult_t process (int dovars); Pointer makeCacheable() const; void subRequestDone (esiStreamContext *, bool); @@ -284,8 +284,8 @@ } flags; esiStreamContext *src; esiStreamContext *alt; - ESISegment *srccontent; - ESISegment *altcontent; + ESISegment::Pointer srccontent; + ESISegment::Pointer altcontent; ESIContext *context; char *srcurl, *alturl; void fail(esiStreamContext *); @@ -296,7 +296,7 @@ void start(); bool started; bool sent; - void copyLeadSegment (ESISegment *&, ESISegment &); + void copyLeadSegment (ESISegment::Pointer &, ESISegment::Pointer); esiInclude(esiInclude const &); }; MemPool *esiInclude::Pool = NULL; @@ -309,7 +309,7 @@ void deleteSelf() const; esiRemove(); - void render(ESISegment *); + void render(ESISegment::Pointer); bool addElement (ESIElement::Pointer); Pointer makeCacheable() const; void finish(); @@ -343,11 +343,11 @@ esiTry(esiTreeParentPtr aParent); ~esiTry(); - void render(ESISegment *); + void render(ESISegment::Pointer); bool addElement (ESIElement::Pointer); void fail(ESIElement *); esiProcessResult_t process (int dovars); - void provideData (ESISegment *data, ESIElement * source); + void provideData (ESISegment::Pointer data, ESIElement * source); Pointer makeCacheable() const; ESIElement::Pointer attempt; @@ -363,7 +363,7 @@ static MemPool *Pool; void notifyParent(); esiTreeParentPtr parent; - ESISegment* exceptbuffer; + ESISegment::Pointer exceptbuffer; esiTry (esiTry const &); }; MemPool *esiTry::Pool = NULL; @@ -387,12 +387,12 @@ esiChoose(esiTreeParentPtr); ~esiChoose(); - void render(ESISegment *); + void render(ESISegment::Pointer); bool addElement (ESIElement::Pointer); void fail(ESIElement *); esiProcessResult_t process (int dovars); - void provideData (ESISegment *data, ESIElement *source); + void provideData (ESISegment::Pointer data, ESIElement *source); Pointer makeCacheable() const; void NULLElements (int start, int end); void NULLUnChosen(); @@ -459,14 +459,20 @@ typedef RefCount esiIncludePtr; struct _esiStreamContext { +public: + void *operator new(size_t); + _esiStreamContext(); int finished; esiIncludePtr include; - ESISegment localbuffer; - ESISegment *buffer; + ESISegment::Pointer localbuffer; + ESISegment::Pointer buffer; }; CBDATA_TYPE (esiStreamContext); +_esiStreamContext::_esiStreamContext() : finished(false), include (NULL), localbuffer (new ESISegment), buffer (NULL) +{} + /* Local functions */ /* ESIContext */ static ESIContext *ESIContextNew(HttpReply *, clientStreamNode *, clientHttpRequest *); @@ -519,24 +525,24 @@ } void -ESIContext::appendOutboundData(ESISegment *theData) +ESIContext::appendOutboundData(ESISegment::Pointer theData) { - if (!outbound) { + if (!outbound.getRaw()) { outbound = theData; outboundtail = outbound; } else { - assert (outboundtail->next == NULL); + assert (outboundtail->next.getRaw() == NULL); outboundtail->next = theData; } fixupOutboundTail(); } void -ESIContext::provideData (ESISegment *theData, ESIElement * source) +ESIContext::provideData (ESISegment::Pointer theData, ESIElement * source) { - debug (86,5)("ESIContext::provideData: %p %p %p\n",this, theData, source); - if (!tree.getRaw()) - return; + debug (86,5)("ESIContext::provideData: %p %p %p\n",this, theData.getRaw(), source); + /* No callbacks permitted after finish() called on the tree */ + assert (tree.getRaw()); assert (source == tree); appendOutboundData(theData); send(); @@ -554,7 +560,7 @@ ESIContext::fixupOutboundTail() { /* TODO: fixup thisNode outboundtail dross a little */ - if (outboundtail) + if (outboundtail.getRaw()) outboundtail = outboundtail->tail(); } @@ -595,8 +601,10 @@ /* Render if we can to get maximal sent data */ assert (tree.getRaw() || flags.error); - if (!outbound) - outbound = outboundtail = new ESISegment; + if (!outbound.getRaw()) { + outboundtail = new ESISegment; + outbound = outboundtail; + } if (!flags.error) { tree->render(outboundtail); fixupOutboundTail(); @@ -669,7 +677,7 @@ if (context->flags.oktosend && context->flags.finished) { StoreIOBuffer tempBuffer = EMPTYIOBUFFER; - assert (!context->outbound); + assert (!context->outbound.getRaw()); /* We've finished processing, and there is no more data buffered */ debug (86,5)("Telling recipient EOF on READ\n"); clientStreamCallback (thisNode, http, NULL, tempBuffer); @@ -683,12 +691,12 @@ } /* no data that is ready to send, and still reading? well, lets get some */ /* secure a buffer */ - if (!context->incoming) { + if (!context->incoming.getRaw()) { /* create a new buffer segment */ context->buffered = new ESISegment; context->incoming = context->buffered; } - assert (context->incoming && context->incoming->len != HTTP_REQBUF_SZ); + assert (context->incoming.getRaw() && context->incoming->len != HTTP_REQBUF_SZ); { StoreIOBuffer tempBuffer = EMPTYIOBUFFER; tempBuffer.offset = context->readpos; @@ -717,7 +725,7 @@ return clientStreamStatus (thisNode, http); } if (context->flags.oktosend && context->flags.finished && - !(context->outbound && context->outbound_offset < context->outbound->len)) { + !(context->outbound.getRaw() && context->outbound_offset < context->outbound->len)) { cbdataReferenceDone (context); debug (86,5) ("Telling recipient EOF on STATUS\n"); return STREAM_UNPLANNED_COMPLETE; /* we don't know lengths in advance */ @@ -747,13 +755,13 @@ void ESIContext::trimBlanks() { - /* trim leading empty buffers ? */ - while (outbound && outbound->next && !outbound->len) { - ESISegment *temp = outbound->next; - cbdataFree (outbound); - outbound = temp; + while (outbound.getRaw() && outbound->next.getRaw() && !outbound->len) { + debug(86,5)("ESIContext::trimBlanks: %p skipping segment %p\n", this, outbound.getRaw()); + outbound = outbound->next; } + if (outboundtail.getRaw()) + assert (outbound.getRaw()); } /* Send data downstream @@ -786,7 +794,7 @@ } #endif - if (!(rep || (outbound && + if (!(rep || (outbound.getRaw() && outbound->len && (outbound_offset <= outbound->len)))) { debug (86,5)("ESIContext::send: Nothing to send.\n"); return 0; @@ -799,7 +807,7 @@ clientStreamNode *next = thisNode->next(); cbdataReference (this); size_t len = 0; - if (outbound) + if (outbound.getRaw()) len = min (next->readBuffer.length, outbound->len - outbound_offset); /* prevent corruption on range requests, even though we don't support them yet */ assert (pos == next->readBuffer.offset); @@ -808,21 +816,15 @@ if (len) { xmemcpy (next->readBuffer.data, &outbound->buf[outbound_offset], len); if (len + outbound_offset == outbound->len) { - ESISegment *temp = outbound->next; + ESISegment::Pointer temp = outbound->next; /* remove the used buffer */ outbound_offset = 0; - cbdataFree (outbound); outbound = temp; } pos += len; - if (!outbound) + if (!outbound.getRaw()) outboundtail = NULL; - /* trim leading empty buffers ? */ - while (outbound && outbound->next && !outbound->len) { - ESISegment *temp = outbound->next; - cbdataFree (outbound); - outbound = temp; - } + trimBlanks(); } flags.clientwantsdata = 0; debug (86,5)("ESIContext::send: this=%p Client no longer wants data \n",this); @@ -935,7 +937,7 @@ assert (thisNode->readBuffer.offset == recievedData.offset); debug (86,5)("esiProcessStream found %u bytes of body data at offset %ld\n", recievedData.length, recievedData.offset); /* secure the data for later use */ - if (!context->incoming) { + if (!context->incoming.getRaw()) { /* create a new buffer segment */ debug (86,5) ("esiProcessStream: Setting up incoming buffer\n"); context->buffered = new ESISegment; @@ -1003,7 +1005,7 @@ */ if (!context->flags.finishedtemplate && !context->reading()) { StoreIOBuffer tempBuffer = EMPTYIOBUFFER; - assert (context->incoming && context->incoming->len < HTTP_REQBUF_SZ); + assert (context->incoming.getRaw() && context->incoming->len < HTTP_REQBUF_SZ); tempBuffer.offset = context->readpos; tempBuffer.length = HTTP_REQBUF_SZ - context->incoming->len; tempBuffer.data = &context->incoming->buf[context->incoming->len]; @@ -1355,7 +1357,7 @@ void ESIContext::parseOneBuffer() { - assert (buffered); + assert (buffered.getRaw()); if (buffered->len) { int lastBlock = buffered->next == NULL && flags.finishedtemplate ? 1 : 0; @@ -1377,9 +1379,8 @@ } } - ESISegment *temp = buffered; + ESISegment::Pointer temp = buffered; buffered = temp->next; - cbdataFree (temp); } void @@ -1395,13 +1396,13 @@ parserState.init(this); /* we have data */ - if (buffered) { + if (buffered.getRaw()) { flags.parsing = 1; /* we don't keep any data around */ PROF_start(esiParsing); - while (buffered && !flags.error) + while (buffered.getRaw() && !flags.error) parseOneBuffer(); PROF_stop(esiParsing); @@ -1439,8 +1440,9 @@ return ESI_PROCESS_FAILED; } - if (!flags.finishedtemplate && !incoming) { - incoming = buffered = new ESISegment; + if (!flags.finishedtemplate && !incoming.getRaw()) { + buffered = new ESISegment; + incoming = buffered; } if (!flags.finishedtemplate) { @@ -1519,8 +1521,10 @@ if (parserState.inited()) { parserState.freeResources(); } - ESISegmentFreeList (&buffered); - ESISegmentFreeList (&outbound); + parserState.popAll(); + ESISegmentFreeList (buffered); + ESISegmentFreeList (outbound); + ESISegmentFreeList (outboundtail); cbdataFree (varState); /* don't touch incoming, it's a pointer into buffered anyway */ } @@ -1605,7 +1609,7 @@ esiStream = (esiStreamContext *)cbdataReference (node->data); /* If segments become more flexible, ignore thisNode */ - assert (recievedData.length <= sizeof(esiStream->localbuffer.buf)); + assert (recievedData.length <= sizeof(esiStream->localbuffer->buf)); assert (!esiStream->finished); debug (86,5) ("esiBufferRecipient rep %p body %p len %d\n", rep, recievedData.data, recievedData.length); @@ -1637,16 +1641,16 @@ if (recievedData.data && recievedData.length) { http->out.offset += recievedData.length; - if (recievedData.data >= esiStream->localbuffer.buf && - recievedData.data < &esiStream->localbuffer.buf[sizeof(esiStream->localbuffer.buf)]) { + if (recievedData.data >= esiStream->localbuffer->buf && + recievedData.data < &esiStream->localbuffer->buf[sizeof(esiStream->localbuffer->buf)]) { /* original static buffer */ - if (recievedData.data != esiStream->localbuffer.buf) { + if (recievedData.data != esiStream->localbuffer->buf) { /* But not the start of it */ - xmemmove (esiStream->localbuffer.buf, recievedData.data, recievedData.length); + xmemmove (esiStream->localbuffer->buf, recievedData.data, recievedData.length); } - esiStream->localbuffer.len = recievedData.length; + esiStream->localbuffer->len = recievedData.length; } else { - assert (esiStream->buffer != NULL); + assert (esiStream->buffer.getRaw() != NULL); esiStream->buffer->len = recievedData.length; } } @@ -1692,10 +1696,10 @@ return; case STREAM_NONE: { StoreIOBuffer tempBuffer = EMPTYIOBUFFER; - if (!esiStream->buffer) { - esiStream->buffer = &esiStream->localbuffer; + if (!esiStream->buffer.getRaw()) { + esiStream->buffer = esiStream->localbuffer; } - while (esiStream->buffer->next) esiStream->buffer = esiStream->buffer->next; + esiStream->buffer = esiStream->buffer->tail(); if (esiStream->buffer->len) { esiStream->buffer->next = new ESISegment; esiStream->buffer = esiStream->buffer->next; @@ -1720,17 +1724,23 @@ { esiStreamContext *esiStream = (esiStreamContext *)data; assert (esiStream); + esiStream->buffer = NULL; + esiStream->localbuffer = NULL; esiStream->include = NULL; - ESISegmentFreeList (&esiStream->localbuffer.next); debug (86,5)("Freeing stream context\n"); } +void * +_esiStreamContext::operator new (size_t count) +{ + CBDATA_INIT_TYPE_FREECB(esiStreamContext, esiStreamContextFree); + return cbdataAlloc(esiStreamContext); +} + esiStreamContext * esiStreamContextNew (esiIncludePtr include) { - esiStreamContext *rv = NULL; - CBDATA_INIT_TYPE_FREECB(esiStreamContext, esiStreamContextFree); - rv = cbdataAlloc(esiStreamContext); + esiStreamContext *rv = new _esiStreamContext; rv->include = include; return rv; } @@ -1774,10 +1784,10 @@ } void -esiComment::render(ESISegment *output) +esiComment::render(ESISegment::Pointer output) { /* Comments do nothing dude */ - debug (86, 5)("esiCommentRender: Rendering comment %p into %p\n", this, output); + debug (86, 5)("esiCommentRender: Rendering comment %p into %p\n", this, output.getRaw()); } ESIElement::Pointer @@ -1812,11 +1822,11 @@ esiLiteral::~esiLiteral() { debug (86, 5) ("esiLiteral::~esiLiteral: %p\n", this); - ESISegmentFreeList (&buffer); + ESISegmentFreeList (buffer); cbdataReferenceDone (varState); } -esiLiteral::esiLiteral(ESISegment *aSegment) +esiLiteral::esiLiteral(ESISegment::Pointer aSegment) { buffer = aSegment; /* we've been handed a complete, processed string */ @@ -1836,7 +1846,7 @@ { assert (s); buffer = new ESISegment; - ESISegment *local = buffer; + ESISegment::Pointer local = buffer; off_t start = 0; int remainingCharacters = numberOfCharacters; while (remainingCharacters > 0) { @@ -1852,13 +1862,12 @@ } void -esiLiteral::render (ESISegment *output) +esiLiteral::render (ESISegment::Pointer output) { debug (86,9)("esiLiteral::render: Rendering %p\n",this); /* append the entire chain */ - ESISegment *myout = output; - assert (myout->next == NULL); - myout->next = buffer; + assert (output->next.getRaw() == NULL); + output->next = buffer; buffer = NULL; } @@ -1868,14 +1877,14 @@ if (flags.donevars) return ESI_PROCESS_COMPLETE; if (dovars) { - ESISegment *temp = buffer; + ESISegment::Pointer temp = buffer; /* Ensure variable state is clean */ - while (temp) { + while (temp.getRaw()) { varState->feedData(temp->buf,temp->len); temp = temp->next; } /* free the pre-processed content */ - ESISegmentFreeList (&buffer); + ESISegmentFreeList (buffer); buffer = varState->extractList (); } flags.donevars = 1; @@ -1945,7 +1954,7 @@ } void -esiSequence::render(ESISegment *output) +esiSequence::render(ESISegment::Pointer output) { /* append all processed elements, and trim processed * and rendered elements @@ -1976,11 +1985,11 @@ void -esiSequence::provideData (ESISegment *data, ESIElement *source) +esiSequence::provideData (ESISegment::Pointer data, ESIElement *source) { if (processing) debug (86,5) ("esiSequence::provideData: %p data provided during processing\n", this); - debug (86,5) ("esiSequence::provideData %p %p %p\n", this, data, source); + debug (86,5) ("esiSequence::provideData %p %p %p\n", this, data.getRaw(), source); /* when data is provided, the element *must* be completed */ /* XXX: when the callback model is complete, * we can introduce 'finished'. And then this rule can be @@ -2015,8 +2024,8 @@ dynamic_cast(elements[elementcount - 1].getRaw())) { debug (86,5)("esiSequenceAdd: tying Literals %p and %p together\n", elements[elementcount - 1].getRaw(), element.getRaw()); - ESISegmentTransferList (&((esiLiteral *)element.getRaw())->buffer, - &((esiLiteral *)elements[elementcount - 1].getRaw())->buffer); + ESISegmentTransferList (((esiLiteral *)element.getRaw())->buffer, + ((esiLiteral *)elements[elementcount - 1].getRaw())->buffer); return true; } elements = (ESIElement::Pointer*)memReallocBuf (elements, ++elementcount * sizeof (ESIElement::Pointer), @@ -2068,6 +2077,7 @@ esiProcessResult_t esiSequence::process (int inheritedVarsFlag) { + debug (86,5) ("esiSequence::process: %p processing\n", this); if (processing) { debug (86,5)("esiSequence::process: %p reentry attempt during processing\n", this); } @@ -2099,12 +2109,12 @@ wontFail(); if (processedcount == elementcount || provideIncrementalData) { - ESISegment *temp = new ESISegment; + ESISegment::Pointer temp(new ESISegment); render (temp); - if (temp->next || temp->len) + if (temp->next.getRaw() || temp->len) parent->provideData(temp, this); else - ESISegmentFreeList (&temp); + ESISegmentFreeList (temp); } /* Depends on full parsing before processing */ @@ -2172,8 +2182,8 @@ esiInclude::~esiInclude() { debug (86,5)("esiInclude::Free %p\n", this); - ESISegmentFreeList (&srccontent); - ESISegmentFreeList (&altcontent); + ESISegmentFreeList (srccontent); + ESISegmentFreeList (altcontent); cbdataReferenceDone (context); safe_free (srcurl); safe_free (alturl); @@ -2239,7 +2249,7 @@ /* url is eaten by the request */ url = vars->extractChar (); debug (86,5)("esiIncludeStart: Starting subrequest with url '%s'\n", url); - if (clientBeginRequest(METHOD_GET, url, esiBufferRecipient, esiBufferDetach, stream, &tempheaders, stream->localbuffer.buf, HTTP_REQBUF_SZ)) { + if (clientBeginRequest(METHOD_GET, url, esiBufferRecipient, esiBufferDetach, stream, &tempheaders, stream->localbuffer->buf, HTTP_REQBUF_SZ)) { debug (86,0) ("starting new ESI subrequest failed\n"); } httpHeaderClean (&tempheaders); @@ -2308,21 +2318,21 @@ } void -esiInclude::render(ESISegment *output) +esiInclude::render(ESISegment::Pointer output) { if (sent) return; - ESISegment *myout = NULL; + ESISegment::Pointer myout; debug (86, 5)("esiIncludeRender: Rendering include %p\n", this); assert (flags.finished || (flags.failed && flags.onerrorcontinue)); if (flags.failed && flags.onerrorcontinue) { return; } /* Render the content */ - if (srccontent) { + if (srccontent.getRaw()) { myout = srccontent; srccontent = NULL; - } else if (altcontent) { + } else if (altcontent.getRaw()) { myout = altcontent; altcontent = NULL; } else @@ -2359,13 +2369,13 @@ } void -esiInclude::copyLeadSegment (ESISegment *&target, ESISegment &source) +esiInclude::copyLeadSegment (ESISegment::Pointer &target, ESISegment::Pointer source) { target = new ESISegment; - xmemcpy (target->buf, source.buf, source.len); - target->len = source.len; - target->next = source.next; - source.next = NULL; + xmemcpy (target->buf, source->buf, source->len); + target->len = source->len; + target->next = source->next; + source->next = NULL; } void @@ -2385,10 +2395,10 @@ } else { /* Fail if there is no alt being retrieved */ debug (86,3)("esiIncludeSubRequestDone: Src FAILED\n"); - if (!(alt || altcontent)) { + if (!(alt || altcontent.getRaw())) { debug (86,3)("esiIncludeSubRequestDone: Include FAILED - No ALT\n"); flags.failed = 1; - } else if (altcontent) { + } else if (altcontent.getRaw()) { debug (86,3)("esiIncludeSubRequestDone: Include PASSED - ALT already Complete\n"); /* ALT was already retrieved, we are done */ flags.finished = 1; @@ -2401,13 +2411,13 @@ /* copy the lead segment */ copyLeadSegment (altcontent, stream->localbuffer); /* we're done! */ - if (!(src || srccontent)) { + if (!(src || srccontent.getRaw())) { /* src already failed, kick ESI processor */ debug (86,3)("esiIncludeSubRequestDone: Include PASSED - SRC already failed.\n"); flags.finished = 1; } } else { - if (!(src || srccontent)) { + if (!(src || srccontent.getRaw())) { debug (86,3)("esiIncludeSubRequestDone: ALT FAILED, Include FAILED - SRC already failed\n"); /* src already failed */ flags.failed = 1; @@ -2423,8 +2433,8 @@ assert (context); if (!flags.failed) { sent = true; - parent->provideData (srccontent ? srccontent:altcontent,this); - if (srccontent) + parent->provideData (srccontent.getRaw() ? srccontent:altcontent,this); + if (srccontent.getRaw()) srccontent = NULL; else altcontent = NULL; @@ -2486,7 +2496,7 @@ } void -esiRemove::render(ESISegment *output) +esiRemove::render(ESISegment::Pointer output) { /* Removes do nothing dude */ debug (86, 5)("esiRemoveRender: Rendering remove %p\n", this); @@ -2541,7 +2551,7 @@ } void -esiTry::render (ESISegment *output) +esiTry::render (ESISegment::Pointer output) { /* Try renders from it's children */ assert (this); @@ -2551,8 +2561,8 @@ if (flags.attemptok) { attempt->render(output); } else if (flags.exceptok) { - if (exceptbuffer) - ESISegmentTransferList(&exceptbuffer, &output); + if (exceptbuffer.getRaw()) + ESISegmentTransferList(exceptbuffer, output); else except->render(output); } else @@ -2682,7 +2692,7 @@ } void -esiTry::provideData (ESISegment *data, ESIElement* source) +esiTry::provideData (ESISegment::Pointer data, ESIElement* source) { if (source == attempt) { flags.attemptok = 1; @@ -2690,8 +2700,8 @@ } else if (source == except) { flags.exceptok = 1; assert (exceptbuffer == NULL); - ESISegment *t = data; - ESISegmentTransferList (&t, &exceptbuffer); + ESISegment::Pointer t = data; + ESISegmentTransferList (t, exceptbuffer); notifyParent(); } } @@ -2807,7 +2817,8 @@ void esiVarState::freeResources() { - ESISegmentFreeList (&output); + input = NULL; + ESISegmentFreeList (output); httpHeaderClean (&hdr); if (query) { unsigned int i; @@ -2976,14 +2987,14 @@ { /* TODO: if needed - tune to skip segment iteration */ debug (86,6)("esiVarState::feedData: accepting %d bytes\n", len); - ESISegmentListAppend (&input, buf, len); + ESISegmentListAppend (input, buf, len); } -ESISegment * +ESISegment::Pointer esiVarState::extractList() { doIt(); - ESISegment *rv = output; + ESISegment::Pointer rv = output; output = NULL; debug (86,6)("esiVarStateExtractList: Extracted list\n"); return rv; @@ -2992,11 +3003,11 @@ char * esiVarState::extractChar () { - if (!input) + if (!input.getRaw()) fatal ("Attempt to extract variable state with no data fed in \n"); doIt(); char *rv = ESISegmentListToChar(output); - ESISegmentFreeList (&output); + ESISegmentFreeList (output); debug (86,6)("esiVarStateExtractList: Extracted char\n"); return rv; } @@ -3041,7 +3052,7 @@ if (!subref && httpHeaderHas(&hdr,HDR_HOST)) { s = httpHeaderGetStr (&hdr, HDR_HOST); } else s = found_default; - ESISegmentListAppend (&output, s, strlen (s)); + ESISegmentListAppend (output, s, strlen (s)); break; case ESI_VAR_COOKIE: flags.cookie = 1; @@ -3051,15 +3062,15 @@ else { String S = httpHeaderGetListMember (&hdr, HDR_COOKIE, subref, ';'); if (strLen(S)) - ESISegmentListAppend (&output, strBuf(S), strLen (S)); + ESISegmentListAppend (output, strBuf(S), strLen (S)); else if (found_default) - ESISegmentListAppend (&output, found_default, strlen (found_default)); + ESISegmentListAppend (output, found_default, strlen (found_default)); stringClean (&S); } } else s = found_default; if (s) - ESISegmentListAppend (&output, s, strlen (s)); + ESISegmentListAppend (output, s, strlen (s)); break; case ESI_VAR_REFERER: flags.referer = 1; @@ -3067,7 +3078,7 @@ s = httpHeaderGetStr (&hdr, HDR_REFERER); else s = found_default; - ESISegmentListAppend (&output, s, strlen (s)); + ESISegmentListAppend (output, s, strlen (s)); break; case ESI_QUERY_STRING: if (!subref) @@ -3082,7 +3093,7 @@ if (!s) s = found_default; } - ESISegmentListAppend (&output, s, strlen (s)); + ESISegmentListAppend (output, s, strlen (s)); break; case ESI_VAR_USERAGENT: flags.useragent = 1; @@ -3100,14 +3111,14 @@ s = ""; } } else s = found_default; - ESISegmentListAppend (&output, s, strlen (s)); + ESISegmentListAppend (output, s, strlen (s)); break; case ESI_VAR_LANGUAGE: flags.language = 1; if (httpHeaderHas(&hdr, HDR_ACCEPT_LANGUAGE)) { if (!subref) { String S = httpHeaderGetList (&hdr, HDR_ACCEPT_LANGUAGE); - ESISegmentListAppend (&output, strBuf(S), strLen (S)); + ESISegmentListAppend (output, strBuf(S), strLen (S)); stringClean (&S); } else { if (httpHeaderHasListMember (&hdr, HDR_ACCEPT_LANGUAGE, subref, ',')) { @@ -3115,17 +3126,17 @@ } else { s = "false"; } - ESISegmentListAppend (&output, s, strlen (s)); + ESISegmentListAppend (output, s, strlen (s)); } } else { s = found_default; - ESISegmentListAppend (&output, s, strlen (s)); + ESISegmentListAppend (output, s, strlen (s)); } break; case ESI_VAR_OTHER: /* No-op. We swallow it */ if (found_default) { - ESISegmentListAppend (&output, found_default, strlen (found_default)); + ESISegmentListAppend (output, found_default, strlen (found_default)); } break; } @@ -3200,7 +3211,7 @@ char * found_subref = NULL; char *found_default = NULL; esiVar_t vartype = ESI_VAR_OTHER; - ESISegmentFreeList (&input); + ESISegmentFreeList (input); while (pos < len) { switch (state) { case 0: /* skipping pre-variables */ @@ -3209,7 +3220,7 @@ } else { if (pos - done_pos) /* extract known good text */ - ESISegmentListAppend (&output, string + done_pos, pos - done_pos); + ESISegmentListAppend (output, string + done_pos, pos - done_pos); done_pos = pos; state = 1; ++pos; @@ -3316,7 +3327,7 @@ } /* pos-done_pos chars are ready to copy */ if (pos-done_pos) - ESISegmentListAppend (&output, string+done_pos, pos - done_pos); + ESISegmentListAppend (output, string+done_pos, pos - done_pos); safe_free (found_default); safe_free (found_subref); } @@ -3383,7 +3394,7 @@ } void -esiChoose::render(ESISegment *output) +esiChoose::render(ESISegment::Pointer output) { /* append all processed elements, and trim processed and rendered elements */ assert (output->next == NULL); @@ -3519,7 +3530,7 @@ } void -esiChoose::provideData (ESISegment *data, ESIElement*source) +esiChoose::provideData (ESISegment::Pointer data, ESIElement*source) { checkValidSource (source); parent->provideData (data, this); Index: squid3/src/ESIContext.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESIContext.h,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -r1.1.2.3 -r1.1.2.4 --- squid3/src/ESIContext.h 22 Dec 2002 07:41:16 -0000 1.1.2.3 +++ squid3/src/ESIContext.h 23 Dec 2002 23:17:49 -0000 1.1.2.4 @@ -1,5 +1,5 @@ /* - * $Id: ESIContext.h,v 1.1.2.3 2002/12/22 07:41:16 rbcollins Exp $ + * $Id: ESIContext.h,v 1.1.2.4 2002/12/23 23:17:49 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -56,7 +56,7 @@ }; /* when esi processing completes */ - void provideData(ESISegment *, ESIElement *source); + void provideData(ESISegment::Pointer, ESIElement *source); void fail (ESIElement *source); void startRead(); void finishRead(); @@ -89,12 +89,12 @@ http_status errorstatus; /* if we error, what code to return */ char *errormessage; /* error to pass to error page */ HttpReply *rep; /* buffered until we pass data downstream */ - ESISegment *buffered; /* unprocessed data - for whatever reason */ - ESISegment *incoming; - ESISegment *outbound; /* processed data we are waiting to send, or for + ESISegment::Pointer buffered; /* unprocessed data - for whatever reason */ + ESISegment::Pointer incoming; + ESISegment::Pointer outbound; /* processed data we are waiting to send, or for * potential errors to be resolved */ - ESISegment *outboundtail; /* our write segment */ + ESISegment::Pointer outboundtail; /* our write segment */ size_t outbound_offset; /* the offset to the next character to send - * non zero if we haven't sent the entire segment * for some reason @@ -129,7 +129,7 @@ void trimBlanks(); size_t send (); bool reading_; - void appendOutboundData(ESISegment *theData); + void appendOutboundData(ESISegment::Pointer theData); esiProcessResult_t process (); void parse(); void parseOneBuffer(); Index: squid3/src/ESIElement.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESIElement.h,v retrieving revision 1.1.2.8 retrieving revision 1.1.2.9 diff -u -r1.1.2.8 -r1.1.2.9 --- squid3/src/ESIElement.h 22 Dec 2002 05:10:31 -0000 1.1.2.8 +++ squid3/src/ESIElement.h 23 Dec 2002 23:17:49 -0000 1.1.2.9 @@ -1,5 +1,5 @@ /* - * $Id: ESIElement.h,v 1.1.2.8 2002/12/22 05:10:31 rbcollins Exp $ + * $Id: ESIElement.h,v 1.1.2.9 2002/12/23 23:17:49 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -34,8 +34,8 @@ #define SQUID_ESIELEMENT_H #include "RefCount.h" +#include "ESISegment.h" -class ESISegment; typedef enum { ESI_PROCESS_COMPLETE, ESI_PROCESS_PENDING_WONTFAIL, @@ -45,7 +45,7 @@ class ESIElement; struct esiTreeParent : public RefCountable { - virtual void provideData (ESISegment *data, ESIElement * source) + virtual void provideData (ESISegment::Pointer data, ESIElement * source) { /* make abstract when all functionality complete */ assert (0); @@ -63,7 +63,7 @@ debug (86,5)("ESIElement::addElement: Failed for %p\n",this); return false; } - virtual void render (ESISegment *) = 0; + virtual void render (ESISegment::Pointer) = 0; /* process this element */ virtual esiProcessResult_t process (int dovars) { debug (86,5) ("esiProcessComplete: Processed %p\n",this); Index: squid3/src/ESISegment.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESISegment.cc,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid3/src/ESISegment.cc 20 Dec 2002 08:36:11 -0000 1.1.2.5 +++ squid3/src/ESISegment.cc 23 Dec 2002 23:17:49 -0000 1.1.2.6 @@ -1,6 +1,6 @@ /* - * $Id: ESISegment.cc,v 1.1.2.5 2002/12/20 08:36:11 rbcollins Exp $ + * $Id: ESISegment.cc,v 1.1.2.6 2002/12/23 23:17:49 rbcollins Exp $ * * DEBUG: section 86 ESI processing * AUTHOR: Robert Collins @@ -40,36 +40,35 @@ /* ESISegment */ void -ESISegmentFreeList (ESISegment **head) { - while (*head) { - ESISegment *temp = *head; - *head = temp->next; - cbdataFree (temp); +ESISegmentFreeList (ESISegment::Pointer &head) { + while (head.getRaw()) { + ESISegment::Pointer temp = head; + head = head->next; + temp->next = NULL; } } void -ESISegmentTransferList (ESISegment **from, ESISegment **to) +ESISegmentTransferList (ESISegment::Pointer &from, ESISegment::Pointer &to) { - if (!*to) { - *to = *from; + if (!to.getRaw()) { + to = from; } else { - ESISegment *temp = *to; - while (temp->next) temp = temp->next; - temp->next = *from; + ESISegment::Pointer temp = to->tail(); + temp->next = from; } - *from = NULL; + from = NULL; } char * -ESISegmentListToChar (ESISegment *head) +ESISegmentListToChar (ESISegment::Pointer const &head) { char *rv; size_t len = 0, pos = 0; - ESISegment *temp; - assert (head); + ESISegment::Pointer temp; + assert (head.getRaw()); temp = head; - while (temp) { + while (temp.getRaw()) { len += temp->len; temp = temp->next; } @@ -77,7 +76,7 @@ assert (rv); rv [ len] = '\0'; temp = head; - while (temp) { + while (temp.getRaw()) { xmemcpy (&rv[pos], temp->buf, temp->len); pos += temp->len; temp = temp->next; @@ -86,19 +85,17 @@ } void -ESISegmentListAppend (ESISegment **head, char const *s, size_t len) +ESISegmentListAppend (ESISegment::Pointer &head, char const *s, size_t len) { - ESISegment *output; + ESISegment::Pointer output; size_t pos=0; - if (!*head) - *head = cbdataAlloc (ESISegment); - output = *head; - while (output->next) - output=output->next; + if (!head.getRaw()) + head = new ESISegment; + output = head->tail(); /* copy the string to output */ while (pos < len) { if (output->len == sizeof (output->buf)) { - assert (output->next == NULL); + assert (output->next.getRaw() == NULL); output->next = new ESISegment; output = output->next; } @@ -123,26 +120,24 @@ } void -ESISegment::deleteSelf() +ESISegment::deleteSelf() const { delete this; } /* XXX: if needed, make this iterative */ -ESISegment * +ESISegment::Pointer ESISegment::clone () const { - ESISegment *result = new ESISegment (*this); - result->next = next ? next->clone() : NULL; + ESISegment::Pointer result = new ESISegment (*this); + result->next = next.getRaw() ? next->clone() : NULL; return result; } size_t ESISegment::append(char const *appendBuffer, size_t appendLength) { - size_t toCopy = appendLength; - if (toCopy > sizeof (buf) - len) - toCopy = sizeof (buf) - len; + size_t toCopy = min(appendLength, sizeof (buf) - len); xmemcpy (&buf[len], appendBuffer, toCopy); len += toCopy; return toCopy; @@ -152,16 +147,20 @@ ESISegment::tail() const { ESISegment const *result = this; - while (result->next) - result = result->next; + while (result->next.getRaw()) + result = result->next.getRaw(); return result; } ESISegment * ESISegment::tail() { - ESISegment *result = this; - while (result->next) + ESISegment::Pointer result = this; + while (result->next.getRaw()) result = result->next; - return result; + return result.getRaw(); +} + +ESISegment::ESISegment() : len(0), next(NULL) +{ } Index: squid3/src/ESISegment.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ESISegment.h,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -r1.1.2.5 -r1.1.2.6 --- squid3/src/ESISegment.h 20 Dec 2002 08:36:11 -0000 1.1.2.5 +++ squid3/src/ESISegment.h 23 Dec 2002 23:17:49 -0000 1.1.2.6 @@ -1,5 +1,5 @@ /* - * $Id: ESISegment.h,v 1.1.2.5 2002/12/20 08:36:11 rbcollins Exp $ + * $Id: ESISegment.h,v 1.1.2.6 2002/12/23 23:17:49 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -37,25 +37,29 @@ * or perhaps use membuffers here? */ -class ESISegment { +#include "RefCount.h" + +class ESISegment : public RefCountable { public: + typedef RefCount Pointer; void *operator new (size_t byteCount); void operator delete (void *address); - void deleteSelf(); + void deleteSelf() const; - ESISegment *clone() const; + ESISegment(); + ESISegment::Pointer clone() const; char buf[HTTP_REQBUF_SZ]; size_t len; /* how much data has been pushed into this */ - ESISegment *next; + Pointer next; size_t append(char const *, size_t); ESISegment const *tail() const; ESISegment *tail(); }; -extern void ESISegmentFreeList (ESISegment **head); -extern void ESISegmentTransferList (ESISegment **from, ESISegment **to); -extern char *ESISegmentListToChar (ESISegment *head); -extern void ESISegmentListAppend (ESISegment **head, char const *, size_t); +extern void ESISegmentFreeList (ESISegment::Pointer &head); +extern void ESISegmentTransferList (ESISegment::Pointer &from, ESISegment::Pointer &to); +extern char *ESISegmentListToChar (ESISegment::Pointer const &); +extern void ESISegmentListAppend (ESISegment::Pointer &, char const *, size_t); #endif /* SQUID_ESISEGMENT_H */