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