1 /* 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors 3 * 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. 7 */ 8 9 #ifndef SQUID_IPC_STORE_MAP_H 10 #define SQUID_IPC_STORE_MAP_H 11 12 #include "Debug.h" 13 #include "ipc/mem/FlexibleArray.h" 14 #include "ipc/mem/Pointer.h" 15 #include "ipc/ReadWriteLock.h" 16 #include "sbuf/SBuf.h" 17 #include "store/forward.h" 18 #include "store_key_md5.h" 19 #include "tools.h" 20 21 #include <atomic> 22 23 namespace Ipc 24 { 25 26 // The MEMMAP_SLOT_KEY_SIZE and MEMMAP_SLOT_DATA_SIZE must be enough big 27 // to hold cached keys and data. Currently MemMap used only to store SSL 28 // shared session data which have keys of 32bytes and at most 10K data 29 #define MEMMAP_SLOT_KEY_SIZE 32 30 #define MEMMAP_SLOT_DATA_SIZE 10*1024 31 32 /// a MemMap basic element, holding basic shareable memory block info 33 class MemMapSlot 34 { 35 public: 36 MemMapSlot(); size()37 size_t size() const {return sizeof(MemMapSlot);} keySize()38 size_t keySize() const {return sizeof(key);} 39 bool sameKey(const cache_key *const aKey) const; 40 void set(const unsigned char *aKey, const void *block, size_t blockSize, time_t expire = 0); 41 bool empty() const; reading()42 bool reading() const { return lock.readers; } writing()43 bool writing() const { return lock.writing; } 44 45 std::atomic<uint8_t> waitingToBeFreed; ///< may be accessed w/o a lock 46 mutable ReadWriteLock lock; ///< protects slot data below 47 unsigned char key[MEMMAP_SLOT_KEY_SIZE]; ///< The entry key 48 unsigned char p[MEMMAP_SLOT_DATA_SIZE]; ///< The memory block; 49 size_t pSize; 50 time_t expire; 51 }; 52 53 class MemMapCleaner; 54 55 /// A map of MemMapSlots indexed by their keys, with read/write slot locking. 56 class MemMap 57 { 58 public: 59 typedef MemMapSlot Slot; 60 61 /// data shared across maps in different processes 62 class Shared 63 { 64 public: 65 Shared(const int aLimit, const size_t anExtrasSize); 66 size_t sharedMemorySize() const; 67 static size_t SharedMemorySize(const int limit, const size_t anExtrasSize); 68 ~Shared(); 69 70 const int limit; ///< maximum number of map slots 71 const size_t extrasSize; ///< size of slot extra data 72 std::atomic<int> count; ///< current number of map slots 73 Ipc::Mem::FlexibleArray<Slot> slots; ///< storage 74 }; 75 76 public: 77 typedef Mem::Owner<Shared> Owner; 78 79 /// initialize shared memory 80 static Owner *Init(const char *const path, const int limit); 81 82 MemMap(const char *const aPath); 83 84 /// finds, locks and return a slot for an empty key position, 85 /// erasing the old entry (if any) 86 Slot *openForWriting(const cache_key *const key, sfileno &fileno); 87 88 /// locks and returns a slot for the empty fileno position; if 89 /// overwriteExisting is false and the position is not empty, returns nil 90 Slot *openForWritingAt(sfileno fileno, bool overwriteExisting = true); 91 92 /// successfully finish writing the entry 93 void closeForWriting(const sfileno fileno); 94 95 /// stop writing the locked entry and start reading it 96 void switchWritingToReading(const sfileno fileno); 97 98 /// only works on locked entries; returns nil unless the slot is readable 99 const Slot *peekAtReader(const sfileno fileno) const; 100 101 /// mark the slot as waiting to be freed and, if possible, free it 102 void free(const sfileno fileno); 103 104 /// open slot for reading, increments read level 105 const Slot *openForReading(const cache_key *const key, sfileno &fileno); 106 107 /// open slot for reading, increments read level 108 const Slot *openForReadingAt(const sfileno fileno); 109 110 /// close slot after reading, decrements read level 111 void closeForReading(const sfileno fileno); 112 113 bool full() const; ///< there are no empty slots left 114 bool valid(const int n) const; ///< whether n is a valid slot coordinate 115 int entryCount() const; ///< number of used slots 116 int entryLimit() const; ///< maximum number of slots that can be used 117 118 /// adds approximate current stats to the supplied ones 119 void updateStats(ReadWriteLockStats &stats) const; 120 121 /// The cleaner MemMapCleaner::noteFreeMapSlot method called when a 122 /// readable entry is freed. 123 MemMapCleaner *cleaner; 124 125 protected: 126 static Owner *Init(const char *const path, const int limit, const size_t extrasSize); 127 128 const SBuf path; ///< cache_dir path, used for logging 129 Mem::Pointer<Shared> shared; 130 131 private: 132 int slotIndexByKey(const cache_key *const key) const; 133 Slot &slotByKey(const cache_key *const key); 134 135 Slot *openForReading(Slot &s); 136 void abortWriting(const sfileno fileno); 137 void freeIfNeeded(Slot &s); 138 void freeLocked(Slot &s, bool keepLocked); 139 }; 140 141 /// API for adjusting external state when dirty map slot is being freed 142 class MemMapCleaner 143 { 144 public: ~MemMapCleaner()145 virtual ~MemMapCleaner() {} 146 147 /// adjust slot-linked state before a locked Readable slot is erased 148 virtual void noteFreeMapSlot(const sfileno slotId) = 0; 149 }; 150 151 } // namespace Ipc 152 153 #endif /* SQUID_IPC_STORE_MAP_H */ 154 155