This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
pxz-hos-client-cpp-module/support/aws-sdk-cpp-master/aws-cpp-sdk-transfer/source/transfer/TransferHandle.cpp

406 lines
14 KiB
C++

/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/
#include <aws/transfer/TransferHandle.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <cassert>
namespace Aws
{
namespace Transfer
{
PartState::PartState() :
m_partId(0),
m_eTag(""),
m_currentProgressInBytes(0),
m_bestProgressInBytes(0),
m_sizeInBytes(0),
m_rangeBegin(0),
m_downloadPartStream(nullptr),
m_downloadBuffer(nullptr),
m_lastPart(false)
{}
PartState::PartState(int partId, size_t bestProgressInBytes, size_t sizeInBytes, bool lastPart) :
m_partId(partId),
m_eTag(""),
m_currentProgressInBytes(0),
m_bestProgressInBytes(bestProgressInBytes),
m_sizeInBytes(sizeInBytes),
m_rangeBegin(0),
m_downloadPartStream(nullptr),
m_downloadBuffer(nullptr),
m_lastPart(lastPart)
{}
void PartState::Reset()
{
m_currentProgressInBytes = 0;
}
void PartState::OnDataTransferred(long long amount, const std::shared_ptr<TransferHandle> &transferHandle)
{
m_currentProgressInBytes += static_cast<size_t>(amount);
if (m_currentProgressInBytes > m_bestProgressInBytes)
{
transferHandle->UpdateBytesTransferred(m_currentProgressInBytes - m_bestProgressInBytes);
m_bestProgressInBytes = m_currentProgressInBytes;
AWS_LOGSTREAM_TRACE(CLASS_TAG, "Transfer handle ID [" << transferHandle->GetId() << "] "
<< m_bestProgressInBytes << " bytes transferred for part [" << m_partId << "].");
}
}
PartStateMap TransferHandle::GetCompletedParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return m_completedParts;
}
TransferHandle::TransferHandle(const Aws::String& bucketName, const Aws::String& keyName, uint64_t totalSize, const Aws::String& targetFilePath) :
m_isMultipart(false),
m_direction(TransferDirection::UPLOAD),
m_bytesTransferred(0),
m_lastPart(false),
m_bytesTotalSize(totalSize),
m_offset(0),
m_bucket(bucketName),
m_key(keyName),
m_fileName(targetFilePath),
m_versionId(""),
m_status(TransferStatus::NOT_STARTED),
m_cancel(false),
m_handleId(Utils::UUID::RandomUUID()),
m_createDownloadStreamFn(),
m_downloadStream(nullptr)
{}
TransferHandle::TransferHandle(const Aws::String& bucketName, const Aws::String& keyName, const Aws::String& targetFilePath) :
m_isMultipart(false),
m_direction(TransferDirection::DOWNLOAD),
m_bytesTransferred(0),
m_lastPart(false),
m_bytesTotalSize(0),
m_offset(0),
m_bucket(bucketName),
m_key(keyName),
m_fileName(targetFilePath),
m_versionId(""),
m_status(TransferStatus::NOT_STARTED),
m_cancel(false),
m_handleId(Utils::UUID::RandomUUID()),
m_createDownloadStreamFn(),
m_downloadStream(nullptr)
{}
TransferHandle::TransferHandle(const Aws::String& bucketName, const Aws::String& keyName, CreateDownloadStreamCallback createDownloadStreamFn, const Aws::String& targetFilePath) :
m_isMultipart(false),
m_direction(TransferDirection::DOWNLOAD),
m_bytesTransferred(0),
m_lastPart(false),
m_bytesTotalSize(0),
m_offset(0),
m_bucket(bucketName),
m_key(keyName),
m_fileName(targetFilePath),
m_versionId(""),
m_status(TransferStatus::NOT_STARTED),
m_cancel(false),
m_handleId(Utils::UUID::RandomUUID()),
m_createDownloadStreamFn(createDownloadStreamFn),
m_downloadStream(nullptr)
{}
TransferHandle::TransferHandle(const Aws::String& bucketName, const Aws::String& keyName,
const uint64_t fileOffset, const uint64_t downloadBytes,
CreateDownloadStreamCallback createDownloadStreamFn, const Aws::String& targetFilePath) :
m_isMultipart(false),
m_direction(TransferDirection::DOWNLOAD),
m_bytesTransferred(0),
m_lastPart(false),
m_bytesTotalSize(downloadBytes),
m_offset(fileOffset),
m_bucket(bucketName),
m_key(keyName),
m_fileName(targetFilePath),
m_versionId(""),
m_status(TransferStatus::NOT_STARTED),
m_cancel(false),
m_handleId(Utils::UUID::RandomUUID()),
m_createDownloadStreamFn(createDownloadStreamFn),
m_downloadStream(nullptr)
{}
TransferHandle::~TransferHandle()
{
CleanupDownloadStream();
}
void TransferHandle::ChangePartToCompleted(const PartPointer& partState, const Aws::String &eTag)
{
std::lock_guard<std::mutex> locker(m_partsLock);
const auto partId = partState->GetPartId();
if (!m_pendingParts.erase(partId))
{
m_failedParts.erase(partId);
}
partState->SetETag(eTag);
if (partState->IsLastPart())
{
AddMetadataEntry("ETag", eTag);
}
m_completedParts[partId] = partState;
AWS_LOGSTREAM_DEBUG(CLASS_TAG, "Transfer handle ID [" << GetId() << "] Setting part [" << partId
<< "] to [" << TransferStatus::COMPLETED << "].");
}
PartStateMap TransferHandle::GetQueuedParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return m_queuedParts;
}
bool TransferHandle::HasQueuedParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return m_queuedParts.size() > 0;
}
void TransferHandle::AddQueuedPart(const PartPointer& partState)
{
std::lock_guard<std::mutex> locker(m_partsLock);
partState->Reset();
m_failedParts.erase(partState->GetPartId());
m_queuedParts[partState->GetPartId()] = partState;
}
PartStateMap TransferHandle::GetPendingParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return m_pendingParts;
}
bool TransferHandle::HasPendingParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return m_pendingParts.size() > 0;
}
void TransferHandle::AddPendingPart(const PartPointer& partState)
{
std::lock_guard<std::mutex> locker(m_partsLock);
m_queuedParts.erase(partState->GetPartId());
m_pendingParts[partState->GetPartId()] = partState;
}
PartStateMap TransferHandle::GetFailedParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return m_failedParts;
}
bool TransferHandle::HasFailedParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return m_failedParts.size() > 0;
}
void TransferHandle::ChangePartToFailed(const PartPointer& partState)
{
int partId = partState->GetPartId();
std::lock_guard<std::mutex> locker(m_partsLock);
partState->Reset();
m_pendingParts.erase(partId);
m_queuedParts.erase(partId);
m_failedParts[partId] = partState;
AWS_LOGSTREAM_DEBUG(CLASS_TAG, "Transfer handle ID [" << GetId() << "] Setting part [" << partId
<< "] to [" << TransferStatus::FAILED << "].");
}
void TransferHandle::GetAllPartsTransactional(PartStateMap& queuedParts, PartStateMap& pendingParts,
PartStateMap& failedParts, PartStateMap& completedParts)
{
std::lock_guard<std::mutex> locker(m_partsLock);
queuedParts = m_queuedParts;
pendingParts = m_pendingParts;
failedParts = m_failedParts;
completedParts = m_completedParts;
}
bool TransferHandle::HasParts() const
{
std::lock_guard<std::mutex> locker(m_partsLock);
return !m_queuedParts.empty() || !m_pendingParts.empty() || !m_failedParts.empty() || !m_completedParts.empty();
}
static bool IsFinishedStatus(TransferStatus value)
{
switch(value)
{
case TransferStatus::ABORTED:
case TransferStatus::COMPLETED:
case TransferStatus::FAILED:
case TransferStatus::CANCELED:
case TransferStatus::EXACT_OBJECT_ALREADY_EXISTS:
return true;
default:
return false;
}
}
static bool IsTransitionAllowed(TransferStatus currentValue, TransferStatus nextState)
{
// If current state is the same as next state, the transition is allowed.
// otherwise, we can only change from a final state to a final state if moving from canceled to aborted
if (currentValue == nextState)
{
return true;
}
if (IsFinishedStatus(currentValue) && IsFinishedStatus(nextState))
{
return currentValue == TransferStatus::CANCELED && nextState == TransferStatus::ABORTED;
}
return true;
}
static Aws::String GetNameForStatus(TransferStatus value)
{
switch (value)
{
case TransferStatus::EXACT_OBJECT_ALREADY_EXISTS:
return "EXACT_OBJECT_ALREADY_EXISTS";
case TransferStatus::NOT_STARTED:
return "NOT_STARTED";
case TransferStatus::IN_PROGRESS:
return "IN_PROGRESS";
case TransferStatus::CANCELED:
return "CANCELED";
case TransferStatus::FAILED:
return "FAILED";
case TransferStatus::COMPLETED:
return "COMPLETED";
case TransferStatus::ABORTED:
return "ABORTED";
default:
return "UNKNOWN";
}
}
Aws::OStream& operator << (Aws::OStream& s, TransferStatus status)
{
s << GetNameForStatus(status);
return s;
}
void TransferHandle::UpdateStatus(TransferStatus value)
{
std::unique_lock<std::mutex> semaphoreLock(m_statusLock);
if(IsTransitionAllowed(m_status, value))
{
AWS_LOGSTREAM_INFO(CLASS_TAG, "Transfer handle ID [" << GetId() << "] Updated handle status from ["
<< m_status << "] to [" << value << "].");
m_status = value;
if (IsFinishedStatus(value))
{
if(value == TransferStatus::COMPLETED)
{
CleanupDownloadStream();
}
semaphoreLock.unlock();
m_waitUntilFinishedSignal.notify_all();
}
}
else
{
AWS_LOGSTREAM_DEBUG(CLASS_TAG, "Transfer handle ID [" << GetId()
<< "] Failed to update handle status from [" << m_status << "] to [" << value
<< "]. Transition is not allowed.");
}
}
void TransferHandle::WaitUntilFinished() const
{
std::unique_lock<std::mutex> semaphoreLock(m_statusLock);
while (!IsFinishedStatus(m_status) || HasPendingParts())
{
m_waitUntilFinishedSignal.wait(semaphoreLock);
}
}
void TransferHandle::Cancel()
{
AWS_LOGSTREAM_TRACE(CLASS_TAG, "Transfer handle ID [" << GetId() << "] Cancelling transfer.");
m_cancel.store(true);
}
void TransferHandle::Restart()
{
AWS_LOGSTREAM_TRACE(CLASS_TAG, "Transfer handle ID [" << GetId() << "] Restarting transfer.");
m_cancel.store(false);
m_lastPart.store(false);
}
bool TransferHandle::ShouldContinue() const
{
return !m_cancel.load();
}
void TransferHandle::WritePartToDownloadStream(Aws::IOStream* partStream, std::size_t writeOffset)
{
std::lock_guard<std::mutex> lock(m_downloadStreamLock);
if(m_downloadStream == nullptr)
{
m_downloadStream = m_createDownloadStreamFn();
assert(m_downloadStream->good());
}
partStream->seekg(0);
m_downloadStream->seekp(writeOffset);
(*m_downloadStream) << partStream->rdbuf();
m_downloadStream->flush();
}
void TransferHandle::ApplyDownloadConfiguration(const DownloadConfiguration& downloadConfig)
{
SetVersionId(downloadConfig.versionId);
}
void TransferHandle::CleanupDownloadStream()
{
std::lock_guard<std::mutex> locker(m_downloadStreamLock);
if(m_downloadStream)
{
m_downloadStream->flush();
Aws::Delete(m_downloadStream);
m_downloadStream = nullptr;
}
}
TransferStatus TransferHandle::GetStatus() const
{
std::lock_guard<std::mutex> lock(m_statusLock);
return m_status;
}
Aws::String TransferHandle::GetId() const
{
return m_handleId;
}
}
}