S3BinaryCacheStore::isValidPath(): Do a GET instead of HEAD

This commit is contained in:
Eelco Dolstra 2016-02-19 17:41:11 +01:00
parent bd76f9120a
commit 2b76094a23
4 changed files with 33 additions and 3 deletions

View file

@ -103,12 +103,12 @@ NarInfo BinaryCacheStore::readNarInfo(const Path & storePath)
} }
} }
stats.narInfoRead++;
auto narInfoFile = narInfoFileFor(storePath); auto narInfoFile = narInfoFileFor(storePath);
auto narInfo = make_ref<NarInfo>(getFile(narInfoFile), narInfoFile); auto narInfo = make_ref<NarInfo>(getFile(narInfoFile), narInfoFile);
assert(narInfo->path == storePath); assert(narInfo->path == storePath);
stats.narInfoRead++;
if (publicKeys) { if (publicKeys) {
if (!narInfo->checkSignature(*publicKeys)) if (!narInfo->checkSignature(*publicKeys))
throw Error(format("invalid signature on NAR info file %1%") % narInfoFile); throw Error(format("invalid signature on NAR info file %1%") % narInfoFile);

View file

@ -74,6 +74,8 @@ private:
void addToCache(const ValidPathInfo & info, const string & nar); void addToCache(const ValidPathInfo & info, const string & nar);
protected:
NarInfo readNarInfo(const Path & storePath); NarInfo readNarInfo(const Path & storePath);
public: public:

View file

@ -1,5 +1,7 @@
#include "s3-binary-cache-store.hh" #include "s3-binary-cache-store.hh"
#include "nar-info.hh"
#include <aws/core/client/ClientConfiguration.h> #include <aws/core/client/ClientConfiguration.h>
#include <aws/s3/S3Client.h> #include <aws/s3/S3Client.h>
#include <aws/s3/model/CreateBucketRequest.h> #include <aws/s3/model/CreateBucketRequest.h>
@ -10,13 +12,22 @@
namespace nix { namespace nix {
struct S3Error : public Error
{
Aws::S3::S3Errors err;
S3Error(Aws::S3::S3Errors err, const FormatOrString & fs)
: Error(fs), err(err) { };
};
/* Helper: given an Outcome<R, E>, return R in case of success, or /* Helper: given an Outcome<R, E>, return R in case of success, or
throw an exception in case of an error. */ throw an exception in case of an error. */
template<typename R, typename E> template<typename R, typename E>
R && checkAws(Aws::Utils::Outcome<R, E> && outcome) R && checkAws(Aws::Utils::Outcome<R, E> && outcome)
{ {
if (!outcome.IsSuccess()) if (!outcome.IsSuccess())
throw Error(format("AWS error: %1%") % outcome.GetError().GetMessage()); throw S3Error(
outcome.GetError().GetErrorType(),
format("AWS error: %1%") % outcome.GetError().GetMessage());
return outcome.GetResultWithOwnership(); return outcome.GetResultWithOwnership();
} }
@ -67,6 +78,21 @@ const S3BinaryCacheStore::Stats & S3BinaryCacheStore::getS3Stats()
return stats; return stats;
} }
/* This is a specialisation of isValidPath() that optimistically
fetches the .narinfo file, rather than first checking for its
existence via a HEAD request. Since .narinfos are small, doing a
GET is unlikely to be slower than HEAD. */
bool S3BinaryCacheStore::isValidPath(const Path & storePath)
{
try {
readNarInfo(storePath);
return true;
} catch (S3Error & e) {
if (e.err == Aws::S3::S3Errors::NO_SUCH_KEY) return false;
throw;
}
}
bool S3BinaryCacheStore::fileExists(const std::string & path) bool S3BinaryCacheStore::fileExists(const std::string & path)
{ {
stats.head++; stats.head++;

View file

@ -39,6 +39,8 @@ public:
const Stats & getS3Stats(); const Stats & getS3Stats();
bool isValidPath(const Path & storePath) override;
private: private:
Stats stats; Stats stats;