]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Prevented STORE_DISK_CLIENT assertions for aborted entries. Polished code.
authorAlex Rousskov <rousskov@measurement-factory.com>
Tue, 30 Jul 2013 17:10:57 +0000 (11:10 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Tue, 30 Jul 2013 17:10:57 +0000 (11:10 -0600)
To prevent store_client.cc:445: "STORE_DISK_CLIENT == getType()" assertions,
rewrote the storeClientNoMoreToSend() function so that it does not send a
STORE_MEM_CLIENT to read from disk. Used this opportunity to polish this
negative function code and convert it into a positive method.

Documented known (and mostly old) StoreEntry::storeClientType() problems.

src/StoreClient.h
src/store.cc
src/store_client.cc

index 9264c6fd7442bcc1da8d93c5f0a8d014f2b2ad9e..f7e2c3b06ecb7b4b8ac99cd9c5d2e7254c4a3c1d 100644 (file)
@@ -98,6 +98,8 @@ public:
     StoreIOBuffer copyInto;
 
 private:
+    bool moreToSend() const;
+
     void fileRead();
     void scheduleDiskRead();
     void scheduleMemRead();
index 20d95824689ca023c34571ee56e7ff76afc6704b..9aabf49d6816d2d0fdc19744634ae28cf8de8acb 100644 (file)
@@ -309,6 +309,11 @@ StoreEntry::setNoDelay (bool const newValue)
         mem_obj->setNoDelay(newValue);
 }
 
+// XXX: Type names mislead. STORE_DISK_CLIENT actually means that we should
+//      open swapin file, aggressively trim memory, and ignore read-ahead gap.
+//      It does not mean we will read from disk exclusively (or at all!).
+// XXX: May create STORE_DISK_CLIENT with no disk caching configured.
+// XXX: Collapsed clients cannot predict their type.
 store_client_t
 StoreEntry::storeClientType() const
 {
@@ -336,7 +341,7 @@ StoreEntry::storeClientType() const
             if (swap_status == SWAPOUT_DONE) {
                 debugs(20,7, HERE << mem_obj << " lo: " << mem_obj->inmem_lo << " hi: " << mem_obj->endOffset() << " size: " << mem_obj->object_sz);
                 if (mem_obj->endOffset() == mem_obj->object_sz) {
-                    /* hot object fully swapped in */
+                    /* hot object fully swapped in (XXX: or swapped out?) */
                     return STORE_MEM_CLIENT;
                 }
             } else {
index 519c0d0e4b788398f146c6937de2a9555723d2cc..58c6dc63dccd6effc7c8474b9ae86e979388f9b3 100644 (file)
@@ -278,31 +278,35 @@ store_client::copy(StoreEntry * anEntry,
     anEntry->unlock("store_client::copy");
 }
 
-/*
- * This function is used below to decide if we have any more data to
- * send to the client.  If the store_status is STORE_PENDING, then we
- * do have more data to send.  If its STORE_OK, then
- * we continue checking.  If the object length is negative, then we
- * don't know the real length and must open the swap file to find out.
- * However, if there is no swap file, then there is no more to send.
- * If the length is >= 0, then we compare it to the requested copy
- * offset.
- */
-static int
-storeClientNoMoreToSend(StoreEntry * e, store_client * sc)
+/// Whether there is (or will be) more entry data for us.
+bool
+store_client::moreToSend() const
 {
-    int64_t len;
+    if (entry->store_status == STORE_PENDING)
+        return true; // there may be more coming
 
-    if (e->store_status == STORE_PENDING)
-        return 0;
+    /* STORE_OK, including aborted entries: no more data is coming */
 
-    if ((len = e->objectLen()) < 0)
-        return e->swap_filen < 0;
+    const int64_t len = entry->objectLen();
 
-    if (sc->copyInto.offset < len)
-        return 0;
+    // If we do not know the entry length, then we have to open the swap file,
+    // which is only possible if there is one AND if we are allowed to use it.
+    const bool canSwapIn = entry->swap_filen >= 0 &&
+                           getType() == STORE_DISK_CLIENT;
+    if (len < 0)
+        return canSwapIn;
 
-    return 1;
+    if (copyInto.offset >= len)
+        return false; // sent everything there is
+
+    if (canSwapIn)
+        return true; // if we lack prefix, we can swap it in
+
+    // If we cannot swap in, make sure we have what we want in RAM. Otherwise,
+    // scheduleRead calls scheduleDiskRead which asserts on STORE_MEM_CLIENTs.
+    const MemObject *mem = entry->mem_obj;
+    return mem &&
+        mem->inmem_lo <= copyInto.offset && copyInto.offset < mem->endOffset();
 }
 
 static void
@@ -359,7 +363,7 @@ store_client::doCopy(StoreEntry *anEntry)
            copyInto.offset << ", hi: " <<
            mem->endOffset());
 
-    if (storeClientNoMoreToSend(entry, this)) {
+    if (!moreToSend()) {
         /* There is no more to send! */
         debugs(33, 3, HERE << "There is no more to send!");
         callback(0);