Skip to content
Snippets Groups Projects
Commit 8e30d3e9 authored by Marco Clemencic's avatar Marco Clemencic
Browse files

Merge branch 'dev/DataObjID' into 'master'

added DataObjID

Fixes GAUDI-1102

this merge is needed to maintain functionality in both Hive and vanilla Gaudi branches.

See merge request !36
parents f75d8a5c 1eb1c5e6
Branches
Tags
No related merge requests found
#ifndef GAUDIKERNEL_DATAOBJID
#define GAUDIKERNEL_DATAOBJID 1
#include "GaudiKernel/ClassID.h"
#include "GaudiKernel/StatusCode.h"
#include <string>
#include <unordered_set>
#include <iostream>
#include <mutex>
//---------------------------------------------------------------------------
/** DataObjID.h GaudiKernel/DataObjID.h
*
* Class used to identify an object in the Data Store, with fast lookup
* using an hash
*
* Objects are identified via either a Gaudi style '/path/to/object' key,
* or ATLAS style (ClassID, 'key') of ('ClassName', 'key')
*
* depending on the style, the hash is either a std::hash<string> of the path,
* or a combination of the std::hash<string> of the key and the ClassID
*
* Collections of DataObjIDs are std::unordered_set<DataObjID> with a provided
* allocator DataObjID_Hasher which the hash function
*
* @author Charles Leggett
* @date 2015-09-01
*/
//---------------------------------------------------------------------------
class DataObjID_Hasher;
class IClassIDSvc;
class DataObjID {
public:
friend DataObjID_Hasher;
DataObjID();
DataObjID(const std::string& key);
DataObjID(const std::string& key, const CLID& clid);
DataObjID(const std::string& key, const std::string& className);
DataObjID(const DataObjID& d);
// only return the last part of the key
const std::string& key() const { return m_key; }
// combination of the key and the ClassName, mostly for debugging
std::string fullKey() const;
CLID clid() const { return m_clid; }
void updateKey(const std::string& key);
friend std::ostream& operator<< (std::ostream& str, const DataObjID& d);
bool operator< ( const DataObjID& other ) const {
return (m_hash < other.m_hash);
}
bool operator==( const DataObjID& other ) const {
return (m_hash == other.m_hash);
}
private:
void hashGen();
void parse(const std::string& key);
void setClid();
void setClassName();
CLID m_clid;
std::size_t m_hash;
std::string m_key;
std::string m_className;
static void getClidSvc();
static IClassIDSvc* p_clidSvc;
static std::once_flag m_ip;
};
inline DataObjID::DataObjID():
m_clid(0), m_hash(0), m_key("INVALID"), m_className("") {}
inline DataObjID::DataObjID(const std::string& key):
m_clid(0), m_key(key), m_className("") {
hashGen();
}
inline DataObjID::DataObjID(const std::string& key, const CLID& clid):
m_clid(clid), m_key(key) {
setClassName();
hashGen();
}
inline DataObjID::DataObjID(const std::string& key, const std::string& className):
m_key(key), m_className(className) {
setClid();
hashGen();
}
inline DataObjID::DataObjID(const DataObjID& d):
m_clid(d.m_clid), m_hash(d.m_hash), m_key(d.m_key), m_className(d.m_className) {}
inline void DataObjID::updateKey(const std::string& key) {
m_key = key;
hashGen();
}
class DataObjID_Hasher {
public:
std::size_t operator()(const DataObjID& k) const {
return (k.m_hash);
}
};
typedef std::unordered_set<DataObjID, DataObjID_Hasher> DataObjIDColl;
namespace Gaudi {
namespace Parsers {
StatusCode parse(DataObjID&, const std::string&);
StatusCode parse(DataObjIDColl&, const std::string&);
}
namespace Utils {
GAUDI_API std::ostream& toStream(const DataObjID& v, std::ostream& o);
GAUDI_API std::ostream& toStream(const DataObjIDColl& v, std::ostream& o);
}
}
#endif
#ifndef GAUDIKERNEL_DATAOBJIDPROPERTY_H
#define GAUDIKERNEL_DATAOBJIDPROPERTY_H 1
#include "GaudiKernel/StatusCode.h"
#include "GaudiKernel/Parsers.h"
#include "GaudiKernel/Property.h"
#include "GaudiKernel/PropertyMgr.h"
#include "GaudiKernel/ToStream.h"
#include "GaudiKernel/DataObjID.h"
#include <iostream>
//---------------------------------------------------------------------------
/** DataObjIDProperty.h GaudiKernel/DataObjProperty.h
*
* Helper class to manage DataObjIDs and DataObjIDColls as properties
*
* TODO: DataObjIDCollProperty implementation
*
* @author Charles Leggett
* @date 2015-09-01
*/
//---------------------------------------------------------------------------
class GAUDI_API DataObjIDProperty : public ::Property {
public:
DataObjIDProperty( const std::string& name, DataObjID& ref );
DataObjIDProperty& operator=( const DataObjID& value );
virtual ~DataObjIDProperty();
virtual DataObjIDProperty* clone() const;
virtual bool load( Property& destination ) const;
virtual bool assign( const Property& source );
virtual std::string toString() const;
virtual void toStream(std::ostream& out) const;
virtual StatusCode fromString(const std::string& s);
const DataObjID& value() const;
bool setValue( const DataObjID& value );
private:
/** Pointer to the real property. Reference would be better,
* but Reflex does not support references yet
*/
DataObjID* m_pValue;
};
template<>
class SimplePropertyRef< DataObjID > :
public ::DataObjIDProperty
{
public:
SimplePropertyRef(const std::string& name, DataObjID& value) :
::DataObjIDProperty(name, value)
{}
/// virtual Destructor
virtual ~SimplePropertyRef() {}
};
inline
DataObjIDProperty&
DataObjIDProperty::operator=( const DataObjID& value )
{
setValue( value );
return *this;
}
inline
DataObjIDProperty*
DataObjIDProperty::clone() const
{
return new DataObjIDProperty( *this );
}
inline
bool
DataObjIDProperty::load( Property& destination ) const
{
return destination.assign( *this );
}
inline
bool
DataObjIDProperty::assign( const Property& source )
{
return fromString( source.toString() ).isSuccess();
}
inline
const DataObjID&
DataObjIDProperty::value() const
{
useReadHandler();
return *m_pValue;
}
//---------------------------------------------------------------------------
class GAUDI_API DataObjIDCollProperty : public ::Property {
public:
DataObjIDCollProperty( const std::string& name, DataObjIDColl& ref );
DataObjIDCollProperty& operator=( const DataObjIDColl& value );
virtual ~DataObjIDCollProperty();
virtual DataObjIDCollProperty* clone() const;
virtual bool load( Property& destination ) const;
virtual bool assign( const Property& source );
virtual std::string toString() const;
virtual void toStream(std::ostream& out) const;
virtual StatusCode fromString(const std::string& s);
const DataObjIDColl& value() const;
bool setValue( const DataObjIDColl& value );
private:
/** Pointer to the real property. Reference would be better,
* but Reflex does not support references yet
*/
DataObjIDColl* m_pValue;
};
template<>
class SimplePropertyRef< DataObjIDColl > :
public ::DataObjIDCollProperty
{
public:
SimplePropertyRef(const std::string& name, DataObjIDColl& value) :
::DataObjIDCollProperty(name, value)
{}
/// virtual Destructor
virtual ~SimplePropertyRef() {}
};
inline
DataObjIDCollProperty&
DataObjIDCollProperty::operator=( const DataObjIDColl& value )
{
setValue( value );
return *this;
}
inline
DataObjIDCollProperty*
DataObjIDCollProperty::clone() const
{
return new DataObjIDCollProperty( *this );
}
inline
bool
DataObjIDCollProperty::load( Property& destination ) const
{
return destination.assign( *this );
}
inline
bool
DataObjIDCollProperty::assign( const Property& source )
{
return fromString( source.toString() ).isSuccess();
}
inline
const DataObjIDColl&
DataObjIDCollProperty::value() const
{
useReadHandler();
return *m_pValue;
}
#endif
// dear emacs, this is -*- C++ -*-
#ifndef GAUDIKERNEL_ICLASSIDSVC_H
# define GAUDIKERNEL_ICLASSIDSVC_H
//<<<<<< INCLUDES >>>>>>
#include <string>
#include "GaudiKernel/IService.h"
#include "GaudiKernel/ClassID.h"
#include "GaudiKernel/StatusCode.h"
//<<<<<< FORWARD DECLARATIONS >>>>>>
namespace Athena {
class PackageInfo;
}
//<<<<<< CLASS DECLARATIONS >>>>>>
/** @class IClassIDSvc
* @brief interface to the CLID database
* @author Paolo Calafiura <pcalafiura@lbl.gov> - ATLAS Collaboration
*$Id: IClassIDSvc.h,v 1.7 2009-01-15 19:05:54 binet Exp $
*/
class IClassIDSvc : virtual public IService {
public:
/// get next available CLID
/// @throws std::runtime_error if no CLID can be allocated
virtual CLID nextAvailableID() const = 0;
/// check if id is used
virtual bool isIDInUse(const CLID& id) const = 0;
/// check if name is used
virtual bool isNameInUse(const std::string& name) const = 0;
/// get user assigned type name associated with clID
virtual StatusCode getTypeNameOfID(const CLID& id, std::string& typeName) const = 0;
/// get user assigned type-info name associated with clID
virtual StatusCode getTypeInfoNameOfID(const CLID& id, std::string& typeInfoName) const = 0;
/// get id associated with type name (if any)
virtual StatusCode getIDOfTypeName(const std::string& typeName, CLID& id) const = 0;
/// get id associated with type-info name (if any)
virtual StatusCode getIDOfTypeInfoName(const std::string& typeInfoName, CLID& id) const = 0;
/// get type name associated with clID (if any)
virtual StatusCode getPackageInfoForID(const CLID& id, Athena::PackageInfo& info) const = 0;
/// associate type name, package info and type-info name with clID
virtual
StatusCode setTypePackageForID(const CLID&,
const std::string& typeName,
const Athena::PackageInfo&,
const std::string& typeInfoName = "") = 0;
/// Gaudi boilerplate
static const InterfaceID& interfaceID();
/// destructor
virtual ~IClassIDSvc();
};
//<<<<<< INLINE MEMBER FUNCTIONS >>>>>>
inline
const InterfaceID&
IClassIDSvc::interfaceID() {
static const InterfaceID _IID("IClassIDSvc", 1, 0);
return _IID;
}
#endif // GAUDIKERNEL_ICLASSIDSVC_H
#include "GaudiKernel/DataObjID.h"
#include "GaudiKernel/Bootstrap.h"
#include "GaudiKernel/IClassIDSvc.h"
#include "GaudiKernel/ISvcLocator.h"
#include <functional>
IClassIDSvc* DataObjID::p_clidSvc(0);
std::once_flag DataObjID::m_ip;
void
DataObjID::hashGen() {
if (m_clid == 0) {
m_hash = (std::hash<std::string>()(m_key));
} else {
// this is a bit redundant since hash<int> is a pass-through
m_hash = (std::hash<std::string>()(m_key)) ^ (std::hash<CLID>()(m_clid) << 1);
}
}
void
DataObjID::getClidSvc() {
p_clidSvc = Gaudi::svcLocator()->service<IClassIDSvc>("ClassIDSvc").get();
}
void
DataObjID::setClid() {
std::call_once( m_ip, &DataObjID::getClidSvc );
if (p_clidSvc == 0 || p_clidSvc->getIDOfTypeName(m_className, m_clid).isFailure()) {
m_clid = 0;
m_className = "UNKNOWN_CLASS:" + m_className;
}
}
void
DataObjID::setClassName() {
std::call_once( m_ip, &DataObjID::getClidSvc );
if (p_clidSvc == 0 || p_clidSvc->getTypeNameOfID(m_clid, m_className).isFailure()) {
m_className = "UNKNOW_CLID:" + std::to_string(m_clid);
}
}
std::ostream&
operator<< (std::ostream& str, const DataObjID& d) {
if (d.m_clid == 0 && d.m_className == "") {
str << "('" << d.m_key << "')";
} else {
str << "('" << d.m_className << "','" << d.m_key << "')";
}
return str;
}
std::string
DataObjID::fullKey() const {
if (m_clid == 0 && m_className == "") {
return m_key;
} else {
return ( m_className + "/" + m_key );
}
}
// stl includes
#include <sstream>
#include <map>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string.hpp>
// StoreGate includes
#include "GaudiKernel/DataObjIDProperty.h"
using namespace Gaudi;
using namespace Gaudi::Parsers;
using namespace Gaudi::Utils;
namespace Gaudi {
namespace Parsers {
StatusCode
parse(DataObjID& v, const std::string& s) {
// default values
StatusCode sc(StatusCode::FAILURE);
std::string prop;
sc = Gaudi::Parsers::parse(prop, s);
if (sc.isSuccess()) {
//split the string in 1 or 2 words:
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep("(), ");
tokenizer tokens(prop, sep);
int nToks(distance(tokens.begin(), tokens.end()));
auto it = tokens.begin();
if (nToks == 1) {
// Gaudi style /path/to/object
std::string k = *it;
boost::erase_all(k,"'");
v = DataObjID( k );
} else if (nToks == 2) {
// ATLAS style (clid, 'key') or ('ClassName', 'key')
CLID c(0);
std::string cn(*it);
DataObjID id;
try {
c = std::stoi(*it);
} catch (const std::invalid_argument& /*e*/) {
// not a number
boost::erase_all(cn,"'");
c = 0;
}
++it;
std::string k = *it;
boost::erase_all(k,"'");
++it;
if ( c != 0) {
v = DataObjID(k,c);
} else {
v = DataObjID(k,cn);
}
} else {
std::cerr << "Unable to instantiate a DataObjID from a Property " << s
<< " :: Format is bad" << std::endl;
sc = StatusCode::FAILURE;
return sc;
}
}
return sc;
}
//---------------------------------------------------------------------------
StatusCode
parse (DataObjIDColl& v, const std::string& s) {
// default values
StatusCode sc(StatusCode::FAILURE);
std::string prop;
sc = Gaudi::Parsers::parse(prop, s);
if (sc.isSuccess()) {
// Reset Collection
v.clear();
bool isGaudi(true);
// Gaudi style [ '/path/to/data', '/other/data' ] or
// ATLAS style [ ('ClassName', 'key') , (ClassID, 'key2') ]
if (s.find("(") != std::string::npos) {
isGaudi = false;
}
// split the string in 1 or 2 words:
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep("[](), ");
tokenizer tokens(prop, sep);
auto it = tokens.begin();
CLID c(0);
std::string cn;
while (it != tokens.end()) {
if (isGaudi) {
v.insert( DataObjID( *it ) );
++it;
} else {
try {
c = std::stoi(*it);
} catch (const std::invalid_argument& /*e*/) {
// class name, not ClassID
cn = *it;
boost::erase_all(cn,"'");
c = 0;
}
++it;
std::string k = *it;
boost::erase_all(k,"'");
++it;
if ( c != 0) {
v.insert( DataObjID(k,c) );
} else {
v.insert( DataObjID(k,cn) );
}
}
}
}
return sc;
}
} //> ns Parsers
namespace Utils {
std::ostream&
toStream(const DataObjID& v, std::ostream& o) {
if (v.clid() == 0) {
o << "'" << v.key() << "'";
} else {
o << "(" << v.clid() << ",'" << v.key() << "')";
}
return o;
}
std::ostream&
toStream(const DataObjIDColl& v, std::ostream& o) {
o << "[";
for (auto &i : v) {
// o << "(" << i.clid() << ",'" << i.key() << "'),";
o << toStream(i,o) << ",";
}
o << "]";
return o;
}
} //> ns Utils
} //> ns Gaudi
//---------------------------------------------------------------------------
DataObjIDProperty::DataObjIDProperty( const std::string& name,
DataObjID& ref )
: Property( name, typeid( DataObjID ) ),
m_pValue( &ref )
{}
//---------------------------------------------------------------------------
DataObjIDProperty::~DataObjIDProperty()
{}
//---------------------------------------------------------------------------
StatusCode
DataObjIDProperty::fromString(const std::string& s)
{
if (!Gaudi::Parsers::parse(*m_pValue, s).isSuccess()) {
return StatusCode::FAILURE;
}
return useUpdateHandler()
? StatusCode::SUCCESS
: StatusCode::FAILURE;
}
//---------------------------------------------------------------------------
bool
DataObjIDProperty::setValue( const DataObjID& value )
{
m_pValue->operator=(value);
return useUpdateHandler();
}
//---------------------------------------------------------------------------
std::string
DataObjIDProperty::toString( ) const
{
useReadHandler();
std::ostringstream o;
Gaudi::Utils::toStream(*m_pValue, o);
return o.str();
}
//---------------------------------------------------------------------------
void
DataObjIDProperty::toStream(std::ostream& out) const
{
useReadHandler();
out << this->toString();
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
DataObjIDCollProperty::DataObjIDCollProperty( const std::string& name,
DataObjIDColl& ref )
: Property( name, typeid( DataObjIDColl ) ),
m_pValue( &ref )
{}
//---------------------------------------------------------------------------
DataObjIDCollProperty::~DataObjIDCollProperty()
{}
//---------------------------------------------------------------------------
StatusCode
DataObjIDCollProperty::fromString(const std::string& s)
{
if (!Gaudi::Parsers::parse(*m_pValue, s).isSuccess()) {
return StatusCode::FAILURE;
}
return useUpdateHandler()
? StatusCode::SUCCESS
: StatusCode::FAILURE;
}
//---------------------------------------------------------------------------
bool
DataObjIDCollProperty::setValue( const DataObjIDColl& value )
{
m_pValue->operator=(value);
return useUpdateHandler();
}
//---------------------------------------------------------------------------
std::string
DataObjIDCollProperty::toString( ) const
{
useReadHandler();
std::ostringstream o;
Gaudi::Utils::toStream(*m_pValue, o);
return o.str();
}
//---------------------------------------------------------------------------
void
DataObjIDCollProperty::toStream(std::ostream& out) const
{
useReadHandler();
out << this->toString();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment