1919
2020#include < cstdlib>
2121#include < mutex>
22- #include < stdexcept >
22+ #include < string >
2323
2424#include < arrow/filesystem/filesystem.h>
2525#ifdef ICEBERG_S3_ENABLED
3232#include " iceberg/arrow/arrow_file_io.h"
3333#include " iceberg/arrow/arrow_fs_file_io_internal.h"
3434#include " iceberg/arrow/arrow_status_internal.h"
35- #include " iceberg/arrow/s3_properties.h"
35+ #include " iceberg/arrow/s3/ s3_properties.h"
3636#include " iceberg/util/macros.h"
37+ #include " iceberg/util/string_util.h"
3738
3839namespace iceberg ::arrow {
3940
4041namespace {
4142
42- Status EnsureS3Initialized () {
4343#if ICEBERG_ARROW_HAS_S3
44+ Status EnsureS3Initialized () {
4445 static std::once_flag init_flag;
4546 static ::arrow::Status init_status = ::arrow::Status::OK ();
4647 std::call_once (init_flag, []() {
47- ::arrow::fs::S3GlobalOptions options ;
48+ auto options = ::arrow::fs::S3GlobalOptions::Defaults () ;
4849 init_status = ::arrow::fs::InitializeS3 (options);
4950 });
5051 if (!init_status.ok ()) {
5152 return std::unexpected (Error{.kind = ::iceberg::arrow::ToErrorKind (init_status),
5253 .message = init_status.ToString ()});
5354 }
5455 return {};
55- #else
56- return NotImplemented (" Arrow S3 support is not enabled" );
57- #endif
5856}
59-
60- #if ICEBERG_ARROW_HAS_S3
6157// / \brief Configure S3Options from a properties map.
6258// /
6359// / \param properties The configuration properties map.
@@ -67,9 +63,9 @@ Result<::arrow::fs::S3Options> ConfigureS3Options(
6763 ::arrow::fs::S3Options options;
6864
6965 // Configure credentials
70- auto access_key_it = properties.find (S3Properties::kAccessKeyId );
71- auto secret_key_it = properties.find (S3Properties::kSecretAccessKey );
72- auto session_token_it = properties.find (S3Properties::kSessionToken );
66+ auto access_key_it = properties.find (std::string ( S3Properties::kAccessKeyId ) );
67+ auto secret_key_it = properties.find (std::string ( S3Properties::kSecretAccessKey ) );
68+ auto session_token_it = properties.find (std::string ( S3Properties::kSessionToken ) );
7369
7470 if (access_key_it != properties.end () && secret_key_it != properties.end ()) {
7571 if (session_token_it != properties.end ()) {
@@ -84,13 +80,13 @@ Result<::arrow::fs::S3Options> ConfigureS3Options(
8480 }
8581
8682 // Configure region
87- auto region_it = properties.find (S3Properties::kRegion );
83+ auto region_it = properties.find (std::string ( S3Properties::kRegion ) );
8884 if (region_it != properties.end ()) {
8985 options.region = region_it->second ;
9086 }
9187
9288 // Configure endpoint (for MinIO, LocalStack, etc.)
93- auto endpoint_it = properties.find (S3Properties::kEndpoint );
89+ auto endpoint_it = properties.find (std::string ( S3Properties::kEndpoint ) );
9490 if (endpoint_it != properties.end ()) {
9591 options.endpoint_override = endpoint_it->second ;
9692 } else {
@@ -106,36 +102,30 @@ Result<::arrow::fs::S3Options> ConfigureS3Options(
106102 }
107103 }
108104
109- auto path_style_it = properties.find (S3Properties::kPathStyleAccess );
105+ auto path_style_it = properties.find (std::string ( S3Properties::kPathStyleAccess ) );
110106 if (path_style_it != properties.end () && path_style_it->second == " true" ) {
111107 options.force_virtual_addressing = false ;
112108 }
113109
114110 // Configure SSL
115- auto ssl_it = properties.find (S3Properties::kSslEnabled );
111+ auto ssl_it = properties.find (std::string ( S3Properties::kSslEnabled ) );
116112 if (ssl_it != properties.end () && ssl_it->second == " false" ) {
117113 options.scheme = " http" ;
118114 }
119115
120116 // Configure timeouts
121- auto connect_timeout_it = properties.find (S3Properties::kConnectTimeoutMs );
117+ auto connect_timeout_it = properties.find (std::string ( S3Properties::kConnectTimeoutMs ) );
122118 if (connect_timeout_it != properties.end ()) {
123- try {
124- options.connect_timeout = std::stod (connect_timeout_it->second ) / 1000.0 ;
125- } catch (const std::exception& e) {
126- return InvalidArgument (" Invalid {}: '{}' ({})" , S3Properties::kConnectTimeoutMs ,
127- connect_timeout_it->second , e.what ());
128- }
119+ ICEBERG_ASSIGN_OR_RAISE (auto timeout_ms,
120+ StringUtils::ParseNumber<double >(connect_timeout_it->second ));
121+ options.connect_timeout = timeout_ms / 1000.0 ;
129122 }
130123
131- auto socket_timeout_it = properties.find (S3Properties::kSocketTimeoutMs );
124+ auto socket_timeout_it = properties.find (std::string ( S3Properties::kSocketTimeoutMs ) );
132125 if (socket_timeout_it != properties.end ()) {
133- try {
134- options.request_timeout = std::stod (socket_timeout_it->second ) / 1000.0 ;
135- } catch (const std::exception& e) {
136- return InvalidArgument (" Invalid {}: '{}' ({})" , S3Properties::kSocketTimeoutMs ,
137- socket_timeout_it->second , e.what ());
138- }
126+ ICEBERG_ASSIGN_OR_RAISE (auto timeout_ms,
127+ StringUtils::ParseNumber<double >(socket_timeout_it->second ));
128+ options.request_timeout = timeout_ms / 1000.0 ;
139129 }
140130
141131 return options;
@@ -145,13 +135,9 @@ Result<::arrow::fs::S3Options> ConfigureS3Options(
145135} // namespace
146136
147137Result<std::unique_ptr<FileIO>> MakeS3FileIO (
148- const std::string& uri,
149138 const std::unordered_map<std::string, std::string>& properties) {
150- if (!uri.starts_with (" s3://" )) {
151- return InvalidArgument (" S3 URI must start with s3://" );
152- }
153139#if !ICEBERG_ARROW_HAS_S3
154- return NotImplemented (" Arrow S3 support is not enabled" );
140+ return NotSupported (" Arrow S3 support is not enabled" );
155141#else
156142 ICEBERG_RETURN_UNEXPECTED (EnsureS3Initialized ());
157143
@@ -163,4 +149,14 @@ Result<std::unique_ptr<FileIO>> MakeS3FileIO(
163149#endif
164150}
165151
152+ Status FinalizeS3 () {
153+ #if ICEBERG_ARROW_HAS_S3
154+ auto status = ::arrow::fs::FinalizeS3 ();
155+ ICEBERG_ARROW_RETURN_NOT_OK (status);
156+ return {};
157+ #else
158+ return NotSupported (" Arrow S3 support is not enabled" );
159+ #endif
160+ }
161+
166162} // namespace iceberg::arrow
0 commit comments