@@ -44,17 +44,63 @@ 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" , live);
73+ }
74+ Aws::ShutdownAPI (options_);
75+ state_.store (State::kFinalized );
76+ return {};
77+ }
78+
79+ Status EnsureInitialized () {
80+ if (state_.load () == State::kInitialized ) return {};
81+ return Initialize ();
82+ }
83+
84+ bool IsInitialized () const { return state_.load () == State::kInitialized ; }
85+ bool IsFinalized () const { return state_.load () == State::kFinalized ; }
86+
87+ void IncrementSessionCount () {
88+ active_session_count_.fetch_add (1 , std::memory_order_relaxed);
89+ }
90+ void DecrementSessionCount () {
91+ active_session_count_.fetch_sub (1 , std::memory_order_relaxed);
92+ }
93+
94+ private:
95+ enum class State : uint8_t { kUninitialized , kInitialized , kFinalized };
96+
97+ AwsSdkLifecycle () = default ;
98+
99+ std::atomic<State> state_{State::kUninitialized };
100+ std::mutex mutex_;
101+ Aws::SDKOptions options_;
102+ std::atomic<size_t > active_session_count_{0 };
103+ };
58104
59105Aws::Http::HttpMethod ToAwsMethod (HttpMethod method) {
60106 switch (method) {
@@ -112,12 +158,11 @@ SigV4AuthSession::SigV4AuthSession(
112158 credentials_provider_(std::move(credentials_provider)),
113159 signer_(std::make_unique<RestSigV4Signer>(
114160 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);
161+ AwsSdkLifecycle::Instance ().IncrementSessionCount ();
117162}
118163
119164SigV4AuthSession::~SigV4AuthSession () {
120- g_active_session_count. fetch_sub ( 1 , std::memory_order_relaxed );
165+ AwsSdkLifecycle::Instance (). DecrementSessionCount ( );
121166}
122167
123168Result<HttpRequest> SigV4AuthSession::Authenticate (const HttpRequest& request) {
@@ -191,7 +236,7 @@ SigV4AuthManager::~SigV4AuthManager() = default;
191236Result<std::shared_ptr<AuthSession>> SigV4AuthManager::InitSession (
192237 HttpClient& init_client,
193238 const std::unordered_map<std::string, std::string>& properties) {
194- ICEBERG_RETURN_UNEXPECTED (EnsureSdkInitialized ());
239+ ICEBERG_RETURN_UNEXPECTED (AwsSdkLifecycle::Instance (). EnsureInitialized ());
195240 ICEBERG_ASSIGN_OR_RAISE (auto delegate_session,
196241 delegate_->InitSession (init_client, properties));
197242 return WrapSession (std::move (delegate_session), properties);
@@ -200,7 +245,7 @@ Result<std::shared_ptr<AuthSession>> SigV4AuthManager::InitSession(
200245Result<std::shared_ptr<AuthSession>> SigV4AuthManager::CatalogSession (
201246 HttpClient& shared_client,
202247 const std::unordered_map<std::string, std::string>& properties) {
203- ICEBERG_RETURN_UNEXPECTED (EnsureSdkInitialized ());
248+ ICEBERG_RETURN_UNEXPECTED (AwsSdkLifecycle::Instance (). EnsureInitialized ());
204249 catalog_properties_ = properties;
205250 ICEBERG_ASSIGN_OR_RAISE (auto delegate_session,
206251 delegate_->CatalogSession (shared_client, properties));
@@ -325,34 +370,13 @@ Result<std::unique_ptr<AuthManager>> MakeSigV4AuthManager(
325370 return std::make_unique<SigV4AuthManager>(std::move (delegate));
326371}
327372
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- }
373+ Status InitializeAwsSdk () { return AwsSdkLifecycle::Instance ().Initialize (); }
339374
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- }
375+ Status FinalizeAwsSdk () { return AwsSdkLifecycle::Instance ().Finalize (); }
352376
353- bool IsAwsSdkInitialized () { return g_state. load () == LifecycleState:: kInitialized ; }
377+ bool IsAwsSdkInitialized () { return AwsSdkLifecycle::Instance (). IsInitialized () ; }
354378
355- bool IsAwsSdkFinalized () { return g_state. load () == LifecycleState:: kFinalized ; }
379+ bool IsAwsSdkFinalized () { return AwsSdkLifecycle::Instance (). IsFinalized () ; }
356380
357381} // namespace iceberg::rest::auth
358382
0 commit comments