@@ -44,17 +44,64 @@ namespace iceberg::rest::auth {
4444
4545namespace {
4646
47- enum class LifecycleState : uint8_t { kUninitialized , kInitialized , kFinalized };
47+ class AwsSdkLifecycle {
48+ public:
49+ static AwsSdkLifecycle& Instance () {
50+ static AwsSdkLifecycle instance;
51+ return instance;
52+ }
4853
49- std::atomic<LifecycleState> g_state{LifecycleState::kUninitialized };
50- std::mutex g_lifecycle_mutex;
51- Aws::SDKOptions g_sdk_options;
52- std::atomic<size_t > g_active_session_count{0 };
54+ Status Initialize () {
55+ std::lock_guard<std::mutex> lock (mutex_);
56+ auto s = state_.load ();
57+ if (s == State::kInitialized ) return {};
58+ if (s == State::kFinalized ) {
59+ return InvalidArgument (" AWS SDK has already been finalized; cannot reinitialize" );
60+ }
61+ Aws::InitAPI (options_);
62+ state_.store (State::kInitialized );
63+ return {};
64+ }
5365
54- Status EnsureSdkInitialized () {
55- if (g_state.load () == LifecycleState::kInitialized ) return {};
56- return InitializeAwsSdk ();
57- }
66+ Status Finalize () {
67+ std::lock_guard<std::mutex> lock (mutex_);
68+ if (state_.load () != State::kInitialized ) return {};
69+ auto live = active_session_count_.load ();
70+ if (live != 0 ) {
71+ return Invalid (
72+ " Cannot finalize AWS SDK while {} SigV4 auth session(s) are still alive" ,
73+ live);
74+ }
75+ Aws::ShutdownAPI (options_);
76+ state_.store (State::kFinalized );
77+ return {};
78+ }
79+
80+ Status EnsureInitialized () {
81+ if (state_.load () == State::kInitialized ) return {};
82+ return Initialize ();
83+ }
84+
85+ bool IsInitialized () const { return state_.load () == State::kInitialized ; }
86+ bool IsFinalized () const { return state_.load () == State::kFinalized ; }
87+
88+ void IncrementSessionCount () {
89+ active_session_count_.fetch_add (1 , std::memory_order_relaxed);
90+ }
91+ void DecrementSessionCount () {
92+ active_session_count_.fetch_sub (1 , std::memory_order_relaxed);
93+ }
94+
95+ private:
96+ enum class State : uint8_t { kUninitialized , kInitialized , kFinalized };
97+
98+ AwsSdkLifecycle () = default ;
99+
100+ std::atomic<State> state_{State::kUninitialized };
101+ std::mutex mutex_;
102+ Aws::SDKOptions options_;
103+ std::atomic<size_t > active_session_count_{0 };
104+ };
58105
59106Aws::Http::HttpMethod ToAwsMethod (HttpMethod method) {
60107 switch (method) {
@@ -112,12 +159,11 @@ SigV4AuthSession::SigV4AuthSession(
112159 credentials_provider_(std::move(credentials_provider)),
113160 signer_(std::make_unique<RestSigV4Signer>(
114161 credentials_provider_, signing_name_.c_str(), signing_region_.c_str())) {
115- // Counted so FinalizeAwsSdk() refuses to ShutdownAPI while sessions exist.
116- g_active_session_count.fetch_add (1 , std::memory_order_relaxed);
162+ AwsSdkLifecycle::Instance ().IncrementSessionCount ();
117163}
118164
119165SigV4AuthSession::~SigV4AuthSession () {
120- g_active_session_count. fetch_sub ( 1 , std::memory_order_relaxed );
166+ AwsSdkLifecycle::Instance (). DecrementSessionCount ( );
121167}
122168
123169Result<HttpRequest> SigV4AuthSession::Authenticate (const HttpRequest& request) {
@@ -191,7 +237,7 @@ SigV4AuthManager::~SigV4AuthManager() = default;
191237Result<std::shared_ptr<AuthSession>> SigV4AuthManager::InitSession (
192238 HttpClient& init_client,
193239 const std::unordered_map<std::string, std::string>& properties) {
194- ICEBERG_RETURN_UNEXPECTED (EnsureSdkInitialized ());
240+ ICEBERG_RETURN_UNEXPECTED (AwsSdkLifecycle::Instance (). EnsureInitialized ());
195241 ICEBERG_ASSIGN_OR_RAISE (auto delegate_session,
196242 delegate_->InitSession (init_client, properties));
197243 return WrapSession (std::move (delegate_session), properties);
@@ -200,7 +246,7 @@ Result<std::shared_ptr<AuthSession>> SigV4AuthManager::InitSession(
200246Result<std::shared_ptr<AuthSession>> SigV4AuthManager::CatalogSession (
201247 HttpClient& shared_client,
202248 const std::unordered_map<std::string, std::string>& properties) {
203- ICEBERG_RETURN_UNEXPECTED (EnsureSdkInitialized ());
249+ ICEBERG_RETURN_UNEXPECTED (AwsSdkLifecycle::Instance (). EnsureInitialized ());
204250 catalog_properties_ = properties;
205251 ICEBERG_ASSIGN_OR_RAISE (auto delegate_session,
206252 delegate_->CatalogSession (shared_client, properties));
@@ -325,34 +371,13 @@ Result<std::unique_ptr<AuthManager>> MakeSigV4AuthManager(
325371 return std::make_unique<SigV4AuthManager>(std::move (delegate));
326372}
327373
328- Status InitializeAwsSdk () {
329- std::lock_guard<std::mutex> lock (g_lifecycle_mutex);
330- auto state = g_state.load ();
331- if (state == LifecycleState::kInitialized ) return {};
332- if (state == LifecycleState::kFinalized ) {
333- return InvalidArgument (" AWS SDK has already been finalized; cannot reinitialize" );
334- }
335- Aws::InitAPI (g_sdk_options);
336- g_state.store (LifecycleState::kInitialized );
337- return {};
338- }
374+ Status InitializeAwsSdk () { return AwsSdkLifecycle::Instance ().Initialize (); }
339375
340- Status FinalizeAwsSdk () {
341- std::lock_guard<std::mutex> lock (g_lifecycle_mutex);
342- if (g_state.load () != LifecycleState::kInitialized ) return {};
343- auto live = g_active_session_count.load ();
344- if (live != 0 ) {
345- return Invalid (
346- " Cannot finalize AWS SDK while {} SigV4 auth session(s) are still alive" , live);
347- }
348- Aws::ShutdownAPI (g_sdk_options);
349- g_state.store (LifecycleState::kFinalized );
350- return {};
351- }
376+ Status FinalizeAwsSdk () { return AwsSdkLifecycle::Instance ().Finalize (); }
352377
353- bool IsAwsSdkInitialized () { return g_state. load () == LifecycleState:: kInitialized ; }
378+ bool IsAwsSdkInitialized () { return AwsSdkLifecycle::Instance (). IsInitialized () ; }
354379
355- bool IsAwsSdkFinalized () { return g_state. load () == LifecycleState:: kFinalized ; }
380+ bool IsAwsSdkFinalized () { return AwsSdkLifecycle::Instance (). IsFinalized () ; }
356381
357382} // namespace iceberg::rest::auth
358383
0 commit comments