void PersistenceManager::restoreCache()

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