in cachelib/persistence/PersistenceManager.cpp [75:162]
void PersistenceManager::saveCache(PersistenceStreamWriter& writer) {
util::Timer timer;
timer.startOrResume();
XLOGF(INFO, "Start saving cache: cacheName {}, cacheDir {}",
*config_.cacheName_ref(), cacheDir_);
writer.write(DATA_BEGIN_CHAR);
// save versions
{
auto buf = Serializer::serializeToIOBuf(versions_);
auto header = makeHeader(PersistenceType::Versions, buf->length());
// The persisted stream consists of headers that are thrift serialized and
// data blocks that are custom serialized in binary format to stream in
// chunks. While restoring/deserializing from the stream, we want to read
// from the stream only the bytes around the serialization boundaries to
// simplify implementation. Hence, we persist the size of thrift header in
// binary format first so that we can read only that much from the stream
// before proceeding to read/copy custom serialized blobs. Only one length
// is persisted if we use BinarySerializer (fix encoding) not
// CompactSerializer(variant encoding), this will be used to deserialize all
// headers in restoreCache().
size_t headerLength = header.length();
writer.write(
folly::IOBuf(CopyBufferOp::COPY_BUFFER, &headerLength, sizeof(size_t)));
writer.write(header);
writer.write(*buf);
}
// save configs
{
writer.write(DATA_MARK_CHAR);
auto buf = Serializer::serializeToIOBuf(config_);
writer.write(makeHeader(PersistenceType::Configs, buf->length()));
writer.write(*buf);
}
// save meta data file (cache_dir/NvmCacheState)
saveFile(writer, PersistenceType::NvmCacheState,
NvmCacheState::getNvmCacheStateFilePath(cacheDir_));
// save shm_info
auto shmInfo =
saveShm(writer, PersistenceType::ShmInfo, detail::kShmInfoName);
// save shm_hash_table
auto shmHT =
saveShm(writer, PersistenceType::ShmHT, detail::kShmHashTableName);
// save shm_chained_alloc_hash_table
auto shmChainedHT = saveShm(writer, PersistenceType::ShmChainedItemHT,
detail::kShmChainedItemHashTableName);
// save /dev/shm/shm_cache to multiple data blocks
auto shmCache =
saveShm(writer, PersistenceType::ShmData, detail::kShmCacheName);
// save navy data
{
writer.write(DATA_MARK_CHAR);
int32_t numBlocks =
util::getAlignedSize(navyFileSize_, kDataBlockSize) / kDataBlockSize;
writer.write(makeHeader(PersistenceType::NavyPartition, navyFileSize_));
for (const std::string& file : navyFiles_) {
folly::File f(file);
for (int32_t i = 0; i < numBlocks; ++i) {
DataBlock db;
// readFull function read up to kDataBlockSize bytes from file
// and return the num of bytes read.
auto res = folly::readFull(f.fd(), db.data, kDataBlockSize);
CACHELIB_CHECK_THROWF(res != -1, "fail to write file {}, errno: {}",
file, errno);
db.header.setLengthAndComputeChecksum(res, db.data);
writer.write(
folly::IOBuf(CopyBufferOp::COPY_BUFFER, &db, sizeof(DataBlock)));
}
}
}
writer.write(DATA_END_CHAR);
writer.flush();
timer.pause();
XLOGF(INFO, "saveCache finish, spent {} seconds", timer.getDurationSec());
}