std::shared_ptr<SSLContext> getSSLContext(folly::StringPiece pemCertPath,
                                          folly::StringPiece pemKeyPath,
                                          folly::StringPiece pemCaPath) {
  static constexpr std::chrono::minutes kSslReloadInterval{5};
  thread_local std::unordered_map<CertPaths, ContextInfo, CertPathsHasher>
  localContexts;

  CertPaths paths;
  paths.pemCertPath = pemCertPath;
  paths.pemKeyPath = pemKeyPath;
  paths.pemCaPath = pemCaPath;

  auto iter = localContexts.find(paths);
  if (localContexts.find(paths) == localContexts.end()) {
    // Copy strings.
    ContextInfo info;
    info.pemCertPath = pemCertPath.toString();
    info.pemKeyPath = pemKeyPath.toString();
    info.pemCaPath = pemCaPath.toString();
    // Point all StringPiece's to our own strings.
    paths.pemCertPath = info.pemCertPath;
    paths.pemKeyPath = info.pemKeyPath;
    paths.pemCaPath = info.pemCaPath;
    iter = localContexts.insert(std::make_pair(paths, std::move(info))).first;
  }

  auto& contextInfo = iter->second;

  auto now = std::chrono::steady_clock::now();
  if (contextInfo.context == nullptr ||
      now - contextInfo.lastLoadTime > kSslReloadInterval) {
    try {
      auto sslContext = std::make_shared<SSLContext>();
      sslContext->loadCertificate(pemCertPath.begin());
      sslContext->loadPrivateKey(pemKeyPath.begin());
      sslContext->loadTrustedCertificates(pemCaPath.begin());
      sslContext->loadClientCAList(pemCaPath.begin());
      // Disable compression if possible to reduce CPU and memory usage.
#ifdef SSL_OP_NO_COMPRESSION
      sslContext->setOptions(SSL_OP_NO_COMPRESSION);
#endif
      contextInfo.lastLoadTime = now;
      contextInfo.context = std::move(sslContext);
    } catch (const apache::thrift::transport::TTransportException& ex) {
      LOG(ERROR) << "Failed to load certificate, ex: " << ex.what();
    }
  }
  return contextInfo.context;
}
std::shared_ptr<SSLContext> getSSLContext(folly::StringPiece pemCertPath,
                                          folly::StringPiece pemKeyPath,
                                          folly::StringPiece pemCaPath) {
  static constexpr std::chrono::minutes kSslReloadInterval{5};
  thread_local std::unordered_map<CertPaths, ContextInfo, CertPathsHasher>
  localContexts;

  CertPaths paths;
  paths.pemCertPath = pemCertPath;
  paths.pemKeyPath = pemKeyPath;
  paths.pemCaPath = pemCaPath;

  auto iter = localContexts.find(paths);
  if (localContexts.find(paths) == localContexts.end()) {
    // Copy strings.
    ContextInfo info;
    info.pemCertPath = pemCertPath.toString();
    info.pemKeyPath = pemKeyPath.toString();
    info.pemCaPath = pemCaPath.toString();
    // Point all StringPiece's to our own strings.
    paths.pemCertPath = info.pemCertPath;
    paths.pemKeyPath = info.pemKeyPath;
    paths.pemCaPath = info.pemCaPath;
    iter = localContexts.insert(std::make_pair(paths, std::move(info))).first;
  }

  auto& contextInfo = iter->second;

  auto now = std::chrono::steady_clock::now();
  if (contextInfo.context == nullptr ||
      now - contextInfo.lastLoadTime > kSslReloadInterval) {

    if (auto updated =
            handleSSLCertsUpdate(pemCertPath, pemKeyPath, pemCaPath)) {
      contextInfo.lastLoadTime = now;
      contextInfo.context = std::move(updated);
    }
  }
  return contextInfo.context;
}