Select Git revision
connection.h
-
Timm Fitschen authoredTimm Fitschen authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
connection.h 7.50 KiB
/*
* This file is a part of the CaosDB Project.
*
* Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
* Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef CAOSDB_CONNECTION_H
#define CAOSDB_CONNECTION_H
/**
* @file caosdb/connection.h
* @author Timm Fitschen
* @date 2021-05-18
* @brief Configuration and setup of the connection.
*/
#ifdef BUILD_ACM
#include "caosdb/acm/user.h" // for User
#include "caosdb/acm/v1alpha1/main.grpc.pb.h" // for AccessControlMan...
#endif
#include "caosdb/authentication.h" // for Authenticator
#include "caosdb/configuration.h" // for ConnectionConfigura...
#include "caosdb/entity/v1/main.grpc.pb.h" // for EntityTransactionSe...
#include "caosdb/info.h" // for VersionInfo
#include "caosdb/info/v1/main.grpc.pb.h" // for GeneralInfoService:...
#include "caosdb/transaction.h" // for Transaction
#include "caosdb/transaction_status.h" // for TransactionStatus
#include <filesystem> // for path
#include <grpcpp/channel.h> // for Channel
#include <map> // for map
#include <memory> // for shared_ptr, unique_ptr
#include <string> // for string, basic_string
#ifdef BUILD_ACM
#include <vector> // for vector
#endif
namespace caosdb::connection {
#ifdef BUILD_ACM
using caosdb::acm::User;
using caosdb::acm::v1alpha1::AccessControlManagementService;
#endif
using caosdb::authentication::Authenticator;
using caosdb::configuration::ConnectionConfiguration;
using caosdb::entity::v1::EntityTransactionService;
using caosdb::entity::v1::FileTransmissionService;
using caosdb::info::VersionInfo;
using caosdb::info::v1::GeneralInfoService;
using caosdb::transaction::Transaction;
using caosdb::transaction::TransactionStatus;
using std::filesystem::path;
/**
* @brief A reusable connection to a CaosDBServer.
*/
class Connection {
public:
explicit Connection(const ConnectionConfiguration &configuration);
/**
* Request the server's version and return the status of this request after
* termination..
*
* The version is stored in the connection object and may be retrieved via
* GetVersionInfo() if the request was successful.
*
* This method does not throw any exceptions. Errors are indicated in the
* return value instead.
*/
auto RetrieveVersionInfoNoExceptions() const noexcept -> TransactionStatus;
/**
* Request and return the server's version.
*
* If the request terminated unsuccessfully, a corresponding exception is
* being thrown.
*/
auto RetrieveVersionInfo() const -> const VersionInfo &;
/**
* Return the server's version.
*
* Clients need to call RetrieveVersionInfo() or
* RetrieveVersionInfoNoExceptions() before the version info is locally
* available. Otherwise a nullptr is being returned.
*/
[[nodiscard]] inline auto GetVersionInfo() const noexcept -> const VersionInfo * {
return this->version_info.get();
};
/**
* Create a new transaction object which uses this connection and return it.
*/
[[nodiscard]] auto CreateTransaction() const -> std::unique_ptr<Transaction>;
#ifdef BUILD_ACM
/**
* Retrieve a single user.
*/
// TODO(tf) find a way to deal with this:
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
[[nodiscard]] auto RetrieveSingleUser(const std::string &realm, const std::string &name) const
-> User;
/**
* Create a new user.
*/
auto CreateSingleUser(const User &user) const -> void;
/**
* Delete an existing user.
*/
// TODO(tf) find a way to deal with this:
// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
auto DeleteSingleUser(const std::string &realm, const std::string &name) const -> void;
/**
* List known users.
*/
auto ListUsers() const -> std::vector<User>;
#endif
private:
/// GRPC-Channel (HTTP/2 Connection plus Authentication). We use a shared
/// pointer because Transaction instances also own the channel.
std::shared_ptr<grpc::Channel> channel;
/// Service for retrieving the server's version. We use a unique pointer
/// because only this connection owns and uses this service.
std::unique_ptr<GeneralInfoService::Stub> general_info_service;
/// The server's version. It's mutable because it is rather a cache than a
/// data member which is subject to change.
mutable std::unique_ptr<VersionInfo> version_info;
/// Service for entity transactions. We use a shared pointer because
/// Transaction instances also own this service stub.
std::shared_ptr<EntityTransactionService::Stub> entity_transaction_service;
/// Service for file transmission (download and upload). We use a shared
/// pointer because Transaction instances also own this service stub.
std::shared_ptr<FileTransmissionService::Stub> file_transmission_service;
#ifdef BUILD_ACM
/// Service for Access Controll Management (Role, Useraccounts, Permissions).
/// We use a unique pointer because only this connection owns and uses this
/// service.
std::unique_ptr<AccessControlManagementService::Stub> access_controll_management_service;
#endif
};
/**
* Lazily creates and caches reusable connection instances. Singleton.
*
* This class delegates the configuration of new connections to the global
* ConfigurationManager.
*
* A reset of the ConfigurationManager also resets the ConnectionManager.
*
* @brief Lazily creates and caches reusable connection instances.
*/
class ConnectionManager {
private:
mutable std::map<std::string, std::shared_ptr<Connection>> connections;
mutable std::string default_connection_name;
inline ConnectionManager(){};
auto mHasConnection(const std::string &name) const -> bool;
auto mGetConnection(const std::string &name) const -> const std::shared_ptr<Connection> &;
auto mGetDefaultConnection() const -> const std::shared_ptr<Connection> &;
inline auto mReset() -> void {
connections.clear();
default_connection_name = std::string();
}
public:
static ConnectionManager &GetInstance() {
static ConnectionManager instance;
return instance;
};
inline static auto HasConnection(const std::string &name) -> bool {
return ConnectionManager::GetInstance().mHasConnection(name);
};
inline static auto GetConnection(const std::string &name) -> const std::shared_ptr<Connection> & {
return ConnectionManager::GetInstance().mGetConnection(name);
};
/**
* Get the connection marked by the "default" key in the configuration.
*/
inline static auto GetDefaultConnection() -> const std::shared_ptr<Connection> & {
return ConnectionManager::GetInstance().mGetDefaultConnection();
};
inline static auto Reset() -> void { return ConnectionManager::GetInstance().mReset(); };
ConnectionManager(ConnectionManager const &) = delete;
void operator=(ConnectionManager const &) = delete;
};
} // namespace caosdb::connection
#endif