Commit 301fd5cf authored by Matthieu Dorier's avatar Matthieu Dorier
Browse files

implemented Ptr functionality

parent c9dec8f5
...@@ -103,6 +103,11 @@ class DataSet : public KeyValueContainer { ...@@ -103,6 +103,11 @@ class DataSet : public KeyValueContainer {
*/ */
~DataSet(); ~DataSet();
/**
* @brief Overrides getDataStore from KeyValueContainer class.
*/
DataStore* getDataStore() const override;
/** /**
* @brief Name of the DataSet. * @brief Name of the DataSet.
* *
...@@ -153,10 +158,10 @@ class DataSet : public KeyValueContainer { ...@@ -153,10 +158,10 @@ class DataSet : public KeyValueContainer {
* @param key Key. * @param key Key.
* @param buffer Binary data to insert. * @param buffer Binary data to insert.
* *
* @return true if the key did not already exist and the write succeeded, * @return a valid ProductID if the key did not already exist and the write succeeded,
* false otherwise. * an invalid one otherwise.
*/ */
bool storeRawData(const std::string& key, const std::vector<char>& buffer); ProductID storeRawData(const std::string& key, const std::vector<char>& buffer) override;
/** /**
* @brief Loads binary data associated with a particular key from the DataSet. * @brief Loads binary data associated with a particular key from the DataSet.
...@@ -169,7 +174,7 @@ class DataSet : public KeyValueContainer { ...@@ -169,7 +174,7 @@ class DataSet : public KeyValueContainer {
* @return true if the key exists and the read succeeded, * @return true if the key exists and the read succeeded,
* false otherwise. * false otherwise.
*/ */
bool loadRawData(const std::string& key, std::vector<char>& buffer) const; bool loadRawData(const std::string& key, std::vector<char>& buffer) const override;
/** /**
* @brief Comparison operator. * @brief Comparison operator.
......
...@@ -12,11 +12,13 @@ ...@@ -12,11 +12,13 @@
namespace hepnos { namespace hepnos {
class ProductID;
class DataSet; class DataSet;
class RunSet; class RunSet;
class Run; class Run;
class SubRun; class SubRun;
class Event; class Event;
template<typename T, typename C = std::vector<T>> class Ptr;
/** /**
* The DataStore class is the main handle referencing an HEPnOS service. * The DataStore class is the main handle referencing an HEPnOS service.
...@@ -24,6 +26,7 @@ class Event; ...@@ -24,6 +26,7 @@ class Event;
*/ */
class DataStore { class DataStore {
friend class ProductID;
friend class DataSet; friend class DataSet;
friend class RunSet; friend class RunSet;
friend class Run; friend class Run;
...@@ -246,6 +249,15 @@ class DataStore { ...@@ -246,6 +249,15 @@ class DataStore {
*/ */
DataSet createDataSet(const std::string& name); DataSet createDataSet(const std::string& name);
template<typename T>
Ptr<T> makePtr(const ProductID& productID);
template<typename T, typename C = std::vector<T>>
Ptr<T,C> makePtr(const ProductID& productID, std::size_t index);
template<typename T>
bool loadProduct(const ProductID& productID, T& t);
/** /**
* @brief Shuts down the HEPnOS service. * @brief Shuts down the HEPnOS service.
*/ */
...@@ -258,6 +270,8 @@ class DataStore { ...@@ -258,6 +270,8 @@ class DataStore {
*/ */
class Impl; class Impl;
std::unique_ptr<Impl> m_impl; /*!< Pointer to implementation */ std::unique_ptr<Impl> m_impl; /*!< Pointer to implementation */
bool loadRawProduct(const ProductID& productID, std::vector<char>& buffer);
}; };
class DataStore::const_iterator { class DataStore::const_iterator {
...@@ -485,4 +499,38 @@ class DataStore::iterator : public DataStore::const_iterator { ...@@ -485,4 +499,38 @@ class DataStore::iterator : public DataStore::const_iterator {
} }
#include <hepnos/ProductID.hpp>
#include <hepnos/Ptr.hpp>
namespace hepnos {
template<typename T>
Ptr<T> DataStore::makePtr(const ProductID& productID) {
return Ptr<T>(this, productID);
}
template<typename T, typename C = std::vector<T>>
Ptr<T,C> DataStore::makePtr(const ProductID& productID, std::size_t index) {
return Ptr<T,C>(this, productID, index);
}
template<typename T>
bool DataStore::loadProduct(const ProductID& productID, T& t) {
std::vector<char> buffer;
if(!loadRawProduct(productID, buffer)) {
return false;
}
std::string serialized(buffer.begin(), buffer.end());
std::stringstream ss(serialized);
InputArchive ia(this, ss);
try {
ia >> t;
} catch(...) {
throw Exception("Exception occured during serialization");
}
return true;
}
}
#endif #endif
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <hepnos/KeyValueContainer.hpp>
#include <hepnos/DataStore.hpp> #include <hepnos/DataStore.hpp>
#include <hepnos/EventNumber.hpp> #include <hepnos/EventNumber.hpp>
#include <hepnos/Exception.hpp> #include <hepnos/Exception.hpp>
#include <hepnos/KeyValueContainer.hpp>
namespace hepnos { namespace hepnos {
...@@ -78,6 +78,11 @@ class Event : public KeyValueContainer { ...@@ -78,6 +78,11 @@ class Event : public KeyValueContainer {
*/ */
~Event(); ~Event();
/**
* @brief Overrides getDataStore from KeyValueContainer class.
*/
DataStore* getDataStore() const override;
/** /**
* @brief Returns the next Event in the same container, * @brief Returns the next Event in the same container,
* sorted by event number. If no such event exists, an Event instance * sorted by event number. If no such event exists, an Event instance
...@@ -102,9 +107,9 @@ class Event : public KeyValueContainer { ...@@ -102,9 +107,9 @@ class Event : public KeyValueContainer {
* @param key Key * @param key Key
* @param buffer Value * @param buffer Value
* *
* @return true if the key did not already exist, false otherwise. * @return a valid ProductID if the key did not already exist, an invalid one otherwise.
*/ */
bool storeRawData(const std::string& key, const std::vector<char>& buffer); ProductID storeRawData(const std::string& key, const std::vector<char>& buffer) override;
/** /**
* @brief Loads raw key/value data from this Event. * @brief Loads raw key/value data from this Event.
...@@ -114,7 +119,7 @@ class Event : public KeyValueContainer { ...@@ -114,7 +119,7 @@ class Event : public KeyValueContainer {
* *
* @return true if the key exists, false otherwise. * @return true if the key exists, false otherwise.
*/ */
bool loadRawData(const std::string& key, std::vector<char>& buffer) const; bool loadRawData(const std::string& key, std::vector<char>& buffer) const override;
/** /**
* @brief Compares this Event with another Event. The Events must point to * @brief Compares this Event with another Event. The Events must point to
......
/*
* (C) 2018 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __HEPNOS_INPUT_ARCHIVE_H
#define __HEPNOS_INPUT_ARCHIVE_H
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/impl/basic_binary_iprimitive.ipp>
#include <boost/archive/impl/basic_binary_iarchive.ipp>
namespace hepnos {
class DataStore;
class InputArchive;
using iarchive = boost::archive::binary_iarchive_impl<InputArchive, std::istream::char_type, std::istream::traits_type>;
/**
* @brief This InputArchive class derives from boost's binary input archive.
* It lets caller embed a pointer to the DataStore storing the object.
* This is necessary to deserialize Ptr instances, for example.
*/
class InputArchive : public iarchive {
friend class boost::archive::detail::interface_iarchive<InputArchive>;
friend class boost::archive::basic_binary_iarchive<InputArchive>;
friend class boost::archive::load_access;
private:
DataStore* m_datastore = nullptr;
public:
template<typename ... Args>
InputArchive(DataStore* datastore, Args&& ... args)
: iarchive(std::forward<Args>(args)..., 0)
, m_datastore(datastore) {}
DataStore* getDataStore() const {
return m_datastore;
}
};
}
#endif
...@@ -8,11 +8,12 @@ ...@@ -8,11 +8,12 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <sstream>
#include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp> #include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/string.hpp> #include <boost/serialization/string.hpp>
#include <hepnos/InputArchive.hpp>
#include <hepnos/ProductID.hpp>
#include <hepnos/Demangle.hpp> #include <hepnos/Demangle.hpp>
#include <hepnos/Exception.hpp> #include <hepnos/Exception.hpp>
...@@ -52,6 +53,13 @@ class KeyValueContainer { ...@@ -52,6 +53,13 @@ class KeyValueContainer {
*/ */
virtual ~KeyValueContainer() = default; virtual ~KeyValueContainer() = default;
/**
* @brief Gets the DataStore to which this instance of KeyValueContainer belongs.
*
* @return DataStore.
*/
virtual DataStore* getDataStore() const = 0;
/** /**
* @brief Stores raw key/value data in this KeyValueContainer. * @brief Stores raw key/value data in this KeyValueContainer.
* This function is virtual and must be overloaded in the child class. * This function is virtual and must be overloaded in the child class.
...@@ -59,9 +67,9 @@ class KeyValueContainer { ...@@ -59,9 +67,9 @@ class KeyValueContainer {
* @param key Key * @param key Key
* @param buffer Value * @param buffer Value
* *
* @return true if the key did not already exist, false otherwise. * @return A valid ProductID if the key did not already exist, an invalid one otherwise.
*/ */
virtual bool storeRawData(const std::string& key, const std::vector<char>& buffer) = 0; virtual ProductID storeRawData(const std::string& key, const std::vector<char>& buffer) = 0;
/** /**
* @brief Loads raw key/value data from this KeyValueContainer. * @brief Loads raw key/value data from this KeyValueContainer.
...@@ -90,7 +98,7 @@ class KeyValueContainer { ...@@ -90,7 +98,7 @@ class KeyValueContainer {
* @return true if the key was found. false otherwise. * @return true if the key was found. false otherwise.
*/ */
template<typename K, typename V> template<typename K, typename V>
bool store(const K& key, const V& value) { ProductID store(const K& key, const V& value) {
std::stringstream ss_value; std::stringstream ss_value;
std::stringstream ss_key; std::stringstream ss_key;
ss_key << key << "#" << demangle<V>(); ss_key << key << "#" << demangle<V>();
...@@ -131,7 +139,8 @@ class KeyValueContainer { ...@@ -131,7 +139,8 @@ class KeyValueContainer {
try { try {
std::string serialized(buffer.begin(), buffer.end()); std::string serialized(buffer.begin(), buffer.end());
std::stringstream ss(serialized); std::stringstream ss(serialized);
boost::archive::binary_iarchive ia(ss); //boost::archive::binary_iarchive ia(ss);
InputArchive ia(getDataStore(), ss);
ia >> value; ia >> value;
} catch(...) { } catch(...) {
throw Exception("Exception occured during serialization"); throw Exception("Exception occured during serialization");
......
/*
* (C) 2018 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __HEPNOS_PRODUCT_ID_H
#define __HEPNOS_PRODUCT_ID_H
#include <string>
#include <boost/serialization/access.hpp>
#include <boost/serialization/string.hpp>
#include <hepnos/DataStore.hpp>
namespace hepnos {
class ProductID {
friend class DataStore;
friend class DataStore::Impl;
friend class boost::serialization::access;
private:
std::uint8_t m_level;
std::string m_containerName;
std::string m_objectName;
ProductID(std::uint8_t level, const std::string& containerName, const std::string& objectName)
: m_level(level)
, m_containerName(containerName)
, m_objectName(objectName) {}
public:
ProductID() = default;
/**
* @brief Copy constructor.
*
* @param other ProductID to copy.
*/
ProductID(const ProductID& other) = default;
/**
* @brief Move constructor.
*
* @param other ProductID to move.
*/
ProductID(ProductID&& other) = default;
/**
* @brief Copy-assignment operator.
*
* @param other ProductID to assign.
*
* @return Reference to this ProductID.
*/
ProductID& operator=(const ProductID& other) = default;
/**
* @brief Move-assignment operator.
*
* @param other ProductID to move from.
*
* @return Reference to this ProductID.
*/
ProductID& operator=(ProductID&& other) = default;
/**
* @brief Destructor.
*/
~ProductID() = default;
/**
* @brief Indicates whether this ProductID instance points to a valid
* product in the underlying storage service.
*
* @return True if the ProductID instance points to a valid product in the
* underlying service, false otherwise.
*/
bool valid() const {
return m_objectName.size() != 0;
}
/**
* @brief Conversion to bool.
*
* @return True if the ProductID instance points to a valid product in the
* underlying service, false otherwise.
*/
inline operator bool() const {
return valid();
}
/**
* @brief Compares this ProductID with another ProductID.
*
* @param other ProductID instance to compare against.
*
* @return true if the ProductIDs are the same, false otherwise.
*/
bool operator==(const ProductID& other) const {
return m_level == other.m_level
&& m_containerName == other.m_containerName
&& m_objectName == other.m_objectName;
}
/**
* @brief Compares this ProductID with another ProductID.
*
* @param other ProductID instance to compare against.
*
* @return true if the ProductIDs are different, false otherwise.
*/
bool operator!=(const ProductID& other) const {
return !(*this == other);
}
private:
template<typename Archive>
void serialize(Archive& ar, const unsigned int version) {
ar & m_level;
ar & m_containerName;
ar & m_objectName;
}
};
}
#endif
/*
* (C) 2018 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#ifndef __HEPNOS_PTR_H
#define __HEPNOS_PTR_H
#include <memory>
#include <string>
#include <vector>
#include <boost/serialization/access.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/split_member.hpp>
#include <hepnos/InputArchive.hpp>
#include <hepnos/ProductID.hpp>
#include <hepnos/DataStore.hpp>
#include <hepnos/Exception.hpp>
namespace hepnos {
template<typename T, typename C>
class Ptr {
friend class boost::serialization::access;
friend class DataStore;
private:
DataStore* m_datastore = nullptr;
ProductID m_product_id = ProductID();
std::size_t m_index = 0;
bool m_is_in_container = false;
C* m_container = nullptr;
T* m_data = nullptr;
size_t* m_refcount = nullptr;
Ptr(DataStore* datastore, const ProductID& product_id)
: m_datastore(datastore)
, m_product_id(product_id)
, m_index(0)
, m_is_in_container(false) {}
Ptr(DataStore* datastore, const ProductID& product_id, std::size_t index)
: m_datastore(datastore)
, m_product_id(product_id)
, m_index(index)
, m_is_in_container(true) {};
public:
Ptr() = default;
/**
* @brief Copy constructor.
*
* @param other Ptr to copy.
*/
Ptr(const Ptr& other)
: m_datastore(other.m_datastore)
, m_product_id(other.m_product_id)
, m_index(other.m_index)
, m_is_in_container(other.m_is_in_container)
, m_data(other.m_data)
, m_container(other.m_container)
, m_refcount(other.m_refcount) {
if(m_refcount) {
*m_refcount += 1;
}
}
/**
* @brief Move constructor.
*
* @param other Ptr to move.
*/
Ptr(Ptr&& other)
: m_datastore(other.m_datastore)
, m_product_id(std::move(other.m_product_id))
, m_index(other.m_index)
, m_is_in_container(other.m_is_in_container)
, m_container(other.m_container)
, m_refcount(other.m_refcount) {
other.m_refcount = nullptr;
other.m_container = nullptr;
other.m_data = nullptr;
other.m_product_id = ProductID();
}
/**
* @brief Copy-assignment operator.
*
* @param other Ptr to assign.
*
* @return Reference to this Ptr.
*/
Ptr& operator=(const Ptr& other) {
if(&other == this) return *this;
if(other.m_data == m_data) return *this;
if(m_data) {
this->~Ptr();
}
m_datastore = other.m_datastore;
m_product_id = other.m_product_id;
m_index = other.m_index;
m_is_in_container = other.m_is_in_container;
m_container = other.m_container;
m_refcount = other.m_refcount;
if(m_refcount) {
*m_refcount += 1;
}
return *this;
}
/**
* @brief Move-assignment operator.
*
* @param other Ptr to move from.
*
* @return Reference to this Ptr.
*/
Ptr& operator=(Ptr&& other) {
if(&other == this) return *this;
if(other.m_data == m_data) return *this;
if(m_data) {
this->~Ptr();