]> git.ipfire.org Git - thirdparty/squid.git/blob - src/ipc/MemMap.h
9189796a174bdca3decf469b205fdd1acc4cb06c
[thirdparty/squid.git] / src / ipc / MemMap.h
1 /*
2 * Copyright (C) 1996-2017 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();
37 size_t size() const {return sizeof(MemMapSlot);}
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;
42 bool reading() const { return lock.readers; }
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, bool lockForReading = false);
94
95 /// only works on locked entries; returns nil unless the slot is readable
96 const Slot *peekAtReader(const sfileno fileno) const;
97
98 /// mark the slot as waiting to be freed and, if possible, free it
99 void free(const sfileno fileno);
100
101 /// open slot for reading, increments read level
102 const Slot *openForReading(const cache_key *const key, sfileno &fileno);
103
104 /// open slot for reading, increments read level
105 const Slot *openForReadingAt(const sfileno fileno);
106
107 /// close slot after reading, decrements read level
108 void closeForReading(const sfileno fileno);
109
110 bool full() const; ///< there are no empty slots left
111 bool valid(const int n) const; ///< whether n is a valid slot coordinate
112 int entryCount() const; ///< number of used slots
113 int entryLimit() const; ///< maximum number of slots that can be used
114
115 /// adds approximate current stats to the supplied ones
116 void updateStats(ReadWriteLockStats &stats) const;
117
118 /// The cleaner MemMapCleaner::noteFreeMapSlot method called when a
119 /// readable entry is freed.
120 MemMapCleaner *cleaner;
121
122 protected:
123 static Owner *Init(const char *const path, const int limit, const size_t extrasSize);
124
125 const SBuf path; ///< cache_dir path, used for logging
126 Mem::Pointer<Shared> shared;
127
128 private:
129 int slotIndexByKey(const cache_key *const key) const;
130 Slot &slotByKey(const cache_key *const key);
131
132 Slot *openForReading(Slot &s);
133 void abortWriting(const sfileno fileno);
134 void freeIfNeeded(Slot &s);
135 void freeLocked(Slot &s, bool keepLocked);
136 };
137
138 /// API for adjusting external state when dirty map slot is being freed
139 class MemMapCleaner
140 {
141 public:
142 virtual ~MemMapCleaner() {}
143
144 /// adjust slot-linked state before a locked Readable slot is erased
145 virtual void noteFreeMapSlot(const sfileno slotId) = 0;
146 };
147
148 } // namespace Ipc
149
150 #endif /* SQUID_IPC_STORE_MAP_H */
151