Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions cpp/example_code/s3-crt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0

# Set the minimum required version of CMake for this project.
cmake_minimum_required(VERSION 3.8)

# Set this project's name.
project("s3-crt-examples")

# Set the C++ standard to use to build this target.
set(CMAKE_CXX_STANDARD 11)

# Enable CTest for testing these code examples.
include(CTest)

# Build shared libraries by default.
if(NOT BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif()

# Find the AWS SDK for C++ package.
find_package(AWSSDK REQUIRED COMPONENTS s3-crt)

# If the compiler is some version of Microsoft Visual C++,
# and building as shared libraries, then dynamically link to those shared libraries.
if(MSVC AND BUILD_SHARED_LIBS)
add_definitions(-DUSE_IMPORT_EXPORT)
# Copy relevant AWS SDK for C++ libraries into the current binary directory for running and debugging.
list(APPEND SERVICE_LIST s3-crt)
AWSSDK_CPY_DYN_LIBS(SERVICE_LIST "" ${CMAKE_CURRENT_BINARY_DIR})
endif()

# Add the code example-specific header files.
file(GLOB AWSDOC_S3CRT_HEADERS
"include/awsdoc/s3-crt/*.h"
)

# Add the code example-specific source files.
file(GLOB AWSDOC_S3CRT_SOURCE
"*.cpp"
)

# Check whether the target system is Windows, including Win64.
if(WIN32)
# Check whether the compiler is some version of Microsoft Visual C++, or another compiler simulating C++.
if(MSVC)
source_group("Header Files\\awsdoc\\s3-crt" FILES ${AWSDOC_S3CRT_HEADERS})
source_group("Source Files" FILES ${AWSDOC_S3CRT_SOURCE})
endif(MSVC)
endif()

foreach(file ${AWSDOC_S3CRT_SOURCE})
get_filename_component(EXAMPLE ${file} NAME_WE)

# Build the code example executables.
set(EXAMPLE_EXE run_${EXAMPLE})

add_executable(${EXAMPLE_EXE} ${AWSDOC_S3CRT_HEADERS} ${file})

if(MSVC AND BUILD_SHARED_LIBS)
target_compile_definitions(${EXAMPLE_EXE} PUBLIC "USE_IMPORT_EXPORT")
target_compile_definitions(${EXAMPLE_EXE} PRIVATE "AWSDOC_S3CRT_EXPORTS")
endif()

target_include_directories(${EXAMPLE_EXE} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_link_libraries(${EXAMPLE_EXE} ${AWSSDK_LINK_LIBRARIES}
${AWSSDK_PLATFORM_DEPS})

if(BUILD_TESTING)
# Enable testing for this directory and below.
enable_testing()

# Build the code example libraries.
set(EXAMPLE_LIB ${EXAMPLE})

add_library(${EXAMPLE_LIB} ${AWSDOC_S3CRT_HEADERS} ${file} )

if(MSVC AND BUILD_SHARED_LIBS)
target_compile_definitions(${EXAMPLE_LIB} PUBLIC "USE_IMPORT_EXPORT")
target_compile_definitions(${EXAMPLE_LIB} PRIVATE "AWSDOC_S3CRT_EXPORTS")
endif()

target_include_directories(${EXAMPLE_LIB} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_link_libraries(${EXAMPLE_LIB} ${AWSSDK_LINK_LIBRARIES}
${AWSSDK_PLATFORM_DEPS})

# Build the code example unit tests.
set(EXAMPLE_TEST test_${EXAMPLE})
set(EXAMPLE_TEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_${EXAMPLE}.cpp)

if(EXISTS ${EXAMPLE_TEST_FILE})
add_executable(${EXAMPLE_TEST} ${EXAMPLE_TEST_FILE} )

target_include_directories(${EXAMPLE_TEST} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
target_link_libraries(${EXAMPLE_TEST} ${EXAMPLE_LIB} )
add_test(${EXAMPLE_TEST} ${EXAMPLE_TEST})
endif()

endif()
endforeach()
27 changes: 27 additions & 0 deletions cpp/example_code/s3-crt/include/awsdoc/s3-crt/S3Crt_EXPORTS.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

#pragma once

#ifdef _MSC_VER
// Disable Windows complaining about max template size.
#pragma warning (disable : 4503)
#endif // _MSC_VER

#ifdef _WIN32
#ifdef _MSC_VER
#pragma warning (disable : 4251)
#endif // _MSC_VER

#ifdef USE_IMPORT_EXPORT
#ifdef AWSDOC_S3CRT_EXPORTS
#define AWSDOC_S3CRT_API __declspec(dllexport)
#else
#define AWSDOC_S3CRT_API __declspec(dllimport)
#endif // AWSDOC_S3CRT_EXPORTS
#else
#define AWSDOC_S3CRT_API
#endif // USE_IMPORT_EXPORT
#else // _WIN32
#define AWSDOC_S3CRT_API
#endif // _WIN32
23 changes: 23 additions & 0 deletions cpp/example_code/s3-crt/include/awsdoc/s3-crt/s3-crt-demo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX - License - Identifier: Apache - 2.0

// Enables test_s3-crt-demo.cpp to test the functionality in s3-crt-demo.cpp.

#pragma once

#include <aws/core/Aws.h>
#include <aws/s3-crt/S3CrtClient.h>
#include <awsdoc/s3-crt/S3Crt_EXPORTS.h>

AWSDOC_S3CRT_API bool ListBuckets(const Aws::S3Crt::S3CrtClient& s3CrtClient,
const Aws::String& bucketName);
AWSDOC_S3CRT_API bool CreateBucket(const Aws::S3Crt::S3CrtClient& s3CrtClient,
const Aws::String& bucketName);
AWSDOC_S3CRT_API bool DeleteBucket(const Aws::S3Crt::S3CrtClient& s3CrtClient,
const Aws::String& bucketName);
AWSDOC_S3CRT_API bool PutObject(const Aws::S3Crt::S3CrtClient& s3CrtClient,
const Aws::String& bucketName, const Aws::String& objectKey, const Aws::String& fileName);
AWSDOC_S3CRT_API bool GetObject(const Aws::S3Crt::S3CrtClient& s3CrtClient,
const Aws::String& bucketName, const Aws::String& objectKey);
AWSDOC_S3CRT_API bool DeleteObject(const Aws::S3Crt::S3CrtClient& s3CrtClient,
const Aws::String& bucketName, const Aws::String& objectKey);
9 changes: 9 additions & 0 deletions cpp/example_code/s3-crt/metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Disregard this file. AWS uses it internally to
# track code coverage and unit test coverage
# within this repository.
---
files:
- path: s3-crt-demo.cpp
services:
- s3-crt
...
225 changes: 225 additions & 0 deletions cpp/example_code/s3-crt/s3-crt-demo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX - License - Identifier: Apache - 2.0

#include <awsdoc/s3-crt/s3-crt-demo.h>
// snippet-start:[s3-crt.cpp.bucket_operations.list_create_delete]
#include <iostream>
#include <fstream>
#include <aws/core/Aws.h>
#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <aws/core/utils/logging/CRTLogSystem.h>
#include <aws/s3-crt/S3CrtClient.h>
#include <aws/s3-crt/model/CreateBucketRequest.h>
#include <aws/s3-crt/model/DeleteBucketRequest.h>
#include <aws/s3-crt/model/PutObjectRequest.h>
#include <aws/s3-crt/model/GetObjectRequest.h>
#include <aws/s3-crt/model/DeleteObjectRequest.h>

static const char ALLOCATION_TAG[] = "s3-crt-demo";

// List all Amazon Simple Storage Service (Amazon S3) buckets under the account.
bool ListBuckets(const Aws::S3Crt::S3CrtClient& s3CrtClient, const Aws::String& bucketName) {

Aws::S3Crt::Model::ListBucketsOutcome outcome = s3CrtClient.ListBuckets();

if (outcome.IsSuccess()) {
std::cout << "All buckets under my account:" << std::endl;

for (auto const& bucket : outcome.GetResult().GetBuckets())
{
std::cout << " * " << bucket.GetName() << std::endl;
}
std::cout << std::endl;

return true;
}
else {
std::cout << "ListBuckets error:\n"<< outcome.GetError() << std::endl << std::endl;

return false;
}
}

// Create an Amazon Simple Storage Service (Amazon S3) bucket.
bool CreateBucket(const Aws::S3Crt::S3CrtClient& s3CrtClient, const Aws::String& bucketName) {

std::cout << "Creating bucket: \"" << bucketName << "\" ..." << std::endl;

Aws::S3Crt::Model::CreateBucketRequest request;
request.SetBucket(bucketName);

Aws::S3Crt::Model::CreateBucketOutcome outcome = s3CrtClient.CreateBucket(request);

if (outcome.IsSuccess()) {
std::cout << "Bucket created." << std::endl << std::endl;

return true;
}
else {
std::cout << "CreateBucket error:\n" << outcome.GetError() << std::endl << std::endl;

return false;
}
}

// Delete an existing Amazon S3 bucket.
bool DeleteBucket(const Aws::S3Crt::S3CrtClient& s3CrtClient, const Aws::String& bucketName) {

std::cout << "Deleting bucket: \"" << bucketName << "\" ..." << std::endl;

Aws::S3Crt::Model::DeleteBucketRequest request;
request.SetBucket(bucketName);

Aws::S3Crt::Model::DeleteBucketOutcome outcome = s3CrtClient.DeleteBucket(request);

if (outcome.IsSuccess()) {
std::cout << "Bucket deleted." << std::endl << std::endl;

return true;
}
else {
std::cout << "DeleteBucket error:\n" << outcome.GetError() << std::endl << std::endl;

return false;
}
}

// Put an Amazon S3 object to the bucket.
bool PutObject(const Aws::S3Crt::S3CrtClient& s3CrtClient, const Aws::String& bucketName, const Aws::String& objectKey, const Aws::String& fileName) {

std::cout << "Putting object: \"" << objectKey << "\" to bucket: \"" << bucketName << "\" ..." << std::endl;

Aws::S3Crt::Model::PutObjectRequest request;
request.SetBucket(bucketName);
request.SetKey(objectKey);
std::shared_ptr<Aws::IOStream> bodyStream = Aws::MakeShared<Aws::FStream>(ALLOCATION_TAG, fileName.c_str(), std::ios_base::in | std::ios_base::binary);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't follow the whole flow for this, but at a first glance it doesn't look like you sharing the ownership of this object. Could it be a unique_ptr?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. SetBody() requires a shared pointer.
  2. It's a shared pointer because we pass this pointer down to the http client. For async call, it will be shared to that thread.
if (!bodyStream->good()) {
std::cout << "Failed to open file: \"" << fileName << "\"." << std::endl << std::endl;
return false;
}
request.SetBody(bodyStream);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[opinion] The existing s3 demo uploads a file from disk. That seems more interesting than uploading the string "s3-crt-demo"


Aws::S3Crt::Model::PutObjectOutcome outcome = s3CrtClient.PutObject(request);

if (outcome.IsSuccess()) {
std::cout << "Object added." << std::endl << std::endl;

return true;
}
else {
std::cout << "PutObject error:\n" << outcome.GetError() << std::endl << std::endl;

return false;
}
}

// Get the Amazon S3 object from the bucket.
bool GetObject(const Aws::S3Crt::S3CrtClient& s3CrtClient, const Aws::String& bucketName, const Aws::String& objectKey) {

std::cout << "Getting object: \"" << objectKey << "\" from bucket: \"" << bucketName << "\" ..." << std::endl;

Aws::S3Crt::Model::GetObjectRequest request;
request.SetBucket(bucketName);
request.SetKey(objectKey);

Aws::S3Crt::Model::GetObjectOutcome outcome = s3CrtClient.GetObject(request);

if (outcome.IsSuccess()) {
std::cout << "Object content: " << outcome.GetResult().GetBody().rdbuf() << std::endl << std::endl;

return true;
}
else {
std::cout << "GetObject error:\n" << outcome.GetError() << std::endl << std::endl;

return false;
}
}

// Delete the Amazon S3 object from the bucket.
bool DeleteObject(const Aws::S3Crt::S3CrtClient& s3CrtClient, const Aws::String& bucketName, const Aws::String& objectKey) {

std::cout << "Deleting object: \"" << objectKey << "\" from bucket: \"" << bucketName << "\" ..." << std::endl;

Aws::S3Crt::Model::DeleteObjectRequest request;
request.SetBucket(bucketName);
request.SetKey(objectKey);

Aws::S3Crt::Model::DeleteObjectOutcome outcome = s3CrtClient.DeleteObject(request);

if (outcome.IsSuccess()) {
std::cout << "Object deleted." << std::endl << std::endl;

return true;
}
else {
std::cout << "DeleteObject error:\n" << outcome.GetError() << std::endl << std::endl;

return false;
}
}

// 1. List all buckets under the account
// 2. Create an Amazon S3 bucket
// 3. Put an object to the bucket
// 4. Get the object
// 5. Delete the object
// 6. Delete the bucket
int main(int argc, char* argv[]) {

Aws::SDKOptions options;

// Override default log level for AWS common runtime libraries to prevent from being overwhelmed by logs from them.
options.loggingOptions.crt_logger_create_fn = []() {
return Aws::MakeShared<Aws::Utils::Logging::DefaultCRTLogSystem>(ALLOCATION_TAG, Aws::Utils::Logging::LogLevel::Warn);
};

// Uncomment the following code to override default global client bootstrap for AWS common runtime libraries.
// options.ioOptions.clientBootstrap_create_fn = []() {
// Aws::Crt::Io::EventLoopGroup eventLoopGroup(0 /* cpuGroup */, 18 /* threadCount */);
// Aws::Crt::Io::DefaultHostResolver defaultHostResolver(eventLoopGroup, 8 /* maxHosts */, 300 /* maxTTL */);
// auto clientBootstrap = Aws::MakeShared<Aws::Crt::Io::ClientBootstrap>(ALLOCATION_TAG, eventLoopGroup, defaultHostResolver);
// clientBootstrap->EnableBlockingShutdown();
// return clientBootstrap;
// };

// Uncomment the following code to override default global TLS connection options for AWS common runtime libraries.
// options.ioOptions.tlsConnectionOptions_create_fn = []() {
// Aws::Crt::Io::TlsContextOptions tlsCtxOptions = Aws::Crt::Io::TlsContextOptions::InitDefaultClient();
// Aws::Crt::Io::TlsContext tlsContext(tlsCtxOptions, Aws::Crt::Io::TlsMode::CLIENT);
// return Aws::MakeShared<Aws::Crt::Io::TlsConnectionOptions>(ALLOCATION_TAG, tlsContext.NewConnectionOptions());
// };

Aws::InitAPI(options);
{
Aws::String bucket_name = "my-bucket";
Aws::String object_key = "my-object";
Aws::String file_name = "my-file";
Aws::String region = Aws::Region::US_EAST_1;
const double throughput_target_gbps = 5;
const uint64_t part_size = 8 * 1024 * 1024; // 8 MB.

Aws::S3Crt::ClientConfiguration config;
config.region = region;
config.throughputTargetGbps = throughput_target_gbps;
config.partSize = part_size;

Aws::S3Crt::S3CrtClient s3_crt_client(config);

ListBuckets(s3_crt_client, bucket_name);

CreateBucket(s3_crt_client, bucket_name);

PutObject(s3_crt_client, bucket_name, object_key, file_name);

GetObject(s3_crt_client, bucket_name, object_key);

DeleteObject(s3_crt_client, bucket_name, object_key);

DeleteBucket(s3_crt_client, bucket_name);
}
Aws::ShutdownAPI(options);

return 0;
}
// snippet-end:[s3-crt.cpp.bucket_operations.list_create_delete]
Loading