Beispiel #1
0
ErrorCode WdtSocket::closeConnectionInternal(bool doTagIOs) {
  WVLOG(1) << "Closing socket " << port_ << " " << fd_;
  if (fd_ < 0) {
    return OK;
  }
  ErrorCode errorCode = getNonRetryableErrCode();
  if (!writesFinalized_) {
    errorCode = getMoreInterestingError(errorCode, finalizeWrites(doTagIOs));
  }
  if (!readsFinalized_) {
    errorCode = getMoreInterestingError(errorCode, finalizeReads(doTagIOs));
  }
  if (::close(fd_) != 0) {
    PLOG(ERROR) << "Failed to close socket " << fd_ << " " << port_;
    errorCode = getMoreInterestingError(ERROR, errorCode);
  }
  // This looks like a reset() make it explicit (and check it's complete)
  fd_ = -1;
  readErrorCode_ = OK;
  writeErrorCode_ = OK;
  encryptionSettingsRead_ = false;
  encryptionSettingsWritten_ = false;
  writesFinalized_ = false;
  readsFinalized_ = false;
  WVLOG(1) << "Error code from close " << errorCodeToStr(errorCode);
  return errorCode;
}
Beispiel #2
0
void WdtBase::configureThrottler() {
  WDT_CHECK(!throttler_);
  WVLOG(1) << "Configuring throttler options";
  throttler_ = Throttler::makeThrottler(options_);
  if (throttler_) {
    WLOG(INFO) << "Enabling throttling " << *throttler_;
  } else {
    WLOG(INFO) << "Throttling not enabled";
  }
}
Beispiel #3
0
string WdtBase::generateTransferId() {
  static std::default_random_engine randomEngine{std::random_device()()};
  static std::mutex mutex;
  string transferId;
  {
    std::lock_guard<std::mutex> lock(mutex);
    transferId = to_string(randomEngine());
  }
  WVLOG(1) << "Generated a transfer id " << transferId;
  return transferId;
}
Beispiel #4
0
void TransferHistoryController::handleGlobalCheckpoint(
    const Checkpoint &checkpoint) {
  auto errPort = checkpoint.port;
  auto it = threadHistoriesMap_.find(errPort);
  if (it == threadHistoriesMap_.end()) {
    WLOG(ERROR) << "Invalid checkpoint " << checkpoint
                << ". No sender thread running on port " << errPort;
    return;
  }
  WVLOG(1) << "received global checkpoint " << checkpoint;
  it->second->setGlobalCheckpoint(checkpoint);
}
Beispiel #5
0
int64_t WdtSocket::ioWithAbortCheck(F readOrWrite, T tbuf, int64_t numBytes,
                                    int timeoutMs, bool tryFull) {
  WDT_CHECK(threadCtx_.getAbortChecker() != nullptr)
      << "abort checker can not be null";
  bool checkAbort = (threadCtx_.getOptions().abort_check_interval_millis > 0);
  auto startTime = Clock::now();
  int64_t doneBytes = 0;
  int retries = 0;
  while (doneBytes < numBytes) {
    const int64_t ret =
        readOrWrite(fd_, tbuf + doneBytes, numBytes - doneBytes);
    if (ret < 0) {
      // error
      if (errno != EINTR && errno != EAGAIN) {
        PLOG(ERROR) << "non-retryable error encountered during socket io "
                    << fd_ << " " << doneBytes << " " << retries;
        return (doneBytes > 0 ? doneBytes : ret);
      }
    } else if (ret == 0) {
      // eof
      WVLOG(1) << "EOF received during socket io. fd : " << fd_
               << ", finished bytes : " << doneBytes
               << ", retries : " << retries;
      return doneBytes;
    } else {
      // success
      doneBytes += ret;
      if (!tryFull) {
        // do not have to read/write entire data
        return doneBytes;
      }
    }
    if (checkAbort && threadCtx_.getAbortChecker()->shouldAbort()) {
      WLOG(ERROR) << "transfer aborted during socket io " << fd_ << " "
                  << doneBytes << " " << retries;
      return (doneBytes > 0 ? doneBytes : -1);
    }
    if (timeoutMs > 0) {
      int duration = durationMillis(Clock::now() - startTime);
      if (duration >= timeoutMs) {
        WLOG(INFO) << "socket io timed out after " << duration
                   << " ms, retries " << retries << " fd " << fd_
                   << " doneBytes " << doneBytes;
        return (doneBytes > 0 ? doneBytes : -1);
      }
    }
    retries++;
  }
  WVLOG_IF(1, retries > 1) << "socket io for " << doneBytes << " bytes took "
                           << retries << " retries";
  return doneBytes;
}
Beispiel #6
0
double Throttler::averageThrottler(const Clock::time_point& now) {
  std::chrono::duration<double> elapsedDuration = now - startTime_;
  double elapsedSeconds = elapsedDuration.count();
  if (avgRateBytesPerSec_ <= 0) {
    WVLOG(2) << "There is no avg rate limit";
    return -1;
  }
  const double allowedProgressBytes = avgRateBytesPerSec_ * elapsedSeconds;
  if (bytesProgress_ > allowedProgressBytes) {
    double idealTime = bytesProgress_ / avgRateBytesPerSec_;
    const double sleepTimeSeconds = idealTime - elapsedSeconds;
    WVLOG(1) << "Throttler : Elapsed " << elapsedSeconds
             << " seconds. Made progress " << bytesProgress_ / kMbToB
             << " Mbytes in " << elapsedSeconds
             << " seconds, maximum allowed progress for this duration is "
             << allowedProgressBytes / kMbToB
             << " Mbytes. Mean Rate allowed is " << avgRateBytesPerSec_ / kMbToB
             << " Mbytes/sec. Sleeping for " << sleepTimeSeconds << " seconds";
    return sleepTimeSeconds;
  }
  return -1;
}
Beispiel #7
0
bool ThreadTransferHistory::addSource(std::unique_ptr<ByteSource> &source) {
  std::lock_guard<std::mutex> lock(mutex_);
  if (globalCheckpoint_) {
    // already received an error for this thread
    WVLOG(1) << "adding source after global checkpoint is received. returning "
                "the source to the queue";
    markSourceAsFailed(source, lastCheckpoint_.get());
    lastCheckpoint_.reset();
    queue_.returnToQueue(source);
    return false;
  }
  history_.emplace_back(std::move(source));
  return true;
}
Beispiel #8
0
std::unique_ptr<TransferReport> Receiver::getTransferReport() {
  TransferStats globalStats;
  for (const auto &receiverThread : receiverThreads_) {
    globalStats += receiverThread->getTransferStats();
  }
  std::unique_ptr<TransferReport> transferReport =
      folly::make_unique<TransferReport>(std::move(globalStats));
  TransferStatus status = getTransferStatus();
  ErrorCode errCode = transferReport->getSummary().getErrorCode();
  if (status == NOT_STARTED && errCode == OK) {
    WLOG(INFO) << "Transfer not started, setting the error code to ERROR";
    transferReport->setErrorCode(ERROR);
  }
  WVLOG(1) << "Summary code " << errCode;
  return transferReport;
}
Beispiel #9
0
ErrorCode WdtSocket::finalizeWrites(bool doTagIOs) {
  WVLOG(1) << "Finalizing writes/encryption " << port_ << " " << fd_;
  ErrorCode code = OK;
  std::string tag;
  if (!encryptor_.finish(tag)) {
    code = ENCRYPTION_ERROR;
  }
  if (!tag.empty() && doTagIOs) {
    const int timeoutMs = threadCtx_.getOptions().write_timeout_millis;
    const int expected = tag.size();
    if (writeInternal(tag.data(), tag.size(), timeoutMs, false) != expected) {
      PLOG(ERROR) << "Encryption Tag write error";
      code = ENCRYPTION_ERROR;
    }
  }
  writesFinalized_ = true;
  return code;
}
Beispiel #10
0
void Receiver::traverseDestinationDir(
    std::vector<FileChunksInfo> &fileChunksInfo) {
  DirectorySourceQueue dirQueue(options_, destDir_, &abortCheckerCallback_);
  dirQueue.buildQueueSynchronously();
  auto &discoveredFilesInfo = dirQueue.getDiscoveredFilesMetaData();
  for (auto &fileInfo : discoveredFilesInfo) {
    if (fileInfo->relPath == kWdtLogName ||
        fileInfo->relPath == kWdtBuggyLogName) {
      // do not include wdt log files
      WVLOG(1) << "Removing " << fileInfo->relPath
               << " from the list of existing files";
      continue;
    }
    FileChunksInfo chunkInfo(fileInfo->seqId, fileInfo->relPath,
                             fileInfo->size);
    chunkInfo.addChunk(Interval(0, fileInfo->size));
    fileChunksInfo.emplace_back(std::move(chunkInfo));
  }
  return;
}
Beispiel #11
0
ErrorCode WdtSocket::finalizeReads(bool doTagIOs) {
  WVLOG(1) << "Finalizing reads/encryption " << port_ << " " << fd_;
  const int toRead = encryptionTypeToTagLen(encryptionParams_.getType());
  std::string tag;
  ErrorCode code = OK;
  if (toRead && doTagIOs) {
    tag.resize(toRead);
    int read = readInternal(&(tag.front()), tag.size(),
                            threadCtx_.getOptions().read_timeout_millis, true);
    if (read != toRead) {
      WLOG(ERROR) << "Unable to read tag at end of stream got " << read
                  << " needed " << toRead << " " << folly::humanify(tag);
      tag.clear();
      code = ENCRYPTION_ERROR;
    }
  }
  if (!decryptor_.finish(tag)) {
    code = ENCRYPTION_ERROR;
  }
  ctxSaveOffset_ = OFFSET_NOT_SET;
  readsFinalized_ = true;
  return code;
}
Beispiel #12
0
double Throttler::calculateSleep(double deltaProgress,
                                 const Clock::time_point& now) {
  folly::SpinLockGuard lock(throttlerMutex_);
  if (refCount_ <= 0) {
    WLOG(ERROR) << "Using the throttler without registering the transfer";
    return -1;
  }
  bytesProgress_ += deltaProgress;
  double avgThrottlerSleep = averageThrottler(now);
  const bool willSleep = (avgThrottlerSleep > 0);
  if (willSleep) {
    return avgThrottlerSleep;
  }
  // we still hold the lock if peak throttler can come into effect
  if ((bucketRateBytesPerSec_ > 0) && (bytesTokenBucketLimit_ > 0)) {
    std::chrono::duration<double> elapsedDuration = now - lastFillTime_;
    lastFillTime_ = now;
    double elapsedSeconds = elapsedDuration.count();
    bytesTokenBucket_ += elapsedSeconds * bucketRateBytesPerSec_;
    if (bytesTokenBucket_ > bytesTokenBucketLimit_) {
      bytesTokenBucket_ = bytesTokenBucketLimit_;
    }
    bytesTokenBucket_ -= deltaProgress;
    if (bytesTokenBucket_ < 0) {
      /*
       * If we have negative number of tokens lets sleep
       * This way we will have positive number of tokens next time
       */
      double peakThrottlerSleep =
          -1.0 * bytesTokenBucket_ / bucketRateBytesPerSec_;
      WVLOG(2) << "Peak throttler wants to sleep " << peakThrottlerSleep
               << " seconds";
      return peakThrottlerSleep;
    }
  }
  return -1;
}
Beispiel #13
0
void WdtBase::setThrottler(std::shared_ptr<Throttler> throttler) {
  WVLOG(2) << "Setting an external throttler";
  throttler_ = throttler;
}
Beispiel #14
0
void TransferHistoryController::addThreadHistory(int32_t port,
                                                 TransferStats &threadStats) {
  WVLOG(1) << "Adding the history for " << port;
  threadHistoriesMap_.emplace(port, std::make_unique<ThreadTransferHistory>(
                                        dirQueue_, threadStats, port));
}
Beispiel #15
0
ThreadTransferHistory::ThreadTransferHistory(DirectorySourceQueue &queue,
                                             TransferStats &threadStats,
                                             int32_t port)
    : queue_(queue), threadStats_(threadStats), port_(port) {
  WVLOG(1) << "Making thread history for port " << port_;
}
Beispiel #16
0
WdtSocket::~WdtSocket() {
  WVLOG(1) << "~WdtSocket " << port_ << " " << fd_;
  closeNoCheck();
}