Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds new handle to object stores that support S3 API #107

Draft
wants to merge 83 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
c70f2ce
feat(S3): initial commit for AWS S3 support
mcakircali Jan 31, 2024
c182574
refactor(S3): removed UPtr and SPtr
mcakircali Feb 1, 2024
e92e14e
feat(S3)!: adds Config, Session, Client, Context
mcakircali Feb 6, 2024
5fbf932
feat(S3): add create,delete,list for bucket and put,list object
mcakircali Feb 7, 2024
4aaec56
feat(S3): adds delete,list object
mcakircali Feb 7, 2024
eda4bfd
fix(S3): throw on unkown S3 client type
mcakircali Feb 7, 2024
3fb4e4d
feat(S3): adds credentials to S3Config
mcakircali Feb 7, 2024
408d9c2
refactor(S3): throw instead of return boolean
mcakircali Feb 8, 2024
028a4ee
chore(S3): remove advanced attribute from AWS_S3 cmake option
mcakircali Feb 8, 2024
7423b5c
style(S3): fix todo style comment
mcakircali Feb 8, 2024
c3e93a2
refactor(S3): namedspace -> unnamed namespace
mcakircali Feb 8, 2024
1aab48f
refactor(S3): cleanup S3Session
mcakircali Feb 8, 2024
d775bff
fix(S3): add missing pragma once
mcakircali Feb 8, 2024
620fd18
refactor(S3): cleanup S3Handle
mcakircali Feb 8, 2024
de556ff
refactor(S3): more cleanup for S3Handle, S3Name
mcakircali Feb 8, 2024
ed4ed4b
fix(S3): aws error parsing
mcakircali Feb 8, 2024
7eaa9be
feat(S3): rework credentials
mcakircali Feb 8, 2024
545f8c6
Add some URI infrastructure, and tweak some tests
simondsmart Feb 8, 2024
e8bcf92
refactor(S3): rework S3Config
mcakircali Feb 9, 2024
c84f046
feat(S3): start S3Name and S3URIManager
mcakircali Feb 9, 2024
a7bdb15
Merge remote-tracking branch 'refs/remotes/origin/feature/backend-s3'…
mcakircali Feb 9, 2024
563679e
fix(S3): authority must be true
mcakircali Feb 9, 2024
2003a5c
feat(Endpoint): construct from a URI
mcakircali Feb 9, 2024
ff342d1
fix(S3): client missing error msg
mcakircali Feb 9, 2024
4fbcea1
feat(S3): S3Name: parse bucket/object, exists, size
mcakircali Feb 9, 2024
929c0f2
feat(S3): add bucket/object exists, object size
mcakircali Feb 9, 2024
611742a
refactor(S3): session cleanup
mcakircali Feb 9, 2024
894bbae
feat(S3): adds open and size to S3Handle
mcakircali Feb 9, 2024
6a95ecb
fix(S3): adapt s3handle test
mcakircali Feb 9, 2024
140d75d
refactor(S3): cleanup and copyright fix
mcakircali Feb 9, 2024
e63bd18
refactor(S3): client and config cleanup
mcakircali Feb 10, 2024
75bb909
feat(S3): adds putObject
mcakircali Feb 10, 2024
fc359d9
feat(S3): adds emptyBucket
mcakircali Feb 10, 2024
eb09b13
refactor(S3): cleanup S3Client and S3Handle
mcakircali Feb 11, 2024
a4a6835
feat(S3): structure for get object (WIP)
mcakircali Feb 11, 2024
3650136
feat(S3): add S3Name asString
mcakircali Feb 11, 2024
f08c0b2
fix(S3): S3Name ref member in S3Handle
mcakircali Feb 11, 2024
833f88c
feat(S3): adds S3Handle read and getObject
mcakircali Feb 11, 2024
ef48592
feat(S3): fix tests3client and add print to S3Client
mcakircali Feb 11, 2024
709e51b
feat(S3): rework s3 config
mcakircali Feb 11, 2024
6b9f2a9
feat(S3): adds range get object and S3Handle fixes (WIP)
mcakircali Feb 13, 2024
e19d671
chore(S3): issue with S3Handle saveInto a MemoryHandle
mcakircali Feb 13, 2024
a0cc783
refactor(S3): correction throw messages
mcakircali Feb 13, 2024
61c0f89
refactor(S3): small cleanup S3Handle and S3Client
mcakircali Feb 14, 2024
d3d3ebe
feat(S3): adds S3Bucket.
nicolau-manubens Feb 14, 2024
26bb157
Merge branch 'feature/backend-s3' of https://github.com/ecmwf/eckit i…
nicolau-manubens Feb 14, 2024
4cfdb36
fix(S3): bug fixes and test for S3Handle, S3Client, S3Name
mcakircali Feb 14, 2024
986ac03
Merge remote-tracking branch 'refs/remotes/origin/feature/backend-s3'…
mcakircali Feb 14, 2024
bd245ef
refactor(S3): remove comment
mcakircali Feb 14, 2024
0585ad7
feat(S3): adds S3Bucket::ensureCreated and ensureDestroyed.
nicolau-manubens Feb 14, 2024
9b9ef61
fix(S3): solve merge conflict.
nicolau-manubens Feb 14, 2024
ce3b2c7
refactor(S3): cleanup test s3handle
mcakircali Feb 15, 2024
e7abb31
Merge remote-tracking branch 'refs/remotes/origin/feature/backend-s3'…
mcakircali Feb 15, 2024
5670806
fix(S3)!: client return type long long
mcakircali Feb 15, 2024
077e64a
fix(S3): assert fix and tidy up S3Handle, fix S3Name Length type
mcakircali Feb 15, 2024
b4cc9de
feat(S3): improve s3handle tests
mcakircali Feb 15, 2024
bec47da
feat(S3): adds a few S3Name features and minor API modifications.
nicolau-manubens Feb 16, 2024
6d01bf8
fix(S3): removed unnecessary stuff from S3Handle
mcakircali Feb 16, 2024
34b8f2c
fix(S3): write throws if object exists
mcakircali Feb 16, 2024
64c15a0
feat(S3): added test for no bucket s3handle
mcakircali Feb 16, 2024
2ffe322
fix(S3): commented expensive code in openForWrite
mcakircali Feb 16, 2024
e17e438
refactor(S3): removed eckit namespaces
mcakircali Feb 16, 2024
ff3342e
refactor(S3)!: S3BucketName
mcakircali Feb 16, 2024
13a3d01
refactor(S3)!: S3ClientAWS throws
mcakircali Feb 16, 2024
b4ae6a1
refactor(S3)!: S3Exception
mcakircali Feb 16, 2024
0c84e60
feat(S3)!: added S3ObjectName
mcakircali Feb 16, 2024
48797f6
fix(S3): memory leak S3Name
mcakircali Feb 17, 2024
f938234
feat(S3): added S3Name accessors
mcakircali Feb 17, 2024
7a47f99
refactor(S3): various log debug
mcakircali Feb 17, 2024
227db9f
fix(S3)!: S3Handle bug read/write return
mcakircali Feb 19, 2024
c07f52c
feat(S3): added S3Handle tests, S3Bucket/Object accessors and change …
mcakircali Feb 19, 2024
9cb443b
fix(S3): S3Client and IMDS bugs
mcakircali Feb 19, 2024
b4c8f7f
feat(S3): tests 1000 object writes
mcakircali Feb 19, 2024
b9e30d2
feat(S3): write performance tests
mcakircali Feb 20, 2024
a9f0cd1
feat(S3): improved perf 20% .. reuse S3Client
mcakircali Feb 20, 2024
17fd771
fix(S3): removed S3Context
mcakircali Feb 20, 2024
b481597
feat(S3): move uri to base
mcakircali Feb 21, 2024
f46d47c
fix(S3): remove debug log
mcakircali Feb 22, 2024
2e53988
chore(S3): removed unused macros file
mcakircali Feb 26, 2024
7d76c42
feat(S3): read credentials from user/default file
mcakircali Feb 27, 2024
650594d
fix(S3): missing headers
mcakircali Feb 28, 2024
a682dfa
fix(S3): more missing headers
mcakircali Feb 28, 2024
27e8f8a
fix(S3): turned off verifySSL
mcakircali Mar 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ ecbuild_add_option( FEATURE RADOS
DESCRIPTION "Ceph/Rados storage support"
REQUIRED_PACKAGES Rados )

### S3 Support

ecbuild_add_option( FEATURE AWS_S3
DEFAULT OFF
REQUIRED_PACKAGES "AWSSDK REQUIRED COMPONENTS s3"
DESCRIPTION "Enables AWS S3 support" )

### Armadillo

ecbuild_add_option( FEATURE ARMADILLO
Expand Down
32 changes: 31 additions & 1 deletion src/eckit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,34 @@ io/rados/RadosAttributes.cc
)
endif()

if(HAVE_AWS_S3)
list( APPEND eckit_io_srcs
io/s3/aws/S3ClientAWS.cc
io/s3/aws/S3ClientAWS.h
io/s3/aws/S3ContextAWS.cc
io/s3/aws/S3ContextAWS.h
io/s3/S3BucketName.cc
io/s3/S3BucketName.h
io/s3/S3Client.cc
io/s3/S3Client.h
io/s3/S3Config.cc
io/s3/S3Config.h
io/s3/S3Credential.h
io/s3/S3Exception.cc
io/s3/S3Exception.h
io/s3/S3Handle.cc
io/s3/S3Handle.h
io/s3/S3Name.cc
io/s3/S3Name.h
io/s3/S3ObjectName.cc
io/s3/S3ObjectName.h
io/s3/S3Session.cc
io/s3/S3Session.h
io/s3/S3URIManager.cc
io/s3/S3URIManager.h
)
endif(HAVE_AWS_S3)

list( APPEND eckit_filesystem_srcs
filesystem/BasePathName.cc
filesystem/BasePathName.h
Expand Down Expand Up @@ -934,12 +962,14 @@ ecbuild_add_library(
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>

PRIVATE_INCLUDES
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/src/eckit/io/s3/aws>
"${CURL_INCLUDE_DIRS}"
"${SNAPPY_INCLUDE_DIRS}"
"${LZ4_INCLUDE_DIRS}"
"${BZIP2_INCLUDE_DIRS}"
"${AEC_INCLUDE_DIRS}"
"${RADOS_INCLUDE_DIRS}"
"${AWSSDK_INCLUDE_DIRS}"
"${OPENSSL_INCLUDE_DIR}"
"${AIO_INCLUDE_DIRS}"

Expand All @@ -953,6 +983,7 @@ ecbuild_add_library(
"${CURL_LIBRARIES}"
"${AIO_LIBRARIES}"
"${RADOS_LIBRARIES}"
"${AWSSDK_LINK_LIBRARIES}"

PUBLIC_LIBS
${CMATH_LIBRARIES}
Expand Down Expand Up @@ -984,4 +1015,3 @@ add_subdirectory( web )
if( HAVE_ECKIT_CODEC )
add_subdirectory( codec )
endif()

95 changes: 95 additions & 0 deletions src/eckit/io/s3/S3BucketName.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* (C) Copyright 1996- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation nor
* does it submit to any jurisdiction.
*/

/*
* This software was developed as part of the EC H2020 funded project IO-SEA
* (Project ID: 955811) iosea-project.eu
*/

#include "eckit/io/s3/S3BucketName.h"

#include "eckit/config/LibEcKit.h"
#include "eckit/filesystem/URI.h"
#include "eckit/io/s3/S3Client.h"
#include "eckit/io/s3/S3Exception.h"
#include "eckit/io/s3/S3ObjectName.h"

namespace eckit {

//----------------------------------------------------------------------------------------------------------------------

S3BucketName::S3BucketName(const URI& uri): S3Name(uri) {
parse();
}

S3BucketName::S3BucketName(const net::Endpoint& endpoint, const std::string& bucket):
S3Name(endpoint, "/"), bucket_(bucket) { }

//----------------------------------------------------------------------------------------------------------------------

auto S3BucketName::asString() const -> std::string {
return S3Name::asString() + "/" + bucket_;
}

void S3BucketName::print(std::ostream& out) const {
out << "S3BucketName[bucket=" << bucket_;
S3Name::print(out);
}

void S3BucketName::parse() {
const auto pairs = parseName();
if (pairs.empty()) { throw S3SeriousBug("Could not parse bucket name!", Here()); }
bucket_ = pairs[0];
}

//----------------------------------------------------------------------------------------------------------------------

auto S3BucketName::makeObject(const std::string& object) const -> std::unique_ptr<S3ObjectName> {
return std::make_unique<S3ObjectName>(endpoint(), bucket_, object);
}

auto S3BucketName::exists() const -> bool {
return client()->bucketExists(bucket_);
}

void S3BucketName::create() {
client()->createBucket(bucket_);
}

void S3BucketName::destroy() {
client()->deleteBucket(bucket_);
}

void S3BucketName::ensureCreated() {
try {
create();
}
catch (S3EntityAlreadyExists& e) {
LOG_DEBUG_LIB(LibEcKit) << e.what() << std::endl;
}
}

void S3BucketName::ensureDestroyed() {
try {
client()->emptyBucket(bucket_);
client()->deleteBucket(bucket_);
}
catch (S3EntityNotFound& e) {
LOG_DEBUG_LIB(LibEcKit) << e.what() << std::endl;
}
}

auto S3BucketName::listObjects() const -> std::vector<std::string> {
return client()->listObjects(bucket_);
}

//----------------------------------------------------------------------------------------------------------------------

} // namespace eckit
65 changes: 65 additions & 0 deletions src/eckit/io/s3/S3BucketName.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* (C) Copyright 1996- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation nor
* does it submit to any jurisdiction.
*/

/*
* This software was developed as part of the EC H2020 funded project IO-SEA
* (Project ID: 955811) iosea-project.eu
*/

/// @file S3BucketName.h
/// @author Metin Cakircali
/// @author Nicolau Manubens
/// @date Feb 2024

#pragma once

#include "eckit/io/s3/S3Name.h"

namespace eckit {

class S3ObjectName;

//----------------------------------------------------------------------------------------------------------------------

class S3BucketName: public S3Name {
public: // methods
explicit S3BucketName(const URI& uri);

S3BucketName(const net::Endpoint& endpoint, const std::string& bucket);

auto makeObject(const std::string& object) const -> std::unique_ptr<S3ObjectName>;

auto exists() const -> bool override;

void create();

void destroy();

void ensureCreated();

void ensureDestroyed();

/// @todo: return S3 object iterator but first add prefix
auto listObjects() const -> std::vector<std::string>;

auto asString() const -> std::string override;

private: // methods
void print(std::ostream& out) const override;

void parse();

private: // members
std::string bucket_;
};

//----------------------------------------------------------------------------------------------------------------------

} // namespace eckit
57 changes: 57 additions & 0 deletions src/eckit/io/s3/S3Client.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* (C) Copyright 1996- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation nor
* does it submit to any jurisdiction.
*/

/*
* This software was developed as part of the EC H2020 funded project IO-SEA
* (Project ID: 955811) iosea-project.eu
*/

#include "eckit/io/s3/S3Client.h"

#include "S3Client.h"
#include "eckit/io/s3/S3Exception.h"
#include "eckit/io/s3/S3Session.h"
#include "eckit/io/s3/aws/S3ClientAWS.h"

namespace eckit {

//----------------------------------------------------------------------------------------------------------------------

S3Client::S3Client(const S3Config& config): config_(config) { }

S3Client::~S3Client() = default;

//----------------------------------------------------------------------------------------------------------------------

void S3Client::print(std::ostream& out) const {
out << "S3Client[config=" << config_ << "]";
}

//----------------------------------------------------------------------------------------------------------------------

auto S3Client::makeShared(const S3Config& config) -> std::shared_ptr<S3Client> {
if (config.type == S3Types::AWS) { return std::make_shared<S3ClientAWS>(config); }
throw S3SeriousBug("Unkown S3 client type!", Here());
}

//----------------------------------------------------------------------------------------------------------------------

auto S3Client::makeUnique(const S3Config& config) -> std::unique_ptr<S3Client> {
if (config.type == S3Types::AWS) { return std::make_unique<S3ClientAWS>(config); }
throw S3SeriousBug("Unkown S3 client type!", Here());
}

auto S3Client::endpoint() const -> const net::Endpoint& {
return config_.endpoint;
}

//----------------------------------------------------------------------------------------------------------------------

} // namespace eckit
86 changes: 86 additions & 0 deletions src/eckit/io/s3/S3Client.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* (C) Copyright 1996- ECMWF.
*
* This software is licensed under the terms of the Apache Licence Version 2.0
* which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
* In applying this licence, ECMWF does not waive the privileges and immunities
* granted to it by virtue of its status as an intergovernmental organisation nor
* does it submit to any jurisdiction.
*/

/*
* This software was developed as part of the EC H2020 funded project IO-SEA
* (Project ID: 955811) iosea-project.eu
*/

/// @file S3Client.h
/// @author Metin Cakircali
/// @date Jan 2024

#pragma once

#include "eckit/io/s3/S3Config.h"
#include "eckit/memory/NonCopyable.h"

#include <memory>
#include <vector>

namespace eckit {

class S3Context;

//----------------------------------------------------------------------------------------------------------------------

class S3Client: private NonCopyable {
public: // methods
virtual ~S3Client();

static auto makeShared(const S3Config& config) -> std::shared_ptr<S3Client>;

static auto makeUnique(const S3Config& config) -> std::unique_ptr<S3Client>;

virtual auto endpoint() const -> const net::Endpoint&;

virtual void createBucket(const std::string& bucket) const = 0;

virtual void emptyBucket(const std::string& bucket) const = 0;

virtual void deleteBucket(const std::string& bucket) const = 0;

virtual auto bucketExists(const std::string& bucket) const -> bool = 0;

virtual auto listBuckets() const -> std::vector<std::string> = 0;

virtual auto putObject(const std::string& bucket, const std::string& object, const void* buffer,
uint64_t length) const -> long long = 0;

virtual auto getObject(const std::string& bucket, const std::string& object, void* buffer, uint64_t offset,
uint64_t length) const -> long long = 0;

virtual void deleteObject(const std::string& bucket, const std::string& object) const = 0;

virtual void deleteObjects(const std::string& bucket, const std::vector<std::string>& objects) const = 0;

virtual auto listObjects(const std::string& bucket) const -> std::vector<std::string> = 0;

virtual auto objectExists(const std::string& bucket, const std::string& object) const -> bool = 0;

virtual auto objectSize(const std::string& bucket, const std::string& object) const -> long long = 0;

friend std::ostream& operator<<(std::ostream& out, const S3Client& client) {
client.print(out);
return out;
}

protected: // methods
explicit S3Client(const S3Config& config);

virtual void print(std::ostream& out) const;

private: // members
S3Config config_;
};

//----------------------------------------------------------------------------------------------------------------------

} // namespace eckit
Loading
Loading