]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Added disk_io_timeout to squid.conf to control approximately how long Squid take07
authorAlex Rousskov <rousskov@measurement-factory.com>
Thu, 4 Aug 2011 07:18:25 +0000 (01:18 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Thu, 4 Aug 2011 07:18:25 +0000 (01:18 -0600)
allowsDisconnecting: Timeout, server not responding. queuing time. If the
anticipated I/O time exceeds the configured limit, Squid will not swap the
corresponding object in or out, allowing for the disk queues to drain.

src/DiskIO/IpcIo/IpcIoFile.cc
src/DiskIO/IpcIo/IpcIoFile.h
src/cf.data.pre
src/fs/rock/RockIoState.cc
src/fs/rock/RockSwapDir.cc
src/ipc/Queue.cc
src/ipc/Queue.h
src/ipc/mem/Pages.cc
src/structs.h

index 679b56645fbdad89b63f2d92912d423fe01f57e1..d58b01006657d45d42f966b47986628aba0432b3 100644 (file)
@@ -17,6 +17,7 @@
 #include "ipc/StrandSearch.h"
 #include "ipc/UdsOp.h"
 #include "ipc/mem/Pages.h"
+#include "SquidTime.h"
 
 CBDATA_CLASS_INIT(IpcIoFile);
 
@@ -159,13 +160,13 @@ IpcIoFile::close()
 bool
 IpcIoFile::canRead() const
 {
-    return diskId >= 0;
+    return diskId >= 0 && canWait();
 }
 
 bool
 IpcIoFile::canWrite() const
 {
-    return diskId >= 0;
+    return diskId >= 0 && canWait();
 }
 
 bool
@@ -304,6 +305,7 @@ IpcIoFile::push(IpcIoPendingRequest *const pending)
     IpcIoMsg ipcIo;
     try {
         ipcIo.requestId = lastRequestId;
+        ipcIo.start = current_time;
         if (pending->readRequest) {
             ipcIo.command = IpcIo::cmdRead;
             ipcIo.offset = pending->readRequest->offset;
@@ -340,6 +342,25 @@ IpcIoFile::push(IpcIoPendingRequest *const pending)
     }
 }
 
+/// whether we think there is enough time to complete the I/O
+bool
+IpcIoFile::canWait() const {
+    if (!Config.Timeout.disk_io)
+        return true; // no timeout specified
+
+    IpcIoMsg oldestIo;
+    if (!queue->peek(diskId, oldestIo) || oldestIo.start.tv_sec <= 0)
+        return true; // we cannot estimate expected wait time; assume it is OK
+
+    const int expectedWait = tvSubMsec(oldestIo.start, current_time);
+    if (expectedWait < 0 ||
+        static_cast<time_msec_t>(expectedWait) < Config.Timeout.disk_io)
+        return true; // expected wait time is acceptible
+
+    debugs(47,2, HERE << "cannot wait: " << expectedWait);
+    return false; // do not want to wait that long
+}
+
 /// called when coordinator responds to worker open request
 void
 IpcIoFile::HandleOpenResponse(const Ipc::StrandSearchResponse &response)
@@ -517,6 +538,7 @@ IpcIoFile::getFD() const
 IpcIoMsg::IpcIoMsg():
     requestId(0), offset(0), len(0), command(IpcIo::cmdNone), xerrno(0)
 {
+    start.tv_sec = 0;
 }
 
 /* IpcIoPendingRequest */
index ba1043133e960b5b41d73b026ac2e32fdcd445c6..f116f98ff7fb8a1a26ee3df4a9f8112b4247028a 100644 (file)
@@ -37,6 +37,7 @@ public:
     Ipc::Mem::PageId page;
 
     IpcIo::Command command; ///< what disker is supposed to do or did
+    struct timeval start; ///< when the I/O request was converted to IpcIoMsg
 
     int xerrno; ///< I/O error code or zero
 };
@@ -75,6 +76,7 @@ protected:
     void openCompleted(const Ipc::StrandSearchResponse *const response);
     void readCompleted(ReadRequest *readRequest, IpcIoMsg *const response);
     void writeCompleted(WriteRequest *writeRequest, const IpcIoMsg *const response);
+    bool canWait() const;
 
 private:
     void trackPendingRequest(IpcIoPendingRequest *const pending);
index 4da9db78399bd5023dafb6405c61c5ae6438a714..566fe00491be246b9c5f475920366046480dd2b5 100644 (file)
@@ -4603,6 +4603,21 @@ DOC_START
        many ident requests going at once.
 DOC_END
 
+NAME: disk_io_timeout
+TYPE: time_msec
+DEFAULT: 0 milliseconds
+LOC: Config.Timeout.disk_io
+DOC_START
+       Squid will not start a new disk I/O operation if it estimates that the
+       operation will take more than the specified disk I/O timeout.
+       Only Rock Store supports this timeout for now.
+
+       By default and when set to zero, disables the disk I/O time limit
+       enforcement.
+DOC_END
+
+
+
 NAME: shutdown_lifetime
 COMMENT: time-units
 TYPE: time_t
index 57fb7d25bcce3388132d70e601b03a0709fd9abb..dbb60f74b0f15a8bef2d0bd3edf419618f962224 100644 (file)
@@ -53,7 +53,6 @@ void
 Rock::IoState::read_(char *buf, size_t len, off_t coreOff, STRCB *cb, void *data)
 {
     assert(theFile != NULL);
-    assert(theFile->canRead());
     assert(coreOff >= 0);
     offset_ = coreOff;
 
@@ -109,7 +108,6 @@ void
 Rock::IoState::startWriting()
 {
     assert(theFile != NULL);
-    assert(theFile->canWrite());
     assert(!theBuf.isNull());
 
     // TODO: if DiskIO module is mmap-based, we should be writing whole pages
index f95f864b47d837eeaca92b0598c85ced62361f59..2b6e81f4c5306838dc87e4a5794eacabc7f5909d 100644 (file)
@@ -43,7 +43,7 @@ Rock::SwapDir::search(String const url, HttpRequest *)
 StoreEntry *
 Rock::SwapDir::get(const cache_key *key)
 {
-    if (!map)
+    if (!map || !theFile || !theFile->canRead())
         return NULL;
 
     sfileno fileno;
index ad1ee0d41bc6310f501ed13a9e3bf37c955e31f0..41e240674e74515104b6d38066558658f2e95e97 100644 (file)
@@ -162,12 +162,12 @@ Ipc::FewToFewBiQueue::validProcessId(const Group group, const int processId) con
     return false;
 }
 
-Ipc::OneToOneUniQueue &
-Ipc::FewToFewBiQueue::oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId)
+int
+Ipc::FewToFewBiQueue::oneToOneQueueIndex(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const
 {
     Must(fromGroup != toGroup);
-    Must(validProcessId(fromGroup, fromProcessId));
-    Must(validProcessId(toGroup, toProcessId));
+    assert(validProcessId(fromGroup, fromProcessId));
+    assert(validProcessId(toGroup, toProcessId));
     int index1;
     int index2;
     int offset;
@@ -181,7 +181,19 @@ Ipc::FewToFewBiQueue::oneToOneQueue(const Group fromGroup, const int fromProcess
         offset = metadata->theGroupASize * metadata->theGroupBSize;
     }
     const int index = offset + index1 * metadata->theGroupBSize + index2;
-    return (*queues)[index];
+    return index;
+}
+
+Ipc::OneToOneUniQueue &
+Ipc::FewToFewBiQueue::oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId)
+{
+    return (*queues)[oneToOneQueueIndex(fromGroup, fromProcessId, toGroup, toProcessId)];
+}
+
+const Ipc::OneToOneUniQueue &
+Ipc::FewToFewBiQueue::oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const
+{
+    return (*queues)[oneToOneQueueIndex(fromGroup, fromProcessId, toGroup, toProcessId)];
 }
 
 Ipc::QueueReader &
index 7d5fdf2086b036bf8c03f6c0dd0feb6fa06514b3..94a98f758e43bbf985f813c62252139651004c8e 100644 (file)
@@ -94,6 +94,9 @@ public:
     /// returns true iff the caller must notify the reader of the pushed item
     template<class Value> bool push(const Value &value, QueueReader *const reader = NULL);
 
+    /// returns true iff the value was set; the value may be stale!
+    template<class Value> bool peek(Value &value) const;
+
 private:
 
     unsigned int theIn; ///< input index, used only in push()
@@ -179,8 +182,13 @@ public:
     /// calls OneToOneUniQueue::push() using the given process queue
     template <class Value> bool push(const int remoteProcessId, const Value &value);
 
+    /// calls OneToOneUniQueue::peek() using the given process queue
+    template<class Value> bool peek(const int remoteProcessId, Value &value) const;
+
 private:
     bool validProcessId(const Group group, const int processId) const;
+    int oneToOneQueueIndex(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const;
+    const OneToOneUniQueue &oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId) const;
     OneToOneUniQueue &oneToOneQueue(const Group fromGroup, const int fromProcessId, const Group toGroup, const int toProcessId);
     QueueReader &reader(const Group group, const int processId);
     int remoteGroupSize() const { return theLocalGroup == groupA ? metadata->theGroupBSize : metadata->theGroupASize; }
@@ -229,6 +237,22 @@ OneToOneUniQueue::pop(Value &value, QueueReader *const reader)
     return true;
 }
 
+template <class Value>
+bool
+OneToOneUniQueue::peek(Value &value) const
+{
+    if (sizeof(value) > theMaxItemSize)
+        throw ItemTooLarge();
+
+    if (empty())
+        return false;
+
+    // the reader may pop() before we copy; making this method imprecise
+    const unsigned int pos = (theOut % theCapacity) * theMaxItemSize;
+    memcpy(&value, theBuffer + pos, sizeof(value));
+    return true;
+}
+
 template <class Value>
 bool
 OneToOneUniQueue::push(const Value &value, QueueReader *const reader)
@@ -296,6 +320,19 @@ FewToFewBiQueue::push(const int remoteProcessId, const Value &value)
     return remoteQueue.push(value, &remoteReader);
 }
 
+template <class Value>
+bool
+FewToFewBiQueue::peek(const int remoteProcessId, Value &value) const
+{
+    // we may be called before remote process configured its queue end
+    if (!validProcessId(remoteGroup(), remoteProcessId))
+        return false;
+
+    const OneToOneUniQueue &remoteQueue = oneToOneQueue(theLocalGroup, theLocalProcessId, remoteGroup(), remoteProcessId);
+    debugs(54, 7, HERE << "peeking from " << theLocalProcessId << " to " << remoteProcessId << " at " << remoteQueue.size());
+    return remoteQueue.peek(value);
+}
+
 } // namespace Ipc
 
 #endif // SQUID_IPC_QUEUE_H
index cdd13af5181a763a4b3170d55e5f91842b13835a..ceed891f99a839e2e3db357cca55c782388ec5f4 100644 (file)
@@ -68,7 +68,7 @@ Ipc::Mem::PageLimit(const int purpose)
         return Config.memMaxSize > 0 ? Config.memMaxSize / PageSize() : 0;
     case PageId::ioPage:
         // XXX: this should be independent from memory cache pages
-        return PageLimit(PageId::cachePage) * 0.5;
+        return PageLimit(PageId::cachePage)/2;
     default:
         Must(false);
     }
index 8d79f866d3aae4618c223f740640e0027d87d796..10d5e2dc3c31bb9bab078a580cc003c7554e6eb0 100644 (file)
@@ -214,6 +214,7 @@ struct SquidConfig {
         int icp_query_max;     /* msec */
         int icp_query_min;     /* msec */
         int mcast_icp_query;   /* msec */
+        time_msec_t disk_io;
 
 #if !USE_DNSSERVERS