void PersistenceManager::saveCache()

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());
}