MemMap.cc
Go to the documentation of this file.
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 /* DEBUG: section 54 Interprocess Communication */
10 
11 #include "squid.h"
12 #include "ipc/MemMap.h"
13 #include "store_key_md5.h"
14 #include "tools.h"
15 
16 Ipc::MemMap::MemMap(const char *const aPath) :
17  cleaner(NULL),
18  path(aPath),
19  shared(shm_old(Shared)(aPath))
20 {
21  assert(shared->limit > 0); // we should not be created otherwise
22  debugs(54, 5, "attached map [" << path << "] created: " <<
23  shared->limit);
24 }
25 
27 Ipc::MemMap::Init(const char *const path, const int limit, const size_t extrasSize)
28 {
29  assert(limit > 0); // we should not be created otherwise
30  Owner *const owner = shm_new(Shared)(path, limit, extrasSize);
31  debugs(54, 5, "new map [" << path << "] created: " << limit);
32  return owner;
33 }
34 
36 Ipc::MemMap::Init(const char *const path, const int limit)
37 {
38  return Init(path, limit, 0);
39 }
40 
43 {
44  debugs(54, 5, "trying to open slot for key " << storeKeyText(key)
45  << " for writing in map [" << path << ']');
46  const int idx = slotIndexByKey(key);
47 
48  if (Slot *slot = openForWritingAt(idx)) {
49  fileno = idx;
50  return slot;
51  }
52 
53  return NULL;
54 }
55 
57 Ipc::MemMap::openForWritingAt(const sfileno fileno, bool overwriteExisting)
58 {
59  Slot &s = shared->slots[fileno];
60  ReadWriteLock &lock = s.lock;
61 
62  if (lock.lockExclusive()) {
63  assert(s.writing() && !s.reading());
64 
65  // bail if we cannot empty this position
66  if (!s.waitingToBeFreed && !s.empty() && !overwriteExisting) {
67  lock.unlockExclusive();
68  debugs(54, 5, "cannot open existing entry " << fileno <<
69  " for writing " << path);
70  return NULL;
71  }
72 
73  // free if the entry was used, keeping the entry locked
74  if (s.waitingToBeFreed || !s.empty())
75  freeLocked(s, true);
76 
77  assert(s.empty());
78  ++shared->count;
79 
80  debugs(54, 5, "opened slot at " << fileno <<
81  " for writing in map [" << path << ']');
82  return &s; // and keep the entry locked
83  }
84 
85  debugs(54, 5, "failed to open slot at " << fileno <<
86  " for writing in map [" << path << ']');
87  return NULL;
88 }
89 
90 void
91 Ipc::MemMap::closeForWriting(const sfileno fileno, bool lockForReading)
92 {
93  debugs(54, 5, "closing slot at " << fileno << " for writing and "
94  "openning for reading in map [" << path << ']');
95  assert(valid(fileno));
96  Slot &s = shared->slots[fileno];
97  assert(s.writing());
98  if (lockForReading)
100  else
101  s.lock.unlockExclusive();
102 }
103 
105 void
107 {
108  debugs(54, 5, "abort writing slot at " << fileno <<
109  " in map [" << path << ']');
110  assert(valid(fileno));
111  Slot &s = shared->slots[fileno];
112  assert(s.writing());
113  freeLocked(s, false);
114 }
115 
116 const Ipc::MemMap::Slot *
118 {
119  assert(valid(fileno));
120  const Slot &s = shared->slots[fileno];
121  if (s.reading())
122  return &s; // immediate access by lock holder so no locking
123  if (s.writing())
124  return NULL; // cannot read the slot when it is being written
125  assert(false); // must be locked for reading or writing
126  return NULL;
127 }
128 
129 void
131 {
132  debugs(54, 5, "marking slot at " << fileno << " to be freed in"
133  " map [" << path << ']');
134 
135  assert(valid(fileno));
136  Slot &s = shared->slots[fileno];
137 
138  if (s.lock.lockExclusive())
139  freeLocked(s, false);
140  else
141  s.waitingToBeFreed = true; // mark to free it later
142 }
143 
144 const Ipc::MemMap::Slot *
146 {
147  debugs(54, 5, "trying to open slot for key " << storeKeyText(key)
148  << " for reading in map [" << path << ']');
149  const int idx = slotIndexByKey(key);
150  if (const Slot *slot = openForReadingAt(idx)) {
151  if (slot->sameKey(key)) {
152  fileno = idx;
153  debugs(54, 5, "opened slot at " << fileno << " for key "
154  << storeKeyText(key) << " for reading in map [" << path <<
155  ']');
156  return slot; // locked for reading
157  }
158  slot->lock.unlockShared();
159  }
160  debugs(54, 5, "failed to open slot for key " << storeKeyText(key)
161  << " for reading in map [" << path << ']');
162  return NULL;
163 }
164 
165 const Ipc::MemMap::Slot *
167 {
168  debugs(54, 5, "trying to open slot at " << fileno << " for "
169  "reading in map [" << path << ']');
170  assert(valid(fileno));
171  Slot &s = shared->slots[fileno];
172 
173  if (!s.lock.lockShared()) {
174  debugs(54, 5, "failed to lock slot at " << fileno << " for "
175  "reading in map [" << path << ']');
176  return NULL;
177  }
178 
179  if (s.empty()) {
180  s.lock.unlockShared();
181  debugs(54, 7, "empty slot at " << fileno << " for "
182  "reading in map [" << path << ']');
183  return NULL;
184  }
185 
186  if (s.waitingToBeFreed) {
187  s.lock.unlockShared();
188  debugs(54, 7, "dirty slot at " << fileno << " for "
189  "reading in map [" << path << ']');
190  return NULL;
191  }
192 
193  debugs(54, 5, "opened slot at " << fileno << " for reading in"
194  " map [" << path << ']');
195  return &s;
196 }
197 
198 void
200 {
201  debugs(54, 5, "closing slot at " << fileno << " for reading in "
202  "map [" << path << ']');
203  assert(valid(fileno));
204  Slot &s = shared->slots[fileno];
205  assert(s.reading());
206  s.lock.unlockShared();
207 }
208 
209 int
211 {
212  return shared->limit;
213 }
214 
215 int
217 {
218  return shared->count;
219 }
220 
221 bool
223 {
224  return entryCount() >= entryLimit();
225 }
226 
227 void
229 {
230  for (int i = 0; i < shared->limit; ++i)
231  shared->slots[i].lock.updateStats(stats);
232 }
233 
234 bool
235 Ipc::MemMap::valid(const int pos) const
236 {
237  return 0 <= pos && pos < entryLimit();
238 }
239 
240 static
241 unsigned int
242 hash_key(const unsigned char *data, unsigned int len, unsigned int hashSize)
243 {
244  unsigned int n;
245  unsigned int j;
246  for (j = 0, n = 0; j < len; j++ ) {
247  n ^= 271 * *data;
248  ++data;
249  }
250  return (n ^ (j * 271)) % hashSize;
251 }
252 
253 int
255 {
256  const unsigned char *k = reinterpret_cast<const unsigned char *>(key);
257  return hash_key(k, MEMMAP_SLOT_KEY_SIZE, shared->limit);
258 }
259 
262 {
263  return shared->slots[slotIndexByKey(key)];
264 }
265 
267 void
268 Ipc::MemMap::freeLocked(Slot &s, bool keepLocked)
269 {
270  if (!s.empty() && cleaner)
271  cleaner->noteFreeMapSlot(&s - shared->slots.raw());
272 
273  s.waitingToBeFreed = false;
274  memset(s.key, 0, sizeof(s.key));
275  if (!keepLocked)
276  s.lock.unlockExclusive();
277  --shared->count;
278  debugs(54, 5, "freed slot at " << (&s - shared->slots.raw()) <<
279  " in map [" << path << ']');
280 }
281 
282 /* Ipc::MemMapSlot */
284  pSize(0),
285  expire(0)
286 {
287  memset(key, 0, sizeof(key));
288  memset(p, 0, sizeof(p));
289 }
290 
291 void
292 Ipc::MemMapSlot::set(const unsigned char *aKey, const void *block, size_t blockSize, time_t expireAt)
293 {
294  memcpy(key, aKey, sizeof(key));
295  if (block)
296  memcpy(p, block, blockSize);
297  pSize = blockSize;
298  expire = expireAt;
299 }
300 
301 bool
302 Ipc::MemMapSlot::sameKey(const cache_key *const aKey) const
303 {
304  return (memcmp(key, aKey, sizeof(key)) == 0);
305 }
306 
307 bool
309 {
310  for (unsigned char const*u = key; u < key + sizeof(key); ++u) {
311  if (*u)
312  return false;
313  }
314  return true;
315 }
316 
317 /* Ipc::MemMap::Shared */
318 
319 Ipc::MemMap::Shared::Shared(const int aLimit, const size_t anExtrasSize):
320  limit(aLimit), extrasSize(anExtrasSize), count(0), slots(aLimit)
321 {
322 }
323 
325 {
326 }
327 
328 size_t
330 {
331  return SharedMemorySize(limit, extrasSize);
332 }
333 
334 size_t
335 Ipc::MemMap::Shared::SharedMemorySize(const int limit, const size_t extrasSize)
336 {
337  return sizeof(Shared) + limit * (sizeof(Slot) + extrasSize);
338 }
339 
bool writing() const
Definition: MemMap.h:43
#define assert(EX)
Definition: assert.h:17
bool empty() const
Definition: MemMap.cc:308
unsigned char p[MEMMAP_SLOT_DATA_SIZE]
The memory block;.
Definition: MemMap.h:48
unsigned char key[MEMMAP_SLOT_KEY_SIZE]
The entry key.
Definition: MemMap.h:47
const Slot * peekAtReader(const sfileno fileno) const
only works on locked entries; returns nil unless the slot is readable
Definition: MemMap.cc:117
unsigned char cache_key
Store key.
Definition: forward.h:29
#define shm_old(Class)
Definition: Pointer.h:180
int i
Definition: membanger.c:49
const char * storeKeyText(const cache_key *key)
class Ping::pingStats_ stats
Shared(const int aLimit, const size_t anExtrasSize)
Definition: MemMap.cc:319
bool sameKey(const cache_key *const aKey) const
Definition: MemMap.cc:302
approximate stats of a set of ReadWriteLocks
Definition: ReadWriteLock.h:56
char * p
Definition: membanger.c:43
void freeLocked(Slot &s, bool keepLocked)
unconditionally frees the already exclusively locked slot and releases lock
Definition: MemMap.cc:268
static Owner * Init(const char *const path, const int limit)
initialize shared memory
Definition: MemMap.cc:36
const Slot * openForReading(const cache_key *const key, sfileno &fileno)
open slot for reading, increments read level
Definition: MemMap.cc:145
ReadWriteLock lock
protects slot data below
Definition: MemMap.h:46
void const char HLPCB void * data
Definition: stub_helper.cc:16
int entryLimit() const
maximum number of slots that can be used
Definition: MemMap.cc:210
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Debug.h:123
#define MEMMAP_SLOT_KEY_SIZE
Definition: MemMap.h:29
int entryCount() const
number of used slots
Definition: MemMap.cc:216
void switchExclusiveToShared()
stop writing, start reading
void set(const unsigned char *aKey, const void *block, size_t blockSize, time_t expire=0)
Definition: MemMap.cc:292
bool valid(const int n) const
whether n is a valid slot coordinate
Definition: MemMap.cc:235
void Init(void)
prepares to parse ACLs configuration
Definition: AclRegs.cc:111
const Slot * openForReadingAt(const sfileno fileno)
open slot for reading, increments read level
Definition: MemMap.cc:166
Slot & slotByKey(const cache_key *const key)
Definition: MemMap.cc:261
a MemMap basic element, holding basic shareable memory block info
Definition: MemMap.h:33
signed_int32_t sfileno
Definition: forward.h:22
Slot * openForWriting(const cache_key *const key, sfileno &fileno)
Definition: MemMap.cc:42
int unsigned int const char *desc STUB void int len
Definition: stub_fd.cc:20
void free(const sfileno fileno)
mark the slot as waiting to be freed and, if possible, free it
Definition: MemMap.cc:130
MemMap(const char *const aPath)
Definition: MemMap.cc:16
#define shm_new(Class)
Definition: Pointer.h:179
bool lockExclusive()
lock for modification or return false
void updateStats(ReadWriteLockStats &stats) const
adds approximate current stats to the supplied ones
Definition: MemMap.cc:228
std::atomic< uint8_t > waitingToBeFreed
may be accessed w/o a lock
Definition: MemMap.h:45
Mem::Pointer< Shared > shared
Definition: MemMap.h:126
void unlockExclusive()
undo successful exclusiveLock()
size_t sharedMemorySize() const
Definition: MemMap.cc:329
bool lockShared()
lock for reading or return false
static size_t SharedMemorySize(const int limit, const size_t anExtrasSize)
Definition: MemMap.cc:335
const SBuf path
cache_dir path, used for logging
Definition: MemMap.h:125
void unlockShared()
undo successful sharedLock()
void const cache_key * key
bool reading() const
Definition: MemMap.h:42
Slot * openForWritingAt(sfileno fileno, bool overwriteExisting=true)
Definition: MemMap.cc:57
void closeForWriting(const sfileno fileno, bool lockForReading=false)
successfully finish writing the entry
Definition: MemMap.cc:91
bool full() const
there are no empty slots left
Definition: MemMap.cc:222
static unsigned int hash_key(const unsigned char *data, unsigned int len, unsigned int hashSize)
Definition: MemMap.cc:242
void closeForReading(const sfileno fileno)
close slot after reading, decrements read level
Definition: MemMap.cc:199
data shared across maps in different processes
Definition: MemMap.h:62
#define NULL
Definition: types.h:166
int slotIndexByKey(const cache_key *const key) const
Definition: MemMap.cc:254
void abortWriting(const sfileno fileno)
terminate writing the entry, freeing its slot for others to use
Definition: MemMap.cc:106

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors