Don't throw in unexceptional cases: read() & readName()

This commit is contained in:
Vitaly Baranov 2021-12-11 19:29:38 +03:00
parent a87f0b483e
commit 8c4e689da3
14 changed files with 105 additions and 90 deletions

View File

@ -433,12 +433,17 @@ bool DiskAccessStorage::exists(const UUID & id) const
}
AccessEntityPtr DiskAccessStorage::readImpl(const UUID & id) const
AccessEntityPtr DiskAccessStorage::readImpl(const UUID & id, bool throw_if_not_exists) const
{
std::lock_guard lock{mutex};
auto it = entries_by_id.find(id);
if (it == entries_by_id.end())
throwNotFound(id);
{
if (throw_if_not_exists)
throwNotFound(id);
else
return nullptr;
}
const auto & entry = it->second;
if (!entry.entity)
@ -447,13 +452,18 @@ AccessEntityPtr DiskAccessStorage::readImpl(const UUID & id) const
}
String DiskAccessStorage::readNameImpl(const UUID & id) const
std::optional<String> DiskAccessStorage::readNameImpl(const UUID & id, bool throw_if_not_exists) const
{
std::lock_guard lock{mutex};
auto it = entries_by_id.find(id);
if (it == entries_by_id.end())
throwNotFound(id);
return String{it->second.name};
{
if (throw_if_not_exists)
throwNotFound(id);
else
return std::nullopt;
}
return it->second.name;
}

View File

@ -33,8 +33,8 @@ public:
private:
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
AccessEntityPtr readImpl(const UUID & id) const override;
String readNameImpl(const UUID & id) const override;
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
std::optional<String> readNameImpl(const UUID & id, bool throw_if_not_exists) const override;
UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override;
void removeImpl(const UUID & id) override;
void updateImpl(const UUID & id, const UpdateFunc & update_func) override;

View File

@ -175,52 +175,48 @@ std::vector<UUID> IAccessStorage::getIDs(AccessEntityType type, const Strings &
}
AccessEntityPtr IAccessStorage::tryReadBase(const UUID & id) const
{
AccessEntityPtr entity;
auto func = [&] { entity = readImpl(id); };
if (!tryCall(func))
return nullptr;
return entity;
}
String IAccessStorage::readName(const UUID & id) const
{
return readNameImpl(id);
return *readNameImpl(id, /* throw_if_not_exists = */ true);
}
Strings IAccessStorage::readNames(const std::vector<UUID> & ids) const
std::optional<String> IAccessStorage::readName(const UUID & id, bool throw_if_not_exists) const
{
return readNameImpl(id, throw_if_not_exists);
}
Strings IAccessStorage::readNames(const std::vector<UUID> & ids, bool throw_if_not_exists) const
{
Strings res;
res.reserve(ids.size());
for (const auto & id : ids)
res.emplace_back(readName(id));
{
if (auto name = readNameImpl(id, throw_if_not_exists))
res.emplace_back(std::move(name).value());
}
return res;
}
std::optional<String> IAccessStorage::tryReadName(const UUID & id) const
{
String name;
auto func = [&] { name = readNameImpl(id); };
if (!tryCall(func))
return {};
return name;
return readName(id, /* throw_if_not_exists = */ false);
}
Strings IAccessStorage::tryReadNames(const std::vector<UUID> & ids) const
{
Strings res;
res.reserve(ids.size());
for (const auto & id : ids)
{
if (auto name = tryReadName(id))
res.emplace_back(std::move(name).value());
}
return res;
return readNames(ids, /* throw_if_not_exists = */ false);
}
std::optional<String> IAccessStorage::readNameImpl(const UUID & id, bool throw_if_not_exists) const
{
if (auto entity = read(id, throw_if_not_exists))
return entity->getName();
return std::nullopt;
}

View File

@ -70,10 +70,10 @@ public:
/// Reads an entity. Throws an exception if not found.
template <typename EntityClassT = IAccessEntity>
std::shared_ptr<const EntityClassT> read(const UUID & id) const;
std::shared_ptr<const EntityClassT> read(const UUID & id, bool throw_if_not_exists = true) const;
template <typename EntityClassT = IAccessEntity>
std::shared_ptr<const EntityClassT> read(const String & name) const;
std::shared_ptr<const EntityClassT> read(const String & name, bool throw_if_not_exists = true) const;
/// Reads an entity. Returns nullptr if not found.
template <typename EntityClassT = IAccessEntity>
@ -84,7 +84,8 @@ public:
/// Reads only name of an entity.
String readName(const UUID & id) const;
Strings readNames(const std::vector<UUID> & ids) const;
std::optional<String> readName(const UUID & id, bool throw_if_not_exists) const;
Strings readNames(const std::vector<UUID> & ids, bool throw_if_not_exists = true) const;
std::optional<String> tryReadName(const UUID & id) const;
Strings tryReadNames(const std::vector<UUID> & ids) const;
@ -148,8 +149,8 @@ public:
protected:
virtual std::optional<UUID> findImpl(AccessEntityType type, const String & name) const = 0;
virtual std::vector<UUID> findAllImpl(AccessEntityType type) const = 0;
virtual AccessEntityPtr readImpl(const UUID & id) const = 0;
virtual String readNameImpl(const UUID & id) const = 0;
virtual AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const = 0;
virtual std::optional<String> readNameImpl(const UUID & id, bool throw_if_not_exists) const;
virtual UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) = 0;
virtual void removeImpl(const UUID & id) = 0;
virtual void updateImpl(const UUID & id, const UpdateFunc & update_func) = 0;
@ -181,23 +182,22 @@ protected:
static void notify(const Notifications & notifications);
private:
AccessEntityPtr tryReadBase(const UUID & id) const;
const String storage_name;
mutable std::atomic<Poco::Logger *> log = nullptr;
};
template <typename EntityClassT>
std::shared_ptr<const EntityClassT> IAccessStorage::read(const UUID & id) const
std::shared_ptr<const EntityClassT> IAccessStorage::read(const UUID & id, bool throw_if_not_exists) const
{
auto entity = readImpl(id);
auto entity = readImpl(id, throw_if_not_exists);
if constexpr (std::is_same_v<EntityClassT, IAccessEntity>)
return entity;
else
{
auto ptr = typeid_cast<std::shared_ptr<const EntityClassT>>(entity);
if (ptr)
if (!entity)
return nullptr;
if (auto ptr = typeid_cast<std::shared_ptr<const EntityClassT>>(entity))
return ptr;
throwBadCast(id, entity->getType(), entity->getName(), EntityClassT::TYPE);
}
@ -205,26 +205,27 @@ std::shared_ptr<const EntityClassT> IAccessStorage::read(const UUID & id) const
template <typename EntityClassT>
std::shared_ptr<const EntityClassT> IAccessStorage::read(const String & name) const
std::shared_ptr<const EntityClassT> IAccessStorage::read(const String & name, bool throw_if_not_exists) const
{
return read<EntityClassT>(getID<EntityClassT>(name));
if (auto id = find<EntityClassT>(name))
return read<EntityClassT>(*id, throw_if_not_exists);
if (throw_if_not_exists)
throwNotFound(EntityClassT::TYPE, name);
else
return nullptr;
}
template <typename EntityClassT>
std::shared_ptr<const EntityClassT> IAccessStorage::tryRead(const UUID & id) const
{
auto entity = tryReadBase(id);
if (!entity)
return nullptr;
return typeid_cast<std::shared_ptr<const EntityClassT>>(entity);
return read<EntityClassT>(id, false);
}
template <typename EntityClassT>
std::shared_ptr<const EntityClassT> IAccessStorage::tryRead(const String & name) const
{
auto id = find<EntityClassT>(name);
return id ? tryRead<EntityClassT>(*id) : nullptr;
return read<EntityClassT>(name, false);
}
}

View File

@ -433,17 +433,17 @@ bool LDAPAccessStorage::exists(const UUID & id) const
}
AccessEntityPtr LDAPAccessStorage::readImpl(const UUID & id) const
AccessEntityPtr LDAPAccessStorage::readImpl(const UUID & id, bool throw_if_not_exists) const
{
std::scoped_lock lock(mutex);
return memory_storage.read(id);
return memory_storage.read(id, throw_if_not_exists);
}
String LDAPAccessStorage::readNameImpl(const UUID & id) const
std::optional<String> LDAPAccessStorage::readNameImpl(const UUID & id, bool throw_if_not_exists) const
{
std::scoped_lock lock(mutex);
return memory_storage.readName(id);
return memory_storage.readName(id, throw_if_not_exists);
}

View File

@ -48,8 +48,8 @@ public: // IAccessStorage implementations.
private: // IAccessStorage implementations.
virtual std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
virtual std::vector<UUID> findAllImpl(AccessEntityType type) const override;
virtual AccessEntityPtr readImpl(const UUID & id) const override;
virtual String readNameImpl(const UUID & id) const override;
virtual AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
virtual std::optional<String> readNameImpl(const UUID & id, bool throw_if_not_exists) const override;
virtual UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override;
virtual void removeImpl(const UUID & id) override;
virtual void updateImpl(const UUID & id, const UpdateFunc & update_func) override;

View File

@ -45,23 +45,22 @@ bool MemoryAccessStorage::exists(const UUID & id) const
}
AccessEntityPtr MemoryAccessStorage::readImpl(const UUID & id) const
AccessEntityPtr MemoryAccessStorage::readImpl(const UUID & id, bool throw_if_not_exists) const
{
std::lock_guard lock{mutex};
auto it = entries_by_id.find(id);
if (it == entries_by_id.end())
throwNotFound(id);
{
if (throw_if_not_exists)
throwNotFound(id);
else
return nullptr;
}
const Entry & entry = it->second;
return entry.entity;
}
String MemoryAccessStorage::readNameImpl(const UUID & id) const
{
return readImpl(id)->getName();
}
UUID MemoryAccessStorage::insertImpl(const AccessEntityPtr & new_entity, bool replace_if_exists)
{
Notifications notifications;

View File

@ -30,8 +30,7 @@ public:
private:
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
AccessEntityPtr readImpl(const UUID & id) const override;
String readNameImpl(const UUID & id) const override;
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override;
void removeImpl(const UUID & id) override;
void updateImpl(const UUID & id, const UpdateFunc & update_func) override;

View File

@ -180,15 +180,27 @@ ConstStoragePtr MultipleAccessStorage::getStorage(const UUID & id) const
return const_cast<MultipleAccessStorage *>(this)->getStorage(id);
}
AccessEntityPtr MultipleAccessStorage::readImpl(const UUID & id) const
AccessEntityPtr MultipleAccessStorage::readImpl(const UUID & id, bool throw_if_not_exists) const
{
return getStorage(id)->read(id);
if (auto storage = findStorage(id))
return storage->read(id, throw_if_not_exists);
if (throw_if_not_exists)
throwNotFound(id);
else
return nullptr;
}
String MultipleAccessStorage::readNameImpl(const UUID & id) const
std::optional<String> MultipleAccessStorage::readNameImpl(const UUID & id, bool throw_if_not_exists) const
{
return getStorage(id)->readName(id);
if (auto storage = findStorage(id))
return storage->readName(id, throw_if_not_exists);
if (throw_if_not_exists)
throwNotFound(id);
else
return std::nullopt;
}

View File

@ -42,8 +42,8 @@ public:
protected:
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
AccessEntityPtr readImpl(const UUID & id) const override;
String readNameImpl(const UUID &id) const override;
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
std::optional<String> readNameImpl(const UUID & id, bool throw_if_not_exists) const override;
UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override;
void removeImpl(const UUID & id) override;
void updateImpl(const UUID & id, const UpdateFunc & update_func) override;

View File

@ -532,23 +532,22 @@ bool ReplicatedAccessStorage::exists(const UUID & id) const
}
AccessEntityPtr ReplicatedAccessStorage::readImpl(const UUID & id) const
AccessEntityPtr ReplicatedAccessStorage::readImpl(const UUID & id, bool throw_if_not_exists) const
{
std::lock_guard lock{mutex};
const auto it = entries_by_id.find(id);
if (it == entries_by_id.end())
throwNotFound(id);
{
if (throw_if_not_exists)
throwNotFound(id);
else
return nullptr;
}
const Entry & entry = it->second;
return entry.entity;
}
String ReplicatedAccessStorage::readNameImpl(const UUID & id) const
{
return readImpl(id)->getName();
}
void ReplicatedAccessStorage::prepareNotifications(const Entry & entry, bool remove, Notifications & notifications) const
{
const AccessEntityPtr entity = remove ? nullptr : entry.entity;

View File

@ -75,8 +75,7 @@ private:
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
AccessEntityPtr readImpl(const UUID & id) const override;
String readNameImpl(const UUID & id) const override;
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
void prepareNotifications(const Entry & entry, bool remove, Notifications & notifications) const;
scope_guard subscribeForChangesImpl(const UUID & id, const OnChangedHandler & handler) const override;

View File

@ -609,15 +609,15 @@ bool UsersConfigAccessStorage::exists(const UUID & id) const
}
AccessEntityPtr UsersConfigAccessStorage::readImpl(const UUID & id) const
AccessEntityPtr UsersConfigAccessStorage::readImpl(const UUID & id, bool throw_if_not_exists) const
{
return memory_storage.read(id);
return memory_storage.read(id, throw_if_not_exists);
}
String UsersConfigAccessStorage::readNameImpl(const UUID & id) const
std::optional<String> UsersConfigAccessStorage::readNameImpl(const UUID & id, bool throw_if_not_exists) const
{
return memory_storage.readName(id);
return memory_storage.readName(id, throw_if_not_exists);
}

View File

@ -50,8 +50,8 @@ private:
std::optional<UUID> findImpl(AccessEntityType type, const String & name) const override;
std::vector<UUID> findAllImpl(AccessEntityType type) const override;
AccessEntityPtr readImpl(const UUID & id) const override;
String readNameImpl(const UUID & id) const override;
AccessEntityPtr readImpl(const UUID & id, bool throw_if_not_exists) const override;
std::optional<String> readNameImpl(const UUID & id, bool throw_if_not_exists) const override;
UUID insertImpl(const AccessEntityPtr & entity, bool replace_if_exists) override;
void removeImpl(const UUID & id) override;
void updateImpl(const UUID & id, const UpdateFunc & update_func) override;