From: Amos Jeffries Date: Wed, 7 Apr 2010 09:49:57 +0000 (+1200) Subject: Author: Matthew Morgan X-Git-Tag: SQUID_3_2_0_1~313 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=11e3fa1c4b0af96ebdeea9a52f776b657900a604;p=thirdparty%2Fsquid.git Author: Matthew Morgan Add acl support to range_offset_limit. It is being parsed using the same data types as reply_body_max_size, which means the limit value gets run through parseBytesLine64, and the acl is optional. If people are using the old global style of range_offset_limit, they shouldn't have to do anything to their configs. getRangeOffsetLimit is now a member of HttpRequest, and it caches it's value the same way reply_body_max_size does for faster repeat checking. --- diff --git a/src/HttpHdrRange.cc b/src/HttpHdrRange.cc index 858ff6d795..8139d32e6a 100644 --- a/src/HttpHdrRange.cc +++ b/src/HttpHdrRange.cc @@ -524,31 +524,29 @@ HttpHdrRange::lowestOffset(int64_t size) const } /* - * Return true if the first range offset is larger than the configured - * limit. - * Note that exceeding the limit (returning true) results in only - * grabbing the needed range elements from the origin. + * \retval true Fetch only requested ranges. The first range is larger that configured limit. + * \retval false Full download. Not a range request, no limit, or the limit is not yet reached. */ bool -HttpHdrRange::offsetLimitExceeded() const +HttpHdrRange::offsetLimitExceeded(const int64_t limit) const { if (NULL == this) /* not a range request */ return false; - if (Config.rangeOffsetLimit == 0) - /* disabled */ + if (limit == 0) + /* 0 == disabled */ return true; - if (-1 == Config.rangeOffsetLimit) - /* forced */ + if (-1 == limit) + /* 'none' == forced */ return false; if (firstOffset() == -1) /* tail request */ return true; - if (Config.rangeOffsetLimit >= firstOffset()) + if (limit >= firstOffset()) /* below the limit */ return false; diff --git a/src/HttpHeaderRange.h b/src/HttpHeaderRange.h index a608b61af4..6c37749381 100644 --- a/src/HttpHeaderRange.h +++ b/src/HttpHeaderRange.h @@ -103,7 +103,7 @@ public: bool willBeComplex() const; int64_t firstOffset() const; int64_t lowestOffset(int64_t) const; - bool offsetLimitExceeded() const; + bool offsetLimitExceeded(const int64_t limit) const; bool contains(HttpHdrRangeSpec& r) const; Vector specs; diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index cc9a060494..e6f8e93dc8 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -43,6 +43,7 @@ #if ICAP_CLIENT #include "adaptation/icap/icap_log.h" #endif +#include "acl/FilledChecklist.h" HttpRequest::HttpRequest() : HttpMsg(hoRequest) { @@ -115,6 +116,7 @@ HttpRequest::init() #if ICAP_CLIENT icapHistory_ = NULL; #endif + rangeOffsetLimit = -2; //a value of -2 means not checked yet } void @@ -614,3 +616,30 @@ void HttpRequest::recordLookup(const DnsLookupDetails &dns) dnsWait = dns.wait; } } + +int64_t +HttpRequest::getRangeOffsetLimit() +{ + /* -2 is the starting value of rangeOffsetLimit. + * If it is -2, that means we haven't checked it yet. + * Otherwise, return the current value */ + if(rangeOffsetLimit != -2) + return rangeOffsetLimit; + + rangeOffsetLimit = 0; // default value for rangeOffsetLimit + + ACLFilledChecklist ch(NULL, this, NULL); + ch.src_addr = client_addr; + ch.my_addr = my_addr; + + for (acl_size_t *l = Config.rangeOffsetLimit; l; l = l -> next) { + /* if there is no ACL list or if the ACLs listed match use this limit value */ + if (!l->aclList || ch.matchAclListFast(l->aclList)) { + debugs(58, 4, HERE << "rangeOffsetLimit=" << rangeOffsetLimit); + rangeOffsetLimit = l->size; // may be -1 + break; + } + } + + return rangeOffsetLimit; +} diff --git a/src/HttpRequest.h b/src/HttpRequest.h index 8946ff2715..c0b4f56fb5 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -249,9 +249,13 @@ public: cbdataReferenceDone(pinned_connection); } + int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */ + private: const char *packableURI(bool full_uri) const; + mutable int64_t rangeOffsetLimit; /* caches the result of getRangeOffsetLimit */ + protected: virtual void packFirstLineInto(Packer * p, bool full_uri) const; diff --git a/src/cf.data.pre b/src/cf.data.pre index 11c00bbd5b..3ac8210caa 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -2107,7 +2107,7 @@ DOC_START usage: neighbor_type_domain neighbor parent|sibling domain domain ... Modifying the neighbor type for specific domains is now - possible. You can treat some domains differently than the the + possible. You can treat some domains differently than the default neighbor type specified on the 'cache_peer' line. Normally it should only be necessary to list domains which should be treated differently because the default neighbor type @@ -3566,28 +3566,42 @@ DOC_START DOC_END NAME: range_offset_limit -COMMENT: (bytes) -TYPE: b_int64_t +COMMENT: size [acl acl...] +TYPE: acl_b_size_t LOC: Config.rangeOffsetLimit -DEFAULT: 0 KB +DEFAULT: none DOC_START - Sets a upper limit on how far into the the file a Range request - may be to cause Squid to prefetch the whole file. If beyond this - limit Squid forwards the Range request as it is and the result - is NOT cached. - + usage: (size) [units] [[!]aclname] + + Sets an upper limit on how far (number of bytes) into the file + a Range request may be to cause Squid to prefetch the whole file. + If beyond this limit, Squid forwards the Range request as it is and + the result is NOT cached. + This is to stop a far ahead range request (lets say start at 17MB) from making Squid fetch the whole object up to that point before sending anything to the client. - - A value of 0 causes Squid to never fetch more than the + + Multiple range_offset_limit lines may be specified, and they will + be searched from top to bottom on each request until a match is found. + The first match found will be used. If no line matches a request, the + default limit of 0 bytes will be used. + + 'size' is the limit specified as a number of units. + + 'units' specifies whether to use bytes, KB, MB, etc. + If no units are specified bytes are assumed. + + A size of 0 causes Squid to never fetch more than the client requested. (default) - - A value of -1 causes Squid to always fetch the object from the + + A size of 'none' causes Squid to always fetch the object from the beginning so it may cache the result. (2.0 style) - - NP: Using -1 here will override any quick_abort settings that may - otherwise apply to the range request. The range request will + + 'aclname' is the name of a defined ACL. + + NP: Using 'none' as the byte value here will override any quick_abort settings + that may otherwise apply to the range request. The range request will be fully fetched from start to finish regardless of the client actions. This affects bandwidth usage. DOC_END diff --git a/src/client_side.cc b/src/client_side.cc index a1075ec3f3..bb12a18c4b 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1127,6 +1127,8 @@ ClientSocketContext::buildRangeHeader(HttpReply * rep) assert(request->range); /* check if we still want to do ranges */ + int64_t roffLimit = request->getRangeOffsetLimit(); + if (!rep) range_err = "no [parse-able] reply"; else if ((rep->sline.status != HTTP_OK) && (rep->sline.status != HTTP_PARTIAL_CONTENT)) @@ -1147,7 +1149,7 @@ ClientSocketContext::buildRangeHeader(HttpReply * rep) range_err = "canonization failed"; else if (http->request->range->isComplex()) range_err = "too complex range header"; - else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded()) + else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded(roffLimit)) range_err = "range outside range_offset_limit"; /* get rid of our range specs on error */ diff --git a/src/http.cc b/src/http.cc index 23ae05ce3b..f8eb026291 100644 --- a/src/http.cc +++ b/src/http.cc @@ -1936,8 +1936,10 @@ HttpStateData::decideIfWeDoRanges (HttpRequest * orig_request) * the server and fetch only the requested content) */ + int64_t roffLimit = orig_request->getRangeOffsetLimit(); + if (NULL == orig_request->range || !orig_request->flags.cachable - || orig_request->range->offsetLimitExceeded() || orig_request->flags.connection_auth) + || orig_request->range->offsetLimitExceeded(roffLimit) || orig_request->flags.connection_auth) result = false; debugs(11, 8, "decideIfWeDoRanges: range specs: " << diff --git a/src/store_client.cc b/src/store_client.cc index 39706e58fc..20d4ddb88f 100644 --- a/src/store_client.cc +++ b/src/store_client.cc @@ -796,7 +796,9 @@ CheckQuickAbort2(StoreEntry * entry) return 0; } - if ( Config.rangeOffsetLimit < 0 && mem->request && mem->request->range ) { + int64_t roffLimit = mem->request->getRangeOffsetLimit(); + + if ( roffLimit < 0 && mem->request && mem->request->range ) { /* Don't abort if the admin has configured range_ofset -1 to download fully for caching. */ debugs(90, 3, "CheckQuickAbort2: NO admin configured range replies to full-download"); return 0; diff --git a/src/structs.h b/src/structs.h index 6a7e71711b..5282e9319f 100644 --- a/src/structs.h +++ b/src/structs.h @@ -551,7 +551,7 @@ struct SquidConfig { } comm_incoming; int max_open_disk_fds; int uri_whitespace; - int64_t rangeOffsetLimit; + acl_size_t *rangeOffsetLimit; #if MULTICAST_MISS_STREAM struct {