in cachelib/persistence/PersistenceManager.cpp [164:275]
void PersistenceManager::restoreCache(PersistenceStreamReader& reader) {
util::Timer timer;
timer.startOrResume();
XLOGF(INFO, "Start restoring cache: cacheName {}, cacheDir {}",
*config_.cacheName_ref(), cacheDir_);
CACHELIB_CHECK_THROW(reader.read() == DATA_BEGIN_CHAR,
"invalid beginning character");
auto headerLengthBuf = reader.read(sizeof(size_t));
size_t headerLength = cast<size_t>(headerLengthBuf.data());
ShmManager::cleanup(cacheDir_, true);
ShmManager shmManager(cacheDir_, true);
SCOPE_SUCCESS { shmManager.shutDown(); };
while (true) {
auto headerBuf = reader.read(headerLength);
CACHELIB_CHECK_THROW(headerBuf.length() == headerLength, "invalid data");
auto header = deserialize<PersistenceHeader>(headerBuf);
size_t dataLen = static_cast<size_t>(*header.length_ref());
XLOGF(INFO, "restoreCache: type {}, len {}, header_len {}",
static_cast<int>(*header.type_ref()), dataLen, headerLength);
switch (*header.type_ref()) {
case PersistenceType::Versions: {
auto buf = reader.read(dataLen);
CACHELIB_CHECK_THROW(buf.length() == dataLen, "invalid data");
deserializeAndValidateVersions(buf);
break;
}
case PersistenceType::Configs: {
auto buf = reader.read(dataLen);
CACHELIB_CHECK_THROW(buf.length() == dataLen, "invalid data");
auto config = deserialize<PersistCacheLibConfig>(buf);
CACHELIB_CHECK_THROWF(config == config_, "Config doesn't match: {}|{}",
*config.cacheName_ref(), *config_.cacheName_ref());
break;
}
case PersistenceType::NvmCacheState: {
auto buf = reader.read(dataLen);
CACHELIB_CHECK_THROW(buf.length() == dataLen, "invalid data");
restoreFile(buf, NvmCacheState::getNvmCacheStateFilePath(cacheDir_));
break;
}
case PersistenceType::ShmInfo: {
auto shm = shmManager.createShm(detail::kShmInfoName, dataLen);
restoreDataFromBlocks(reader, static_cast<uint8_t*>(shm.addr), dataLen);
break;
}
case PersistenceType::ShmHT: {
auto shm = shmManager.createShm(detail::kShmHashTableName, dataLen);
restoreDataFromBlocks(reader, static_cast<uint8_t*>(shm.addr), dataLen);
break;
}
case PersistenceType::ShmChainedItemHT: {
auto shm =
shmManager.createShm(detail::kShmChainedItemHashTableName, dataLen);
restoreDataFromBlocks(reader, static_cast<uint8_t*>(shm.addr), dataLen);
break;
}
case PersistenceType::ShmData: {
ShmSegmentOpts opts;
opts.alignment = sizeof(Slab); // 4MB
auto shm = shmManager.createShm(detail::kShmCacheName,
*header.length_ref(), nullptr, opts);
restoreDataFromBlocks(reader, static_cast<uint8_t*>(shm.addr),
*header.length_ref());
break;
}
case PersistenceType::NavyPartition: {
int32_t navyFileSize = *header.length_ref();
int32_t numBlock =
util::getAlignedSize(navyFileSize, kDataBlockSize) / kDataBlockSize;
for (size_t i = 0; i < navyFiles_.size(); ++i) {
folly::File f(navyFiles_[i], O_CREAT | O_WRONLY | O_TRUNC);
for (int32_t j = 0; j < numBlock; ++j) {
auto buf = reader.read(sizeof(DataBlock));
CACHELIB_CHECK_THROW(buf.length() == sizeof(DataBlock),
"invalid data");
const DataBlock& db = cast<DataBlock>(buf.data());
CACHELIB_CHECK_THROW(db.validate(), "invalid checksum");
auto res = folly::writeFull(f.fd(), db.data, db.header.length);
CACHELIB_CHECK_THROWF(res != -1, "fail to write file {}, errno: {}",
navyFiles_[i], errno);
}
}
break;
}
default:
CACHELIB_CHECK_THROWF(false, "Unknow header type: {}",
static_cast<int>(*header.type_ref()));
}
char mark = reader.read();
switch (mark) {
case DATA_MARK_CHAR:
continue;
case DATA_END_CHAR:
timer.pause();
XLOGF(INFO, "restoreCache finish, spent {} seconds",
timer.getDurationSec());
return;
default:
CACHELIB_CHECK_THROWF(false, "Unknown character: {}", mark);
}
}
}