]> git.ipfire.org Git - thirdparty/squid.git/blobdiff - src/pconn.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / pconn.cc
index 248b1ca898d56fa5bbdc30a5d6b66ca2372a3e51..397a6b8b6b825e40a35d42f5e0f93d852b95b914 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
  *
  * Squid software is distributed under GPLv2+ license and includes
  * contributions from numerous individuals and organizations.
@@ -31,13 +31,19 @@ CBDATA_CLASS_INIT(IdleConnList);
 
 /* ========== IdleConnList ============================================ */
 
-IdleConnList::IdleConnList(const char *key, PconnPool *thePool) :
+IdleConnList::IdleConnList(const char *aKey, PconnPool *thePool) :
     capacity_(PCONN_FDS_SZ),
     size_(0),
     parent_(thePool)
 {
-    hash.key = xstrdup(key);
+    //Initialize hash_link members
+    key = xstrdup(aKey);
+    next = NULL;
+
     theList_ = new Comm::ConnectionPointer[capacity_];
+
+    registerRunner();
+
 // TODO: re-attach to MemPools. WAS: theList = (?? *)pconn_fds_pool->alloc();
 }
 
@@ -53,7 +59,7 @@ IdleConnList::~IdleConnList()
 
     delete[] theList_;
 
-    xfree(hash.key);
+    xfree(key);
 }
 
 /** Search the list. Matches by FD socket number.
@@ -94,7 +100,7 @@ IdleConnList::removeAt(int index)
     if (parent_) {
         parent_->noteConnectionRemoved();
         if (size_ == 0) {
-            debugs(48, 3, HERE << "deleting " << hashKeyStr(&hash));
+            debugs(48, 3, "deleting " << hashKeyStr(this));
             delete this;
         }
     }
@@ -145,7 +151,7 @@ IdleConnList::closeN(size_t n)
     }
 
     if (parent_ && size_ == 0) {
-        debugs(48, 3, HERE << "deleting " << hashKeyStr(&hash));
+        debugs(48, 3, "deleting " << hashKeyStr(this));
         delete this;
     }
 }
@@ -236,25 +242,25 @@ IdleConnList::pop()
  * quite a bit of CPU. Just keep it in mind.
  */
 Comm::ConnectionPointer
-IdleConnList::findUseable(const Comm::ConnectionPointer &key)
+IdleConnList::findUseable(const Comm::ConnectionPointer &aKey)
 {
     assert(size_);
 
     // small optimization: do the constant bool tests only once.
-    const bool keyCheckAddr = !key->local.isAnyAddr();
-    const bool keyCheckPort = key->local.port() > 0;
+    const bool keyCheckAddr = !aKey->local.isAnyAddr();
+    const bool keyCheckPort = aKey->local.port() > 0;
 
     for (int i=size_-1; i>=0; --i) {
 
         if (!isAvailable(i))
             continue;
 
-        // local end port is required, but dont match.
-        if (keyCheckPort && key->local.port() != theList_[i]->local.port())
+        // local end port is required, but do not match.
+        if (keyCheckPort && aKey->local.port() != theList_[i]->local.port())
             continue;
 
         // local address is required, but does not match.
-        if (keyCheckAddr && key->local.matchIPAddr(theList_[i]->local) != 0)
+        if (keyCheckAddr && aKey->local.matchIPAddr(theList_[i]->local) != 0)
             continue;
 
         // our connection timeout handler is scheduled to run already. unsafe for now.
@@ -313,6 +319,12 @@ IdleConnList::Timeout(const CommTimeoutCbParams &io)
     list->findAndClose(io.conn);
 }
 
+void
+IdleConnList::endingShutdown()
+{
+    closeN(size_);
+}
+
 /* ========== PconnPool PRIVATE FUNCTIONS ============================================ */
 
 const char *
@@ -321,6 +333,11 @@ PconnPool::key(const Comm::ConnectionPointer &destLink, const char *domain)
     LOCAL_ARRAY(char, buf, SQUIDHOSTNAMELEN * 3 + 10);
 
     destLink->remote.toUrl(buf, SQUIDHOSTNAMELEN * 3 + 10);
+
+    // when connecting through a cache_peer, ignore the final destination
+    if (destLink->getPeer())
+        domain = nullptr;
+
     if (domain) {
         const int used = strlen(buf);
         snprintf(buf+used, SQUIDHOSTNAMELEN * 3 + 10-used, "/%s", domain);
@@ -380,7 +397,7 @@ PconnPool::PconnPool(const char *aDescr, const CbcPointer<PeerPoolMgr> &aMgr):
 static void
 DeleteIdleConnList(void *hashItem)
 {
-    delete reinterpret_cast<IdleConnList*>(hashItem);
+    delete static_cast<IdleConnList*>(hashItem);
 }
 
 PconnPool::~PconnPool()
@@ -410,10 +427,10 @@ PconnPool::push(const Comm::ConnectionPointer &conn, const char *domain)
 
     if (list == NULL) {
         list = new IdleConnList(aKey, this);
-        debugs(48, 3, HERE << "new IdleConnList for {" << hashKeyStr(&list->hash) << "}" );
-        hash_join(table, &list->hash);
+        debugs(48, 3, "new IdleConnList for {" << hashKeyStr(list) << "}" );
+        hash_join(table, list);
     } else {
-        debugs(48, 3, HERE << "found IdleConnList for {" << hashKeyStr(&list->hash) << "}" );
+        debugs(48, 3, "found IdleConnList for {" << hashKeyStr(list) << "}" );
     }
 
     list->push(conn);
@@ -431,28 +448,52 @@ PconnPool::push(const Comm::ConnectionPointer &conn, const char *domain)
 Comm::ConnectionPointer
 PconnPool::pop(const Comm::ConnectionPointer &dest, const char *domain, bool keepOpen)
 {
+    // always call shared pool first because we need to close an idle
+    // connection there if we have to use a standby connection.
+    if (const auto direct = popStored(dest, domain, keepOpen))
+        return direct;
+
+    // either there was no pconn to pop or this is not a retriable xaction
+    if (const auto peer = dest->getPeer()) {
+        if (peer->standby.pool)
+            return peer->standby.pool->popStored(dest, domain, true);
+    }
+
+    return nullptr;
+}
 
+/// implements pop() API while disregarding peer standby pools
+/// \returns an open connection or nil
+Comm::ConnectionPointer
+PconnPool::popStored(const Comm::ConnectionPointer &dest, const char *domain, const bool keepOpen)
+{
     const char * aKey = key(dest, domain);
 
     IdleConnList *list = (IdleConnList *)hash_lookup(table, aKey);
     if (list == NULL) {
         debugs(48, 3, HERE << "lookup for key {" << aKey << "} failed.");
         // failure notifications resume standby conn creation after fdUsageHigh
-        notifyManager("pop failure");
+        notifyManager("pop lookup failure");
         return Comm::ConnectionPointer();
     } else {
-        debugs(48, 3, HERE << "found " << hashKeyStr(&list->hash) <<
+        debugs(48, 3, "found " << hashKeyStr(list) <<
                (keepOpen ? " to use" : " to kill"));
     }
 
-    /* may delete list */
-    Comm::ConnectionPointer popped = list->findUseable(dest);
-    if (!keepOpen && Comm::IsConnOpen(popped))
+    if (const auto popped = list->findUseable(dest)) { // may delete list
+        // successful pop notifications replenish standby connections pool
+        notifyManager("pop");
+
+        if (keepOpen)
+            return popped;
+
         popped->close();
+        return Comm::ConnectionPointer();
+    }
 
-    // successful pop notifications replenish standby connections pool
-    notifyManager("pop");
-    return popped;
+    // failure notifications resume standby conn creation after fdUsageHigh
+    notifyManager("pop usability failure");
+    return Comm::ConnectionPointer();
 }
 
 void
@@ -479,7 +520,7 @@ PconnPool::closeN(int n)
         }
 
         // may delete current
-        reinterpret_cast<IdleConnList*>(current)->closeN(1);
+        static_cast<IdleConnList*>(current)->closeN(1);
     }
 }
 
@@ -488,7 +529,7 @@ PconnPool::unlinkList(IdleConnList *list)
 {
     theCount -= list->count();
     assert(theCount >= 0);
-    hash_remove_link(table, &list->hash);
+    hash_remove_link(table, list);
 }
 
 void