From d7d0cce278a587d5c3657a39311ea81f0dddc59f Mon Sep 17 00:00:00 2001 From: Shaun Roe <shaun.roe@cern.ch> Date: Thu, 13 Jun 2019 15:06:03 +0000 Subject: [PATCH] 22.0-introduce_CREST_2-IOVDbSvc --- Database/IOVDbSvc/CMakeLists.txt | 96 +++-- Database/IOVDbSvc/python/CondDB.py | 6 +- Database/IOVDbSvc/src/BasicFolder.cxx | 116 ++++++ Database/IOVDbSvc/src/BasicFolder.h | 59 +++ Database/IOVDbSvc/src/Cool2Json.cxx | 244 +++++++++++++ Database/IOVDbSvc/src/Cool2Json.h | 105 ++++++ Database/IOVDbSvc/src/FolderTypes.h | 13 +- Database/IOVDbSvc/src/IOVDbConn.h | 6 +- Database/IOVDbSvc/src/IOVDbCoolFunctions.h | 4 +- Database/IOVDbSvc/src/IOVDbFolder.cxx | 336 ++++++++++++------ Database/IOVDbSvc/src/IOVDbFolder.h | 21 +- Database/IOVDbSvc/src/IOVDbParser.h | 4 +- Database/IOVDbSvc/src/IOVDbResolveTag.cxx | 44 +++ Database/IOVDbSvc/src/IOVDbResolveTag.h | 18 + .../IOVDbSvc/src/IOVDbStringFunctions.cxx | 5 +- Database/IOVDbSvc/src/IOVDbStringFunctions.h | 4 +- Database/IOVDbSvc/src/IOVDbSvc.cxx | 18 +- Database/IOVDbSvc/src/IOVDbSvc.h | 36 +- Database/IOVDbSvc/src/IOVDbSvcCurl.cxx | 65 ++++ Database/IOVDbSvc/src/IOVDbSvcCurl.h | 58 +++ Database/IOVDbSvc/src/IovStore.h | 7 +- Database/IOVDbSvc/src/Json2Cool.cxx | 238 +++++++++++++ Database/IOVDbSvc/src/Json2Cool.h | 48 +++ Database/IOVDbSvc/src/ReadFromFileMetaData.h | 5 +- Database/IOVDbSvc/src/TagFunctions.h | 4 +- Database/IOVDbSvc/test/BasicFolder_test.cxx | 149 ++++++++ Database/IOVDbSvc/test/Cool2Json_test.cxx | 146 ++++++++ Database/IOVDbSvc/test/FolderTypes_test.cxx | 2 +- Database/IOVDbSvc/test/IOVDbFolder_test.cxx | 4 +- Database/IOVDbSvc/test/IOVDbSvcCurl_test.cxx | 40 +++ Database/IOVDbSvc/test/IOVDbSvc_test.cxx | 2 +- Database/IOVDbSvc/test/Json2Cool_test.cxx | 113 ++++++ .../test/ReadFromFileMetaData_test.cxx | 2 +- Database/IOVDbSvc/test/TagFunctions_test.cxx | 2 +- 34 files changed, 1812 insertions(+), 208 deletions(-) create mode 100644 Database/IOVDbSvc/src/BasicFolder.cxx create mode 100644 Database/IOVDbSvc/src/BasicFolder.h create mode 100644 Database/IOVDbSvc/src/Cool2Json.cxx create mode 100644 Database/IOVDbSvc/src/Cool2Json.h create mode 100644 Database/IOVDbSvc/src/IOVDbResolveTag.cxx create mode 100644 Database/IOVDbSvc/src/IOVDbResolveTag.h create mode 100644 Database/IOVDbSvc/src/IOVDbSvcCurl.cxx create mode 100644 Database/IOVDbSvc/src/IOVDbSvcCurl.h create mode 100644 Database/IOVDbSvc/src/Json2Cool.cxx create mode 100644 Database/IOVDbSvc/src/Json2Cool.h create mode 100644 Database/IOVDbSvc/test/BasicFolder_test.cxx create mode 100644 Database/IOVDbSvc/test/Cool2Json_test.cxx create mode 100644 Database/IOVDbSvc/test/IOVDbSvcCurl_test.cxx create mode 100644 Database/IOVDbSvc/test/Json2Cool_test.cxx diff --git a/Database/IOVDbSvc/CMakeLists.txt b/Database/IOVDbSvc/CMakeLists.txt index 74448c0636e..208895f205a 100644 --- a/Database/IOVDbSvc/CMakeLists.txt +++ b/Database/IOVDbSvc/CMakeLists.txt @@ -32,41 +32,47 @@ find_package( COOL COMPONENTS CoolKernel CoolApplication ) find_package( CORAL COMPONENTS CoralBase ) find_package( ROOT COMPONENTS Core ) find_package( Boost COMPONENTS unit_test_framework ) +find_package( nlohmann_json ) +find_package( CURL REQUIRED ) # Component(s) in the package: atlas_add_library( IOVDbSvcLib IOVDbSvc/*.h INTERFACE PUBLIC_HEADERS IOVDbSvc - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} - LINK_LIBRARIES ${COOL_LIBRARIES} GaudiKernel ) + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} nlohmann_json::nlohmann_json ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${COOL_LIBRARIES} GaudiKernel nlohmann_json::nlohmann_json ${CURL_LIBRARIES} + ) atlas_add_component( IOVDbSvc src/*.h src/*.cxx src/components/*.cxx - INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} ${COOL_INCLUDE_DIRS} - LINK_LIBRARIES ${ROOT_LIBRARIES} ${CORAL_LIBRARIES} ${COOL_LIBRARIES} - GaudiKernel AthenaBaseComps AthenaKernel CxxUtils SGTools StoreGateLib - FileCatalog AthenaPoolUtilities CoraCool IOVDbDataModel EventInfo EventInfoUtils IOVDbSvcLib ) + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} ${COOL_INCLUDE_DIRS} nlohmann_json::nlohmann_json ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ${CORAL_LIBRARIES} ${COOL_LIBRARIES} nlohmann_json::nlohmann_json ${CURL_LIBRARIES} GaudiKernel AthenaBaseComps AthenaKernel CxxUtils SGTools StoreGateLib + FileCatalog AthenaPoolUtilities CoraCool IOVDbDataModel EventInfo EventInfoUtils IOVDbSvcLib + ) + # Install files from the package: atlas_install_python_modules( python/*.py ) atlas_install_joboptions( share/*.py ) atlas_install_joboptions( share/*.txt ) +message(STATUS "CURL_INCLUDE_DIRS=${CURL_INCLUDE_DIRS}") +message(STATUS "CURL_LIBRARIES=${CURL_LIBRARIES}") atlas_add_test( IOVDbSvc_test SOURCES test/IOVDbSvc_test.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} - LINK_LIBRARIES AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} ${CURL_LIBRARIES} PROPERTIES TIMEOUT 300 EXTRA_PATTERNS "^HistogramPersis.* INFO|^IOVSvc +DEBUG|^IOVSvcTool +DEBUG |Warning in <TFile::Init>: no |Initializing" ) atlas_add_test( IOVDbSvc_Boost_test SOURCES test/IOVDbSvc_Boost_test.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} ${CURL_LIBRARIES} EXTRA_PATTERNS "^HistogramPersis.* INFO|^IOVSvc +DEBUG|^IOVSvcTool +DEBUG" ) set_target_properties( IOVDbSvc_IOVDbSvc_Boost_test PROPERTIES ENABLE_EXPORTS True ) @@ -74,67 +80,99 @@ set_target_properties( IOVDbSvc_IOVDbSvc_Boost_test PROPERTIES ENABLE_EXPORTS T atlas_add_test( IOVDbConn_test SOURCES test/IOVDbConn_test.cxx src/IOVDbConn.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} CoraCool ) + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} CoraCool ${CURL_LIBRARIES} + ) atlas_add_test( IOVDbStringFunctions_test SOURCES test/IOVDbStringFunctions_test.cxx src/IOVDbStringFunctions.cxx - INCLUDE_DIRS ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} IOVSvcLib + INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} IOVSvcLib ${CURL_LIBRARIES} ) atlas_add_test( IOVDbParser_test SOURCES test/IOVDbParser_test.cxx src/IOVDbParser.cxx src/IOVDbStringFunctions.cxx - INCLUDE_DIRS ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} IOVSvcLib + INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} IOVSvcLib ${CURL_LIBRARIES} ) atlas_add_test( FolderTypes_test SOURCES test/FolderTypes_test.cxx src/IOVDbStringFunctions.cxx src/FolderTypes.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib ${CURL_LIBRARIES} ) atlas_add_test( IOVDbCoolFunctions_test SOURCES test/IOVDbCoolFunctions_test.cxx src/IOVDbCoolFunctions.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib ${CURL_LIBRARIES} ) atlas_add_test( ReadFromFileMetaData_test SOURCES test/ReadFromFileMetaData_test.cxx src/ReadFromFileMetaData.cxx src/FolderTypes.cxx src/IOVDbCoolFunctions.cxx src/IOVDbStringFunctions.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVDbDataModel IOVSvcLib + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVDbDataModel IOVSvcLib ${CURL_LIBRARIES} ) atlas_add_test( IOVDbFolder_test SOURCES - test/IOVDbFolder_test.cxx src/IOVDbFolder.cxx src/IovStore.cxx src/IOVDbConn.cxx src/IOVDbParser.cxx src/FolderTypes.cxx src/IOVDbCoolFunctions.cxx src/IOVDbStringFunctions.cxx src/ReadFromFileMetaData.cxx src/TagFunctions.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} CoraCool + test/IOVDbFolder_test.cxx src/IOVDbFolder.cxx src/Cool2Json.cxx src/Json2Cool.cxx src/IovStore.cxx src/IOVDbConn.cxx src/IOVDbParser.cxx src/FolderTypes.cxx src/IOVDbCoolFunctions.cxx src/IOVDbStringFunctions.cxx src/ReadFromFileMetaData.cxx src/TagFunctions.cxx src/BasicFolder.cxx src/IOVDbSvcCurl.cxx src/IOVDbResolveTag.cxx + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} nlohmann_json::nlohmann_json ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} CoraCool nlohmann_json::nlohmann_json ${CURL_LIBRARIES} EXTRA_PATTERNS "^HistogramPersis.* INFO|^IOVSvc +DEBUG|^IOVSvcTool +DEBUG" ) atlas_add_test( IovStore_test SOURCES test/IovStore_test.cxx src/IovStore.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib ${CURL_LIBRARIES} ) atlas_add_test( TagFunctions_test SOURCES test/TagFunctions_test.cxx src/TagFunctions.cxx src/IOVDbStringFunctions.cxx - INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} - LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} AthenaKernel StoreGateLib GaudiKernel TestTools EventInfo IOVSvcLib PersistentDataModel ${COOL_LIBRARIES} + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} AthenaKernel StoreGateLib GaudiKernel TestTools EventInfo IOVSvcLib PersistentDataModel ${COOL_LIBRARIES} ${CURL_LIBRARIES} + ) + +atlas_add_test( IOVDbSvcCurl_test + SOURCES + test/IOVDbSvcCurl_test.cxx src/IOVDbSvcCurl.cxx + INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${CURL_LIBRARIES} IOVSvcLib + ) + +atlas_add_test( BasicFolder_test + SOURCES + test/BasicFolder_test.cxx src/BasicFolder.cxx + INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${COOL_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib ${CURL_LIBRARIES} + ) + +atlas_add_test( Json2Cool_test + SOURCES + test/Json2Cool_test.cxx src/Json2Cool.cxx src/BasicFolder.cxx + INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${COOL_INCLUDE_DIRS} nlohmann_json::nlohmann_json ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} ${COOL_LIBRARIES} IOVSvcLib nlohmann_json::nlohmann_json ${CURL_LIBRARIES} + ) + +atlas_add_test( Cool2Json_test + SOURCES + test/Cool2Json_test.cxx src/Cool2Json.cxx src/IOVDbConn.cxx src/IOVDbParser.cxx src/FolderTypes.cxx src/IOVDbCoolFunctions.cxx src/IOVDbStringFunctions.cxx src/ReadFromFileMetaData.cxx src/TagFunctions.cxx src/BasicFolder.cxx src/IOVDbSvcCurl.cxx src/IOVDbResolveTag.cxx + INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS} nlohmann_json::nlohmann_json ${CURL_INCLUDE_DIRS} + LINK_LIBRARIES ${Boost_LIBRARIES} AthenaBaseComps AthenaKernel SGTools StoreGateLib SGtests GaudiKernel TestTools EventInfo IOVSvcLib xAODEventInfo PersistentDataModel ${COOL_LIBRARIES} CoraCool nlohmann_json::nlohmann_json ${CURL_LIBRARIES} + EXTRA_PATTERNS "^HistogramPersis.* INFO|^IOVSvc +DEBUG|^IOVSvcTool +DEBUG" ) if( NOT SIMULATIONBASE ) atlas_add_test( IOVDbSvcCfgTest SCRIPT python -m IOVDbSvc.IOVDbSvcConfig POST_EXEC_SCRIPT nopost.sh ) endif() + + diff --git a/Database/IOVDbSvc/python/CondDB.py b/Database/IOVDbSvc/python/CondDB.py index 01d3dd59918..122714889ba 100644 --- a/Database/IOVDbSvc/python/CondDB.py +++ b/Database/IOVDbSvc/python/CondDB.py @@ -294,7 +294,11 @@ This allows the possibility of later adding a new IOV using IOVSvc::setRange.""" def setRequireLock(self,lock=True): "Set the flag indicating global tags will be required to be locked" self.iovdbsvc.CheckLock=lock - + + def setWriteDataToFile(self, writeData=False): + "Set option to write data to file" + self.iovdbsvc.OutputToFile=writeData + def extractFolder(self,folderstr): "Extract the folder name (non-XML text) from a IOVDbSvc.Folders entry" diff --git a/Database/IOVDbSvc/src/BasicFolder.cxx b/Database/IOVDbSvc/src/BasicFolder.cxx new file mode 100644 index 00000000000..81f1e1d38ad --- /dev/null +++ b/Database/IOVDbSvc/src/BasicFolder.cxx @@ -0,0 +1,116 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +#include "BasicFolder.h" +#include <iostream> + +namespace IOVDbNamespace{ + +static const std::pair<cool::ValidityKey, cool::ValidityKey> infiniteIov(0,cool::ValidityKeyMax); +static const coral::AttributeList invalidPayload{}; +static const std::vector<coral::AttributeList> invalidVectorPayload{}; + + + BasicFolder::BasicFolder(): + m_payload{}, + m_vectorPayload{}, + m_name2Channel{}, + m_channel2Name{}, + m_isVectorPayload{}, + m_channels{}, + m_iov{infiniteIov} { + + } + bool + BasicFolder::empty() const{ + return m_channels.empty(); + } + + void + BasicFolder::setVectorPayloadFlag(const bool flag){ + m_isVectorPayload=flag; + } + + bool + BasicFolder::isVectorPayload() const { + return m_isVectorPayload; + } + // + void + BasicFolder::setIov(const std::pair<cool::ValidityKey, cool::ValidityKey> & iov){ + m_iov=iov; + } + + //add attributeList + void + BasicFolder::addChannelPayload(const cool::ChannelId & channelId, const std::string & name, const coral::AttributeList & payload){ + m_name2Channel[name]=channelId; + m_channel2Name[channelId]=name; + addChannelPayload(channelId, payload); + } + + void + BasicFolder::addChannelPayload(const cool::ChannelId & channelId, const coral::AttributeList& payload){ + + m_channels.push_back(channelId); + m_payload[channelId]=payload; + } + + //add vector payload + void + BasicFolder::addChannelPayload(const cool::ChannelId & channelId, const std::string & name, const std::vector<coral::AttributeList> & payload){ + m_name2Channel[name]=channelId; + m_channel2Name[channelId]=name; + addChannelPayload(channelId, payload); + } + + void + BasicFolder::addChannelPayload(const cool::ChannelId & channelId, const std::vector<coral::AttributeList> & payload){ + m_channels.push_back(channelId); + m_vectorPayload[channelId]=payload; + } + + // + coral::AttributeList + BasicFolder::getPayload(const cool::ChannelId & channelId){ + return m_payload.find(channelId)->second; + } + + coral::AttributeList + BasicFolder::getPayload(const std::string & channelName){ + if (m_isVectorPayload) return invalidPayload; + const auto chanPtr= m_name2Channel.find(channelName); + bool nameExists = (chanPtr != m_name2Channel.end()); + if (not nameExists) return invalidPayload; + const cool::ChannelId channel=chanPtr->second; + return getPayload(channel); + } + + std::vector<coral::AttributeList> + BasicFolder::getVectorPayload(const cool::ChannelId & channelId){ + return m_vectorPayload.find(channelId)->second; + } + + std::vector<coral::AttributeList> + BasicFolder::getVectorPayload(const std::string & channelName){ + if (not m_isVectorPayload) return invalidVectorPayload; + const auto chanPtr= m_name2Channel.find(channelName); + bool nameExists = (chanPtr != m_name2Channel.end()); + if (not nameExists) return invalidVectorPayload; + const cool::ChannelId channel=chanPtr->second; + return getVectorPayload(channel); + } + + std::vector<cool::ChannelId> + BasicFolder::channelIds(){ + return m_channels; + } + + std::pair<cool::ValidityKey, cool::ValidityKey> + BasicFolder::iov(){ + return m_iov; + } + + + }//namespace end + diff --git a/Database/IOVDbSvc/src/BasicFolder.h b/Database/IOVDbSvc/src/BasicFolder.h new file mode 100644 index 00000000000..e0cb50fea71 --- /dev/null +++ b/Database/IOVDbSvc/src/BasicFolder.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +// @file BasicFolder.h +// Header for FolderTypes utilities +// @author Shaun Roe +// @date May 2019 +#ifndef IOVDbSvc_BasicFolder_h +#define IOVDbSvc_BasicFolder_h + +#include <utility> +#include "CoolKernel/ValidityKey.h" //a typedef +#include "CoolKernel/ChannelId.h" +#include <string> +#include <vector> +#include "CoralBase/AttributeList.h" +#include <map> + +namespace IOVDbNamespace{ +//@Basic data structure to hold the folder data retrieved from CREST or file +class BasicFolder{ + public: + BasicFolder(); + void setVectorPayloadFlag(const bool flag); + bool isVectorPayload() const; + // + void setIov(const std::pair<cool::ValidityKey, cool::ValidityKey> & iov); + //add attributeList + void addChannelPayload(const cool::ChannelId & channelId, const std::string & name, const coral::AttributeList & payload); + void addChannelPayload(const cool::ChannelId & channelId, const coral::AttributeList & payload); + //add vector payload + void addChannelPayload(const cool::ChannelId & channelId, const std::string & name, const std::vector<coral::AttributeList> & payload); + void addChannelPayload(const cool::ChannelId & channelId, const std::vector<coral::AttributeList> & payload); + // + coral::AttributeList getPayload(const cool::ChannelId & channelId); + coral::AttributeList getPayload(const std::string & channelName); + std::vector<coral::AttributeList> getVectorPayload(const cool::ChannelId & channelId); + std::vector<coral::AttributeList> getVectorPayload(const std::string & channelName); + std::vector<cool::ChannelId> channelIds(); + std::pair<cool::ValidityKey, cool::ValidityKey> iov(); + // + bool empty() const; + + private: + //ugh, should be templated, and consider using hashmaps + std::map<int, coral::AttributeList> m_payload; + std::map<int, std::vector<coral::AttributeList>> m_vectorPayload; + //could use single bidirectional map + std::map<std::string, int> m_name2Channel; + std::map<int, std::string> m_channel2Name; + //ugliness + bool m_isVectorPayload; + std::vector<cool::ChannelId> m_channels; + std::pair<cool::ValidityKey, cool::ValidityKey> m_iov; +}; + +} +#endif + diff --git a/Database/IOVDbSvc/src/Cool2Json.cxx b/Database/IOVDbSvc/src/Cool2Json.cxx new file mode 100644 index 00000000000..9c2494529e4 --- /dev/null +++ b/Database/IOVDbSvc/src/Cool2Json.cxx @@ -0,0 +1,244 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +#include "Cool2Json.h" +#include "CoolKernel/IFolderSpecification.h" + +#include "CoolKernel/IObject.h" +#include "CoolKernel/IObjectIterator.h" +#include "CoolKernel/IRecord.h" +#include "CoolKernel/IRecordIterator.h" +#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeListSpecification.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeSpecification.h" +#include "CoralBase/Blob.h" +#include "TStopwatch.h" + +#include "CoraCool/CoraCoolDatabase.h" +#include "CoraCool/CoraCoolFolder.h" +#include "CoraCool/CoraCoolObject.h" +#include "CoraCool/CoraCoolObjectIter.h" + +#include "AthenaPoolUtilities/AthenaAttributeList.h" +#include "AthenaPoolUtilities/AthenaAttrListAddress.h" +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "AthenaPoolUtilities/CondAttrListCollAddress.h" +#include "AthenaPoolUtilities/CondAttrListVec.h" +#include "AthenaPoolUtilities/CondAttrListVecAddress.h" +#include "FolderTypes.h" +#include "IOVDbStringFunctions.h" + +namespace { + std::string + spec2String(const cool::IFolderPtr & pFolder){ + //open bracket, close bracket for json objects + const std::string ob=""; + const std::string cb=""; + const std::string objName="\"folder_payloadspec\": \""; + std::string result=ob+objName; + const auto & rspec = pFolder->payloadSpecification(); + std::string sep{""}; + for (unsigned int i(0); i<rspec.size();++i){ + if (i==1) sep=", "; + const auto & f = rspec[i]; + result+=sep+f.name()+": "+f.storageType().name(); + } + result+="\""+cb; + return result; + } +} + +namespace IOVDbNamespace { + Cool2Json::Cool2Json(const cool::IFolderPtr & pFolder, + const cool::ValidityKey & since, + const cool::ValidityKey & until, + const cool::ChannelSelection & chansel, + const std::string& folderTag): + m_pFolder(pFolder), + m_start(since), + m_stop(until), + m_chansel(chansel), + m_tag(folderTag), + m_desc(pFolder->description()), + m_spec(spec2String(pFolder)), + m_nchans(0){ + const auto & channums=pFolder->listChannels(); + //find channels in the chansel which are chan nums + //theres no 'size' method in the ChannelSelection class + for (const auto &i:channums){ + m_nchans+=m_chansel.inSelection(i);//bool casts to 0 or 1 + } + } + + std::string + Cool2Json::description() const{ + std::string saneXml=sanitiseXml(m_desc); + return "\"node_description\" : \""+saneXml+"\"\n"; + } + + std::string + Cool2Json::payloadSpec() const{ + return m_spec; + } + + std::string + Cool2Json::open(){ + return "{"; + } + + std::string + Cool2Json::close(){ + return "}"; + } + + std::string + Cool2Json::delimiter(){ + return ", "; + } + + std::string + Cool2Json::payload() { + std::string result("\"data_array\" : ["); + cool::IObjectIteratorPtr itr=m_pFolder->browseObjects(m_start,m_stop,m_chansel,m_tag); + IOVDbNamespace::FolderType ftype = determineFolderType(m_pFolder); + std::string sep=""; + while (itr->goToNext()){ + const cool::IObject& ref=itr->currentRef(); + result+=sep; + const long long cId=ref.channelId(); + result+="{ "+quote(std::to_string(cId))+" : "; + switch (ftype){ + case IOVDbNamespace::CoolVector: + result+=formatCvp(itr); + break; + case IOVDbNamespace::AttrList: + result +=formatAttrList(itr); + break; + case IOVDbNamespace::AttrListColl: + result +=formatAttrList(itr); + break; + case IOVDbNamespace::PoolRef: + result +=formatPoolRef(itr); + break; + case IOVDbNamespace::PoolRefColl: + result += formatAttrList(itr); + break; + case IOVDbNamespace::CoraCool: + result += " CoraCool"; + break; + default: + result+=" a_data_value"; + } + if (sep.empty()) sep=",\n"; + result+="}"; + } + result+="]"; + itr->close(); + return result; + } + + unsigned int + Cool2Json::nchans() const{ + return m_nchans; + } + + std::string + Cool2Json::iovBase() const{ + std::string result(""); + //run-lumi and run-event can both be found in our database, but the meaning is run-lumi + if (m_desc.find("<timeStamp>run-lumi</timeStamp>") != std::string::npos) result = "run-lumi"; + if (m_desc.find("<timeStamp>run-event</timeStamp>") != std::string::npos) result = "run-lumi"; + if (m_desc.find("<timeStamp>time</timeStamp>") != std::string::npos) result = "time"; + return result; + } + + std::string + Cool2Json::tag() const{ + return m_tag; + } + + std::string + Cool2Json::formatCvp(const cool::IObjectIteratorPtr & itr){ + std::string os; + const cool::IObject& ref=itr->currentRef(); + cool::IRecordIterator& pitr=ref.payloadIterator(); + auto pvec=pitr.fetchAllAsVector(); + std::string sep=""; + os+="[";//vector of vectors + for (const auto & vitr:*pvec){ + os+=sep; + const coral::AttributeList& atrlist=(vitr)->attributeList(); + os+=jsonAttributeList(atrlist); + if (sep.empty()) sep =", "; + } + os+="]"; + return os; + } + + std::string + Cool2Json::formatAttrList(const cool::IObjectIteratorPtr & itr){ + const cool::IObject& ref=itr->currentRef(); + const coral::AttributeList& atrlist=ref.payload().attributeList(); + std::string sep=""; + return jsonAttributeList(atrlist); + } + + std::string + Cool2Json::formatPoolRef(const cool::IObjectIteratorPtr & itr){ + const cool::IObject& ref=itr->currentRef(); + const coral::AttributeList& atrlist=ref.payload().attributeList(); + std::ostringstream os; + atrlist[0].toOutputStream(os); + auto res=os.str(); + const std::string sep(" : "); + const auto separatorPosition = res.find(sep); + const std::string payloadOnly=res.substr(separatorPosition+3); + return quote(payloadOnly); + } + + std::string + Cool2Json::iov() const{ + std::string iovString("\"iov\" : "); + return iovString+"["+std::to_string(m_start)+", "+std::to_string(m_stop)+"]"; + } + + std::ostream &operator<<(std::ostream &o, const Cool2Json &c){ + o << c.description() << std::endl; + return o; + } + + std::string + Cool2Json::jsonAttribute(const coral::Attribute & attr){ + std::ostringstream os; + attr.toOutputStream(os); + const std::string native=os.str(); + const bool stringPayload=(native.find(" (string) ") != std::string::npos); + //take away anything between brackets in the original + const std::string regex=R"delim( \(.*\))delim"; + const std::string deleted= deleteRegex(native,regex); + const std::string sep(" : "); + const auto separatorPosition = deleted.find(sep); + const std::string payloadOnly=deleted.substr(separatorPosition+3); + if (stringPayload) return quote(payloadOnly); + std::string result(payloadOnly); + if (result=="NULL"){ + result="null"; + } + return result; + } + + std::string + Cool2Json::jsonAttributeList(const coral::AttributeList& atrlist){ + std::string os("["); + const unsigned int nelement=atrlist.size(); + std::string delimiter(" "); + for (unsigned int i(0);i!=nelement;++i){ + if (i==1) delimiter = ", "; + os+=delimiter; + os+=jsonAttribute(atrlist[i]); + } + os+="]\n"; + return os; + } +} diff --git a/Database/IOVDbSvc/src/Cool2Json.h b/Database/IOVDbSvc/src/Cool2Json.h new file mode 100644 index 00000000000..d4b4bc98f3a --- /dev/null +++ b/Database/IOVDbSvc/src/Cool2Json.h @@ -0,0 +1,105 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +// @file Cool2Json.h +// Header for Cool2Json class +// @author Shaun Roe +// @date 04 October 2017 +#ifndef IOVDbSvc_Cool2Json_h +#define IOVDbSvc_Cool2Json_h + +#include <string> +#include <iostream> + +#include "CoolKernel/ValidityKey.h"//its a typedef +#include "CoolKernel/IFolder.h" +#include "CoolKernel/pointers.h" //IFolderPtr etc, typedefs + +namespace cool{ + class ChannelSelection; +} + + +namespace IOVDbNamespace { + //@brief Formatter helper class + //Formats cool attributes, lists to json string representation and provides JSON + class Cool2Json{ + //@stream insertion + friend std::ostream& operator<<(std::ostream& o, const Cool2Json &c); + // + public: + //class methods + ///Produce a representation of a coral::Attribute as a json string + static std::string jsonAttribute(const coral::Attribute&); + + ///Produce a representation of a coral::AttributeList as a json string + static std::string jsonAttributeList(const coral::AttributeList&); + + //@Constructor sets internal variables + Cool2Json(const cool::IFolderPtr & pFolder, const cool::ValidityKey & since, + const cool::ValidityKey & until, const cool::ChannelSelection & m_chansel, + const std::string& folderTag); + + ///Folder description string + std::string description() const; + + ///Payload specification for this folder + std::string payloadSpec() const; + + ///Payload (data for the given channel selection and iov) + std::string payload(); + + ///Formatted iov as '[<since>, <until>]' + std::string iov() const; + + ///Number of channels in the folder + unsigned int nchans() const; + + ///'time' (ns of epoch) or 'run-lumi' + std::string iovBase() const; + + ///Simply the tag string passed to the constructor + std::string tag() const; + + ///json open tag, '{' + static std::string open(); + + ///json close tag, '}' + static std::string close(); + + ///json standard delimiter ', ' + static std::string delimiter(); + + + private: + enum FolderType { + AttrList=0, + AttrListColl, + PoolRef, + PoolRefColl, + CoraCool, + CoolVector, + JSON, + NUM_FOLDER_TYPES + }; + const cool::IFolderPtr m_pFolder; + const cool::ValidityKey m_start; + const cool::ValidityKey m_stop; + const cool::ChannelSelection m_chansel; + const std::string m_tag; + const std::string m_desc; + const std::string m_spec; + unsigned int m_nchans; + std::string formatCvp(const cool::IObjectIteratorPtr & itr); + std::string formatAttrList(const cool::IObjectIteratorPtr & itr); + std::string formatPoolRef(const cool::IObjectIteratorPtr & itr); + }; + + + std::ostream &operator<<(std::ostream &o, const Cool2Json &c); + + +} + + +#endif diff --git a/Database/IOVDbSvc/src/FolderTypes.h b/Database/IOVDbSvc/src/FolderTypes.h index cc0f12b94da..7b7a8220104 100644 --- a/Database/IOVDbSvc/src/FolderTypes.h +++ b/Database/IOVDbSvc/src/FolderTypes.h @@ -5,8 +5,8 @@ // Header for FolderTypes utilities // @author Shaun Roe // @date 05 October 2017 -#ifndef FolderTypes_H -#define FolderTypes_H +#ifndef IOVDbSvc_FolderTypes_h +#define IOVDbSvc_FolderTypes_h #include "CoolKernel/IFolder.h" #include "CoolKernel/pointers.h" //IFolderPtr etc, typdefs @@ -34,22 +34,28 @@ namespace IOVDbNamespace{ NUM_FOLDER_TYPES }; - //determine folder type with optional check using clid service to check clid matches typename + ///Determine folder type with optional check using clid service to check clid matches typename FolderType determineFolderType(const cool::IFolderPtr & pFolder, IClassIDSvc* clidsvc=nullptr); + ///Give a string name for the folder type std::string folderTypeName(const FolderType f); + ///Determine folder type using the CondAttrListCollection pointer FolderType determineFolderType(const CondAttrListCollection * pAttrListColl); + ///Determine folder typeusing the CondAttrListCollection reference FolderType determineFolderType(const CondAttrListCollection & pAttrListColl); + ///Determine folder type using the coral::AttributeSpecification FolderType determineFolderType(const coral::AttributeSpecification& spec); + //@{ + /** Is the folder type compatible with Pool storage type? */ bool poolCompatible(const cool::IRecordSpecification& rspec); @@ -58,6 +64,7 @@ namespace IOVDbNamespace{ bool poolCompatible(const CondAttrListCollection & pAttrListColl); + //@} } #endif diff --git a/Database/IOVDbSvc/src/IOVDbConn.h b/Database/IOVDbSvc/src/IOVDbConn.h index dc30011a611..159bcb96b2d 100644 --- a/Database/IOVDbSvc/src/IOVDbConn.h +++ b/Database/IOVDbSvc/src/IOVDbConn.h @@ -5,8 +5,8 @@ // IOVDbConn.h // helper class for IOVDbSvc managing DB connections // Richard Hawkings, started 24/11/08 -#ifndef __IOVDBCONN_H__ -#define __IOVDBCONN_H__ +#ifndef IOVDbSvc_IOVDbConn_h +#define IOVDbSvc_IOVDbConn_h #include "CoolKernel/IDatabase.h" #include "CoraCool/CoraCoolTypes.h" @@ -58,4 +58,4 @@ inline void IOVDbConn::incUsage() { ++m_nfolder; } inline void IOVDbConn::decUsage() { --m_nfolder; } -#endif // __IOVDBCONN_H__ +#endif // IOVDbSvc_IOVDbConn_h diff --git a/Database/IOVDbSvc/src/IOVDbCoolFunctions.h b/Database/IOVDbSvc/src/IOVDbCoolFunctions.h index 58310c3554e..ed3871b6f3d 100644 --- a/Database/IOVDbSvc/src/IOVDbCoolFunctions.h +++ b/Database/IOVDbSvc/src/IOVDbCoolFunctions.h @@ -4,8 +4,8 @@ //@file IOVDbCoolFunctions.h //@brief Numeric and COOL/Coral dependent helper functions //@author Shaun Roe -#ifndef IOVDbCoolFunctions_h -#define IOVDbCoolFunctions_h +#ifndef IOVDbSvc_IOVDbCoolFunctions_h +#define IOVDbSvc_IOVDbCoolFunctions_h #include "CoolKernel/ChannelId.h" #include "CoolKernel/ValidityKey.h" diff --git a/Database/IOVDbSvc/src/IOVDbFolder.cxx b/Database/IOVDbSvc/src/IOVDbFolder.cxx index baf2e4fabe4..3ff54e60692 100644 --- a/Database/IOVDbSvc/src/IOVDbFolder.cxx +++ b/Database/IOVDbSvc/src/IOVDbFolder.cxx @@ -7,6 +7,7 @@ #include <sstream> #include <stdexcept> +#include <fstream> #include "GaudiKernel/Bootstrap.h" @@ -15,7 +16,6 @@ #include "GaudiKernel/IAddressCreator.h" #include "GaudiKernel/ISvcLocator.h" - #include "StoreGate/StoreGateSvc.h" #include "CoolKernel/IObject.h" #include "CoolKernel/IObjectIterator.h" @@ -55,13 +55,42 @@ #include "TagFunctions.h" #include "CxxUtils/make_unique.h" -using namespace IOVDbNamespace; +#include "Cool2Json.h" +#include "Json2Cool.h" +#include "IOVDbSvcCurl.h" +#include "BasicFolder.h" +#include "IOVDbResolveTag.h" +using namespace IOVDbNamespace; +namespace{ + const std::string fileSuffix{".json"}; + const std::string delimiter{"."}; + std::string + jsonTagName(const std::string &globalTag, const std::string & folderName){ + return resolveCrestTag(globalTag,folderName); + } + + std::string + extractHashFromJson(const std::string & jsonReply){ + std::string hash{}; + try{ + std::string signature="payloadHash\":\""; + auto startOfHash=jsonReply.find(signature) + signature.size(); + auto endOfHash=jsonReply.find("\"",startOfHash); + auto len=endOfHash-startOfHash; + hash=jsonReply.substr(startOfHash, len); + } catch (std::exception & e){ + std::cout<<__FILE__<<":"<<__LINE__<< ": "<<e.what()<<"\n while trying to find the hash in "<<jsonReply<<std::endl; + } + return hash; + } +} IOVDbFolder::IOVDbFolder(IOVDbConn* conn, const IOVDbParser& folderprop, MsgStream & /*msg*/, - IClassIDSvc* clidsvc, const bool checklock): + IClassIDSvc* clidsvc, const bool checklock, const bool outputToFile, + const std::string & source): p_detStore(0), p_clidSvc(clidsvc), @@ -104,6 +133,8 @@ IOVDbFolder::IOVDbFolder(IOVDbConn* conn, m_nchan(0), m_retrieved(false), m_cachespec(0), + m_outputToFile{outputToFile}, + m_source{source}, m_msg("IOVDbFolder") { // extract settings from the properties @@ -248,15 +279,48 @@ IOVDbFolder::loadCache(const cool::ValidityKey vkey, // timer to track amount of time in loadCache TStopwatch cachetimer; const auto & [cachestart, cachestop] = m_iovs.getCacheBounds(); + BasicFolder b; + if (m_source == "CREST"){ + const std::string urlBase{"http://crest-undertow.web.cern.ch/crestapi"}; + const std::string getTagByName{"/tags/"}; + const std::string getAllIovsForTag{"/iovs?tagname="}; + const std::string objectForHash{"/payloads/"}; + const std::string jsonFolderName=sanitiseFilename(m_foldername).substr(1, std::string::npos); + const std::string completeTag=jsonTagName(globalTag, m_foldername); + ATH_MSG_INFO("Download tag would be: "<<completeTag); + std::string url=urlBase+getAllIovsForTag+completeTag; + std::string reply; + std::string hash; + { + IOVDbSvcCurl request(url); + reply=request.get(); + hash=extractHashFromJson(reply); + ATH_MSG_DEBUG("Hash: "<<hash); + } + { + auto payloadForHash=[](const std::string &h){return "/payloads/"+h+"/data";}; + std::string url=urlBase+payloadForHash(hash); + ATH_MSG_DEBUG("URL requested: "<<url); + IOVDbSvcCurl request(url); + reply=request.get(); + } + // + std::istringstream ss(reply); + //basic folder now contains the info + Json2Cool inputJson(ss, b); + if (b.empty()){ + ATH_MSG_FATAL("Reading channel data from "<<jsonFolderName<<" failed."); + return false; + } + } + ATH_MSG_DEBUG( "Load cache for folder " << m_foldername << " validitykey " << vkey); // if not first time through, and limit not reached,and cache was not reset, // and we are going forwards in time, double cachesize if (m_ndbread>0 && m_cacheinc<3 && (cachestop!=cachestart) && vkey>cachestart && m_autocache) { m_cachelength*=2; ++m_cacheinc; - ATH_MSG_INFO( "Increase cache length (step " << m_cacheinc << - ") for folder " << m_foldername - << " to " << m_cachelength << " at validityKey " << vkey ); + ATH_MSG_INFO( "Increase cache length (step " << m_cacheinc << ") for folder " << m_foldername << " to " << m_cachelength << " at validityKey " << vkey ); } ++m_ndbread; auto [changedCacheLo, changedCacheHi] = m_iovs.getCacheBounds(); @@ -285,7 +349,12 @@ IOVDbFolder::loadCache(const cool::ValidityKey vkey, // const auto & [since, until] = m_iovs.getCacheBounds(); ATH_MSG_DEBUG( "IOVDbFolder:loadCache limits set to [" << since << "," << until << "]" ); - + bool vectorPayload{}; + if (m_source=="CREST"){ + vectorPayload = b.isVectorPayload(); + } else { + vectorPayload = (m_foldertype ==CoraCool) or (m_foldertype == CoolVector); + } if (m_cachespec==0) { // on first init, guess size based on channel count unsigned int estsize=m_nchan; @@ -299,7 +368,7 @@ IOVDbFolder::loadCache(const cool::ValidityKey vkey, // actual datastorage is mainly allocated by pointer elsewhere m_cachechan.reserve(estsize); m_cacheattr.reserve(estsize); - if (m_foldertype==CoraCool || m_foldertype==CoolVector) { + if (vectorPayload) { m_cacheccstart.reserve(estsize); m_cacheccend.reserve(estsize); } @@ -309,130 +378,178 @@ IOVDbFolder::loadCache(const cool::ValidityKey vkey, // avoiding some attributelist construction/destruction clearCache(); } - - // query to fill cache - request for database activates connection - cool::IDatabasePtr dbPtr=m_conn->getCoolDb(); - if (dbPtr.get()==0) { - ATH_MSG_FATAL( "Conditions database connection " << - m_conn->name() << " cannot be opened - STOP" ); - return false; - } - // access COOL inside try/catch in case of using stale connection - unsigned int attempts=0; bool retrievedone=false; unsigned int nChannelsExpected = (m_chanrange.empty())? (m_nchan) : (IOVDbNamespace::countSelectedChannels(m_channums, m_chansel)); - ATH_MSG_DEBUG( "Expecting to see " << nChannelsExpected << " channels" ); - // - while (attempts<2 && !retrievedone) { - ++attempts; - try { - unsigned int iadd=0; - m_iovs.setIovSpan(IovStore::Iov_t(0,cool::ValidityKeyMax)); - // check pointer is still valid - can go stale in AthenaMT environment - // according to CORAL server tests done by Andrea Valassi (23/6/09) - if (not dbPtr.get()) throw std::runtime_error("COOL database pointer invalidated"); - // access COOL folder in case needed to resolve tag (even for CoraCool) - cool::IFolderPtr folder=dbPtr->getFolder(m_foldername); - // resolve the tag for MV folders if not already done so - if (m_multiversion && m_tag.empty()) { - if (!resolveTag(folder,globalTag)) return false; - ATH_MSG_DEBUG( "resolveTag returns " << m_tag); + if (m_source == "COOL_DATABASE"){ + // query to fill cache - request for database activates connection + cool::IDatabasePtr dbPtr=m_conn->getCoolDb(); + if (dbPtr.get()==0) { + ATH_MSG_FATAL( "Conditions database connection " <<m_conn->name() << " cannot be opened - STOP" ); + return false; + } + // access COOL inside try/catch in case of using stale connection + unsigned int attempts=0; + + ATH_MSG_DEBUG( "Expecting to see " << nChannelsExpected << " channels" ); + // + while (attempts<2 && !retrievedone) { + ++attempts; + try { + unsigned int iadd=0; + m_iovs.setIovSpan(IovStore::Iov_t(0,cool::ValidityKeyMax)); + // check pointer is still valid - can go stale in AthenaMT environment + // according to CORAL server tests done by Andrea Valassi (23/6/09) + if (not dbPtr.get()) throw std::runtime_error("COOL database pointer invalidated"); + // access COOL folder in case needed to resolve tag (even for CoraCool) + cool::IFolderPtr folder=dbPtr->getFolder(m_foldername); + + // resolve the tag for MV folders if not already done so + if (m_multiversion && m_tag.empty()) { + if (!resolveTag(folder,globalTag)) return false; + ATH_MSG_DEBUG( "resolveTag returns " << m_tag); - } - if (m_foldertype==CoraCool) { - // CoraCool retrieve - // initialise CoraCool connection - CoraCoolDatabasePtr ccDbPtr=m_conn->getCoraCoolDb(); - CoraCoolFolderPtr ccfolder=ccDbPtr->getFolder(m_foldername); - auto [since,until] = m_iovs.getCacheBounds(); - CoraCoolObjectIterPtr itr=ccfolder->browseObjects(since, until,m_chansel,m_tag); - while (itr->hasNext()) { - CoraCoolObjectPtr obj=itr->next(); - addIOVtoCache(obj->since(),obj->until()); - m_cachechan.push_back(obj->channelId()); - // store all the attributeLists in the buffer - // save pointer to start - const unsigned int istart=m_cacheattr.size(); - for (CoraCoolObject::const_iterator pitr=obj->begin(); - pitr!=obj->end(); ++pitr) { - // setup shared specification on first store - if (m_cachespec==0) setSharedSpec(*pitr); - // use the shared specification in storing the payload - m_cacheattr.push_back(coral::AttributeList(*m_cachespec,true)); - m_cacheattr[m_cacheattr.size()-1].fastCopyData(*pitr); - m_nbytesread+=IOVDbNamespace::attributeListSize(*pitr); - } - // save pointers to start and end - m_cacheccstart.push_back(istart); - m_cacheccend.push_back(m_cacheattr.size()); - ++iadd; } - itr->close(); - retrievedone=true; - } else { - auto [since,until] = m_iovs.getCacheBounds(); - cool::IObjectIteratorPtr itr=folder->browseObjects(since,until,m_chansel,m_tag); - while (itr->goToNext()) { - const cool::IObject& ref=itr->currentRef(); - addIOVtoCache(ref.since(),ref.until()); - m_cachechan.push_back(ref.channelId()); - if (m_foldertype==CoolVector) { + if (m_foldertype==CoraCool) { + // CoraCool retrieve + // initialise CoraCool connection + CoraCoolDatabasePtr ccDbPtr=m_conn->getCoraCoolDb(); + CoraCoolFolderPtr ccfolder=ccDbPtr->getFolder(m_foldername); + auto [since,until] = m_iovs.getCacheBounds(); + CoraCoolObjectIterPtr itr=ccfolder->browseObjects(since, until,m_chansel,m_tag); + while (itr->hasNext()) { + CoraCoolObjectPtr obj=itr->next(); + //should be skipping non-selected channels here? + addIOVtoCache(obj->since(),obj->until()); + m_cachechan.push_back(obj->channelId()); // store all the attributeLists in the buffer // save pointer to start const unsigned int istart=m_cacheattr.size(); - // get payload iterator and vector of payload records - cool::IRecordIterator& pitr=ref.payloadIterator(); - const cool::IRecordVectorPtr& pvec=pitr.fetchAllAsVector(); - for (cool::IRecordVector::const_iterator vitr=pvec->begin(); - vitr!=pvec->end();++vitr) { - const coral::AttributeList& atrlist=(*vitr)->attributeList(); + for (CoraCoolObject::const_iterator pitr=obj->begin();pitr!=obj->end(); ++pitr) { // setup shared specification on first store - if (m_cachespec==0) setSharedSpec(atrlist); + if (m_cachespec==0) setSharedSpec(*pitr); // use the shared specification in storing the payload m_cacheattr.push_back(coral::AttributeList(*m_cachespec,true)); - m_cacheattr[m_cacheattr.size()-1].fastCopyData(atrlist); - m_nbytesread+=IOVDbNamespace::attributeListSize(atrlist); + m_cacheattr.back().fastCopyData(*pitr); + m_nbytesread+=IOVDbNamespace::attributeListSize(*pitr); } // save pointers to start and end m_cacheccstart.push_back(istart); m_cacheccend.push_back(m_cacheattr.size()); ++iadd; - pitr.close(); - } else { - // standard COOL retrieve - const coral::AttributeList& atrlist=ref.payload().attributeList(); - // setup shared specification on first store - if (m_cachespec==0) setSharedSpec(atrlist); - // use the shared specification in storing the payload - m_cacheattr.push_back(coral::AttributeList(*m_cachespec,true)); - m_cacheattr[iadd].fastCopyData(atrlist); - ++iadd; - m_nbytesread+=IOVDbNamespace::attributeListSize(atrlist); } + itr->close(); + retrievedone=true; + } else { + auto [since,until] = m_iovs.getCacheBounds(); + cool::IObjectIteratorPtr itr=folder->browseObjects(since,until,m_chansel,m_tag); + if (m_outputToFile){ + Cool2Json json(folder, since, until, m_chansel, m_tag); + std::ofstream myFile; + const std::string sanitisedFolder=sanitiseFilename(m_foldername); + const std::string fabricatedName=sanitisedFolder+delimiter+std::to_string(since)+fileSuffix; + myFile.open(fabricatedName,std::ios::out); + if (not myFile.is_open()){ + ATH_MSG_FATAL("File creation for "<<fabricatedName<<" failed."); + } else{ + ATH_MSG_INFO("File "<<fabricatedName<<" created."); + } + myFile<<json.open(); + myFile<<json.description()<<json.delimiter()<<std::endl; + myFile<<json.payloadSpec()<<json.delimiter()<<std::endl; + myFile<<json.iov()<<json.delimiter()<<std::endl; + myFile<<json.payload()<<std::endl; + myFile<<json.close(); + } + while (itr->goToNext()) { + const cool::IObject& ref=itr->currentRef(); + addIOVtoCache(ref.since(),ref.until()); + m_cachechan.push_back(ref.channelId()); + if (m_foldertype==CoolVector) { + // store all the attributeLists in the buffer + // save pointer to start + const unsigned int istart=m_cacheattr.size(); + // get payload iterator and vector of payload records + cool::IRecordIterator& pitr=ref.payloadIterator(); + const cool::IRecordVectorPtr& pvec=pitr.fetchAllAsVector(); + for (cool::IRecordVector::const_iterator vitr=pvec->begin();vitr!=pvec->end();++vitr) { + const coral::AttributeList& atrlist=(*vitr)->attributeList(); + // setup shared specification on first store + if (m_cachespec==0) setSharedSpec(atrlist); + // use the shared specification in storing the payload + m_cacheattr.push_back(coral::AttributeList(*m_cachespec,true)); + m_cacheattr.back().fastCopyData(atrlist); + m_nbytesread+=IOVDbNamespace::attributeListSize(atrlist); + } + // save pointers to start and end + m_cacheccstart.push_back(istart); + m_cacheccend.push_back(m_cacheattr.size()); + ++iadd; + pitr.close(); + } else { + // standard COOL retrieve + const coral::AttributeList& atrlist=ref.payload().attributeList(); + // setup shared specification on first store + if (m_cachespec==0) setSharedSpec(atrlist); + // use the shared specification in storing the payload + m_cacheattr.push_back(coral::AttributeList(*m_cachespec,true)); + m_cacheattr[iadd].fastCopyData(atrlist); + ++iadd; + m_nbytesread+=IOVDbNamespace::attributeListSize(atrlist); + } + } + itr->close(); + retrievedone=true; } - itr->close(); - retrievedone=true; - } - ATH_MSG_DEBUG( "Retrieved " << iadd << " objects for "<< m_nchan << " channels into cache" ); - m_nobjread+=iadd; - } catch (std::exception& e) { - ATH_MSG_WARNING( "COOL retrieve attempt " << attempts << " failed: " << e.what() ); - // disconnect and reconnect - try { - m_conn->setInactive(); - dbPtr=m_conn->getCoolDb(); + ATH_MSG_DEBUG( "Retrieved " << iadd << " objects for "<< m_nchan << " channels into cache" ); + m_nobjread+=iadd; } catch (std::exception& e) { - ATH_MSG_WARNING( "Exception from disconnect/reconnect: " <<e.what() ); - // try once more to connect + ATH_MSG_WARNING( "COOL retrieve attempt " << attempts << " failed: " << e.what() ); + // disconnect and reconnect try { + m_conn->setInactive(); dbPtr=m_conn->getCoolDb(); } catch (std::exception& e) { - ATH_MSG_ERROR( "Cannot reconnect to database:" << e.what()); + ATH_MSG_WARNING( "Exception from disconnect/reconnect: " <<e.what() ); + // try once more to connect + try { + dbPtr=m_conn->getCoolDb(); + } catch (std::exception& e) { + ATH_MSG_ERROR( "Cannot reconnect to database:" << e.what()); + } } } } - } + } /*end of 'if ... COOL_DATABASE'*/ else { + //this is code using CREST objects now + addIOVtoCache(b.iov().first, b.iov().second); + ATH_MSG_INFO("Adding IOV to cache"); + const auto & channelNumbers=b.channelIds(); + unsigned int iadd{}; + for (const auto & chan: channelNumbers){ + m_cachechan.push_back(chan); + if (b.isVectorPayload()) { + const auto & vPayload = b.getVectorPayload(chan); + const unsigned int istart=m_cacheattr.size(); + for (const auto & attList:vPayload){ + m_cacheattr.push_back(coral::AttributeList(*m_cachespec,true));// maybe needs to be cleared before + m_cacheattr.back().fastCopyData(attList); + m_nbytesread+=IOVDbNamespace::attributeListSize(attList); + } + m_cacheccstart.push_back(istart); + m_cacheccend.push_back(m_cacheattr.size()); + //m_cache.saveCoraCoolEndpoints(istart, m_cache.size()); + ++iadd; + } else { + auto const & attList = b.getPayload(chan); + m_cacheattr.push_back(coral::AttributeList(*m_cachespec,true));// maybe needs to be cleared before + m_cacheattr.back().fastCopyData(attList); + m_nbytesread+=IOVDbNamespace::attributeListSize(attList); + ++iadd; + } + } + retrievedone=true; + } //end of attempted retrieves using one of the methods if (!retrievedone) { const auto & [since,until] = m_iovs.getCacheBounds(); ATH_MSG_ERROR( "Could not retrieve COOL data for folder " << @@ -504,7 +621,7 @@ bool IOVDbFolder::loadCacheIfDbChanged(const cool::ValidityKey vkey, CoraCoolFolderPtr ccfolder = ccDbPtr->getFolder(m_foldername); // this returns all the objects whose IOVRanges crosses this range . CoraCoolObjectIterPtr itr = ccfolder->browseObjects(vkey+1, vkey+2,m_chansel,m_tag); - while (itr->hasNext()) { + while (objectIteratorIsValid(itr)) { CoraCoolObjectPtr obj = itr->next(); //code delegated to templated member, allowing for difference between CoraCoolObjectPtr and IObject counter+=cacheUpdateImplementation(*obj,iovSvc); @@ -513,7 +630,7 @@ bool IOVDbFolder::loadCacheIfDbChanged(const cool::ValidityKey vkey, } else { // this returns all the objects whose IOVRanges crosses this range . cool::IObjectIteratorPtr itr=folder->browseObjects(vkey+1, vkey+2, m_chansel,m_tag); - while (itr->goToNext()) { + while (objectIteratorIsValid(itr)) { const cool::IObject& ref=itr->currentRef(); //code delegated to templated member, allowing for difference between CoraCoolObjectPtr and IObject counter+=cacheUpdateImplementation(ref,iovSvc); @@ -1087,7 +1204,6 @@ IOVDbFolder::setSharedSpec(const coral::AttributeList& atrlist) { void IOVDbFolder::addIOVtoCache(cool::ValidityKey since,cool::ValidityKey until) { - // add IOV to the cache m_iovs.addIov(since, until); } diff --git a/Database/IOVDbSvc/src/IOVDbFolder.h b/Database/IOVDbSvc/src/IOVDbFolder.h index 1290345319e..41acaf429f1 100644 --- a/Database/IOVDbSvc/src/IOVDbFolder.h +++ b/Database/IOVDbSvc/src/IOVDbFolder.h @@ -5,8 +5,8 @@ // IOVDbFolder.h // helper class for IOVDbSvc managing folder access // Richard Hawkings, started 24/11/08 -#ifndef IOVDBSVC_IOVDBFOLDER_H -#define IOVDBSVC_IOVDBFOLDER_H +#ifndef IOVDbSvc_IOVDbFolder_h +#define IOVDbSvc_IOVDbFolder_h #include <string> #include "AthenaKernel/MsgStreamMember.h" @@ -41,7 +41,8 @@ class CondAttrListCollection; class IOVDbFolder { public: IOVDbFolder(IOVDbConn* conn, const IOVDbParser& folderprop, MsgStream & /*msg*/, - IClassIDSvc* clidsvc,const bool checkglock); + IClassIDSvc* clidsvc,const bool checkglock, const bool outputToFile=false, + const std::string & source="COOL_DATABASE"); ~IOVDbFolder(); @@ -184,6 +185,18 @@ private: } return counter; } + + + bool + objectIteratorIsValid( cool::IObjectIteratorPtr & objItr){ + return objItr->goToNext(); + } + + bool + objectIteratorIsValid(CoraCoolObjectIterPtr & objItr){ + return objItr->hasNext(); + } + // cache update for online mode void specialCacheUpdate(CoraCoolObject & obj, @@ -255,6 +268,8 @@ private: std::vector<unsigned int> m_cacheccstart; std::vector<unsigned int> m_cacheccend; IOVDbNamespace::IovStore m_iovs; + const bool m_outputToFile; + const std::string m_source; protected: /// Log a message using the Athena controlled logging system diff --git a/Database/IOVDbSvc/src/IOVDbParser.h b/Database/IOVDbSvc/src/IOVDbParser.h index 04ee28c1571..6a1d4f6d238 100644 --- a/Database/IOVDbSvc/src/IOVDbParser.h +++ b/Database/IOVDbSvc/src/IOVDbParser.h @@ -6,8 +6,8 @@ //@brief helper class for IOVDbSvc implementing a simple XML-style parser to parse // the folder description string or the provided folder description in job options //@author Richard Hawkings, started 29/11/08 -#ifndef __IOVDBPARSER_H__ -#define __IOVDBPARSER_H__ +#ifndef IOVDbSvc_IOVDbParser_h +#define IOVDbSvc_IOVDbParser_h #include <string> #include <map> diff --git a/Database/IOVDbSvc/src/IOVDbResolveTag.cxx b/Database/IOVDbSvc/src/IOVDbResolveTag.cxx new file mode 100644 index 00000000000..17ee925e23e --- /dev/null +++ b/Database/IOVDbSvc/src/IOVDbResolveTag.cxx @@ -0,0 +1,44 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ +// @file IOVDbResolveTag.cxx +// Implementation for tag resolving function, associating global tag to local folder +// @author Shaun Roe +// @date 10 April 2018 + +#include "IOVDbResolveTag.h" +#include "IOVDbSvcCurl.h" +#include "nlohmann/json.hpp" +#include <sstream> +#include <iostream> + +using json = nlohmann::json; + +namespace IOVDbNamespace{ + std::string + resolveCrestTag(const std::string & globalTagName, const std::string & folderName, const std::string forceTag){ + std::string result{}; + static std::string curlReply{};//preserves state, not very threadsafe + if (not forceTag.empty()) return forceTag; + if (curlReply.empty()){ + const std::string urlBase{"http://crest-undertow.web.cern.ch/crestapi"}; + const std::string getTagMap="/globaltagmaps/"+globalTagName; + const std::string url=urlBase+getTagMap; + std::cout<<"Calling CURL"<<std::endl; + IOVDbSvcCurl request(url); + curlReply=request.get(); + } + std::istringstream ss(curlReply); + json j; + ss>>j; + for (const auto &i:j){ + if (i["label"] == folderName){ + result=i["tagName"]; + break; + } + } + return result; + } + + +} \ No newline at end of file diff --git a/Database/IOVDbSvc/src/IOVDbResolveTag.h b/Database/IOVDbSvc/src/IOVDbResolveTag.h new file mode 100644 index 00000000000..cc4239e3080 --- /dev/null +++ b/Database/IOVDbSvc/src/IOVDbResolveTag.h @@ -0,0 +1,18 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef IOVDbSvc_IOVDbResolveTag_h +#define IOVDbSvc_IOVDbResolveTag_h +// @file IOVDbResolveTag.h +// Header for tag resolving function, associating global tag to local folder +// @author Shaun Roe +// @date 10 April 2018 + +#include <string> + + namespace IOVDbNamespace{ + std::string + resolveCrestTag(const std::string & globalTagName, const std::string & folderName, const std::string forceTag=""); + + } + #endif \ No newline at end of file diff --git a/Database/IOVDbSvc/src/IOVDbStringFunctions.cxx b/Database/IOVDbSvc/src/IOVDbStringFunctions.cxx index 67dd5f1060c..2b4d4759762 100644 --- a/Database/IOVDbSvc/src/IOVDbStringFunctions.cxx +++ b/Database/IOVDbSvc/src/IOVDbStringFunctions.cxx @@ -107,11 +107,8 @@ namespace IOVDbNamespace{ result.reserve(bufsize); for(size_t pos = 0; pos != strSize; ++pos) { switch(pseudoXmlString[pos]) { - //case '&': result.append("&"); break; case '\"': result.append("\\\""); break; - //case '\'': result.append("'"); break; - //case '<': result.append("<"); break; - //case '>': result.append(">"); break; + default: result.append(&pseudoXmlString[pos], 1); break; } } diff --git a/Database/IOVDbSvc/src/IOVDbStringFunctions.h b/Database/IOVDbSvc/src/IOVDbStringFunctions.h index 5225a9b2577..f6fc9fd2a5b 100644 --- a/Database/IOVDbSvc/src/IOVDbStringFunctions.h +++ b/Database/IOVDbSvc/src/IOVDbStringFunctions.h @@ -4,8 +4,8 @@ //@file IOVDbStringFunctions.h //@brief Helper functions for string manipulation and parsing //@author Shaun Roe -#ifndef IOVDbStringFunctions_H -#define IOVDbStringFunctions_H +#ifndef IOVDbSvc_IOVDbStringFunctions_h +#define IOVDbSvc_IOVDbStringFunctions_h #include <string> #include <vector> diff --git a/Database/IOVDbSvc/src/IOVDbSvc.cxx b/Database/IOVDbSvc/src/IOVDbSvc.cxx index b4dab112643..bf13393400e 100644 --- a/Database/IOVDbSvc/src/IOVDbSvc.cxx +++ b/Database/IOVDbSvc/src/IOVDbSvc.cxx @@ -23,8 +23,8 @@ #include "EventInfo/TagInfo.h" #include "EventInfoUtils/EventIDFromStore.h" - #include "IOVDbParser.h" + #include "IOVDbFolder.h" #include "IOVDbSvc.h" @@ -88,6 +88,8 @@ IOVDbSvc::IOVDbSvc( const std::string& name, ISvcLocator* svc ) m_par_cacheAlign(0), m_par_onlineMode(false), m_par_checklock(false), + m_par_source("COOL_DATABASE"), + m_par_format(""), //default format for the source is empty m_h_IOVSvc ("IOVSvc", name), m_h_sgSvc ("StoreGateSvc", name), m_h_detStore ("DetectorStore", name), @@ -97,14 +99,12 @@ IOVDbSvc::IOVDbSvc( const std::string& name, ISvcLocator* svc ) m_h_poolSvc ("PoolSvc", name), m_h_metaDataTool("IOVDbMetaDataTool"), m_h_tagInfoMgr("TagInfoMgr", name), - //m_log(0), m_poolPayloadRequested(false), m_poolSvcContext(0), m_state (INITIALIZATION), m_globalTag(""), m_iovslop(), - m_abort(false)//, - //m_msg("IOVDbSvc") + m_abort(false) { // declare all properties declareProperty("dbConnection", m_par_defaultConnection); @@ -126,6 +126,9 @@ IOVDbSvc::IOVDbSvc( const std::string& name, ISvcLocator* svc ) declareProperty("CacheAlign", m_par_cacheAlign); declareProperty("OnlineMode", m_par_onlineMode); declareProperty("CheckLock", m_par_checklock); + declareProperty("Source", m_par_source); + declareProperty("Format", m_par_format); + declareProperty("OutputToFile", m_outputToFile); } IOVDbSvc::~IOVDbSvc() {} @@ -146,8 +149,6 @@ IOVDbSvc::queryInterface(const InterfaceID& riid, void** ppvInterface) { StatusCode IOVDbSvc::initialize() { if (StatusCode::SUCCESS!=AthService::initialize()) return StatusCode::FAILURE; - // initialise message stream after service init to get correct print level - //m_log=new MsgStream(msgSvc(),name()); // subscribe to events ServiceHandle<IIncidentSvc> incSvc("IncidentSvc",name()); if (StatusCode::SUCCESS!=incSvc.retrieve()) { @@ -234,6 +235,7 @@ StatusCode IOVDbSvc::initialize() { m_state=IOVDbSvc::INITIALIZATION; ATH_MSG_INFO( "Initialised with " << m_connections.size() << " connections and " << m_foldermap.size() << " folders" ); + if (m_outputToFile) ATH_MSG_INFO("Db dump to file activated"); ATH_MSG_INFO( "Service IOVDbSvc initialised successfully" ); return StatusCode::SUCCESS; } @@ -316,8 +318,6 @@ StatusCode IOVDbSvc::preLoadAddresses(StoreID::type storeID,tadList& tlist) { if (fitr->second->folderName()==fname && !(fitr->second->tagOverride())) { ATH_MSG_INFO( "Folder " << fname << " will be taken from file metadata" ); fitr->second->setMetaCon(cont.cptr()); - // print metadata if in debug mode - //ATH_MSG_DEBUG( printMetaDataContainer(cont.cptr())); ++nused; break; } @@ -1062,7 +1062,7 @@ StatusCode IOVDbSvc::setupFolders() { // create the new folder, but only if a folder for this SG key has not // already been requested IOVDbFolder* folder=new IOVDbFolder(conn,folderdata,msg(),&(*m_h_clidSvc), - m_par_checklock); + m_par_checklock, m_outputToFile, m_par_source); const std::string& key=folder->key(); if (m_foldermap.find(key)==m_foldermap.end()) { //This check is too weak. For POOL-based folders, the SG key is in the folder description (not known at this point). m_foldermap[key]=folder; diff --git a/Database/IOVDbSvc/src/IOVDbSvc.h b/Database/IOVDbSvc/src/IOVDbSvc.h index 525092dd95b..aee51187ff3 100644 --- a/Database/IOVDbSvc/src/IOVDbSvc.h +++ b/Database/IOVDbSvc/src/IOVDbSvc.h @@ -13,8 +13,8 @@ * $Header: /build/atlas/cvs/atlas/offline/Database/IOVDbSvc/src/IOVDbSvc.h,v 1.48 2009-02-10 14:09:58 hawkings Exp $ */ -#ifndef IOVDBSVC_IOVDBSVC_H -#define IOVDBSVC_IOVDBSVC_H +#ifndef IOVDbSvc_IOVDbSvc_h +#define IOVDbSvc_IOVDbSvc_h #include "GaudiKernel/IInterface.h" #include "GaudiKernel/IService.h" @@ -38,10 +38,6 @@ #include "IOVDbConn.h" -//for using the msg service - //#include "AthenaKernel/MsgStreamMember.h" - //#include "AthenaBaseComps/AthMsgStreamMacros.h" - #include <string> #include <vector> @@ -233,7 +229,12 @@ private: BooleanProperty m_par_onlineMode; // check to ensure global/HVS tags are locked (for production) BooleanProperty m_par_checklock; - + // Source of data as a string; default is "COOL_DATABASE" + std::string m_par_source{}; + // Format of data; default is empty string (default for a given source) + std::string m_par_format{}; + // Can output to file for debugging purposes + bool m_outputToFile{false}; // internal parameters // handles to other services and tools ServiceHandle<IIOVSvc> m_h_IOVSvc; @@ -245,8 +246,6 @@ private: ServiceHandle<IPoolSvc> m_h_poolSvc; ToolHandle<IIOVDbMetaDataTool> m_h_metaDataTool; ServiceHandle<ITagInfoMgr> m_h_tagInfoMgr; - // message stream - //MsgStream* m_log; // Flag to signal when a pool payload has been requested. This // implies that a pool file has been open during an event, and will @@ -287,24 +286,7 @@ private: FolderMap m_foldermap; // gloal abort flag bool m_abort; - - protected: - /// Log a message using the Athena controlled logging system - /** - MsgStream& - msg(MSG::Level lvl) const { - return m_msg.get() << lvl; - } - - /// Check whether the logging system is active at the provided verbosity level - bool - msgLvl(MSG::Level lvl) { - return m_msg.get().level() <= lvl; - } - - /// Private message stream member - mutable Athena::MsgStreamMember m_msg;**/ - + }; #endif diff --git a/Database/IOVDbSvc/src/IOVDbSvcCurl.cxx b/Database/IOVDbSvc/src/IOVDbSvcCurl.cxx new file mode 100644 index 00000000000..df75393a083 --- /dev/null +++ b/Database/IOVDbSvc/src/IOVDbSvcCurl.cxx @@ -0,0 +1,65 @@ +// Basic Curl wrapper +// @author Shaun Roe +// @date 21 March 2018 + +#include "IOVDbSvcCurl.h" + +namespace IOVDbNamespace{ + + IOVDbSvcCurl::IOVDbSvcCurl(const std::string & url) { + m_handle = curl_easy_init(); + if ( m_handle == nullptr ) throw CurlException("Unable to initialize curl handler"); + if ( url.empty() ) throw CurlException("URL can't be of zero length"); + m_url = url; + } + + std::string + IOVDbSvcCurl::get(){ + setOptions(); + sendGetRequest(); + return m_data; + } + + IOVDbSvcCurl::~IOVDbSvcCurl() { + curl_easy_cleanup(m_handle); + curl_global_cleanup(); + } + + void + IOVDbSvcCurl::setOptions(){ + //set the url + check( curl_easy_setopt(m_handle, CURLOPT_URL, m_url.c_str()) ); + //no progress bar + check( curl_easy_setopt(m_handle, CURLOPT_NOPROGRESS, 1L)); + //set the callback function + check( curl_easy_setopt(m_handle, CURLOPT_WRITEFUNCTION,IOVDbSvcCurl::writeDataCallback)); + //set pointer in call back function + check( curl_easy_setopt(m_handle, CURLOPT_WRITEDATA, this)); + } + + void + IOVDbSvcCurl::check(CURLcode res){ + if ( res != CURLE_OK) throw CurlException(res); + } + + void + IOVDbSvcCurl::sendGetRequest(){ + check( curl_easy_perform(m_handle)); + } + + size_t + IOVDbSvcCurl::writeDataCallback(void *ptr, size_t size,size_t nmemb, void* pInstance){ + return (static_cast<IOVDbSvcCurl*>(pInstance))->writeData(ptr, size, nmemb); + } + + size_t + IOVDbSvcCurl::writeData(void* ptr, size_t size, size_t nmemb){ + size_t numOfBytes = size * nmemb; + char *iter = (char*)ptr; + char *iterEnd = iter + numOfBytes; + m_data += std::string(iter, iterEnd); + return numOfBytes; + } + +} + diff --git a/Database/IOVDbSvc/src/IOVDbSvcCurl.h b/Database/IOVDbSvc/src/IOVDbSvcCurl.h new file mode 100644 index 00000000000..110b94a76ff --- /dev/null +++ b/Database/IOVDbSvc/src/IOVDbSvcCurl.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +// @file Curl.h +// Basic Curl wrapper +// @author Shaun Roe +// @date 21 March 2018 +#ifndef IOVDbSvc_IOVDbSvcCurl_h +#define IOVDbSvc_IOVDbSvcCurl_h + +#include <string> +#include <stdexcept> + +extern "C"{ + #include "curl/curl.h" + #include <stdlib.h> +} + +namespace IOVDbNamespace{ + ///CurlException class to use with IOVDbSvcCurl + class CurlException : public std::runtime_error{ + public: + CurlException(std::string const& message): std::runtime_error(message) {} + CurlException(CURLcode error): std::runtime_error(curl_easy_strerror(error)) {} + }; + + //@brief Minimal interface to Curl library to perform http get + class IOVDbSvcCurl{ + public: + ///Constructor takes URL as string + IOVDbSvcCurl(const std::string & url); + ///simple http GET to the URL, return data as a string + std::string get(); + ///Destructor does curl cleanup + ~IOVDbSvcCurl(); + private: + ///Set curl options + void setOptions(); + ///Check return codes and throw if not ok + void check(CURLcode res); + ///Perform request after options are set + void sendGetRequest(); + ///Callback function with static linkage for curl to use in the GET + static size_t writeDataCallback(void *ptr, size_t size,size_t nmemb, void* pInstance); + ///Actual function used in the callback + size_t writeData(void* ptr, size_t size, size_t nmemb); + + //data members + CURL *m_handle; + std::string m_url; + std::string m_data; + + }; + +}//namespace + +#endif + diff --git a/Database/IOVDbSvc/src/IovStore.h b/Database/IOVDbSvc/src/IovStore.h index 53bef5e037c..b58659712f8 100644 --- a/Database/IOVDbSvc/src/IovStore.h +++ b/Database/IOVDbSvc/src/IovStore.h @@ -3,8 +3,8 @@ */ -#ifndef IOVDBSVC_IOVSTORE_H -#define IOVDBSVC_IOVSTORE_H +#ifndef IOVDbSvc_IovStore_h +#define IOVDbSvc_IovStore_h /** * @file IovStore.h * @brief helper class for IOVDbFolder managing cached iov since/until pairs @@ -15,7 +15,8 @@ #include <utility> //pair namespace IOVDbNamespace{ - + //@brief Manages the caching of IOV since/until pairs but encapsulating the functionality + //in a single class class IovStore{ public: typedef std::pair<cool::ValidityKey, cool::ValidityKey> Iov_t; diff --git a/Database/IOVDbSvc/src/Json2Cool.cxx b/Database/IOVDbSvc/src/Json2Cool.cxx new file mode 100644 index 00000000000..a95c0a15339 --- /dev/null +++ b/Database/IOVDbSvc/src/Json2Cool.cxx @@ -0,0 +1,238 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "Json2Cool.h" + +#include "IOVDbStringFunctions.h" +#include "CoolKernel/RecordSpecification.h" +#include "CoolKernel/Record.h" +#include "CoralBase/AttributeList.h" +#include "CoralBase/Attribute.h" +#include "boost/regex.hpp" +#include <stdexcept> +#include <iostream> + +using json = nlohmann::json; +using namespace cool; +using namespace IOVDbNamespace; + +namespace IOVDbNamespace{ + +const std::map<std::string, cool::StorageType::TypeId> Json2Cool::m_typeCorrespondance={ + //http://cool-doxygen.web.cern.ch/COOL-doxygen/classcool_1_1_storage_type.html + {"Bool", StorageType::Bool}, + {"UChar",StorageType::UChar}, + {"Int16", StorageType::Int16}, + {"UInt16", StorageType::UInt16}, + {"Int32", StorageType::Int32}, + {"UInt32", StorageType::UInt32}, + {"UInt63",StorageType::UInt63}, + {"Int64", StorageType::Int64}, + {"Float", StorageType::Float}, + {"Double", StorageType::Double}, + {"String255", StorageType::String255}, + {"String4k", StorageType::String4k}, + {"String64k", StorageType::String64k}, + {"String16M", StorageType::String16M}, + {"Blob64k", StorageType::Blob64k}, + {"Blob16M", StorageType::Blob16M} + }; + + + Json2Cool::Json2Cool(std::istream & stream, BasicFolder & b):m_basicFolder(b){ + init(stream); + } + + void + Json2Cool::init(std::istream & s){ + if (not s.good()){ + const std::string msg("Json2Cool constructor; Input is invalid and could not be opened."); + throw std::runtime_error(msg); + } else { + json j; + try{ + s>>j; //read into json + }catch (const std::exception& e) { + std::cout<<"ERROR AT LINE "<<__LINE__<<" of "<<__FILE__<<std::endl; + std::cout<<e.what()<<std::endl; //typically a parsing error + } + const std::string specString=j["folder_payloadspec"]; + const std::string description=j["node_description"]; + m_isVectorPayload =(description.find("CondAttrListVec") != std::string::npos); + m_sharedSpec = parsePayloadSpec(specString); + const auto & payload=j["data_array"];//payload is an array in any case + m_basicFolder.setVectorPayloadFlag(m_isVectorPayload); + const auto & iovFromFile=j["iov"];//iov is a two-element array + const std::pair<cool::ValidityKey, cool::ValidityKey> iov(iovFromFile[0], iovFromFile[1]); + m_basicFolder.setIov(iov); + if (m_isVectorPayload){ + for (json::const_iterator k=payload.begin();k!=payload.end();++k){ //k are {"0":} + const json f=k.value(); //channel id + std::vector<coral::AttributeList> tempVector;//can optimise this by pre constructing it and using 'clear' + for (json::const_iterator i=f.begin();i!=f.end();++i){ + const std::string keyString=i.key(); + const long long key=std::stoll(keyString); + auto & val=i.value(); + for (const auto & aList:val){ + auto r=createAttributeList(m_sharedSpec,aList); + const auto & attList=r.attributeList(); + tempVector.push_back(attList); + } + m_basicFolder.addChannelPayload(key, tempVector); + } + //add payload with channelId here + } + } else { + for (json::const_iterator i=payload.begin();i!=payload.end();++i){ + const json f=i.value(); + for (json::const_iterator k=f.begin();k!=f.end();++k){ + const std::string keyString=k.key(); + const long long key=std::stoll(keyString); + auto & val=k.value(); + auto r=createAttributeList(m_sharedSpec,val); + const auto & attList=r.attributeList(); + m_basicFolder.addChannelPayload(key, attList); + } + } + } + } + } + + //parsing something like + // "folder_payloadspec": "crate: UChar, slot: UChar, ROB: Int32, SRCid: Int32, BCIDOffset: Int16, slave0: Int32, slave1: Int32, slave2: Int32, slave3: Int32" + cool::RecordSpecification * + Json2Cool::parsePayloadSpec(const std::string & stringSpecification){ + if (stringSpecification.empty()) return nullptr; + std::string input(stringSpecification); + auto spec = new cool::RecordSpecification(); + + std::string regex=R"delim(([^\s]*):\s?([^\s,]*),?)delim"; + boost::regex expression(regex); + boost::smatch what; + + bool match=boost::regex_search(input, what, expression); + while (match){ + std::string n(what[1]); + std::string t(what[2]); + //todo: need to catch error if type not found, also + spec->extend(n, m_typeCorrespondance.find(t)->second); + input = what.suffix(); + match=boost::regex_search(input, what, expression); + } + return spec; + } + + cool::Record + Json2Cool::createAttributeList(cool::RecordSpecification * pSpec, const nlohmann::json & j){ + cool::Record a(*pSpec); + unsigned int s=a.size(); + json::const_iterator it = j.begin(); + for (unsigned int i(0);i!=s;++i){ + auto & f=a[i]; + const auto & n = f.storageType().name(); + const auto & v = it.value(); + it++; + try{ + auto & att=const_cast<coral::Attribute&>(a.attributeList()[i]); + if (v.is_null()){ + att.setNull(); + continue; + } + if (v.is_string()){ + const std::string & thisVal=v; + att.setValue<std::string>(thisVal); + } else { + auto & thisVal=v; + //nasty + + switch (f.storageType().id()){ + case (StorageType::Bool): + { + const bool newVal=thisVal; + att.setValue<bool>(newVal); + } + break; + case (StorageType::UChar): + { + const unsigned char newVal=thisVal; + att.setValue<unsigned char>(newVal); + } + break; + case (StorageType::Int16): + { + const short newVal=thisVal; + att.setValue<short>(newVal); + } + break; + case (StorageType::UInt16): + { + const unsigned short newVal=thisVal; + att.setValue<unsigned short>(newVal); + } + break; + + case (StorageType::Int32): + { + const int newVal=thisVal; + att.setValue<int>(newVal); + } + break; + case (StorageType::UInt32): + { + const unsigned int newVal=thisVal; + att.setValue<unsigned int>(newVal); + } + break; + case (StorageType::UInt63): + { + const unsigned long long newVal=thisVal; + att.setValue<unsigned long long>(newVal); + } + break; + case (StorageType::Int64): + { + const long long newVal=thisVal; + att.setValue< long long>(newVal); + } + break; + case (StorageType::Float): + { + const float newVal=thisVal; + att.setValue<float>(newVal); + } + break; + case (StorageType::Double): + { + const double newVal=thisVal; + att.setValue<double>(newVal); + } + break; + + case (StorageType::String255): + case (StorageType::String4k): + case (StorageType::String64k): + case (StorageType::String16M): + { + const std::string newVal=thisVal; + att.setValue<std::string>(newVal); + } + break; + default: + //nop + break; + } + } + } catch (json::exception& e){ + std::cout<<e.what()<<std::endl; + } + } + return a; + } + + + Json2Cool::~Json2Cool(){ + } + +}//end of namespace + diff --git a/Database/IOVDbSvc/src/Json2Cool.h b/Database/IOVDbSvc/src/Json2Cool.h new file mode 100644 index 00000000000..17f1094e451 --- /dev/null +++ b/Database/IOVDbSvc/src/Json2Cool.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +#ifndef IOVDbSvc_Json2Cool_h +#define IOVDbSvc_Json2Cool_h + +#include "CoolKernel/StorageType.h" +#include <string> +#include <istream> +#include <map> +#include "nlohmann/json.hpp" +#include "BasicFolder.h" + +namespace cool{ + class RecordSpecification; + class Record; +} + + +namespace IOVDbNamespace { + //@brief Produces cool objects from their JSON representation, storing them in a 'BasicFolder' + class Json2Cool { + public: + + Json2Cool(std::istream & stream, BasicFolder & b); + ~Json2Cool(); + + static cool::Record + createAttributeList(cool::RecordSpecification * pSpec, const nlohmann::json & j); + + static cool::RecordSpecification * + parsePayloadSpec(const std::string & stringSpecification); + + private: + void init(std::istream & stream); + static const std::map<std::string, cool::StorageType::TypeId> m_typeCorrespondance; + cool::RecordSpecification * m_sharedSpec; + // + bool m_isVectorPayload; + // + BasicFolder &m_basicFolder; + + + }; + +} +#endif + diff --git a/Database/IOVDbSvc/src/ReadFromFileMetaData.h b/Database/IOVDbSvc/src/ReadFromFileMetaData.h index f0351070090..67eecee8946 100644 --- a/Database/IOVDbSvc/src/ReadFromFileMetaData.h +++ b/Database/IOVDbSvc/src/ReadFromFileMetaData.h @@ -5,8 +5,8 @@ //@file ReadFromFileMetaData.h //@brief Class to read from file metadata and give the results //@author Shaun Roe -#ifndef IOVDBSVC_ReadFromFileMetaData_H -#define IOVDBSVC_ReadFromFileMetaData_H +#ifndef IOVDbSvc_ReadFromFileMetaData_h +#define IOVDbSvc_ReadFromFileMetaData_h #include "CoolKernel/ValidityKey.h" @@ -26,6 +26,7 @@ namespace coral{ } namespace IOVDbNamespace{ + //@brief Encapsulates the functionality to read database quantities from file metadata class ReadFromFileMetaData{ public: ReadFromFileMetaData()=delete; diff --git a/Database/IOVDbSvc/src/TagFunctions.h b/Database/IOVDbSvc/src/TagFunctions.h index 949df32929b..d1eac85fbf9 100644 --- a/Database/IOVDbSvc/src/TagFunctions.h +++ b/Database/IOVDbSvc/src/TagFunctions.h @@ -4,8 +4,8 @@ //@file TagFunctions.h //@brief Helper functions for tag resolution //@author Shaun Roe -#ifndef TagFunctions_H -#define TagFunctions_H +#ifndef IOVDbSvc_TagFunctions_h +#define IOVDbSvc_TagFunctions_h #include "CoolKernel/IFolder.h" #include <string> diff --git a/Database/IOVDbSvc/test/BasicFolder_test.cxx b/Database/IOVDbSvc/test/BasicFolder_test.cxx new file mode 100644 index 00000000000..05ce4e320e3 --- /dev/null +++ b/Database/IOVDbSvc/test/BasicFolder_test.cxx @@ -0,0 +1,149 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +/* + */ +/** + * @file IOVDbSvc/test/BasicFolder_test.cxx + * @author Shaun Roe + * @date May, 2019 + * @brief Some tests for BasicFolder class in the Boost framework + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE TEST_IOVDBSVC + + +#include <boost/test/unit_test.hpp> +// +#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeListSpecification.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeSpecification.h" + +#include "../src/BasicFolder.h" +#include <string> + +using namespace IOVDbNamespace; +BOOST_AUTO_TEST_SUITE(BasicFolderTest) + BOOST_AUTO_TEST_CASE(constructor){ + BOOST_CHECK_NO_THROW(BasicFolder()); + } + BOOST_AUTO_TEST_CASE(emptyAfterConstruction){ + BasicFolder b; + BOOST_CHECK(b.empty()); + BOOST_CHECK(b.isVectorPayload() ==false); + } + BOOST_AUTO_TEST_CASE(addPayloadByChannelNumber){ + BasicFolder b; + //need a coral::AttributeList argument + auto pSpec=new coral::AttributeListSpecification; + pSpec->extend<int>("myInt"); + pSpec->extend<std::string>("PoolRef"); + coral::AttributeList attrList(*pSpec, true); + attrList[0].setValue(1); + attrList[1].setValue(std::string("hello")); + BOOST_CHECK_NO_THROW(b.addChannelPayload(0,attrList)); + BOOST_CHECK(b.empty() == false); + BOOST_CHECK(b.getPayload(0) == attrList); + } + + BOOST_AUTO_TEST_CASE(addPayloadWithChannelName){ + BasicFolder b; + //need a coral::AttributeList argument + auto pSpec=new coral::AttributeListSpecification; + pSpec->extend<int>("myInt"); + pSpec->extend<std::string>("PoolRef"); + coral::AttributeList attrList(*pSpec, true); + attrList[0].setValue(1); + attrList[1].setValue(std::string("hello")); + BOOST_CHECK_NO_THROW(b.addChannelPayload(0,"uniqueChannel",attrList)); + BOOST_CHECK(b.empty() == false); + BOOST_CHECK(b.getPayload("uniqueChannel") == attrList); + } + BOOST_AUTO_TEST_CASE(setVectorPayloadFlag){ + BasicFolder b; + BOOST_CHECK_NO_THROW(b.setVectorPayloadFlag(true)); + BOOST_CHECK(b.isVectorPayload() == true); + } + BOOST_AUTO_TEST_CASE(addVectorPayloadByChannelNumber){ + BasicFolder b; + b.setVectorPayloadFlag(true); + //need a coral::AttributeList argument + auto pSpec=new coral::AttributeListSpecification; + pSpec->extend<int>("myInt"); + pSpec->extend<std::string>("PoolRef"); + coral::AttributeList attrList(*pSpec, true); + std::vector<coral::AttributeList> vectorPayload{ + coral::AttributeList(*pSpec, true), + coral::AttributeList(*pSpec, true), + coral::AttributeList(*pSpec, true) + }; + //set values + vectorPayload[0][0].setValue(1); + vectorPayload[0][1].setValue(std::string("hello")); + // + vectorPayload[1][0].setValue(2); + vectorPayload[1][1].setValue(std::string("bonjour")); + // + vectorPayload[2][0].setValue(3); + vectorPayload[2][1].setValue(std::string("ni hao")); + // + BOOST_CHECK_NO_THROW(b.addChannelPayload(0,vectorPayload)); + BOOST_CHECK(b.empty() == false); + BOOST_TEST(b.getVectorPayload(0) == vectorPayload); + } + + BOOST_AUTO_TEST_CASE(addVectorPayloadByName){ + BasicFolder b; + b.setVectorPayloadFlag(true); + //need a coral::AttributeList argument + auto pSpec=new coral::AttributeListSpecification; + pSpec->extend<int>("myInt"); + pSpec->extend<std::string>("PoolRef"); + coral::AttributeList attrList(*pSpec, true); + std::vector<coral::AttributeList> vectorPayload{ + coral::AttributeList(*pSpec, true), + coral::AttributeList(*pSpec, true), + coral::AttributeList(*pSpec, true) + }; + //set values + vectorPayload[0][0].setValue(1); + vectorPayload[0][1].setValue(std::string("hello")); + // + vectorPayload[1][0].setValue(2); + vectorPayload[1][1].setValue(std::string("bonjour")); + // + vectorPayload[2][0].setValue(3); + vectorPayload[2][1].setValue(std::string("ni hao")); + // + BOOST_CHECK_NO_THROW(b.addChannelPayload(0,"yummy",vectorPayload)); + BOOST_CHECK(b.empty() == false); + BOOST_TEST(b.getVectorPayload("yummy") == vectorPayload); + } + + BOOST_AUTO_TEST_CASE(checkChannelIds){ + BasicFolder b; + //need a coral::AttributeList argument + auto pSpec=new coral::AttributeListSpecification; + pSpec->extend<int>("myInt"); + pSpec->extend<std::string>("PoolRef"); + coral::AttributeList attrList(*pSpec, true); + attrList[0].setValue(1); + attrList[1].setValue(std::string("hello")); + b.addChannelPayload(100,attrList); + b.addChannelPayload(200,attrList); + const std::vector<cool::ChannelId> refChannelIds{100,200}; + BOOST_TEST(b.channelIds() == refChannelIds, boost::test_tools::per_element() ); + } + + BOOST_AUTO_TEST_CASE(setAndGetIov){ + BasicFolder b; + const std::pair<cool::ValidityKey, cool::ValidityKey> refIov(56,200); + BOOST_CHECK_NO_THROW(b.setIov(refIov)); + BOOST_CHECK(b.iov() == refIov); + } + + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Database/IOVDbSvc/test/Cool2Json_test.cxx b/Database/IOVDbSvc/test/Cool2Json_test.cxx new file mode 100644 index 00000000000..c96a02517d0 --- /dev/null +++ b/Database/IOVDbSvc/test/Cool2Json_test.cxx @@ -0,0 +1,146 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +// @file Cool2Json_test.cxx +// Cool2Json test executable, in Boost test framework +// @author Shaun Roe +// @date June 2019 + + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE TEST_IOVDBSVC + +#include <boost/test/unit_test.hpp> +// +#include "GaudiKernel/ServiceHandle.h" +#include "GaudiKernel/IMessageSvc.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/IAddressCreator.h" +#include "StoreGate/StoreGateSvc.h" +#include "AthenaKernel/IIOVDbSvc.h" +// +#include "CoolKernel/IDatabaseSvc.h" +#include "CoolKernel/FolderSpecification.h" +#include "CoolApplication/DatabaseSvcFactory.h" +#include "CoolKernel/Record.h" +// +//#include "../src/IOVDbFolder.h" +#include "../src/IOVDbConn.h" +#include "../src/Cool2Json.h" +#include "../src/IOVDbParser.h" + +// +#include "GaudiKernelFixtureBase.h" + +using namespace IOVDbNamespace; +struct GaudiKernelFixture:public GaudiKernelFixtureBase{ + GaudiKernelFixture():GaudiKernelFixtureBase(__FILE__){ + //nop, everything in base. + } +}; + +//note destructor is separate here +struct TestFolderFixture{ + ServiceHandle<IIOVDbSvc> iovdbsvc; + ServiceHandle<StoreGateSvc> detStore; + const std::string fixtureFoldername; + const std::string invalidFoldername; + cool::IFolderPtr folderPtr; + cool::IDatabasePtr coolDb; + cool::RecordSpecification spec; + TestFolderFixture():iovdbsvc("IOVDbSvc", "test"),detStore("DetectorStore",""),fixtureFoldername("/key1"),invalidFoldername("nonsense") { + if (not iovdbsvc.retrieve().isSuccess()){ + throw (std::runtime_error("IOVDbSvc could not be retrieved in the TestFolderFixture")); + } + if (not detStore.retrieve().isSuccess()){ + throw (std::runtime_error("detStore could not be retrieved in the TestFolderFixture")); + } + unlink ("Cool2JsonTest.db"); + cool::IDatabaseSvc& dbSvc=cool::DatabaseSvcFactory::databaseService(); + coolDb = dbSvc.createDatabase("sqlite://;schema=Cool2JsonTest.db;dbname=OFLP200"); + spec.extend ("int", cool::StorageType::Int32); + cool::FolderSpecification fSpec (cool::FolderVersioning::SINGLE_VERSION,spec,cool::PayloadMode::INLINEPAYLOAD); + std::string desc = "<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"; + { + folderPtr = coolDb->createFolder (fixtureFoldername, fSpec, desc); + cool::Record payload (folderPtr->payloadSpecification()); + payload[0].setValue (1); + folderPtr->storeObject ((10ull<<32) + 10, (10ull<<32) + 20, payload, 0); + payload[0].setValue (2); + folderPtr->storeObject ((10ull<<32) + 30, cool::ValidityKeyMax, payload, 0); + } + + } + ~TestFolderFixture(){ + coolDb->closeDatabase(); + } +}; + +struct IOVDbConnFixture{ + ServiceHandle<IMessageSvc> msgSvc; + const std::string connectionString; + MsgStream log; + IOVDbConn connection; + IOVDbConnFixture():msgSvc("msgSvc","test"), + connectionString("sqlite://;schema=Cool2JsonTest.db;dbname=OFLP200"), + log(msgSvc.get(), "Cool2Json_test"), + connection(connectionString, true, log){ + } +}; + +struct IOVDbParserFixture{ + ServiceHandle<IMessageSvc> msgSvc; + const std::string descriptionString; + MsgStream log; + IOVDbParser parser; + IOVDbParserFixture():msgSvc("msgSvc","test"), + descriptionString{"/key1<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"}, + log(msgSvc.get(), "Cool2Json_test"), + parser(descriptionString, log){ + } +}; + + +BOOST_FIXTURE_TEST_SUITE(Cool2JsonTestSetup , GaudiKernelFixture) + BOOST_AUTO_TEST_CASE( SanityCheck ){ + BOOST_TEST(gaudiIsInitialised); + BOOST_TEST(svcLoc!=nullptr); + } + //pre-requisites + IOVDbConnFixture connectionFixture; + IOVDbParserFixture parserFixture; + //need IClassIDSvc + ServiceHandle<IClassIDSvc> clidSvc("ClassIDSvc","test"); + BOOST_FIXTURE_TEST_SUITE(Cool2JsonTest, TestFolderFixture) + BOOST_AUTO_TEST_CASE(Construction){ + cool::ChannelSelection selection(0,10); + const std::string folderTag{}; + BOOST_CHECK_NO_THROW(Cool2Json(folderPtr, (10ull<<32) + 10, (10ull<<32) + 20, selection, folderTag)); + } + BOOST_AUTO_TEST_CASE(PublicMethods){ + //simple returns + cool::ChannelSelection selection(0,10); + const std::string folderTag{}; + Cool2Json testObject(folderPtr, (10ull<<32) + 10, (10ull<<32) + 20, selection, folderTag); + BOOST_TEST(testObject.open() == "{"); + BOOST_TEST(testObject.close() == "}"); + BOOST_TEST(testObject.delimiter() == ", "); + std::string referenceDescription=R"delim("node_description" : "<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>")delim"; + referenceDescription+="\n"; + BOOST_CHECK(testObject.description() == referenceDescription); + std::string referenceSpec=R"delim("folder_payloadspec": "int: Int32")delim"; + BOOST_CHECK(testObject.payloadSpec() == referenceSpec); + //careful about editing, the following is a multi-line raw string literal: + std::string referencePayload = R"delim("data_array" : [{ "0" : [ 1] +}])delim"; + BOOST_CHECK(testObject.payload() == referencePayload); + std::string referenceIov = R"delim("iov" : [42949672970, 42949672980])delim"; + BOOST_CHECK(testObject.iov() == referenceIov); + BOOST_CHECK(testObject.nchans() == 1); + BOOST_CHECK(testObject.iovBase() == "run-lumi"); + BOOST_CHECK(testObject.tag() == ""); + + } + BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() diff --git a/Database/IOVDbSvc/test/FolderTypes_test.cxx b/Database/IOVDbSvc/test/FolderTypes_test.cxx index aaeff5d1e2d..6be95999243 100644 --- a/Database/IOVDbSvc/test/FolderTypes_test.cxx +++ b/Database/IOVDbSvc/test/FolderTypes_test.cxx @@ -68,7 +68,7 @@ struct TestFolderFixture{ coolDb = dbSvc.createDatabase("sqlite://;schema=FolderTypesTest.db;dbname=OFLP200"); spec.extend ("int", cool::StorageType::Int32); cool::FolderSpecification fSpec (cool::FolderVersioning::SINGLE_VERSION,spec,cool::PayloadMode::INLINEPAYLOAD); - std::string desc = "<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"; + std::string desc = "<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"; { folderPtr = coolDb->createFolder (fixtureFoldername, fSpec, desc); cool::Record payload (folderPtr->payloadSpecification()); diff --git a/Database/IOVDbSvc/test/IOVDbFolder_test.cxx b/Database/IOVDbSvc/test/IOVDbFolder_test.cxx index 69e8d6bd13d..bbd4c5206f8 100644 --- a/Database/IOVDbSvc/test/IOVDbFolder_test.cxx +++ b/Database/IOVDbSvc/test/IOVDbFolder_test.cxx @@ -62,7 +62,7 @@ struct IOVDbParserFixture{ MsgStream log; IOVDbParser parser; IOVDbParserFixture():msgSvc("msgSvc","test"), - descriptionString{"/key1<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"}, + descriptionString{"/key1<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"}, log(msgSvc.get(), "IOVDbFolder_test"), parser(descriptionString, log){ } @@ -84,7 +84,7 @@ BOOST_FIXTURE_TEST_SUITE(IOVDbFolderTest , GaudiKernelFixture) BOOST_AUTO_TEST_CASE(PublicMethods){ //preload tests IOVDbConn connection("sqlite://;schema=IOVDbFolderTest.db;dbname=OFLP200", true, parserFixture.log); - IOVDbFolder iovDbFolder(&connection, parserFixture.parser, parserFixture.log, clidSvc.get(),false); + IOVDbFolder iovDbFolder(&connection, parserFixture.parser, parserFixture.log, clidSvc.get(),false,true); BOOST_TEST_CHECKPOINT("After instantiation, but before any loading method call"); BOOST_TEST(iovDbFolder.folderName() == "/key1"); BOOST_TEST(iovDbFolder.key() == "/key1"); diff --git a/Database/IOVDbSvc/test/IOVDbSvcCurl_test.cxx b/Database/IOVDbSvc/test/IOVDbSvcCurl_test.cxx new file mode 100644 index 00000000000..5cbf7db262b --- /dev/null +++ b/Database/IOVDbSvc/test/IOVDbSvcCurl_test.cxx @@ -0,0 +1,40 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +/* + */ +/** + * @file IOVDbSvc/test/IOVDbSvcCurl_test.cxx + * @author Shaun Roe + * @date May, 2019 + * @brief Some tests for IOVDbSvcCurl + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE TEST_IOVDBSVC + + +#include <boost/test/unit_test.hpp> +// + +#include "../src/IOVDbSvcCurl.h" + +using namespace IOVDbNamespace; + +BOOST_AUTO_TEST_SUITE(IOVDbSvcCurlTest) + BOOST_AUTO_TEST_CASE(constructor){ + BOOST_CHECK_NO_THROW(IOVDbSvcCurl("https://home.cern")); + } + BOOST_AUTO_TEST_CASE(getCernHomePage){ + IOVDbSvcCurl myCurlObject("https://home.cern"); + BOOST_CHECK_NO_THROW(myCurlObject.get()); + const auto & cernHome=myCurlObject.get(); + BOOST_CHECK(cernHome.substr(0,15) == "<!DOCTYPE html>"); + } + BOOST_AUTO_TEST_CASE(getNonexistentPage){ + IOVDbSvcCurl myCurlObject("https://hgafsdjafgda"); + BOOST_CHECK_THROW(myCurlObject.get(), CurlException); + } + +BOOST_AUTO_TEST_SUITE_END() diff --git a/Database/IOVDbSvc/test/IOVDbSvc_test.cxx b/Database/IOVDbSvc/test/IOVDbSvc_test.cxx index 6b14fac6610..ba2c04f3a18 100644 --- a/Database/IOVDbSvc/test/IOVDbSvc_test.cxx +++ b/Database/IOVDbSvc/test/IOVDbSvc_test.cxx @@ -75,7 +75,7 @@ int main() cool::FolderSpecification fSpec (cool::FolderVersioning::SINGLE_VERSION, spec, cool::PayloadMode::INLINEPAYLOAD); - std::string desc = "<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"; + std::string desc = "<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"; { cool::IFolderPtr f = coolDb->createFolder ("/key1", fSpec, desc); diff --git a/Database/IOVDbSvc/test/Json2Cool_test.cxx b/Database/IOVDbSvc/test/Json2Cool_test.cxx new file mode 100644 index 00000000000..bc92492955b --- /dev/null +++ b/Database/IOVDbSvc/test/Json2Cool_test.cxx @@ -0,0 +1,113 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ +/* + */ +/** + * @file IOVDbSvc/test/Json2Cool_test.cxx + * @author Shaun Roe + * @date May, 2019 + * @brief Some tests for Json2Cool class in the Boost framework + */ + +#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MAIN +#define BOOST_TEST_MODULE TEST_IOVDBSVC + + +#include <boost/test/unit_test.hpp> + +#include <boost/test/output_test_stream.hpp> + +#include "../src/Json2Cool.h" +#include "../src/BasicFolder.h" + +#include "CoralBase/AttributeList.h" +#include "CoralBase/AttributeListSpecification.h" +#include "CoralBase/Attribute.h" +#include "CoralBase/AttributeSpecification.h" +#include "CoolKernel/StorageType.h" +// +#include "CoolKernel/RecordSpecification.h" +#include "CoolKernel/Record.h" + +#include <istream> +#include <string> +#include <sstream> + +using namespace IOVDbNamespace; +using namespace cool; +const auto pixelJson=R"foo({"node_description" : "<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>", "folder_payloadspec": "stave: Int32, eta: Int32, mag: Float, base: Float, free: Float", "iov" : [0, 4294967295], "data_array" : [{ "100" : [ 0, 0, 0, 0, 0]},{ "200" : [ 1, 0, 0.3, 0, 0]}]})foo"; + + +BOOST_AUTO_TEST_SUITE(Json2CoolTest) + BOOST_AUTO_TEST_CASE(Constructor){ + BasicFolder b; + std::istringstream initializerStream(pixelJson); + BOOST_CHECK_NO_THROW(Json2Cool j(initializerStream,b)); + BOOST_CHECK(b.empty() == false); + } + BOOST_AUTO_TEST_CASE(convertedProperties){ + auto pSpec=new coral::AttributeListSpecification; + pSpec->extend<int>("stave"); + pSpec->extend<int>("eta"); + pSpec->extend<float>("mag"); + pSpec->extend<float>("base"); + pSpec->extend<float>("free"); + coral::AttributeList attrList(*pSpec, true); + attrList[0].setValue(1); + attrList[1].setValue(0); + attrList[2].setValue(0.3f); + attrList[3].setValue(0.f); + attrList[4].setValue(0.f); + BasicFolder b; + std::istringstream initializerStream(pixelJson); + BOOST_CHECK_NO_THROW(Json2Cool j(initializerStream,b)); + BOOST_CHECK(b.getPayload(200) == attrList); + const std::pair<cool::ValidityKey, cool::ValidityKey> refIov(0, 4294967295); + BOOST_CHECK(b.iov() == refIov); + } + + BOOST_AUTO_TEST_CASE(parsePayloadSpec){ + const std::string testSpecString="crate: UChar, ROB: Int32, BCIDOffset: Int16, AName: String255"; + auto referenceSpec = new cool::RecordSpecification(); + referenceSpec->extend("crate", StorageType::UChar); + referenceSpec->extend("ROB", StorageType::Int32); + referenceSpec->extend("BCIDOffset", StorageType::Int16); + referenceSpec->extend("AName", StorageType::String255); + auto returnedSpec = Json2Cool::parsePayloadSpec(testSpecString); + BOOST_CHECK(*(returnedSpec) == *referenceSpec); + } + BOOST_AUTO_TEST_CASE(createAttributeList){ + auto referenceSpec = new cool::RecordSpecification(); + referenceSpec->extend("crate", StorageType::UChar); + referenceSpec->extend("ROB", StorageType::Int32); + referenceSpec->extend("BCIDOffset", StorageType::Int16); + referenceSpec->extend("AName", StorageType::String255); + const std::string jsonValues="[1,2,3,\"purple\"]"; + std::istringstream initializerStream(jsonValues); + nlohmann::json j; + initializerStream >>j; + auto record=Json2Cool::createAttributeList(referenceSpec, j); + cool::Record reference(*referenceSpec); + BOOST_CHECK(record.size() == reference.size()); + // + auto & att0=const_cast<coral::Attribute&>(reference.attributeList()[0]); + unsigned char set0(1); + att0.setValue<unsigned char>(set0); + // + auto & att1=const_cast<coral::Attribute&>(reference.attributeList()[1]); + att1.setValue<int>(2); + // + auto & att2=const_cast<coral::Attribute&>(reference.attributeList()[2]); + short set2(3); + att2.setValue<short>(set2); + // + auto & att3=const_cast<coral::Attribute&>(reference.attributeList()[3]); + att3.setValue<std::string>("purple"); + // + BOOST_CHECK(reference == record); + } + +BOOST_AUTO_TEST_SUITE_END() + diff --git a/Database/IOVDbSvc/test/ReadFromFileMetaData_test.cxx b/Database/IOVDbSvc/test/ReadFromFileMetaData_test.cxx index 17507e9af21..e86970a8a1c 100644 --- a/Database/IOVDbSvc/test/ReadFromFileMetaData_test.cxx +++ b/Database/IOVDbSvc/test/ReadFromFileMetaData_test.cxx @@ -36,7 +36,7 @@ struct IOVMetaDataContainerFixture{ const std::string folderDescription; IOVMetaDataContainer metaDataContainer; IOVMetaDataContainerFixture():folderName{"/key1"}, - folderDescription{"<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"}, + folderDescription{"<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"}, metaDataContainer{folderName, folderDescription}{ //nop } diff --git a/Database/IOVDbSvc/test/TagFunctions_test.cxx b/Database/IOVDbSvc/test/TagFunctions_test.cxx index 536d76f451b..aa261f9410d 100644 --- a/Database/IOVDbSvc/test/TagFunctions_test.cxx +++ b/Database/IOVDbSvc/test/TagFunctions_test.cxx @@ -60,7 +60,7 @@ struct TestFolderFixture{ coolDb = dbSvc.createDatabase("sqlite://;schema=TagFunctionsTest.db;dbname=OFLP200"); spec.extend ("int", cool::StorageType::Int32); cool::FolderSpecification fSpec (cool::FolderVersioning::SINGLE_VERSION,spec,cool::PayloadMode::INLINEPAYLOAD); - std::string desc = "<timeStamp>run-event</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"; + std::string desc = "<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\"71\" clid=\"1238547719\" /></addrHeader><typeName>CondAttrListCollection</typeName>"; { folderPtr = coolDb->createFolder (fixtureFoldername, fSpec, desc); cool::Record payload (folderPtr->payloadSpecification()); -- GitLab