about summary refs log tree commit diff
path: root/src/libstore/s3-binary-cache-store.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/s3-binary-cache-store.cc')
-rw-r--r--src/libstore/s3-binary-cache-store.cc55
1 files changed, 43 insertions, 12 deletions
diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc
index fb36dbc7be74..145a8191c55c 100644
--- a/src/libstore/s3-binary-cache-store.cc
+++ b/src/libstore/s3-binary-cache-store.cc
@@ -12,6 +12,8 @@
 #include <aws/core/Aws.h>
 #include <aws/core/client/ClientConfiguration.h>
 #include <aws/core/client/DefaultRetryStrategy.h>
+#include <aws/core/utils/logging/FormattedLogSystem.h>
+#include <aws/core/utils/logging/LogMacros.h>
 #include <aws/s3/S3Client.h>
 #include <aws/s3/model/CreateBucketRequest.h>
 #include <aws/s3/model/GetBucketLocationRequest.h>
@@ -41,6 +43,16 @@ R && checkAws(const FormatOrString & fs, Aws::Utils::Outcome<R, E> && outcome)
     return outcome.GetResultWithOwnership();
 }
 
+class AwsLogger : public Aws::Utils::Logging::FormattedLogSystem
+{
+    using Aws::Utils::Logging::FormattedLogSystem::FormattedLogSystem;
+
+    void ProcessFormattedStatement(Aws::String && statement) override
+    {
+        debug("AWS: %s", chomp(statement));
+    }
+};
+
 static void initAWS()
 {
     static std::once_flag flag;
@@ -51,25 +63,36 @@ static void initAWS()
            shared.cc), so don't let aws-sdk-cpp override it. */
         options.cryptoOptions.initAndCleanupOpenSSL = false;
 
+        if (verbosity >= lvlDebug) {
+            options.loggingOptions.logLevel =
+                verbosity == lvlDebug
+                ? Aws::Utils::Logging::LogLevel::Debug
+                : Aws::Utils::Logging::LogLevel::Trace;
+            options.loggingOptions.logger_create_fn = [options]() {
+                return std::make_shared<AwsLogger>(options.loggingOptions.logLevel);
+            };
+        }
+
         Aws::InitAPI(options);
     });
 }
 
 S3Helper::S3Helper(const string & region)
     : config(makeConfig(region))
-    , client(make_ref<Aws::S3::S3Client>(*config))
+    , client(make_ref<Aws::S3::S3Client>(*config, true, false))
 {
 }
 
 /* Log AWS retries. */
 class RetryStrategy : public Aws::Client::DefaultRetryStrategy
 {
-    long CalculateDelayBeforeNextRetry(const Aws::Client::AWSError<Aws::Client::CoreErrors>& error, long attemptedRetries) const override
+    bool ShouldRetry(const Aws::Client::AWSError<Aws::Client::CoreErrors>& error, long attemptedRetries) const override
     {
-        auto res = Aws::Client::DefaultRetryStrategy::CalculateDelayBeforeNextRetry(error, attemptedRetries);
-        printError("AWS error '%s' (%s), will retry in %d ms",
-            error.GetExceptionName(), error.GetMessage(), res);
-        return res;
+        auto retry = Aws::Client::DefaultRetryStrategy::ShouldRetry(error, attemptedRetries);
+        if (retry)
+            printError("AWS error '%s' (%s), will retry in %d ms",
+                error.GetExceptionName(), error.GetMessage(), CalculateDelayBeforeNextRetry(error, attemptedRetries));
+        return retry;
     }
 };
 
@@ -164,14 +187,20 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
                 if (res.GetError().GetErrorType() != Aws::S3::S3Errors::NO_SUCH_BUCKET)
                     throw Error(format("AWS error checking bucket ‘%s’: %s") % bucketName % res.GetError().GetMessage());
 
+                printInfo("creating S3 bucket ‘%s’...", bucketName);
+
+                // Stupid S3 bucket locations.
+                auto bucketConfig = Aws::S3::Model::CreateBucketConfiguration();
+                if (s3Helper.config->region != "us-east-1")
+                    bucketConfig.SetLocationConstraint(
+                        Aws::S3::Model::BucketLocationConstraintMapper::GetBucketLocationConstraintForName(
+                            s3Helper.config->region));
+
                 checkAws(format("AWS error creating bucket ‘%s’") % bucketName,
                     s3Helper.client->CreateBucket(
                         Aws::S3::Model::CreateBucketRequest()
                         .WithBucket(bucketName)
-                        .WithCreateBucketConfiguration(
-                            Aws::S3::Model::CreateBucketConfiguration()
-                            /* .WithLocationConstraint(
-                               Aws::S3::Model::BucketLocationConstraint::US) */ )));
+                        .WithCreateBucketConfiguration(bucketConfig)));
             }
 
             BinaryCacheStore::init();
@@ -210,8 +239,10 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
 
         if (!res.IsSuccess()) {
             auto & error = res.GetError();
-            if (error.GetErrorType() == Aws::S3::S3Errors::UNKNOWN // FIXME
-                && error.GetMessage().find("404") != std::string::npos)
+            if (error.GetErrorType() == Aws::S3::S3Errors::RESOURCE_NOT_FOUND
+                || error.GetErrorType() == Aws::S3::S3Errors::NO_SUCH_KEY
+                || (error.GetErrorType() == Aws::S3::S3Errors::UNKNOWN // FIXME
+                    && error.GetMessage().find("404") != std::string::npos))
                 return false;
             throw Error(format("AWS error fetching ‘%s’: %s") % path % error.GetMessage());
         }