Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-02-19 05:08:16

0001 #ifndef CondTools_RunInfo_OMSAccess_h
0002 #define CondTools_RunInfo_OMSAccess_h
0003 
0004 #include <string>
0005 #include <stdexcept>
0006 #include <boost/property_tree/ptree.hpp>
0007 #include <boost/property_tree/json_parser.hpp>
0008 #include <boost/date_time/posix_time/posix_time.hpp>
0009 #include <memory>
0010 
0011 namespace cond {
0012 
0013   // implementation details for data extraction from json/ data conversion to build query urls
0014   namespace impl {
0015 
0016     static constexpr const char* const OMS_TIME_FMT = "%Y-%m-%dT%H:%M:%SZ";
0017 
0018     template <typename T, T fun(const std::string&)>
0019     inline T from_string_impl(const std::string& attributeValue, T zero) {
0020       T ret = zero;
0021       if (not attributeValue.empty() && attributeValue != "null") {
0022         ret = fun(attributeValue);
0023       }
0024       return ret;
0025     }
0026 
0027     template <typename T>
0028     inline T from_string(const std::string& attributeValue) {
0029       throw std::invalid_argument("");
0030     }
0031 
0032     template <>
0033     inline std::string from_string(const std::string& attributeValue) {
0034       return std::string(attributeValue);
0035     }
0036 
0037     inline float s_to_f(const std::string& val) { return std::stof(val); }
0038     template <>
0039     inline float from_string(const std::string& attributeValue) {
0040       return from_string_impl<float, &s_to_f>(attributeValue, 0.);
0041     }
0042 
0043     inline int s_to_i(const std::string& val) { return std::stoi(val); }
0044     template <>
0045     inline int from_string(const std::string& attributeValue) {
0046       return from_string_impl<int, &s_to_i>(attributeValue, 0);
0047     }
0048 
0049     inline unsigned long s_to_ul(const std::string& val) { return std::stoul(val); }
0050     template <>
0051     inline unsigned short from_string(const std::string& attributeValue) {
0052       unsigned long int_val = from_string_impl<unsigned long, &s_to_ul>(attributeValue, 0);
0053       return (unsigned short)int_val;
0054     }
0055 
0056     inline boost::posix_time::ptime s_to_time(const std::string& val) {
0057       boost::posix_time::time_input_facet* facet = new boost::posix_time::time_input_facet(OMS_TIME_FMT);
0058       std::stringstream ss;
0059       ss.imbue(std::locale(std::locale(), facet));
0060       ss << val;
0061       boost::posix_time::ptime time;
0062       ss >> time;
0063       return time;
0064     }
0065     template <>
0066     inline boost::posix_time::ptime from_string(const std::string& attributeValue) {
0067       return from_string_impl<boost::posix_time::ptime, &s_to_time>(attributeValue, boost::posix_time::ptime());
0068     }
0069 
0070     template <typename V>
0071     inline std::string to_string(const V& value) {
0072       return std::to_string(value);
0073     }
0074     template <typename V>
0075     inline std::string to_string(const V* value) {
0076       return std::to_string(*value);
0077     }
0078     template <>
0079     inline std::string to_string(const std::string& value) {
0080       return std::string(value);
0081     }
0082     template <>
0083     inline std::string to_string(const char* value) {
0084       return std::string(value);
0085     }
0086     template <>
0087     inline std::string to_string(const boost::posix_time::ptime& value) {
0088       boost::posix_time::time_facet* facet = new boost::posix_time::time_facet();
0089       facet->format(OMS_TIME_FMT);
0090       std::stringstream stream;
0091       stream.imbue(std::locale(std::locale::classic(), facet));
0092       stream << value;
0093       return stream.str();
0094     }
0095 
0096   }  // namespace impl
0097 
0098   // reference of a result set row. it does not own/hold data.
0099   class OMSServiceResultRef {
0100   public:
0101     OMSServiceResultRef() = delete;
0102     OMSServiceResultRef(const boost::property_tree::ptree* row);
0103 
0104     // return true if no attribute is available
0105     bool empty();
0106     // typed getter for single param
0107     template <typename T>
0108     inline T get(const std::string& attributeName) {
0109       return impl::from_string<T>(getAttribute(attributeName));
0110     }
0111     // getter for arrays
0112     template <typename primitive>
0113     std::vector<primitive> getArray(const std::string& attributeName) {
0114       std::vector<primitive> ret;
0115       for (auto& item : m_row->get_child(attributeName)) {
0116         ret.push_back(item.second.get_value<primitive>());
0117       }
0118       return ret;
0119     }
0120 
0121   private:
0122     std::string getAttribute(const std::string& attributeName);
0123     const boost::property_tree::ptree* m_row = nullptr;
0124   };
0125 
0126   // iterator object for result
0127   class OMSServiceResultIterator {
0128   public:
0129     OMSServiceResultIterator() = delete;
0130     OMSServiceResultIterator(boost::property_tree::ptree::const_iterator iter);
0131 
0132     OMSServiceResultRef operator*();
0133     OMSServiceResultIterator& operator++();
0134 
0135     bool operator==(const OMSServiceResultIterator& rhs);
0136     bool operator!=(const OMSServiceResultIterator& rhs);
0137 
0138   private:
0139     boost::property_tree::ptree::const_iterator m_iter;
0140   };
0141 
0142   // container wrapping the query result, based on boost property tree
0143   class OMSServiceResult {
0144   public:
0145     OMSServiceResult();
0146     // basic iterators, to enable the C++11 for loop semantics
0147     OMSServiceResultIterator begin() const;
0148     OMSServiceResultIterator end() const;
0149 
0150     // parse json returned from curl, filling the property tree
0151     size_t parseData(const std::string& data);
0152 
0153     // returns the number of top level elements of the tree ( result set "rows" )
0154     size_t size() const;
0155 
0156     // returns size()==0
0157     bool empty() const;
0158 
0159   private:
0160     boost::property_tree::ptree m_root;
0161     boost::property_tree::ptree* m_data;
0162   };
0163 
0164   // Query object
0165   class OMSServiceQuery {
0166   public:
0167     // comparison operator label, used in query urls
0168     static constexpr const char* const NEQ = "NEQ";
0169     static constexpr const char* const EQ = "EQ";
0170     static constexpr const char* const LT = "LT";
0171     static constexpr const char* const GT = "GT";
0172     static constexpr const char* const SNULL = "null";
0173 
0174   public:
0175     OMSServiceQuery() = delete;
0176     OMSServiceQuery(const std::string& baseUrl, const std::string& function);
0177 
0178     // functions to restring query output to specific variables
0179     OMSServiceQuery& addOutputVar(const std::string& varName);
0180     OMSServiceQuery& addOutputVars(const std::initializer_list<const char*>& varNames);
0181 
0182     // generic query filter
0183     template <typename T>
0184     inline OMSServiceQuery& filter(const char* cmp, const std::string& varName, const T& value) {
0185       std::stringstream filter;
0186       if (m_filter.empty()) {
0187         filter << "?";
0188       } else {
0189         filter << m_filter << "&";
0190       }
0191       filter << "filter[" << varName << "][" << cmp << "]=" << impl::to_string(value);
0192       m_filter = filter.str();
0193       return *this;
0194     }
0195     // filters with specific comparison operators
0196     template <typename T>
0197     inline OMSServiceQuery& filterEQ(const std::string& varName, const T& value) {
0198       return filter<T>(EQ, varName, value);
0199     }
0200     template <typename T>
0201     inline OMSServiceQuery& filterNEQ(const std::string& varName, const T& value) {
0202       return filter<T>(NEQ, varName, value);
0203     }
0204     template <typename T>
0205     inline OMSServiceQuery& filterGT(const std::string& varName, const T& value) {
0206       return filter<T>(GT, varName, value);
0207     }
0208     template <typename T>
0209     inline OMSServiceQuery& filterLT(const std::string& varName, const T& value) {
0210       return filter<T>(LT, varName, value);
0211     }
0212     // not null filter
0213     inline OMSServiceQuery& filterNotNull(const std::string& varName) { return filterNEQ(varName, SNULL); }
0214 
0215     // triggers the execution of the query ( calling curl functions )
0216     bool execute();
0217 
0218     // return code from curl
0219     unsigned long status();
0220 
0221     // result from the query. memory allocated for data is owned by the query object itself
0222     OMSServiceResult& result();
0223 
0224     // the url constructed and used for the query
0225     std::string url();
0226 
0227   private:
0228     void addVar(const std::string& varName);
0229 
0230   private:
0231     std::string m_url;
0232     std::string m_filter;
0233     std::string m_varList;
0234     std::unique_ptr<OMSServiceResult> m_result;
0235     unsigned long m_status = 0;
0236   };
0237 
0238   // provides query access to OMS Web services
0239   class OMSService {
0240   public:
0241     OMSService();
0242 
0243     void connect(const std::string& baseUrl);
0244     std::unique_ptr<OMSServiceQuery> query(const std::string& function) const;
0245 
0246   private:
0247     std::string m_baseUrl;
0248   };
0249 }  // namespace cond
0250 
0251 #endif