[PDT] TDE-3114: prevent a race-condition when creating the S3 cache

This commit is contained in:
mupdt 2022-12-21 04:50:40 -05:00
parent 1437582ccd
commit bc8ab21c5a

View file

@ -166,16 +166,37 @@ public:
return i->second; return i->second;
} }
std::optional<Cache> queryCacheRaw(State & state, const std::string & uri)
{
auto i = state.caches.find(uri);
if (i == state.caches.end()) {
auto queryCache(state.queryCache.use()(uri)(time(0) - cacheInfoTtl));
if (!queryCache.next())
return std::nullopt;
state.caches.emplace(uri,
Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)});
}
return getCache(state, uri);
}
void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) override void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) override
{ {
retrySQLite<void>([&]() { retrySQLite<void>([&]() {
auto state(_state.lock()); auto state(_state.lock());
SQLiteTxn txn(state->db);
// FIXME: race // To avoid the race, we have to check if maybe someone hasn't yet created
// the cache for this URI in the meantime.
auto cache(queryCacheRaw(*state, uri));
if (cache)
return;
state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority).exec(); state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority).exec();
assert(sqlite3_changes(state->db) == 1); assert(sqlite3_changes(state->db) == 1);
state->caches[uri] = Cache{(int) sqlite3_last_insert_rowid(state->db), storeDir, wantMassQuery, priority}; state->caches[uri] = Cache{(int) sqlite3_last_insert_rowid(state->db), storeDir, wantMassQuery, priority};
txn.commit();
}); });
} }
@ -183,21 +204,12 @@ public:
{ {
return retrySQLite<std::optional<CacheInfo>>([&]() -> std::optional<CacheInfo> { return retrySQLite<std::optional<CacheInfo>>([&]() -> std::optional<CacheInfo> {
auto state(_state.lock()); auto state(_state.lock());
auto cache(queryCacheRaw(*state, uri));
auto i = state->caches.find(uri); if (!cache)
if (i == state->caches.end()) {
auto queryCache(state->queryCache.use()(uri)(time(0) - cacheInfoTtl));
if (!queryCache.next())
return std::nullopt; return std::nullopt;
state->caches.emplace(uri,
Cache{(int) queryCache.getInt(0), queryCache.getStr(1), queryCache.getInt(2) != 0, (int) queryCache.getInt(3)});
}
auto & cache(getCache(*state, uri));
return CacheInfo { return CacheInfo {
.wantMassQuery = cache.wantMassQuery, .wantMassQuery = cache->wantMassQuery,
.priority = cache.priority .priority = cache->priority
}; };
}); });
} }