Anonymous avatar Anonymous committed 965658b

add UserDataStore from trunk

Comments (0)

Files changed (7)

+2012-05-02 Walter Lampl <walter.lampl@cern.ch>
+	* Move Add UserDataStore from trunk 
+	* Tag DataModel-00-23-20-04
+
 2012-02-22  scott snyder  <snyder@bnl.gov>
 
 	* Tagging DataModel-00-23-20-03.

DataModel/DataModelDict.h

 #include "SGTools/IProxyDictWithPool.h"
 #include "SGTools/IStringPool.h"
 #include "AthenaKernel/IProxyDict.h"
+#include "DataModel/UserDataStore.h"

DataModel/UDSLabelHashTable.h

+//Dear emacs, this is -*-c++-*-
+
+
+//Move to DataModel/tools ???
+
+#ifndef LABELHASHTABLE
+#define LABELHASHTABLE
+
+#include "SGTools/crc64.h"
+#include <map>
+#include <string>
+#include "GaudiKernel/MsgStream.h"
+
+#include <stdint.h>
+
+
+/** @class UDSLabelHashTable
+ * @brief Helper class for UserDataStore
+ * Provides the hash function and keeps a map<hash,label>
+ */
+
+class UDSLabelHashTable {
+
+ public:
+  typedef uint32_t hash_t;
+
+  enum {INVALID=0};
+
+  hash_t hash(const std::string& label) const;
+  const std::string& getLabel(const hash_t number) const;
+  hash_t addLabel(const std::string& label);
+
+  std::vector<const std::string*> getAllLabels() const;
+
+  size_t size() const {return m_hashLabels.size();}
+
+ private:
+  std::map<hash_t, std::string> m_hashLabels;
+  std::string m_empty;
+  
+  
+};
+  
+inline
+UDSLabelHashTable::hash_t UDSLabelHashTable::hash(const std::string& label) const {
+  const uint64_t hash64=SG::crc64(label);
+  return (hash_t)(hash64 & 0xFFFFFFFF);
+}
+
+#endif

DataModel/UserDataStore.h

+//Dear emacs, this is -*-c++-*-
+#ifndef USERDATASTORE_H
+#define USERDATASTORE_H
+
+#include "GaudiKernel/StatusCode.h"
+#include "AthenaKernel/IAthenaBarCode.h"
+#include "GaudiKernel/MsgStream.h"
+#include <string>
+#include <map>
+
+//#include <ext/hash_map>
+//#include <boost/unordered_map.hpp>
+
+
+#include "DataModel/UDSLabelHashTable.h"
+#include "SGTools/CLASS_DEF.h"
+
+#include "boost/any.hpp"
+
+/** @class UserDataStoreObj
+ * @brief User Data store for type T
+ */
+
+class UserDataStore {
+ 
+  friend class UserDataStoreCnv_p1;
+
+public:
+
+  /// Default constructor
+  UserDataStore();  
+
+  /**
+   * @brief Record method with template payload
+   * @param abc A data-object implmenting the IAthenaBarCode interface
+   * @param label String label of the decoration
+   * @param value Decoration payload 
+   */
+  template<typename T>
+  StatusCode record(const IAthenaBarCode& obj, const std::string& label, const T& value); 
+
+
+  /**
+   * @brief Retrieve method with template payload
+   * @param abc A data-object implmenting the IAthenaBarCode interface
+   * @param label String label of the decoration
+   * @param[out] value Decoration payload 
+   */
+  template<typename T>
+  StatusCode retrieve(const IAthenaBarCode& obj, const std::string& label, T& value) const; 
+
+
+  /** 
+   * @brief Contains method for element decorations
+   * @param abc A data-object implmenting the IAthenaBarCode interface
+   * @param label String label of the decoration
+   * @return True if the decoration exists
+   */ 
+  bool contains(const IAthenaBarCode& obj, const std::string& label) const;
+
+
+  /**
+   * @brief Table-of-contents method
+   * @param barcode A data-object implmenting the IAthenaBarCode interface
+   * @return A vector of labels existing for this object
+   */
+  std::vector<const std::string*> getLabels(const AthenaBarCode_t& barcode) const;
+
+
+  
+  /**
+   * @brief Record method with boost::any as payload 
+   * @param abc A data-object implmenting the IAthenaBarCode interface
+   * @param label String label of the decoration
+   * @param value Decoration payload 
+   */
+  StatusCode recordAny(const IAthenaBarCode& obj, const std::string& label, const boost::any& value);
+
+
+  /**
+   * @brief Retrieve method with boost::any as payload
+   * @param abc A data-object implmenting the IAthenaBarCode interface
+   * @param label String label of the decoration
+   * @param[out] value Decoration payload 
+   */
+  StatusCode retrieveAny(const IAthenaBarCode& obj, const std::string& label, const boost::any*& value) const;
+
+
+  /**
+   * @brief Method to set the AthenaBarCode of this event (called by UserDataSvc)
+   * @param eventABC The AthenaBarCode
+   */
+  void setEventABC(const AthenaBarCode_t& eventABC);
+
+
+
+  /**
+   * @brief Method to get the AthenaBarCode of this event (called by UserDataSvc)
+   * @return The AthenaBarCode
+   */
+  AthenaBarCode_t getEventABC() const { return m_eventABC; }
+
+
+  enum NotFoundTypes {
+    ALLGOOD=0,
+    BARCODE,
+    LABEL
+  };
+
+private: 
+
+  // For experimental use of hash-maps instead of std::map
+  // class abcHashFcn {
+  //   public:
+  //     size_t operator()(const AthenaBarCode_t abc) const { return ((abc & 0xFFFFFFFF)>>6); } //Extract the 26 counter-bits
+  //   };
+  
+  typedef boost::any payload_t; 
+
+  typedef UDSLabelHashTable::hash_t index_t;
+
+  typedef std::map<AthenaBarCode_t,std::map<index_t, payload_t > > mapmap_t;
+  //typedef __gnu_cxx::hash_map<AthenaBarCode_t,std::map<index_t, payload_t >, abcHashFcn > mapmap_t;
+  //typedef boost::unordered_map<AthenaBarCode_t,std::map<index_t, payload_t >, abcHashFcn > mapmap_t;
+
+  typedef std::map<index_t, payload_t >::iterator iterator;
+  typedef std::map<index_t, payload_t >::const_iterator const_iterator;
+
+  mapmap_t m_data;
+
+  //find a label (const version)
+  const_iterator find(const AthenaBarCode_t& barcode, const std::string& label) const;
+
+  //Update the cached map-iterator m_lastIt;
+  //void updateIt(const AthenaBarCode_t& barcode);
+
+  const_iterator m_notFoundIt;
+  const std::map<index_t, payload_t > m_defaultEntry;
+
+  UDSLabelHashTable m_labelTable;
+
+  ///Cache of last barcode/object (const)
+  mutable  mapmap_t::const_iterator m_lastIt;
+
+  ///Cache of last barcode/object (non-const)
+  mutable  mapmap_t::iterator m_lastIt_nc;
+
+  ///AthenaBarCode for this event
+  AthenaBarCode_t m_eventABC;
+
+  ///Cached Message Stream
+  mutable MsgStream m_msg;
+
+  mutable NotFoundTypes m_whyNotFound;
+
+};
+  
+CLASS_DEF( UserDataStore , 51567825 , 1 )
+  
+template<typename T>
+StatusCode UserDataStore::retrieve(const IAthenaBarCode& obj, const std::string& label, T& value) const {
+  const boost::any* aValue=0;
+  StatusCode sc=this->retrieveAny(obj,label, aValue);
+  if (sc.isFailure()) return sc;
+  if (typeid(T) != aValue->type()) { 
+    m_msg << MSG::ERROR << "Typeid mismatch while retrieving user data with label " << label << endreq;
+    return StatusCode::FAILURE;
+  }
+  const T* decoPtr=boost::any_cast<T>(aValue);
+  value=*decoPtr; //Deep copy! 
+  return StatusCode::SUCCESS;
+}
+
+
+template<typename T>
+StatusCode UserDataStore::record(const IAthenaBarCode& obj, const std::string& label, const T& value) {
+  boost::any aValue(value);
+  return this->recordAny(obj,label, aValue);
+}
+
+#endif

DataModel/selection.xml

   <class name="IProxyDictWithPool"/>
   <class name="IStringPool"/>
   <class name="IProxyDict"/>
+
+  <class name="UserDataStore"/>
 </lcgdict>

src/UDSLabelHashTable.cxx

+#include "DataModel/UDSLabelHashTable.h"
+#include "AthenaKernel/getMessageSvc.h"
+
+UDSLabelHashTable::hash_t UDSLabelHashTable::addLabel(const std::string& label) {
+  if (label.size()==0) {
+    MsgStream logstr(Athena::getMessageSvc(), "UDSLabelHashTable");
+    logstr << MSG::ERROR << "Zero-length string given as Label!" << endreq;
+    return INVALID;
+  }
+  hash_t h=this->hash(label);
+  if (h==INVALID) {
+    MsgStream logstr(Athena::getMessageSvc(), "UDSLabelHashTable");
+    logstr << MSG::ERROR << "Label " << label << " yields an invalid hash. Please choose different name!" << endreq;
+    return INVALID;
+  }
+
+  std::map<hash_t, std::string>::const_iterator it=m_hashLabels.find(h);
+  if (it==m_hashLabels.end()) {
+    //new label, new hash
+    m_hashLabels[h]=label;
+  }
+  else {
+    //Hash exists already
+    if (it->second!=label) { //Same hash but different label -> hash-collision! 
+      MsgStream logstr(Athena::getMessageSvc(), "UDSLabelHashTable");
+      logstr << MSG::ERROR << "Hash collision between label " << label << " and label " << it->second << endreq;
+      return INVALID;
+    }
+  }
+  return h;
+}
+   
+
+const std::string& UDSLabelHashTable::getLabel(const hash_t number) const {
+  std::map<hash_t, std::string>::const_iterator it=m_hashLabels.find(number);
+  if (it==m_hashLabels.end()) 
+    return m_empty;
+  else 
+    return it->second;
+}
+
+
+std::vector<const std::string*> UDSLabelHashTable::getAllLabels() const {
+
+  std::vector<const std::string*> allLabels;
+  allLabels.reserve(m_hashLabels.size());
+  std::map<hash_t, std::string>::const_iterator it=m_hashLabels.begin();
+  std::map<hash_t, std::string>::const_iterator it_e=m_hashLabels.end();
+  for(;it!=it_e;++it) 
+    allLabels.push_back(&(it->second));
+
+  return allLabels;
+}

src/UserDataStore.cxx

+#include "DataModel/UserDataStore.h"
+#include "AthenaKernel/getMessageSvc.h"
+
+UserDataStore::UserDataStore() : 
+  m_data(), 
+  m_lastIt(m_data.end()), 
+  m_lastIt_nc(m_data.end()),
+  m_eventABC(IAthenaBarCode::UNDEFINEDBARCODE),
+  m_msg(Athena::getMessageSvc(),"UserDataStore"),
+  m_whyNotFound(ALLGOOD)
+
+ {}
+
+
+
+UserDataStore::const_iterator
+UserDataStore::find(const AthenaBarCode_t& barcode, const std::string& label) const {
+  m_whyNotFound=ALLGOOD;
+  if (m_lastIt==m_data.end() || m_lastIt->first!=barcode) 
+    m_lastIt=m_data.find(barcode);
+  
+  if (m_lastIt==m_data.end()) { //No user data for this bar-code
+    m_whyNotFound=BARCODE;
+    return m_notFoundIt;
+  }
+
+  const index_t idx=m_labelTable.hash(label);
+  const_iterator label_it=m_lastIt->second.find(idx);
+  if (label_it==m_lastIt->second.end()) {
+    //std::cout << "Did not find label " << label << "(hash=" << idx << ")" << std::endl;
+    m_whyNotFound=LABEL;
+    return m_notFoundIt;
+  }
+  else 
+    return label_it;
+}
+
+void UserDataStore::setEventABC(const AthenaBarCode_t& eventABC) {
+  if (m_eventABC==IAthenaBarCode::UNDEFINEDBARCODE)  m_eventABC=eventABC;
+}
+    
+
+
+StatusCode UserDataStore::recordAny(const IAthenaBarCode& obj, const std::string& label, const boost::any& value) {
+  const AthenaBarCode_t& barcode=obj.getAthenaBarCode();
+  
+  if (barcode==IAthenaBarCode::UNDEFINEDBARCODE) {
+    m_msg << MSG::ERROR << "Attempt to record UserData for an object with undefined AthenaBarCode. Label=" << label << endreq;
+    return StatusCode::FAILURE;
+  }
+
+  const index_t idx=m_labelTable.addLabel(label);
+  if (idx==UDSLabelHashTable::INVALID) {
+    m_msg << MSG::ERROR << "Failed to convert label '" << label << "' into a hash value" << endreq;
+    return StatusCode::FAILURE;
+  }
+  else {
+    if (m_lastIt_nc==m_data.end() || m_lastIt_nc->first!=barcode) {
+      m_lastIt_nc=m_data.find(barcode);
+    }
+    if (m_lastIt_nc==m_data.end()) {
+      m_lastIt_nc=m_data.insert(std::make_pair(barcode,m_defaultEntry)).first;
+    }
+    (m_lastIt_nc->second)[idx]=value;
+    return StatusCode::SUCCESS;
+  }
+}
+
+
+StatusCode UserDataStore::retrieveAny(const IAthenaBarCode& obj, const std::string& label, const boost::any*& value) const {
+  const AthenaBarCode_t& barcode=obj.getAthenaBarCode();
+  
+  const_iterator it=this->find(barcode,label);
+  if (it==m_notFoundIt) {
+    if (m_whyNotFound==BARCODE) 
+      m_msg << MSG::ERROR << "No user data found for bar code " << barcode << endreq;
+    if (m_whyNotFound==LABEL) 
+      m_msg << MSG::ERROR << "No user data with label '" << label << "' found for this barcode" << endreq;
+    return StatusCode::FAILURE;
+  }
+  else {
+    value=&(it->second);
+    return StatusCode::SUCCESS;
+  }
+}
+
+
+bool UserDataStore::contains(const IAthenaBarCode& obj, const std::string& label) const {
+ const AthenaBarCode_t& barcode=obj.getAthenaBarCode();
+ const_iterator it=this->find(barcode,label);
+ return (it!=m_notFoundIt);
+}
+
+
+std::vector<const std::string*> UserDataStore::getLabels(const AthenaBarCode_t& barcode) const {
+  
+  std::vector<const std::string*> out;
+  mapmap_t::const_iterator abc_it=m_data.find(barcode);
+  if (abc_it!=m_data.end()) {
+    const std::map<index_t, boost::any>& labelMap=abc_it->second;
+    const_iterator it=labelMap.begin();
+    const_iterator it_e=labelMap.end();
+    for (;it!=it_e;++it) {
+      const std::string& sLabel=m_labelTable.getLabel(it->first);
+      out.push_back(&sLabel);
+    }
+  }// end if abc_it!=m_data.end()
+  return out;
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.