// should be configurable.
}
-void Adaptation::Icap::ServiceRep::putConnection(int fd, bool isReusable, const char *comment)
+ // returns a persistent or brand new connection; negative int on failures
+ int Adaptation::Icap::ServiceRep::getConnection(bool retriableXact, bool &reused)
+ {
+ Ip::Address client_addr;
+
+ int connection = theIdleConns.pop(cfg().host.termedBuf(), cfg().port, NULL, client_addr,
+ retriableXact);
+
+ reused = connection >= 0; // reused a persistent connection
+
+ if (!reused) { // need a new connection
+ Ip::Address outgoing; // default: IP6_ANY_ADDR
+ if (!Ip::EnableIpv6)
+ outgoing.SetIPv4();
+ else if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && !cfg().ipv6) {
+ /* split-stack for now requires default IPv4-only socket */
+ outgoing.SetIPv4();
+ }
+ connection = comm_open(SOCK_STREAM, 0, outgoing, COMM_NONBLOCKING, cfg().uri.termedBuf());
+ }
+
+ if (connection >= 0)
+ ++theBusyConns;
+
+ return connection;
+ }
+
+ // pools connection if it is reusable or closes it
- debugs(93, 3, HERE << "closing pconn" << comment);
++void Adaptation::Icap::ServiceRep::putConnection(int fd, bool isReusable, bool sendReset, const char *comment)
+ {
+ Must(fd >= 0);
+ // do not pool an idle connection if we owe connections
+ if (isReusable && excessConnections() == 0) {
+ debugs(93, 3, HERE << "pushing pconn" << comment);
+ commSetTimeout(fd, -1, NULL, NULL);
+ Ip::Address anyAddr;
+ theIdleConns.push(fd, cfg().host.termedBuf(), cfg().port, NULL, anyAddr);
+ } else {
- comm_close(fd);
++ debugs(93, 3, HERE << (sendReset ? "RST" : "FIN") << "-closing " <<
++ comment);
+ // comm_close will clear timeout
++ if (sendReset)
++ comm_reset_close(fd);
++ else
++ comm_close(fd);
+ }
+
+ Must(theBusyConns > 0);
+ --theBusyConns;
+ // a connection slot released. Check if there are waiters....
+ busyCheckpoint();
+ }
+
+ // a wrapper to avoid exposing theIdleConns
+ void Adaptation::Icap::ServiceRep::noteConnectionUse(int fd)
+ {
+ Must(fd >= 0);
+ fd_table[fd].noteUse(&theIdleConns);
+ }
+
+ void Adaptation::Icap::ServiceRep::setMaxConnections()
+ {
+ if (cfg().maxConn >= 0)
+ theMaxConnections = cfg().maxConn;
+ else if (theOptions && theOptions->max_connections >= 0)
+ theMaxConnections = theOptions->max_connections;
+ else {
+ theMaxConnections = -1;
+ return;
+ }
+
+ if (::Config.workers > 1 )
+ theMaxConnections /= ::Config.workers;
+ }
+
+ int Adaptation::Icap::ServiceRep::availableConnections() const
+ {
+ if (theMaxConnections < 0)
+ return -1;
+
+ // we are available if we can open or reuse connections
+ // in other words, if we will not create debt
+ int available = max(0, theMaxConnections - theBusyConns);
+
+ if (!available && !connOverloadReported) {
+ debugs(93, DBG_IMPORTANT, "WARNING: ICAP Max-Connections limit " <<
+ "exceeded for service " << cfg().uri << ". Open connections now: " <<
+ theBusyConns + theIdleConns.count() << ", including " <<
+ theIdleConns.count() << " idle persistent connections.");
+ connOverloadReported = true;
+ }
+
+ if (cfg().onOverload == srvForce)
+ return -1;
+
+ return available;
+ }
+
+ // The number of connections which excess the Max-Connections limit
+ int Adaptation::Icap::ServiceRep::excessConnections() const
+ {
+ if (theMaxConnections < 0)
+ return 0;
+
+ // Waiters affect the number of needed connections but a needed
+ // connection may still be excessive from Max-Connections p.o.v.
+ // so we should not account for waiting transaction needs here.
+ const int debt = theBusyConns + theIdleConns.count() - theMaxConnections;
+ if (debt > 0)
+ return debt;
+ else
+ return 0;
+ }
+
+ void Adaptation::Icap::ServiceRep::noteGoneWaiter()
+ {
+ theAllWaiters--;
+
+ // in case the notified transaction did not take the connection slot
+ busyCheckpoint();
+ }
+
+ // called when a connection slot may become available
+ void Adaptation::Icap::ServiceRep::busyCheckpoint()
+ {
+ if (theNotificationWaiters.empty()) // nobody is waiting for a slot
+ return;
+
+ int freed = 0;
+ int available = availableConnections();
+
+ if (available < 0) {
+ // It is possible to have waiters when no limit on connections exist in
+ // case of reconfigure or because new Options received.
+ // In this case, notify all waiting transactions.
+ freed = theNotificationWaiters.size();
+ } else {
+ // avoid notifying more waiters than there will be available slots
+ const int notifiedWaiters = theAllWaiters - theNotificationWaiters.size();
+ freed = available - notifiedWaiters;
+ }
+
+ debugs(93,7, HERE << "Available connections: " << available <<
+ " freed slots: " << freed <<
+ " waiting in queue: " << theNotificationWaiters.size());
+
+ while (freed > 0 && !theNotificationWaiters.empty()) {
+ Client i = theNotificationWaiters.front();
+ theNotificationWaiters.pop_front();
+ ScheduleCallHere(i.callback);
+ i.callback = NULL;
+ --freed;
+ }
+ }
+
void Adaptation::Icap::ServiceRep::suspend(const char *reason)
{
if (isSuspended) {
- /*
- * $Id$
- *
- * DEBUG: section 20 Storage Manager
- * AUTHOR: Robert Collins
- *
- * 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"
- StorePointer Store::CurrentRoot = NULL;
+ #define STUB_API "store.cc"
+ #include "tests/STUB.h"
+
+ /* and code defined in the wrong .cc file */
+ #include "SwapDir.h"
+ void StoreController::maintain() STUB
+ #include "RemovalPolicy.h"
+ RemovalPolicy * createRemovalPolicy(RemovalPolicySettings * settings) STUB_RETVAL(NULL)
- extern "C" void
- storeAppendPrintf(StoreEntry * e, const char *fmt,...)
- {
- fatal("storeAppendPrintf: Not implemented");
- }
- void
- storeAppendVPrintf(StoreEntry * e, const char *fmt, va_list vargs)
+ #include "Store.h"
+ StorePointer Store::CurrentRoot = NULL;
+ StoreIoStats store_io_stats;
+ bool StoreEntry::checkDeferRead(int fd) const STUB_RETVAL(false)
+ const char *StoreEntry::getMD5Text() const STUB_RETVAL(NULL)
+ StoreEntry::StoreEntry() STUB
+ StoreEntry::StoreEntry(const char *url, const char *log_url) STUB
+ HttpReply const *StoreEntry::getReply() const STUB_RETVAL(NULL)
+ void StoreEntry::write(StoreIOBuffer) STUB
+ bool StoreEntry::isAccepting() const STUB_RETVAL(false)
+ size_t StoreEntry::bytesWanted(Range<size_t> const) const STUB_RETVAL(0)
+ void StoreEntry::complete() STUB
+ store_client_t StoreEntry::storeClientType() const STUB_RETVAL(STORE_NON_CLIENT)
+ char const *StoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
-void StoreEntry::replaceHttpReply(HttpReply *) STUB
++void StoreEntry::replaceHttpReply(HttpReply *, bool andStartWriting) STUB
+ bool StoreEntry::swapoutPossible() STUB_RETVAL(false)
+ void StoreEntry::trimMemory() STUB
+ void StoreEntry::abort() STUB
+ void StoreEntry::unlink() STUB
+ void StoreEntry::makePublic() STUB
+ void StoreEntry::makePrivate() STUB
+ void StoreEntry::setPublicKey() STUB
+ void StoreEntry::setPrivateKey() STUB
+ void StoreEntry::expireNow() STUB
+ void StoreEntry::releaseRequest() STUB
+ void StoreEntry::negativeCache() STUB
+ void StoreEntry::cacheNegatively() STUB
+ void StoreEntry::invokeHandlers() STUB
+ void StoreEntry::purgeMem() STUB
+ void StoreEntry::swapOut() STUB
+ bool StoreEntry::swapOutAble() const STUB_RETVAL(false)
-void StoreEntry::swapOutFileClose() STUB
++void StoreEntry::swapOutFileClose(int how) STUB
+ const char *StoreEntry::url() const STUB_RETVAL(NULL)
+ int StoreEntry::checkCachable() STUB_RETVAL(0)
+ int StoreEntry::checkNegativeHit() const STUB_RETVAL(0)
+ int StoreEntry::locked() const STUB_RETVAL(0)
+ int StoreEntry::validToSend() const STUB_RETVAL(0)
-int StoreEntry::keepInMemory() const STUB_RETVAL(0)
++bool StoreEntry::memoryCachable() const STUB_RETVAL(false)
+ void StoreEntry::createMemObject(const char *, const char *) STUB
++void StoreEntry::hideMemObject() STUB
+ void StoreEntry::dump(int debug_lvl) const STUB
+ void StoreEntry::hashDelete() STUB
+ void StoreEntry::hashInsert(const cache_key *) STUB
+ void StoreEntry::registerAbort(STABH * cb, void *) STUB
+ void StoreEntry::reset() STUB
+ void StoreEntry::setMemStatus(mem_status_t) STUB
+ void StoreEntry::timestampsSet() STUB
+ void StoreEntry::unregisterAbort() STUB
+ void StoreEntry::destroyMemObject() STUB
+ int StoreEntry::checkTooSmall() STUB_RETVAL(0)
+ void StoreEntry::delayAwareRead(int fd, char *buf, int len, AsyncCall::Pointer callback) STUB
+ void StoreEntry::setNoDelay (bool const) STUB
+ bool StoreEntry::modifiedSince(HttpRequest * request) const STUB_RETVAL(false)
+ bool StoreEntry::hasIfMatchEtag(const HttpRequest &request) const STUB_RETVAL(false)
+ bool StoreEntry::hasIfNoneMatchEtag(const HttpRequest &request) const STUB_RETVAL(false)
-RefCount<Store> StoreEntry::store() const STUB_RETVAL(StorePointer())
++RefCount<SwapDir> StoreEntry::store() const STUB_RETVAL(NULL)
+ size_t StoreEntry::inUseCount() STUB_RETVAL(0)
+ void StoreEntry::getPublicByRequestMethod(StoreClient * aClient, HttpRequest * request, const HttpRequestMethod& method) STUB
+ void StoreEntry::getPublicByRequest(StoreClient * aClient, HttpRequest * request) STUB
+ void StoreEntry::getPublic(StoreClient * aClient, const char *uri, const HttpRequestMethod& method) STUB
+ void *StoreEntry::operator new(size_t byteCount)
{
- fatal("storeAppendVPrintf: Not implemented");
+ STUB
+ return new StoreEntry();
}
+ void StoreEntry::operator delete(void *address) STUB
+ void StoreEntry::setReleaseFlag() STUB
+ //#if USE_SQUID_ESI
+ //ESIElement::Pointer StoreEntry::cachedESITree STUB_RETVAL(NULL)
+ //#endif
+ void StoreEntry::append(char const *, int len) STUB
+ void StoreEntry::buffer() STUB
+ void StoreEntry::flush() STUB
+ int StoreEntry::unlock() STUB_RETVAL(0)
+ int64_t StoreEntry::objectLen() const STUB_RETVAL(0)
+ int64_t StoreEntry::contentLen() const STUB_RETVAL(0)
+ void StoreEntry::lock() STUB
+ void StoreEntry::release() STUB
+
+ NullStoreEntry *NullStoreEntry::getInstance() STUB_RETVAL(NULL)
+ const char *NullStoreEntry::getMD5Text() const STUB_RETVAL(NULL)
+ void NullStoreEntry::operator delete(void *address) STUB
+ // private virtual. Why is this linked from outside?
+ const char *NullStoreEntry::getSerialisedMetaData() STUB_RETVAL(NULL)
+
+ void Store::Root(Store *) STUB
+ void Store::Root(RefCount<Store>) STUB
+ void Store::Stats(StoreEntry * output) STUB
+ void Store::Maintain(void *unused) STUB
+ void Store::create() STUB
+ void Store::diskFull() STUB
+ void Store::sync() STUB
+ void Store::unlink(StoreEntry &) STUB
+
+ SQUIDCEXTERN size_t storeEntryInUse() STUB_RETVAL(0)
+ SQUIDCEXTERN const char *storeEntryFlags(const StoreEntry *) STUB_RETVAL(NULL)
+ void storeEntryReplaceObject(StoreEntry *, HttpReply *) STUB
+ SQUIDCEXTERN StoreEntry *storeGetPublic(const char *uri, const HttpRequestMethod& method) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeGetPublicByRequest(HttpRequest * request) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeGetPublicByRequestMethod(HttpRequest * request, const HttpRequestMethod& method) STUB_RETVAL(NULL)
+ SQUIDCEXTERN StoreEntry *storeCreateEntry(const char *, const char *, request_flags, const HttpRequestMethod&) STUB_RETVAL(NULL)
+ SQUIDCEXTERN void storeInit(void) STUB
+ SQUIDCEXTERN void storeConfigure(void) STUB
+ SQUIDCEXTERN void storeFreeMemory(void) STUB
+ SQUIDCEXTERN int expiresMoreThan(time_t, time_t) STUB_RETVAL(0)
+ SQUIDCEXTERN void storeAppendPrintf(StoreEntry *, const char *,...) STUB
+ void storeAppendVPrintf(StoreEntry *, const char *, va_list ap) STUB
+ SQUIDCEXTERN int storeTooManyDiskFilesOpen(void) STUB_RETVAL(0)
+ SQUIDCEXTERN void storeHeapPositionUpdate(StoreEntry *, SwapDir *) STUB
+ SQUIDCEXTERN void storeSwapFileNumberSet(StoreEntry * e, sfileno filn) STUB
+ SQUIDCEXTERN void storeFsInit(void) STUB
+ SQUIDCEXTERN void storeFsDone(void) STUB
+ SQUIDCEXTERN void storeReplAdd(const char *, REMOVALPOLICYCREATE *) STUB
+ void destroyStoreEntry(void *) STUB
+ // in Packer.cc !? SQUIDCEXTERN void packerToStoreInit(Packer * p, StoreEntry * e) STUB
+ SQUIDCEXTERN void storeGetMemSpace(int size) STUB
#if !_USE_INLINE_
#include "Store.cci"