2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
9 #ifndef SQUID_IPC_IOFILE_H
10 #define SQUID_IPC_IOFILE_H
12 #include "base/AsyncCall.h"
14 #include "DiskIO/DiskFile.h"
15 #include "DiskIO/IORequestor.h"
16 #include "ipc/forward.h"
17 #include "ipc/mem/Page.h"
18 #include "SquidString.h"
25 class FewToFewBiQueue
;
28 // TODO: expand to all classes
32 /// what kind of I/O the disker needs to do or have done
33 typedef enum { cmdNone
, cmdOpen
, cmdRead
, cmdWrite
} Command
;
37 std::ostream
&operator <<(std::ostream
&, IpcIo::Command
);
39 /// converts DiskIO requests to IPC queue messages
45 /// prints message parameters; suitable for cache manager reports
46 void stat(std::ostream
&);
49 unsigned int requestId
; ///< unique for requestor; matches request w/ response
53 Ipc::Mem::PageId page
;
54 pid_t workerPid
; ///< the process ID of the I/O requestor
56 IpcIo::Command command
; ///< what disker is supposed to do or did
57 struct timeval start
; ///< when the I/O request was converted to IpcIoMsg
59 int xerrno
; ///< I/O error code or zero
62 class IpcIoPendingRequest
;
64 /// In a worker process, represents a single (remote) cache_dir disker file.
65 /// In a disker process, used as a bunch of static methods handling that file.
66 class IpcIoFile
: public DiskFile
68 CBDATA_CLASS(IpcIoFile
);
71 typedef RefCount
<IpcIoFile
> Pointer
;
73 IpcIoFile(char const *aDb
);
77 virtual void configure(const Config
&cfg
);
78 virtual void open(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
);
79 virtual void create(int flags
, mode_t mode
, RefCount
<IORequestor
> callback
);
80 virtual void read(ReadRequest
*);
81 virtual void write(WriteRequest
*);
83 virtual bool error() const;
84 virtual int getFD() const;
85 virtual bool canRead() const;
86 virtual bool canWrite() const;
87 virtual bool ioInProgress() const;
89 /// handle open response from coordinator
90 static void HandleOpenResponse(const Ipc::StrandMessage
&);
92 /// handle queue push notifications from worker or disker
93 static void HandleNotification(const Ipc::TypedMsgHdr
&msg
);
95 /// prints IPC message queue state; suitable for cache manager reports
96 static void StatQueue(std::ostream
&);
98 DiskFile::Config config
; ///< supported configuration options
101 friend class IpcIoPendingRequest
;
102 void openCompleted(const Ipc::StrandMessage
*);
103 void readCompleted(ReadRequest
*readRequest
, IpcIoMsg
*const response
);
104 void writeCompleted(WriteRequest
*writeRequest
, const IpcIoMsg
*const response
);
105 bool canWait() const;
108 void trackPendingRequest(const unsigned int id
, IpcIoPendingRequest
*const pending
);
109 void push(IpcIoPendingRequest
*const pending
);
110 IpcIoPendingRequest
*dequeueRequest(const unsigned int requestId
);
112 /// the total number of I/O requests in push queue and pop queue
113 /// (but no, the implementation does not add push and pop queue sizes)
114 size_t pendingRequests() const { return olderRequests
->size() + newerRequests
->size(); }
116 static void Notify(const int peerId
);
118 static void OpenTimeout(void *const param
);
119 static void CheckTimeouts(void *const param
);
120 void checkTimeouts();
121 void scheduleTimeoutCheck();
123 static void HandleResponses(const char *const when
);
124 void handleResponse(IpcIoMsg
&ipcIo
);
126 static void DiskerHandleMoreRequests(void*);
127 static void DiskerHandleRequests();
128 static void DiskerHandleRequest(const int workerId
, IpcIoMsg
&ipcIo
);
129 static bool WaitBeforePop();
132 const String dbName
; ///< the name of the file we are managing
133 const pid_t myPid
; ///< optimization: cached process ID of our process
134 int diskId
; ///< the kid ID of the disker we talk to
135 RefCount
<IORequestor
> ioRequestor
;
137 bool error_
; ///< whether we have seen at least one I/O error (XXX)
139 unsigned int lastRequestId
; ///< last requestId used
141 /// maps requestId to the handleResponse callback
142 typedef std::map
<unsigned int, IpcIoPendingRequest
*> RequestMap
;
143 RequestMap requestMap1
; ///< older (or newer) pending requests
144 RequestMap requestMap2
; ///< newer (or older) pending requests
145 RequestMap
*olderRequests
; ///< older requests (map1 or map2)
146 RequestMap
*newerRequests
; ///< newer requests (map2 or map1)
147 bool timeoutCheckScheduled
; ///< we expect a CheckTimeouts() call
149 static const double Timeout
; ///< timeout value in seconds
151 typedef std::list
<Pointer
> IpcIoFileList
;
152 static IpcIoFileList WaitingForOpen
; ///< pending open requests
154 ///< maps diskerId to IpcIoFile, cleared in destructor
155 typedef std::map
<int, IpcIoFile
*> IpcIoFilesMap
;
156 static IpcIoFilesMap IpcIoFiles
;
158 typedef Ipc::FewToFewBiQueue Queue
;
159 static std::unique_ptr
<Queue
> queue
; ///< IPC queue
161 /// whether we are waiting for an event to handle still queued I/O requests
162 static bool DiskerHandleMoreRequestsScheduled
;
165 /// keeps original I/O request parameters while disker is handling the request
166 class IpcIoPendingRequest
169 IpcIoPendingRequest(const IpcIoFile::Pointer
&aFile
);
171 /// called when response is received and, with a nil response, on timeouts
172 void completeIo(IpcIoMsg
*const response
);
175 const IpcIoFile::Pointer file
; ///< the file object waiting for the response
176 ReadRequest
*readRequest
; ///< set if this is a read requests
177 WriteRequest
*writeRequest
; ///< set if this is a write request
179 CodeContext::Pointer codeContext
; ///< requestor's context
182 IpcIoPendingRequest(const IpcIoPendingRequest
&d
); // not implemented
183 IpcIoPendingRequest
&operator =(const IpcIoPendingRequest
&d
); // ditto
186 #endif /* SQUID_IPC_IOFILE_H */