[prev in list] [next in list] [prev in thread] [next in thread]
List: squid-dev
Subject: Re: [PATCH] HttpHdrSc c++ refactoring
From: Kinkie <gkinkie () gmail ! com>
Date: 2011-11-18 7:42:19
Message-ID: CA+Y8hcMOeFOw44HM5JNjOnNe1Wer+xmxArCrVZArW0aeWPK_Ug () mail ! gmail ! com
[Download RAW message or body]
>> +/**
>> + * look for the last occurrence of a character in a c-string with a set maximum length
>> + */
>> +SQUIDCEXTERN const char *strnrchr(const char *s, size_t slen, char c);
>
> Please fix the strnrchr() description. To match the implementation, the
> description should say that we scan from the beginning and stop at the
> end of the c-string or n-th character, whichever comes first (and
> s/slen/n/).
Done (although s/slen/count/ to match the
> I would also recommend checking whether your strnrchr() implementation
> matches that of GNU API. Their documentation is even worse:
> http://gnugeneration.com/mirrors/kernel-api/r2320.html
Done.
>
>
>> - if (!sctusable || sctusable->content.size() == 0)
>> + if (!sctusable || sctusable->hasContent())
>
> Sorry if I asked you about this already, but is the reversal of the
> second condition above intentional?
No, it wasn't.
Thanks for spotting that, and sorry for missing it if you asked already :(
>> class HttpHdrSc
>> {
>>
>> public:
>> + bool parse(const String *str);
>> + ~HttpHdrSc();
>> + HttpHdrSc(const HttpHdrSc &);
>
> Please move the parse() declaration below constructors/destructors.
Done.
>> + HttpHdrSc() {};
>
> Extra semicolon.
Removed.
>>>> >> + String Content() const { return content; }
>>> >
>>> > I would s/content/content_/ instead, especially since content data
>>> > member is private. Capitalization should be used for static methods.
>>
>> Ok.
>
> If that "Ok" meant "will do later", then please note that you have not
> done that.
Gah! Sorry.. Now done.
New version attached.
--
/kinkie
["playground-httphdrsc-v4.patch" (text/x-diff)]
=== modified file 'compat/Makefile.am'
--- compat/Makefile.am 2011-10-26 16:33:46 +0000
+++ compat/Makefile.am 2011-11-17 23:25:48 +0000
@@ -22,40 +22,42 @@
debug.h \
drand48.h \
eui64_aton.h \
fdsetsize.h \
getaddrinfo.h \
getnameinfo.h \
GnuRegex.c \
GnuRegex.h \
inet_ntop.h \
inet_pton.h \
initgroups.h \
osdetect.h \
psignal.h \
shm.cc \
shm.h \
stdio.h \
stdvarargs.h \
strnstr.cc \
strsep.h \
strtoll.h \
+ strnrchr.h \
+ strnrchr.c \
tempnam.h \
types.h \
unsafe.h \
valgrind.h \
xalloc.cc \
xalloc.h \
xis.h \
xstrerror.cc \
xstrerror.h \
xstring.cc \
xstring.h \
xstrto.cc \
xstrto.h \
\
os/aix.h \
os/dragonfly.h \
os/freebsd.h \
os/hpux.h \
os/linux.h \
os/macosx.h \
=== added file 'compat/strnrchr.c'
--- compat/strnrchr.c 1970-01-01 00:00:00 +0000
+++ compat/strnrchr.c 2011-11-18 06:09:15 +0000
@@ -0,0 +1,46 @@
+/*
+ * strnrchr.c
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ */
+
+#include "config.h"
+#include "strnrchr.h"
+
+const char *
+strnrchr(const char *s, size_t count, int c)
+{
+ const char *rv=NULL;
+ const char *l=s;
+ while (count > 0 && *l != 0) {
+ if (*l==c)
+ rv=l;
+ ++l;
+ --count;
+ }
+ return rv;
+}
=== added file 'compat/strnrchr.h'
--- compat/strnrchr.h 1970-01-01 00:00:00 +0000
+++ compat/strnrchr.h 2011-11-18 06:09:00 +0000
@@ -0,0 +1,46 @@
+/*
+ * strnrchr.h
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ */
+
+#ifndef COMPAT_STRNRCHR_H_
+#define COMPAT_STRNRCHR_H_
+
+#if HAVE_STDDEF_H
+#include <stddef.h>
+#endif
+
+/**
+ * look for the last occurrence of a character in a c-string.
+ *
+ * Scanning starts at the beginning of the c-string, and ends
+ * after count bytes or at the end of the c-string, whichever happens first
+ */
+SQUIDCEXTERN const char *strnrchr(const char *s, size_t count, int c);
+
+#endif /* COMPAT_STRNRCHR_H_ */
=== modified file 'src/HttpHdrSc.cc'
--- src/HttpHdrSc.cc 2010-11-02 00:49:51 +0000
+++ src/HttpHdrSc.cc 2011-11-18 06:25:02 +0000
@@ -1,407 +1,394 @@
/*
* $Id$
*
* DEBUG: section 90 HTTP Cache Control Header
* AUTHOR: Alex Rousskov
* Robert Collins (Surrogate-Control is derived from
* Cache-Control).
+ * Francesco Chemolli (c++ refactoring)
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
* Squid is the result of efforts by numerous individuals from
* the Internet community; see the CONTRIBUTORS file for full
* details. Many organizations have provided support for Squid's
* development; see the SPONSORS file for full details. Squid is
* Copyrighted (C) 2001 by the Regents of the University of
* California; see the COPYRIGHT file for full details. Squid
* incorporates software developed and/or copyrighted by other
* sources; see the CREDITS file for full details.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#include "squid.h"
#include "Store.h"
#include "HttpHeader.h"
#include "HttpHdrSc.h"
+#if HAVE_MAP
+#include <map>
+#endif
+
+/* a row in the table used for parsing surrogate-control header and statistics */
+typedef struct {
+ const char *name;
+ http_hdr_sc_type id;
+ HttpHeaderFieldStat stat;
+} HttpHeaderScFields;
+
/* this table is used for parsing surrogate control header */
+/* order must match that of enum http_hdr_sc_type. The constraint is verified at \
initialization time */ +//todo: implement constraint
static const HttpHeaderFieldAttrs ScAttrs[SC_ENUM_END] = {
{"no-store", (http_hdr_type)SC_NO_STORE},
-
{"no-store-remote", (http_hdr_type)SC_NO_STORE_REMOTE},
{"max-age", (http_hdr_type)SC_MAX_AGE},
{"content", (http_hdr_type)SC_CONTENT},
{"Other,", (http_hdr_type)SC_OTHER} /* ',' will protect from matches */
};
HttpHeaderFieldInfo *ScFieldsInfo = NULL;
http_hdr_sc_type &operator++ (http_hdr_sc_type &aHeader)
{
int tmp = (int)aHeader;
aHeader = (http_hdr_sc_type)(++tmp);
return aHeader;
}
int operator - (http_hdr_sc_type const &anSc, http_hdr_sc_type const &anSc2)
{
return (int)anSc - (int)anSc2;
}
-/* local prototypes */
-static int httpHdrScParseInit(HttpHdrSc * sc, const String * str);
-
/* module initialization */
void
httpHdrScInitModule(void)
{
ScFieldsInfo = httpHeaderBuildFieldsInfo(ScAttrs, SC_ENUM_END);
}
void
httpHdrScCleanModule(void)
{
httpHeaderDestroyFieldsInfo(ScFieldsInfo, SC_ENUM_END);
ScFieldsInfo = NULL;
}
/* implementation */
-HttpHdrSc *
-httpHdrScCreate(void)
-{
- return new HttpHdrSc();
-}
-
/* creates an sc object from a 0-terminating string */
HttpHdrSc *
-httpHdrScParseCreate(const String * str)
+httpHdrScParseCreate(const String & str)
{
- HttpHdrSc *sc = httpHdrScCreate();
+ HttpHdrSc *sc = new HttpHdrSc();
- if (!httpHdrScParseInit(sc, str)) {
- httpHdrScDestroy(sc);
+ if (!sc->parse(&str)) {
+ delete sc;
sc = NULL;
}
return sc;
}
/* parses a 0-terminating string and inits sc */
-static int
-httpHdrScParseInit(HttpHdrSc * sc, const String * str)
+bool
+HttpHdrSc::parse(const String * str)
{
+ HttpHdrSc * sc=this;
const char *item;
const char *p; /* '=' parameter */
const char *pos = NULL;
const char *target = NULL; /* ;foo */
const char *temp = NULL; /* temp buffer */
int type;
int ilen, vlen;
int initiallen;
HttpHdrScTarget *sct;
- assert(sc && str);
+ assert(str);
/* iterate through comma separated list */
while (strListGetItem(str, ',', &item, &ilen, &pos)) {
initiallen = ilen;
vlen = 0;
/* decrease ilen to still match the token for '=' statements */
if ((p = strchr(item, '=')) && (p - item < ilen)) {
vlen = ilen - (p + 1 - item);
ilen = p - item;
p++;
}
/* decrease ilen to still match the token for ';' qualified non '=' \
statments */ else if ((p = strchr(item, ';')) && (p - item < ilen))
ilen = p++ - item;
/* find type */
+ /* TODO: use a type-safe map-based lookup */
type = httpHeaderIdByName(item, ilen,
ScFieldsInfo, SC_ENUM_END);
if (type < 0) {
debugs(90, 2, "hdr sc: unknown control-directive: near '" << item << "' \
in '" << str << "'"); type = SC_OTHER;
}
/* Is this a targeted directive? */
- /* TODO sometime: implement a strnrchr that looks at a substring */
+ /* TODO: remove the temporary useage and use memrchr and the information we \
have instead */ temp = xstrndup (item, initiallen + 1);
if (!((target = strrchr (temp, ';')) && !strchr (target, '"') && *(target + \
1) != '\0')) target = NULL;
else
++target;
- sct = httpHdrScFindTarget (sc, target);
+ sct = sc->findTarget(target);
if (!sct) {
- sct = httpHdrScTargetCreate (target);
- dlinkAdd(sct, &sct->node, &sc->targets);
+ sct = new HttpHdrScTarget(target);
+ addTarget(sct);
}
safe_free (temp);
- if (EBIT_TEST(sct->mask, type)) {
+ if (sct->isSet(static_cast<http_hdr_sc_type>(type))) {
if (type != SC_OTHER)
debugs(90, 2, "hdr sc: ignoring duplicate control-directive: near '" \
<< item << "' in '" << str << "'");
ScFieldsInfo[type].stat.repCount++;
continue;
}
- /* update mask */
- EBIT_SET(sct->mask, type);
-
- /* post-processing special cases */
+ /* process directives */
switch (type) {
+ case SC_NO_STORE:
+ sct->noStore(true);
+ break;
- case SC_MAX_AGE:
-
- if (!p || !httpHeaderParseInt(p, &sct->max_age)) {
- debugs(90, 2, "sc: invalid max-age specs near '" << item << "'");
- sct->max_age = -1;
- EBIT_CLR(sct->mask, type);
- }
-
- if ((p = strchr (p, '+')))
- if (!httpHeaderParseInt(++p, &sct->max_stale)) {
- debugs(90, 2, "sc: invalid max-stale specs near '" << item << \
"'");
- sct->max_stale = 0;
- /* leave the max-age alone */
- }
-
+ case SC_NO_STORE_REMOTE:
+ sct->noStoreRemote(true);
break;
+ case SC_MAX_AGE:
+ {
+ int ma;
+ if (p && httpHeaderParseInt(p, &ma)) {
+ sct->maxAge(ma);
+ } else {
+ debugs(90, 2, "sc: invalid max-age specs near '" << item << "'");
+ sct->clearMaxAge();
+ }
+
+ if ((p = strchr (p, '+'))) {
+ int ms;
+ ++p; //skip the + char
+ if (httpHeaderParseInt(p, &ms)) {
+ sct->maxStale(ms);
+ } else {
+ debugs(90, 2, "sc: invalid max-stale specs near '" << item << \
"'"); + sct->clearMaxStale();
+ /* leave the max-age alone */
+ }
+ }
+ break;
+ }
+
case SC_CONTENT:
- if (!p || !httpHeaderParseQuotedString(p, vlen, &sct->content)) {
+ if ( p && httpHeaderParseQuotedString(p, vlen, &sct->content_)) {
+ sct->setMask(SC_CONTENT,true); // ugly but saves a copy
+ } else {
debugs(90, 2, "sc: invalid content= quoted string near '" << item << \
"'");
- sct->content.clean();
- EBIT_CLR(sct->mask, type);
+ sct->clearContent();
}
+ break;
+ case SC_OTHER:
default:
break;
}
}
return sc->targets.head != NULL;
}
-void
-httpHdrScDestroy(HttpHdrSc * sc)
+HttpHdrSc::~HttpHdrSc()
{
- assert(sc);
-
- if (sc->targets.head) {
- dlink_node *sct = sc->targets.head;
+ if (targets.head) {
+ dlink_node *sct = targets.head;
while (sct) {
- HttpHdrScTarget *t = (HttpHdrScTarget *)sct->data;
+ HttpHdrScTarget *t = static_cast<HttpHdrScTarget *>(sct->data);
sct = sct->next;
- dlinkDelete (&t->node, &sc->targets);
- httpHdrScTargetDestroy (t);
+ dlinkDelete (&t->node, &targets);
+ delete t;
}
}
-
- delete sc;
}
-HttpHdrSc *
-httpHdrScDup(const HttpHdrSc * sc)
+
+HttpHdrSc::HttpHdrSc(const HttpHdrSc &sc)
{
- HttpHdrSc *dup;
- dlink_node *node;
- assert(sc);
- node = sc->targets.head;
- dup = httpHdrScCreate();
+ dlink_node *node = sc.targets.head;
while (node) {
- HttpHdrScTarget *dupsct;
- dupsct = httpHdrScTargetDup ((HttpHdrScTarget *)node->data);
- dlinkAddTail (dupsct, &dupsct->node, &dup->targets);
+ HttpHdrScTarget *dupsct = new HttpHdrScTarget(*static_cast<HttpHdrScTarget \
*>(node->data)); + addTargetAtTail(dupsct);
node = node->next;
}
-
- return dup;
}
void
-httpHdrScTargetPackInto(const HttpHdrScTarget * sc, Packer * p)
+HttpHdrScTarget::packInto(Packer * p) const
{
http_hdr_sc_type flag;
int pcount = 0;
- assert(sc && p);
+ assert (p);
for (flag = SC_NO_STORE; flag < SC_ENUM_END; ++flag) {
- if (EBIT_TEST(sc->mask, flag) && flag != SC_OTHER) {
+ if (isSet(flag) && flag != SC_OTHER) {
/* print option name */
packerPrintf(p, (pcount ? ", " SQUIDSTRINGPH : SQUIDSTRINGPH),
SQUIDSTRINGPRINT(ScFieldsInfo[flag].name));
/* handle options with values */
if (flag == SC_MAX_AGE)
- packerPrintf(p, "=%d", (int) sc->max_age);
+ packerPrintf(p, "=%d", (int) max_age);
if (flag == SC_CONTENT)
- packerPrintf(p, "=\"" SQUIDSTRINGPH "\"", \
SQUIDSTRINGPRINT(sc->content)); + packerPrintf(p, "=\"" SQUIDSTRINGPH \
"\"", SQUIDSTRINGPRINT(content_));
pcount++;
}
}
- if (sc->target.size())
- packerPrintf (p, ";" SQUIDSTRINGPH, SQUIDSTRINGPRINT(sc->target));
+ if (hasTarget())
+ packerPrintf (p, ";" SQUIDSTRINGPH, SQUIDSTRINGPRINT(target));
}
void
-httpHdrScPackInto(const HttpHdrSc * sc, Packer * p)
+HttpHdrSc::packInto(Packer * p) const
{
dlink_node *node;
- assert(sc && p);
- node = sc->targets.head;
+ assert(p);
+ node = targets.head;
while (node) {
- httpHdrScTargetPackInto((HttpHdrScTarget *)node->data, p);
+ static_cast<HttpHdrScTarget *>(node->data)->packInto(p);
node = node->next;
}
}
-void
-httpHdrScJoinWith(HttpHdrSc * sc, const HttpHdrSc * new_sc)
-{
- assert(sc && new_sc);
-#if 0
- /* RC TODO: check that both have the same target */
-
- if (sc->max_age < 0)
- sc->max_age = new_sc->max_age;
-
- /* RC TODO: copy unique missing stringlist entries */
- cc->mask |= new_cc->mask;
-
-#endif
-}
-
/* negative max_age will clean old max_Age setting */
void
-httpHdrScSetMaxAge(HttpHdrSc * sc, char const *target, int max_age)
+HttpHdrSc::setMaxAge(char const *target, int max_age)
{
- HttpHdrScTarget *sct;
- assert(sc);
- sct = httpHdrScFindTarget (sc, target);
+ HttpHdrScTarget *sct = findTarget(target);
if (!sct) {
- sct = httpHdrScTargetCreate (target);
- dlinkAddTail (sct, &sct->node, &sc->targets);
+ sct = new HttpHdrScTarget(target);
+ dlinkAddTail (sct, &sct->node, &targets);
}
- httpHdrScTargetSetMaxAge(sct, max_age);
+ sct->maxAge(max_age);
}
void
-httpHdrScUpdateStats(const HttpHdrSc * sc, StatHist * hist)
+HttpHdrSc::updateStats(StatHist * hist) const
{
- dlink_node *sct;
- assert(sc);
- sct = sc->targets.head;
+ dlink_node *sct = targets.head;
while (sct) {
- httpHdrScTargetUpdateStats((HttpHdrScTarget *)sct->data, hist);
+ static_cast<HttpHdrScTarget *>(sct->data)->updateStats(hist);
sct = sct->next;
}
}
void
httpHdrScTargetStatDumper(StoreEntry * sentry, int idx, double val, double size, int \
count) {
extern const HttpHeaderStat *dump_stat; /* argh! */
const int id = (int) val;
const int valid_id = id >= 0 && id < SC_ENUM_END;
const char *name = valid_id ? ScFieldsInfo[id].name.termedBuf() : "INVALID";
if (count || valid_id)
storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
id, name, count, xdiv(count, dump_stat->scParsedCount));
}
void
httpHdrScStatDumper(StoreEntry * sentry, int idx, double val, double size, int \
count) {
extern const HttpHeaderStat *dump_stat; /* argh! */
const int id = (int) val;
const int valid_id = id >= 0 && id < SC_ENUM_END;
const char *name = valid_id ? ScFieldsInfo[id].name.termedBuf() : "INVALID";
if (count || valid_id)
storeAppendPrintf(sentry, "%2d\t %-20s\t %5d\t %6.2f\n",
id, name, count, xdiv(count, dump_stat->scParsedCount));
}
HttpHdrScTarget *
-httpHdrScFindTarget (HttpHdrSc *sc, const char *target)
+HttpHdrSc::findTarget(const char *target)
{
dlink_node *node;
- assert (sc);
- node = sc->targets.head;
+ node = targets.head;
while (node) {
HttpHdrScTarget *sct = (HttpHdrScTarget *)node->data;
if (target && sct->target.defined() && !strcmp (target, \
sct->target.termedBuf())) return sct;
else if (!target && sct->target.undefined())
return sct;
node = node->next;
}
return NULL;
}
HttpHdrScTarget *
-httpHdrScGetMergedTarget (HttpHdrSc *sc, const char *ourtarget)
+HttpHdrSc::getMergedTarget(const char *ourtarget)
{
- HttpHdrScTarget *sctus = httpHdrScFindTarget (sc, ourtarget);
- HttpHdrScTarget *sctgeneric = httpHdrScFindTarget (sc, NULL);
+ HttpHdrScTarget *sctus = findTarget(ourtarget);
+ HttpHdrScTarget *sctgeneric = findTarget(NULL);
if (sctgeneric || sctus) {
- HttpHdrScTarget *sctusable = httpHdrScTargetCreate (NULL);
+ HttpHdrScTarget *sctusable = new HttpHdrScTarget(NULL);
if (sctgeneric)
- httpHdrScTargetMergeWith (sctusable, sctgeneric);
+ sctusable->mergeWith(sctgeneric);
if (sctus)
- httpHdrScTargetMergeWith (sctusable, sctus);
+ sctusable->mergeWith(sctus);
return sctusable;
}
return NULL;
}
=== modified file 'src/HttpHdrSc.h'
--- src/HttpHdrSc.h 2009-01-21 03:47:47 +0000
+++ src/HttpHdrSc.h 2011-11-18 06:20:50 +0000
@@ -26,45 +26,53 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#ifndef SQUID_HTTPHDRSURROGATECONTROL_H
#define SQUID_HTTPHDRSURROGATECONTROL_H
#include "dlink.h"
#include "HttpHdrScTarget.h"
/* http surogate control header field */
class HttpHdrSc
{
public:
+ HttpHdrSc(const HttpHdrSc &);
+ HttpHdrSc() {}
+ ~HttpHdrSc();
+
+ bool parse(const String *str);
+ void packInto(Packer * p) const;
+ void updateStats(StatHist *) const;
+ HttpHdrScTarget * getMergedTarget (const char *ourtarget); //todo: make const?
+ void setMaxAge(char const *target, int max_age);
+ void addTarget(HttpHdrScTarget *t) {
+ dlinkAdd(t, &t->node, &targets);
+ }
+ void addTargetAtTail(HttpHdrScTarget *t) {
+ dlinkAddTail (t, &t->node, &targets);
+ }
+
MEMPROXY_CLASS(HttpHdrSc);
dlink_list targets;
+private:
+ HttpHdrScTarget * findTarget (const char *target);
+
};
MEMPROXY_CLASS_INLINE(HttpHdrSc);
/* Http Surrogate Control Header Field */
extern void httpHdrScStatDumper(StoreEntry * sentry, int idx, double val, double \
size, int count); extern void httpHdrScInitModule (void);
extern void httpHdrScCleanModule (void);
-extern HttpHdrSc *httpHdrScCreate(void);
-extern HttpHdrSc *httpHdrScParseCreate(String const *);
-extern void httpHdrScDestroy(HttpHdrSc * sc);
-extern HttpHdrSc *httpHdrScDup(const HttpHdrSc * sc);
-extern void httpHdrScPackInto(const HttpHdrSc * sc, Packer * p);
-extern void httpHdrScJoinWith(HttpHdrSc *, const HttpHdrSc *);
+extern HttpHdrSc *httpHdrScParseCreate(String const &);
extern void httpHdrScSetMaxAge(HttpHdrSc *, char const *, int);
-extern void httpHdrScUpdateStats(const HttpHdrSc *, StatHist *);
-extern HttpHdrScTarget * httpHdrScFindTarget (HttpHdrSc *sc, const char *target);
-extern HttpHdrScTarget * httpHdrScGetMergedTarget (HttpHdrSc *sc, const char \
*ourtarget);
-
-extern void httpHeaderPutSc(HttpHeader *hdr, const HttpHdrSc *sc);
-extern HttpHdrSc *httpHeaderGetSc(const HttpHeader *hdr);
#endif /* SQUID_HTTPHDRSURROGATECONTROL_H */
=== modified file 'src/HttpHdrScTarget.cc'
--- src/HttpHdrScTarget.cc 2009-01-31 18:23:44 +0000
+++ src/HttpHdrScTarget.cc 2011-11-18 06:25:35 +0000
@@ -21,131 +21,55 @@
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#include "squid.h"
#include "HttpHdrSc.h"
-/* local prototypes */
-
-/* module initialization */
-
-/* implementation */
-
-HttpHdrScTarget *
-httpHdrScTargetCreate(char const *target)
-{
- HttpHdrScTarget *sc = new HttpHdrScTarget();
- sc->max_age = -1;
- /* max_stale is specified as 0 if not specified in the header */
- sc->target = target;
- return sc;
-}
-
-void
-httpHdrScTargetDestroy(HttpHdrScTarget * sc)
-{
- assert(sc);
- sc->target.clean();
- sc->content.clean();
- delete sc;
-}
-
-HttpHdrScTarget *
-httpHdrScTargetDup(const HttpHdrScTarget * sc)
-{
- HttpHdrScTarget *dup;
- assert(sc);
- dup = httpHdrScTargetCreate(sc->target.termedBuf());
- dup->mask = sc->mask;
- dup->max_age = sc->max_age;
- dup->content = sc->content;
- return dup;
-}
-
-/* union of two targets */
-void
-httpHdrScTargetJoinWith(HttpHdrScTarget * sc, const HttpHdrScTarget * new_sc)
-{
- assert(sc && new_sc);
- /* TODO: check both targets are the same */
-
- if (sc->max_age < 0)
- sc->max_age = new_sc->max_age;
-
- if (sc->max_stale < new_sc->max_stale)
- sc->max_stale = new_sc->max_stale;
-
- /* RC TODO: copy unique missing content stringlist entries */
- sc->mask |= new_sc->mask;
-}
-
extern http_hdr_sc_type &operator++ (http_hdr_sc_type &aHeader);
-extern int operator - (http_hdr_sc_type const &anSc, http_hdr_sc_type const &anSc2);
/* copies non-extant fields from new_sc to this sc */
void
-httpHdrScTargetMergeWith(HttpHdrScTarget * sc, const HttpHdrScTarget * new_sc)
+HttpHdrScTarget::mergeWith(const HttpHdrScTarget * new_sc)
{
- http_hdr_sc_type c;
- assert(sc && new_sc);
+ assert(new_sc);
/* Don't touch the target - this is used to get the operations for a
* single surrogate
*/
- for (c = SC_NO_STORE; c < SC_ENUM_END; ++c)
- if (!EBIT_TEST(sc->mask, c) && EBIT_TEST(new_sc->mask,c)) {
- EBIT_SET(sc->mask, c);
+ if (new_sc->hasNoStore())
+ noStore(true);
- switch (c) {
+ if (new_sc->hasNoStoreRemote())
+ noStoreRemote(true);
- case SC_MAX_AGE:
- sc->max_age = new_sc->max_age;
- sc->max_stale = new_sc->max_stale;
- break;
-
- case SC_CONTENT:
- assert (sc->content.size() == 0);
- sc->content = new_sc->content;
- break;
-
- default:
- break;
- }
- }
-}
+ if (new_sc->hasMaxAge() && !hasMaxAge()) {
+ maxAge(new_sc->maxAge());
+ maxStale(new_sc->maxStale());
+ }
-/* negative max_age will clean old max_Age setting */
-void
-httpHdrScTargetSetMaxAge(HttpHdrScTarget * sc, int max_age)
-{
- assert(sc);
- sc->max_age = max_age;
+ if (new_sc->hasContent() && !hasContent())
+ Content(new_sc->content());
- if (max_age >= 0)
- EBIT_SET(sc->mask, SC_MAX_AGE);
- else
- EBIT_CLR(sc->mask, SC_MAX_AGE);
}
void
-httpHdrScTargetUpdateStats(const HttpHdrScTarget * sc, StatHist * hist)
+HttpHdrScTarget::updateStats(StatHist * hist) const
{
http_hdr_sc_type c;
- assert(sc);
for (c = SC_NO_STORE; c < SC_ENUM_END; ++c)
- if (EBIT_TEST(sc->mask, c))
+ if (isSet(c))
statHistCount(hist, c);
}
=== modified file 'src/HttpHdrScTarget.h'
--- src/HttpHdrScTarget.h 2009-01-21 03:47:47 +0000
+++ src/HttpHdrScTarget.h 2011-11-18 06:25:35 +0000
@@ -18,59 +18,116 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#ifndef SQUID_HTTPHDRSURROGATECONTROLTARGET_H
#define SQUID_HTTPHDRSURROGATECONTROLTARGET_H
class Packer;
class StoreEntry;
-/* for MEMPROXY_CLASS() macros */
#include "MemPool.h"
-/* for dlink_node */
#include "dlink.h"
-/* for String */
#include "SquidString.h"
+#include "typedefs.h"
-/** HTTP Surogate-Control: header field */
+/** Representation of HTTP Surogate-Control header field targeted directive
+ *
+ * \see HttpHdrSc
+ */
class HttpHdrScTarget
{
+ // parsing is done in HttpHdrSc, need to grant them access.
+ friend class HttpHdrSc;
public:
+ static const int MAX_AGE_UNSET=-1; //max-age is unset
+ static const int MAX_STALE_UNSET=0; //max-stale is unset
+
+ HttpHdrScTarget(const char *target_):
+ mask(0), max_age(MAX_AGE_UNSET), max_stale(MAX_STALE_UNSET),target(target_) \
{} + HttpHdrScTarget(const String &target_):
+ mask(0), max_age(MAX_AGE_UNSET), max_stale(MAX_STALE_UNSET),target(target_) \
{} + HttpHdrScTarget(const HttpHdrScTarget &t):
+ mask(t.mask), max_age(t.max_age), max_stale(t.max_stale),
+ content_(t.content_), target(t.target) {}
+
+ bool hasNoStore() const {return isSet(SC_NO_STORE); }
+ void noStore(bool v) { setMask(SC_NO_STORE,v); }
+ bool noStore() const { return isSet(SC_NO_STORE); }
+ void clearNoStore() { setMask(SC_NO_STORE, false); }
+
+ bool hasNoStoreRemote() const {return isSet(SC_NO_STORE_REMOTE); }
+ void noStoreRemote(bool v) { setMask(SC_NO_STORE_REMOTE,v); }
+ bool noStoreRemote() const { return isSet(SC_NO_STORE_REMOTE); }
+ void clearNoStoreRemote() { setMask(SC_NO_STORE_REMOTE, false); }
+
+ bool hasMaxAge() const { return isSet(SC_MAX_AGE); }
+ void maxAge(int v) {
+ if (v >= 0) { //setting
+ setMask(SC_MAX_AGE,true);
+ max_age=v;
+ } else {
+ setMask(SC_MAX_AGE,false);
+ max_age=MAX_AGE_UNSET;
+ }
+ }
+ int maxAge() const { return max_age; }
+ void clearMaxAge() { setMask(SC_MAX_AGE,false); max_age=MAX_AGE_UNSET; }
+
+ //max_stale has no associated status-bit
+ bool hasMaxStale() const { return max_stale != MAX_STALE_UNSET; }
+ void maxStale(int v) { max_stale=v; }
+ int maxStale() const { return max_stale; }
+ void clearMaxStale() { max_stale=MAX_STALE_UNSET; }
+
+ bool hasContent() const { return isSet(SC_CONTENT); }
+ void Content(const String &v) {
+ setMask(SC_CONTENT,true);
+ content_=v;
+ }
+ String content() const { return content_; }
+ void clearContent() { setMask(SC_CONTENT,false); content_.clean(); }
+
+ bool hasTarget() const { return target.size() != 0; }
+ String Target() const { return target; }
+
+ void mergeWith(const HttpHdrScTarget * new_sc);
+ void packInto (Packer *p) const;
+ void updateStats(StatHist *) const;
+
MEMPROXY_CLASS(HttpHdrScTarget);
- dlink_node node;
+private:
+ bool isSet(http_hdr_sc_type id) const {
+ assert (id >= SC_NO_STORE && id < SC_ENUM_END);
+ return EBIT_TEST(mask,id);
+ }
+
+ void setMask(http_hdr_sc_type id, bool newval) {
+ if (newval) EBIT_SET(mask,id);
+ else EBIT_CLR(mask,id);
+ }
+
int mask;
int max_age;
int max_stale;
- String content;
+ String content_;
String target;
+ dlink_node node;
};
MEMPROXY_CLASS_INLINE(HttpHdrScTarget);
-/* Http Surrogate control header field 'targets' */
-extern HttpHdrScTarget * httpHdrScTargetCreate (const char *);
-extern void httpHdrScTargetDestroy(HttpHdrScTarget *);
-extern HttpHdrScTarget *httpHdrScTargetDup(const HttpHdrScTarget *);
-extern void httpHdrScTargetPackInto(const HttpHdrScTarget *, Packer *);
-extern void httpHdrScTargetSetMaxAge(HttpHdrScTarget *, int);
-extern void httpHdrScTargetJoinWith(HttpHdrScTarget *, const HttpHdrScTarget *);
-extern void httpHdrScTargetMergeWith(HttpHdrScTarget *, const HttpHdrScTarget *);
extern void httpHdrScTargetStatDumper(StoreEntry * sentry, int idx, double val, \
double size, int count);
-/* for StatHist */
-#include "typedefs.h"
-
-extern void httpHdrScTargetUpdateStats(const HttpHdrScTarget *, StatHist *);
#endif /* SQUID_HTTPHDRSURROGATECONTROLTARGET_H */
=== modified file 'src/HttpHeader.cc'
--- src/HttpHeader.cc 2011-09-28 12:13:22 +0000
+++ src/HttpHeader.cc 2011-11-17 23:55:24 +0000
@@ -1192,41 +1192,41 @@
packerToMemInit(&p, &mb);
range->packInto(&p);
/* put */
addEntry(new HttpHeaderEntry(HDR_RANGE, NULL, mb.buf));
/* cleanup */
packerClean(&p);
mb.clean();
}
void
HttpHeader::putSc(HttpHdrSc *sc)
{
MemBuf mb;
Packer p;
assert(sc);
/* remove old directives if any */
delById(HDR_SURROGATE_CONTROL);
/* pack into mb */
mb.init();
packerToMemInit(&p, &mb);
- httpHdrScPackInto(sc, &p);
+ sc->packInto(&p);
/* put */
addEntry(new HttpHeaderEntry(HDR_SURROGATE_CONTROL, NULL, mb.buf));
/* cleanup */
packerClean(&p);
mb.clean();
}
void
HttpHeader::putWarning(const int code, const char *const text)
{
char buf[512];
snprintf(buf, sizeof(buf), "%i %s \"%s\"", code, visible_appname_string, text);
putStr(HDR_WARNING, buf);
}
/* add extension header (these fields are not parsed/analyzed/joined, etc.) */
void
HttpHeader::putExt(const char *name, const char *value)
{
assert(name && value);
@@ -1349,46 +1349,46 @@
if ((e = findEntry(HDR_RANGE)) ||
(e = findEntry(HDR_REQUEST_RANGE))) {
r = HttpHdrRange::ParseCreate(&e->value);
httpHeaderNoteParsedEntry(e->id, e->value, !r);
}
return r;
}
HttpHdrSc *
HttpHeader::getSc() const
{
if (!CBIT_TEST(mask, HDR_SURROGATE_CONTROL))
return NULL;
String s;
(void) getList(HDR_SURROGATE_CONTROL, &s);
- HttpHdrSc *sc = httpHdrScParseCreate(&s);
+ HttpHdrSc *sc = httpHdrScParseCreate(s);
- HttpHeaderStats[owner].ccParsedCount++;
+ ++HttpHeaderStats[owner].ccParsedCount;
if (sc)
- httpHdrScUpdateStats(sc, &HttpHeaderStats[owner].scTypeDistr);
+ sc->updateStats(&HttpHeaderStats[owner].scTypeDistr);
httpHeaderNoteParsedEntry(HDR_SURROGATE_CONTROL, s, !sc);
return sc;
}
HttpHdrContRange *
HttpHeader::getContRange() const
{
HttpHdrContRange *cr = NULL;
HttpHeaderEntry *e;
if ((e = findEntry(HDR_CONTENT_RANGE))) {
cr = httpHdrContRangeParseCreate(e->value.termedBuf());
httpHeaderNoteParsedEntry(e->id, e->value, !cr);
}
return cr;
}
=== modified file 'src/HttpReply.cc'
--- src/HttpReply.cc 2011-09-28 22:42:19 +0000
+++ src/HttpReply.cc 2011-10-04 22:01:48 +0000
@@ -391,41 +391,41 @@
content_type.limitInit(str, strcspn(str, ";\t "));
else
content_type = String();
/* be sure to set expires after date and cache-control */
expires = hdrExpirationTime();
}
/* sync this routine when you update HttpReply struct */
void
HttpReply::hdrCacheClean()
{
content_type.clean();
if (cache_control) {
delete cache_control;
cache_control = NULL;
}
if (surrogate_control) {
- httpHdrScDestroy(surrogate_control);
+ delete surrogate_control;
surrogate_control = NULL;
}
if (content_range) {
httpHdrContRangeDestroy(content_range);
content_range = NULL;
}
}
/*
* Returns the body size of a HTTP response
*/
int64_t
HttpReply::bodySize(const HttpRequestMethod& method) const
{
if (sline.version.major < 1)
return -1;
else if (method.id() == METHOD_HEAD)
return 0;
else if (sline.status == HTTP_OK)
=== modified file 'src/esi/Esi.cc'
--- src/esi/Esi.cc 2011-05-13 08:13:01 +0000
+++ src/esi/Esi.cc 2011-11-18 06:25:35 +0000
@@ -2415,39 +2415,39 @@
CBDATA_INIT_TYPE_FREECB(esiOtherwise, esiSequence::Free);
rv = (void *)cbdataAlloc (esiOtherwise);
return rv;
}
void
esiOtherwise::operator delete (void *address)
{
cbdataFree (address);
}
#endif
/* TODO: implement surrogate targeting and control processing */
int
esiEnableProcessing (HttpReply *rep)
{
int rv = 0;
if (rep->surrogate_control) {
- HttpHdrScTarget *sctusable = httpHdrScGetMergedTarget \
(rep->surrogate_control,
- Config.Accel.surrogate_id);
+ HttpHdrScTarget *sctusable =
+ rep->surrogate_control->getMergedTarget(Config.Accel.surrogate_id);
- if (!sctusable || sctusable->content.size() == 0)
+ if (!sctusable || !sctusable->hasContent())
/* Nothing generic or targeted at us, or no
* content processing requested
*/
return 0;
- if (sctusable->content.pos("ESI/1.0") != NULL)
+ if (sctusable->content().pos("ESI/1.0") != NULL)
rv = 1;
- httpHdrScTargetDestroy (sctusable);
+ delete sctusable;
}
return rv;
}
#endif /* USE_SQUID_ESI == 1 */
=== modified file 'src/htcp.cc'
--- src/htcp.cc 2011-09-02 12:35:57 +0000
+++ src/htcp.cc 2011-11-17 18:16:28 +0000
@@ -32,40 +32,41 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#include "squid.h"
#include "AccessLogEntry.h"
#include "acl/FilledChecklist.h"
#include "acl/Acl.h"
#include "comm.h"
#include "comm/Loops.h"
#include "htcp.h"
#include "http.h"
#include "HttpRequest.h"
#include "icmp/net_db.h"
#include "ipc/StartListening.h"
#include "ip/tools.h"
#include "MemBuf.h"
#include "SquidTime.h"
#include "Store.h"
#include "StoreClient.h"
+#include "compat/xalloc.h"
/// dials htcpIncomingConnectionOpened call
class HtcpListeningStartedDialer: public CallDialer,
public Ipc::StartListeningCb
{
public:
typedef void (*Handler)(int errNo);
HtcpListeningStartedDialer(Handler aHandler): handler(aHandler) {}
virtual void print(std::ostream &os) const { startPrint(os) << ')'; }
virtual bool canDial(AsyncCall &) const { return true; }
virtual void dial(AsyncCall &) { (handler)(errNo); }
public:
Handler handler;
};
typedef struct _Countstr Countstr;
typedef struct _htcpHeader htcpHeader;
=== modified file 'src/http.cc'
--- src/http.cc 2011-10-21 16:20:42 +0000
+++ src/http.cc 2011-11-17 23:25:48 +0000
@@ -268,68 +268,68 @@
* changed.
*/
if (e->mem_obj->request)
pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD);
else
pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD);
if (pe != NULL) {
assert(e != pe);
#if USE_HTCP
neighborsHtcpClear(e, NULL, e->mem_obj->request, \
HttpRequestMethod(METHOD_HEAD), HTCP_CLR_INVALIDATION); #endif
pe->release();
}
}
void
HttpStateData::processSurrogateControl(HttpReply *reply)
{
if (request->flags.accelerated && reply->surrogate_control) {
- HttpHdrScTarget *sctusable = \
httpHdrScGetMergedTarget(reply->surrogate_control, Config.Accel.surrogate_id); + \
HttpHdrScTarget *sctusable = \
reply->surrogate_control->getMergedTarget(Config.Accel.surrogate_id);
if (sctusable) {
- if (EBIT_TEST(sctusable->mask, SC_NO_STORE) ||
+ if (sctusable->noStore() ||
(Config.onoff.surrogate_is_remote
- && EBIT_TEST(sctusable->mask, SC_NO_STORE_REMOTE))) {
+ && sctusable->noStoreRemote())) {
surrogateNoStore = true;
entry->makePrivate();
}
/* The HttpHeader logic cannot tell if the header it's parsing is a \
reply to an
* accelerated request or not...
* Still, this is an abstraction breach. - RC
*/
- if (sctusable->max_age != -1) {
- if (sctusable->max_age < sctusable->max_stale)
- reply->expires = reply->date + sctusable->max_age;
+ if (sctusable->hasMaxAge()) {
+ if (sctusable->maxAge() < sctusable->maxStale())
+ reply->expires = reply->date + sctusable->maxAge();
else
- reply->expires = reply->date + sctusable->max_stale;
+ reply->expires = reply->date + sctusable->maxStale();
/* And update the timestamps */
entry->timestampsSet();
}
/* We ignore cache-control directives as per the Surrogate specification \
*/ ignoreCacheControl = true;
- httpHdrScTargetDestroy(sctusable);
+ delete sctusable;
}
}
}
int
HttpStateData::cacheableReply()
{
HttpReply const *rep = finalReply();
HttpHeader const *hdr = &rep->header;
const char *v;
#if USE_HTTP_VIOLATIONS
const refresh_t *R = NULL;
/* This strange looking define first looks up the refresh pattern
* and then checks if the specified flag is set. The main purpose
* of this is to simplify the refresh pattern lookup and USE_HTTP_VIOLATIONS
* condition
*/
#define REFRESH_OVERRIDE(flag) \
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic