static const char SharedMemoryName[] = "RockDirMap";
-Rock::DirMap::DirMap(const char *const path, const int limit):
- shm(SharedMemoryName(path))
+Rock::DirMap::DirMap(const char *const aPath, const int limit):
+ path(aPath), shm(sharedMemoryName())
{
- shm.create(limit);
+ shm.create(SharedSize(limit));
assert(shm.mem());
shared = new (shm.mem()) Shared(limit);
+ debugs(79, 5, HERE << "] new map [" << path << "] created using a new "
+ "shared memory segment for cache_dir '" << path << "' with limit=" <<
+ entryLimit());
}
-Rock::DirMap::DirMap(const char *const path):
- shm(SharedMemoryName(path))
+Rock::DirMap::DirMap(const char *const aPath):
+ path(aPath), shm(sharedMemoryName())
{
shm.open();
assert(shm.mem());
shared = reinterpret_cast<Shared *>(shm.mem());
+ debugs(79, 5, HERE << "] new map [" << path << "] created using existing "
+ "shared memory segment for cache_dir '" << path << "' with limit=" <<
+ entryLimit());
}
StoreEntryBasics *
Rock::DirMap::openForWriting(const cache_key *const key, sfileno &fileno)
{
+ debugs(79, 5, HERE << " trying to open entry for key " << storeKeyText(key)
+ << " for writing in map [" << path << ']');
const int idx = slotIdx(key);
free(idx);
Slot &s = shared->slots[idx];
if (s.state.swap_if(Slot::Empty, Slot::Writing)) {
+ fileno = idx;
s.setKey(key);
+ debugs(79, 5, HERE << " opened entry at " << fileno << " for key " <<
+ storeKeyText(key) << " for writing in map [" << path << ']');
return &s.seBasics;
}
+ debugs(79, 5, HERE << " failed to open entry for key " << storeKeyText(key)
+ << " for writing in map [" << path << ']');
return 0;
}
void
Rock::DirMap::closeForWriting(const sfileno fileno)
{
+ debugs(79, 5, HERE << " closing entry at " << fileno << " for writing in "
+ "map [" << path << ']');
assert(valid(fileno));
Slot &s = shared->slots[fileno];
assert(s.state == Slot::Writing);
bool
Rock::DirMap::free(const sfileno fileno)
{
+ debugs(79, 5, HERE << " trying to mark entry at " << fileno << " to be "
+ "freed in map [" << path << ']');
if (openForReadingAt(fileno)) {
Slot &s = shared->slots[fileno];
s.state.swap_if(Slot::Usable, Slot::WaitingToBeFreed);
--s.readLevel;
freeIfNeeded(s);
+ debugs(79, 5, HERE << " marked entry at " << fileno << " to be freed in"
+ " map [" << path << ']');
return true;
}
+ debugs(79, 5, HERE << " failed to mark entry at " << fileno << " to be "
+ "freed in map [" << path << ']');
return false;
}
const StoreEntryBasics *
Rock::DirMap::openForReading(const cache_key *const key, sfileno &fileno)
{
+ debugs(79, 5, HERE << " trying to open entry for key " << storeKeyText(key)
+ << " for reading in map [" << path << ']');
const int idx = slotIdx(key);
const StoreEntryBasics *const seBasics = openForReadingAt(idx);
- if (seBasics && shared->slots[idx].checkKey(key)) {
- fileno = idx;
- return seBasics;
+ if (seBasics) {
+ Slot &s = shared->slots[idx];
+ if (s.checkKey(key)) {
+ fileno = idx;
+ debugs(79, 5, HERE << " opened entry at " << fileno << " for key "
+ << storeKeyText(key) << " for reading in map [" << path <<
+ ']');
+ return seBasics;
+ }
+ --s.readLevel;
+ freeIfNeeded(s);
}
+ debugs(79, 5, HERE << " failed to open entry for key " << storeKeyText(key)
+ << " for reading in map [" << path << ']');
return 0;
}
const StoreEntryBasics *
Rock::DirMap::openForReadingAt(const sfileno fileno)
{
+ debugs(79, 5, HERE << " trying to open entry at " << fileno << " for "
+ "reading in map [" << path << ']');
assert(valid(fileno));
Slot &s = shared->slots[fileno];
++s.readLevel;
- if (s.state == Slot::Usable)
+ if (s.state == Slot::Usable) {
+ debugs(79, 5, HERE << " opened entry at " << fileno << " for reading in"
+ " map [" << path << ']');
return &s.seBasics;
+ }
--s.readLevel;
freeIfNeeded(s);
+ debugs(79, 5, HERE << " failed to open entry at " << fileno << " for "
+ "reading in map [" << path << ']');
return 0;
}
void
Rock::DirMap::closeForReading(const sfileno fileno)
{
+ debugs(79, 5, HERE << " closing entry at " << fileno << " for reading in "
+ "map [" << path << ']');
assert(valid(fileno));
Slot &s = shared->slots[fileno];
assert(s.readLevel > 0);
int
Rock::DirMap::slotIdx(const cache_key *const key) const
{
- const uint64_t *const k = reinterpret_cast<const uint64_t *>(&key);
+ const uint64_t *const k = reinterpret_cast<const uint64_t *>(key);
// TODO: use a better hash function
return (k[0] + k[1]) % shared->limit;
}
}
}
-int
-Rock::DirMap::SharedSize(const int limit)
-{
- return sizeof(Shared) + limit * sizeof(Slot);
-}
-
String
-Rock::DirMap::SharedMemoryName(const char *path)
+Rock::DirMap::sharedMemoryName()
{
String result;
- for (const char *p = strchr(path, '/'); p; p = strchr(path, '/')) {
- if (path != p) {
+ const char *begin = path.termedBuf();
+ for (const char *end = strchr(begin, '/'); end; end = strchr(begin, '/')) {
+ if (begin != end) {
+ result.append(begin, end - begin);
result.append('.');
- result.append(path, p - path);
}
- path = p + 1;
+ begin = end + 1;
}
- result.append(path);
+ result.append(begin);
return result;
}
+int
+Rock::DirMap::SharedSize(const int limit)
+{
+ return sizeof(Shared) + limit * sizeof(Slot);
+}
+
void
Rock::DirMap::Slot::setKey(const cache_key *const aKey)
{
EBIT_CLR(e->flags, KEY_PRIVATE);
EBIT_SET(e->flags, ENTRY_VALIDATED);
+ e->hashInsert(key);
trackReferences(*e);
return e;
int idx;
StoreEntryBasics *const basics = map->openForWriting(key, idx);
- if (!basics || fileno != idx) {
- debugs(47, 5, HERE << "Rock::SwapDir::addEntry: map->add failed");
- if (basics) {
- map->closeForWriting(idx);
- map->free(idx);
- }
+ if (!basics) {
+ debugs(47, 5, HERE << "Rock::SwapDir::addEntry: the entry loaded from "
+ "disk clashed with locked newer entries");
+ return false;
+ } else if (fileno != idx) {
+ debugs(47, 5, HERE << "Rock::SwapDir::addEntry: the entry loaded from "
+ "disk was hashed to a new slot");
+ map->closeForWriting(idx);
+ map->free(idx);
return false;
}
basics->set(from);
}
if (!map->openForReadingAt(e.swap_filen)) {
- debugs(47,1, HERE << "bug: dir " << index << " lost fileno: " <<
+ debugs(47,1, HERE << "bug: dir " << index << " lost locked fileno: " <<
std::setfill('0') << std::hex << std::uppercase << std::setw(8) <<
e.swap_filen);
return NULL;