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
No related branches found
No related tags found
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.
Finish editing this message first!
Please register or to comment