/* * Copyright (C) 1996-2015 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. */ #ifndef SQUID_IPC_IOFILE_H #define SQUID_IPC_IOFILE_H #include "base/AsyncCall.h" #include "cbdata.h" #include "DiskIO/DiskFile.h" #include "DiskIO/IORequestor.h" #include "ipc/forward.h" #include "ipc/mem/Page.h" #include "SquidString.h" #include #include #include namespace Ipc { class FewToFewBiQueue; } // Ipc // TODO: expand to all classes namespace IpcIo { /// what kind of I/O the disker needs to do or have done typedef enum { cmdNone, cmdOpen, cmdRead, cmdWrite } Command; } // namespace IpcIo /// converts DiskIO requests to IPC queue messages class IpcIoMsg { public: IpcIoMsg(); public: unsigned int requestId; ///< unique for requestor; matches request w/ response off_t offset; size_t len; 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 }; class IpcIoPendingRequest; class IpcIoFile: public DiskFile { public: typedef RefCount Pointer; IpcIoFile(char const *aDb); virtual ~IpcIoFile(); /* DiskFile API */ virtual void configure(const Config &cfg); virtual void open(int flags, mode_t mode, RefCount callback); virtual void create(int flags, mode_t mode, RefCount callback); virtual void read(ReadRequest *); virtual void write(WriteRequest *); virtual void close(); virtual bool error() const; virtual int getFD() const; virtual bool canRead() const; virtual bool canWrite() const; virtual bool ioInProgress() const; /// handle open response from coordinator static void HandleOpenResponse(const Ipc::StrandSearchResponse &response); /// handle queue push notifications from worker or disker static void HandleNotification(const Ipc::TypedMsgHdr &msg); DiskFile::Config config; ///< supported configuration options protected: friend class IpcIoPendingRequest; 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(const unsigned int id, IpcIoPendingRequest *const pending); void push(IpcIoPendingRequest *const pending); IpcIoPendingRequest *dequeueRequest(const unsigned int requestId); static void Notify(const int peerId); static void OpenTimeout(void *const param); static void CheckTimeouts(void *const param); void checkTimeouts(); void scheduleTimeoutCheck(); static void HandleResponses(const char *const when); void handleResponse(IpcIoMsg &ipcIo); static void DiskerHandleMoreRequests(void*); static void DiskerHandleRequests(); static void DiskerHandleRequest(const int workerId, IpcIoMsg &ipcIo); static bool WaitBeforePop(); private: const String dbName; ///< the name of the file we are managing int diskId; ///< the process ID of the disker we talk to RefCount ioRequestor; bool error_; ///< whether we have seen at least one I/O error (XXX) unsigned int lastRequestId; ///< last requestId used /// maps requestId to the handleResponse callback typedef std::map RequestMap; RequestMap requestMap1; ///< older (or newer) pending requests RequestMap requestMap2; ///< newer (or older) pending requests RequestMap *olderRequests; ///< older requests (map1 or map2) RequestMap *newerRequests; ///< newer requests (map2 or map1) bool timeoutCheckScheduled; ///< we expect a CheckTimeouts() call static const double Timeout; ///< timeout value in seconds typedef std::list IpcIoFileList; static IpcIoFileList WaitingForOpen; ///< pending open requests ///< maps diskerId to IpcIoFile, cleared in destructor typedef std::map IpcIoFilesMap; static IpcIoFilesMap IpcIoFiles; typedef Ipc::FewToFewBiQueue Queue; static std::unique_ptr queue; ///< IPC queue /// whether we are waiting for an event to handle still queued I/O requests static bool DiskerHandleMoreRequestsScheduled; CBDATA_CLASS2(IpcIoFile); }; /// keeps original I/O request parameters while disker is handling the request class IpcIoPendingRequest { public: IpcIoPendingRequest(const IpcIoFile::Pointer &aFile); /// called when response is received and, with a nil response, on timeouts void completeIo(IpcIoMsg *const response); public: const IpcIoFile::Pointer file; ///< the file object waiting for the response ReadRequest *readRequest; ///< set if this is a read requests WriteRequest *writeRequest; ///< set if this is a write request private: IpcIoPendingRequest(const IpcIoPendingRequest &d); // not implemented IpcIoPendingRequest &operator =(const IpcIoPendingRequest &d); // ditto }; #endif /* SQUID_IPC_IOFILE_H */