私はAWS CPP SDK(https://github.com/aws/aws-iot-device-sdk-cpp)を使用して、小さなLinuxシステム(32 MB RAMのみ)のS3からファイルをダウンロードしています。私は以下のようにGetObjectRequestクラスを使用していました。それは素晴らしい仕事をし、私のシステム上でFStreamにファイルをダウンロードしたので、あまりにも多くのRAMを消費しませんでした。AWS CPP TransferManagerとGetObjectRequestストリームをファイルfstream OOM
進捗コールバックを取得するために、ダウンロードコードをTransferManagerメソッドに変換したいと思います。私はコードのその部分を書き直しました、そして、それは同様に以下に示されています。それはうまく始まり、ダウンロードされたパーセンテージを出力しますが、14 MBのRAM(ダウンロード時にLinuxで利用可能な量)に達すると、あまりにも多くのRAMを使用するためにカーネルによって殺されます。
私はGetObjectRequestの場合と同じようにファイルストリームを作成しました。私は間違って何をしていますか?これをどうすれば解決できますか?ありがとう。最終的にあまりにも多くのRAMを使用し、カーネルによって殺され
// Old way
GetObjectRequest getObjectRequest;
getObjectRequest.SetBucket(bucket.c_str());
getObjectRequest.SetKey(keyName.c_str());
getObjectRequest.SetResponseStreamFactory([&destination](){
return Aws::New<Aws::FStream>(
"s3file", destination, std::ios_base::out); });
GetObjectOutcome getObjectOutcome = SessionClient->GetObject(getObjectRequest);
if(getObjectOutcome.IsSuccess())
{
std::cout << "<AWS DOWNLOAD> Get FW success!" << std::endl;
}
else
{
std::cout << "<AWS DOWNLOAD> Get FW failed: " << getObjectOutcome.GetError().GetMessage() << std::endl;
exit(1);
}
新しい方法:
// New way
Aws::Transfer::TransferManagerConfiguration transferConfig;
transferConfig.s3Client = SessionClient;
std::shared_ptr<Aws::Transfer::TransferHandle> requestPtr(nullptr);
transferConfig.downloadProgressCallback =
[](const Aws::Transfer::TransferManager*, const Aws::Transfer::TransferHandle& handle)
{
std::cout << "\r" << "<AWS DOWNLOAD> Download Progress: " << static_cast<int>(handle.GetBytesTransferred() * 100.0/handle.GetBytesTotalSize()) << " Percent " << handle.GetBytesTransferred() << " bytes\n";
};
Aws::Transfer::TransferManager transferManager(transferConfig);
requestPtr = transferManager.DownloadFile(bucket.c_str(), keyName.c_str(), [&destination](){
Aws::FStream *stream = Aws::New<Aws::FStream>("s3file", destination, std::ios_base::out);
stream->rdbuf()->pubsetbuf(NULL, 0);
return stream; });
requestPtr->WaitUntilFinished();
size_t retries = 0;
//just make sure we don't fail because a download part failed. (e.g. network problems or interuptions)
while (requestPtr->GetStatus() == Aws::Transfer::TransferStatus::FAILED && retries++ < 5)
{
std::cout << "<AWS DOWNLOAD> FW Download trying download again!" << std::endl;
transferManager.RetryDownload(requestPtr);
requestPtr->WaitUntilFinished();
}
// Check status
if (requestPtr->GetStatus() == Aws::Transfer::TransferStatus::COMPLETED) {
if (requestPtr->GetBytesTotalSize() == requestPtr->GetBytesTransferred()) {
std::cout << "<AWS DOWNLOAD> Get FW success!" << std::endl;
exit(0);
}
else {
std::cout << "<AWS DOWNLOAD> Get FW failed - Bytes downloaded did not equal requested number of bytes: " << requestPtr->GetBytesTotalSize() << requestPtr->GetBytesTransferred() << std::endl;
exit(1);
}
}
else {
std::cout << "<AWS DOWNLOAD> Get FW failed - download was never completed even after retries" << std::endl;
exit(1);
}