Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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++, or another compiler simulating C++,

Choose a reason for hiding this comment

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

what you mean with "simulating c++"?

Copy link
Author

Choose a reason for hiding this comment

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

This file is copied from existing C++ SDK, I will make it more accurate.

# 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

#if defined (_WIN32)

Choose a reason for hiding this comment

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

Why "if defined" here, but "ifdef" in the other lines?

#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 // defined (WIN32)
#define AWSDOC_S3CRT_API
#endif // defined (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-demo.pp to test the functionality in s3-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);
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
...
222 changes: 222 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,222 @@
// 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 <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 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 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) {

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

Aws::S3Crt::Model::PutObjectRequest request;
request.SetBucket(bucketName);
request.SetKey(objectKey);
auto bodyStream = Aws::MakeShared<Aws::StringStream>(ALLOCATION_TAG);
*bodyStream << "s3-crt-demo";
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);
};

#if 0

Choose a reason for hiding this comment

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

if 0?

Copy link
Author

Choose a reason for hiding this comment

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

I could comment out those lines as well.

Choose a reason for hiding this comment

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

Why we release commented code?

// Override default global client bootstrap for AWS common runtime libraries here.
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;
};

// Override default global TLS connection options for AWS common runtime libraries here.
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());
};
#endif

Aws::InitAPI(options);
{
Aws::String bucket_name = "my-bucket";
Aws::String object_key = "my-object";
Aws::String region = Aws::Region::US_EAST_1;
double throughput_target_gbps = 5;
Copy link

Choose a reason for hiding this comment

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

I think they set the default bandwidth for CLI to be 25, might want to use that here too

Choose a reason for hiding this comment

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

I think they set the default bandwidth for CLI to be 25, might want to use that here too

Dengke saying that CLI is also 5Gbps

Copy link
Author

Choose a reason for hiding this comment

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

I will keep 5 Gbps here.

uint64_t part_size = 5 * 1024 * 1024; // 5 MB.
Copy link

Choose a reason for hiding this comment

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

Ryan was telling me that 8MB is a good default, and that's what's used in the C-API if a target throughput isn't specified.

I'm not sure if, in the C++ bindings, it's possible for the user to get a "default" part size

Copy link
Author

Choose a reason for hiding this comment

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


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);

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