From 1017d2a648566e41b411bda8c5053cb9f4594ced Mon Sep 17 00:00:00 2001 From: Sarun Nuntaviriyakul <48861591+guyzsarun@users.noreply.github.com> Date: Tue, 8 Aug 2023 14:57:30 +0200 Subject: [PATCH] Feature: CMSJson (#2) * Add json tfc * Update cmake * bump specfile * update gitignore * add tests * add storarge.json --- .gitignore | 1 + CMakeLists.txt | 41 ++++- cmake/FindJsoncpp.cmake | 24 +++ spec/xrootd-cmstfc.spec | 19 +-- src/json/XrdCmsJson.cc | 329 +++++++++++++++++++++++++++++++++++++ src/json/XrdCmsJson.hh | 128 +++++++++++++++ src/{ => xml}/XrdCmsTfc.cc | 0 src/{ => xml}/XrdCmsTfc.hh | 0 tests/storage.json | 84 ++++++++++ tests/test_json.cc | 22 +++ tests/test_xml.cc | 22 +++ 11 files changed, 653 insertions(+), 17 deletions(-) create mode 100644 cmake/FindJsoncpp.cmake create mode 100644 src/json/XrdCmsJson.cc create mode 100644 src/json/XrdCmsJson.hh rename src/{ => xml}/XrdCmsTfc.cc (100%) rename src/{ => xml}/XrdCmsTfc.hh (100%) create mode 100644 tests/storage.json create mode 100644 tests/test_json.cc create mode 100644 tests/test_xml.cc diff --git a/.gitignore b/.gitignore index 93cb9a6..10ea32c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ cmake_install.cmake CMakeFiles CMakeCache.txt Makefile +build/* \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 4d8cf4d..64870fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required( VERSION 2.6 ) +cmake_minimum_required( VERSION 3.1 ) project( xrootd-cmstfc ) set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ) @@ -6,6 +6,7 @@ set( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake ) find_package( Xrootd REQUIRED ) find_package( XercesC REQUIRED ) find_package( Pcre REQUIRED ) +find_package( Jsoncpp REQUIRED ) if( CMAKE_COMPILER_IS_GNUCXX ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror" ) @@ -15,14 +16,26 @@ if( CMAKE_COMPILER_IS_GNUCC ) set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror" ) endif() -include_directories( "${PROJECT_SOURCE_DIR}" "${XROOTD_INCLUDES}" -"${XERCES_INCLUDES}" "${PCRE_INCLUDES}" ) +include_directories( "${PROJECT_SOURCE_DIR}" "${XROOTD_INCLUDES}" "${XERCES_INCLUDES}" "${PCRE_INCLUDES}" "${JSONCPP_INCLUDES}") + +add_library( XrdCmsTfc MODULE src/xml/XrdCmsTfc.cc src/xml/XrdCmsTfc.hh ) +add_library( XrdCmsJson MODULE src/json/XrdCmsJson.cc src/json/XrdCmsJson.hh ) -add_library( XrdCmsTfc MODULE src/XrdCmsTfc.cc src/XrdCmsTfc.hh ) target_link_libraries(XrdCmsTfc ${XROOTD_UTILS} ${XERCES_LIB} ${PCRE_LIB}) +target_link_libraries(XrdCmsJson ${XROOTD_UTILS} ${JSONCPP_LIBRARIES}) + + +if(BUILD_TEST) + add_executable(test_xml.o src/xml/XrdCmsTfc.cc src/xml/XrdCmsTfc.hh tests/test_xml.cc) + target_link_libraries(test_xml.o ${XROOTD_UTILS} ${XERCES_LIB} ${PCRE_LIB}) + + add_executable(test_json.o src/json/XrdCmsJson.cc src/json/XrdCmsJson.hh tests/test_json.cc) + target_link_libraries(test_json.o ${XROOTD_UTILS} ${JSONCPP_LIBRARIES}) + +endif() if (NOT DEFINED CMAKE_INSTALL_LIBDIR) - SET(CMAKE_INSTALL_LIBDIR "lib") + SET(CMAKE_INSTALL_LIBDIR "lib64") endif() install( @@ -30,7 +43,15 @@ install( LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) install( - FILES ${CMAKE_SOURCE_DIR}/src/XrdCmsTfc.hh + TARGETS XrdCmsJson + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ) + +install( + FILES ${CMAKE_SOURCE_DIR}/src/xml/XrdCmsTfc.hh + DESTINATION include ) + +install( + FILES ${CMAKE_SOURCE_DIR}/src/json/XrdCmsJson.hh DESTINATION include ) set_target_properties( @@ -40,3 +61,11 @@ set_target_properties( SOVERSION "0" LINK_INTERFACE_LIBRARIES "" ) +set_target_properties( + XrdCmsJson + PROPERTIES + VERSION "0.0.1" + SOVERSION "0" + LINK_INTERFACE_LIBRARIES "" ) + + diff --git a/cmake/FindJsoncpp.cmake b/cmake/FindJsoncpp.cmake new file mode 100644 index 0000000..49447ca --- /dev/null +++ b/cmake/FindJsoncpp.cmake @@ -0,0 +1,24 @@ + +FIND_PATH(JSONCPP_INCLUDES json.h + HINTS + ${JSONCPP_DIR} + $ENV{JSONCPP_DIR} + /usr + /opt/jsoncpp/ + PATH_SUFFIXES include/json + PATHS /opt/json +) + + +FIND_LIBRARY(JSONCPP_LIBRARIES jsoncpp + HINTS + ${JSONCPP_DIR} + $ENV{JSONCPP_DIR} + /usr + /opt/jsoncpp/ + PATH_SUFFIXES lib +) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(Jsoncpp DEFAULT_MSG JSONCPP_LIBRARIES JSONCPP_INCLUDES) + diff --git a/spec/xrootd-cmstfc.spec b/spec/xrootd-cmstfc.spec index c287dac..dc79a02 100644 --- a/spec/xrootd-cmstfc.spec +++ b/spec/xrootd-cmstfc.spec @@ -1,11 +1,11 @@ Name: xrootd-cmstfc -Version: 1.5.2 -Release: 7%{?dist} +Version: 2.0.0 +Release: 1%{?dist} Summary: CMS TFC plugin for xrootd Group: System Environment/Daemons License: BSD -URL: https://github.com/bbockelm/xrootd-cmstfc +URL: https://github.com/CMSCompOps/xrootd-cmstfc # Generated from: # git-archive master | gzip -7 > ~/rpmbuild/SOURCES/xrootd-lcmaps.tar.gz Source0: %{name}.tar.gz @@ -25,15 +25,9 @@ BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) BuildRequires: xrootd-devel >= 1:%{xrootd_current_major}.0.0-1 BuildRequires: xrootd-devel < 1:%{xrootd_next_major}.0.0-1 -BuildRequires: pcre-devel +BuildRequires: cmake pcre-devel xerces-c-devel jsoncpp-devel >= 1.9.4 -BuildRequires: xerces-c-devel - -BuildRequires: cmake -#BuildRequires: xrootd-compat-libs - -Requires: /usr/bin/xrootd pcre xerces-c -#Requires: xrootd-compat-libs +Requires: /usr/bin/xrootd pcre xerces-c jsoncpp >= 1.9.4 #%if 0%%{?rhel} < 7 #Requires: xrootd4 >= 1:4.1.0 @@ -71,12 +65,15 @@ rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) %{_libdir}/libXrdCmsTfc.so +%{_libdir}/libXrdCmsJson.so %if 0%{?rhel} < 8 %{_libdir}/libXrdCmsTfc.so.* +%{_libdir}/libXrdCmsJson.so.* %endif %files devel %defattr(-,root,root,-) %{_includedir}/XrdCmsTfc.hh +%{_includedir}/XrdCmsJson.hh %changelog * Fri Jul 28 2023 Mátyás Selmeci - 1.5.2-7 diff --git a/src/json/XrdCmsJson.cc b/src/json/XrdCmsJson.cc new file mode 100644 index 0000000..d7f6aa7 --- /dev/null +++ b/src/json/XrdCmsJson.cc @@ -0,0 +1,329 @@ +#include "XrdCmsJson.hh" +#include "XrdSys/XrdSysError.hh" + +#include +#include +#include +#include +#include +#include +#include + +#define BUFFSIZE 1024 +#define OVECCOUNT 30 + +using namespace XrdCmsJson; + +extern "C" +{ + XrdOucName2Name *XrdOucgetName2Name(XrdSysError *eDest, const char *confg, + const char *parms, const char *lroot, const char *rroot) + { + eDest->Say("CERN CMS Facilities and Services Site Support"); + + eDest->Say("Params: ", parms); + + PathTranslation *myTranslation = new PathTranslation(eDest, parms); + return myTranslation; + } +} + +XrdCmsJson::PathTranslation::PathTranslation(XrdSysError *lp, const char * url_translation) : XrdOucName2Name(), m_destination("any") +{ + m_url = url_translation; + eDest = lp; + parse(); + //testCMSNamespaces(); + +} + +int XrdCmsJson::PathTranslation::testCMSNamespaces () +{ + // Test all "required" paths so site admins can see if there is any wrong configuration + for(const auto lfn_area : CMS_ALL_NAMESPACES) + { + int blen = 4096; + char* buff = (char*) malloc(blen); + const char* n_lfn = lfn_area.c_str(); + this->lfn2pfn(n_lfn, buff, blen); + } + return 0; +} + +int XrdCmsJson::PathTranslation::appendRuleJson (std::string lfn, std::string pfn, Json::Value *m_rules) +{ + Json::Value rule; + rule["lfn"] = lfn; + rule["pfn"] = pfn; + m_rules->append(rule); + return 0; +} + +Json::Value XrdCmsJson::PathTranslation::buildRule (std::string lfn, std::string pfn, std::string chain) +{ + Json::Value rule; + rule["lfn"] = lfn; + rule["pfn"] = pfn; + if (!chain.empty()) + { + rule["chain"] = chain; + } + return rule; +} + +std::string XrdCmsJson::PathTranslation::resolveChain(Json::Value rule_root, Json::Value rule_chain) +{ + //"davs://my.domain.ch:2880/$1" + std::string pfn = rule_root["pfn"].asString(); + //"/+(.*)" + std::regex lfn_expr (rule_root["lfn"].asString()); + // "/pnfs/$1" + std::string pfn_chain = rule_chain["pfn"].asString(); + // "davs://my.domain.ch:2880/pnfs/$1" + std::string pfn_resolved = regex_replace(pfn_chain, lfn_expr, pfn); + return pfn_resolved; +} + +Json::Value XrdCmsJson::PathTranslation::parseChain(Json::Value rule_root, Json::Value rule_chain) +{ + std::string pfn_resolved = resolveChain(rule_root, rule_chain); + Json::Value r_rule_chained = buildRule(rule_chain["lfn"].asString(), pfn_resolved, rule_chain["chain"].asString()); + return r_rule_chained; + +} + +int XrdCmsJson::PathTranslation::verifyFormatRule(Json::Value rule) +{ + if (rule["lfn"].empty() or rule["pfn"].empty()) + { + eDest->Say("Rule doesn't have PFN or LFN "); + return XRDCMSJSON_ERR_RULE; + } + return XRDCMSJSON_OK; +} + +Json::Value XrdCmsJson::PathTranslation::simplifyProtocol(Json::Value protocol) +{ + // If the upper rule includes the lower ones, they will never be used --> trigger alarm + if (!protocol["rules"].empty()) + { + int num_rules = protocol["rules"].size(); + for( int idx_rule = 0; idx_rule < num_rules; idx_rule++) + { + for (int idx_subrule = idx_rule+1; idx_subrule < num_rules; idx_subrule++) + { + std::string lfn_nextrule = protocol["rules"][idx_subrule]["lfn"].asString(); + std::regex rgx_lfn_nextrule(lfn_nextrule); + + //std::cout << " pro " << protocol["rules"][idx_rule]["lfn"].asString() << "RGX " << lfn_nextrule.c_str() << std::endl; + + //if (regex_match(protocol["rules"][idx_rule]["lfn"].asString(), rgx_lfn_nextrule)); + //{ + // std::cout << "UNUSED RULE INDEX " << idx_subrule << std::endl; + //} + } + } + + } + return protocol; +} + + +int XrdCmsJson::PathTranslation::verifyFormatProtocol(Json::Value prot) +{ + //std::cout << "Protocol " << m_protocol << " with access: " << m_json[m_protocol]["access"].asString() << std::endl; + + if (prot["prefix"].empty() and m_json[m_protocol]["rules"].empty()) + { + eDest->Say("No rule nor prefix specified"); + return XRDCMSJSON_ERR_PROTOCOL; + } + + return XRDCMSJSON_OK; +} + +Json::Value XrdCmsJson::PathTranslation::parsePrefix(std::string pfn) +{ + std::string prefix_pfn = pfn + "$1"; + std::string empty_str; + Json::Value rule_built = buildRule("(/.*)", prefix_pfn , empty_str); + return rule_built; +} + +std::string XrdCmsJson::PathTranslation::matchLFN(Json::Value rule, std::string target_lfn) +{ + std::string pfn; + std::regex lfn_expr(rule["lfn"].asString() == "(.*)" ? "(.+)" :rule["lfn"].asString()); + if (regex_match (target_lfn.c_str(),lfn_expr)) + { + pfn = rule["pfn"].asString(); + pfn = regex_replace(target_lfn.c_str(), lfn_expr, pfn); + } + return pfn; +} + + +Json::Value XrdCmsJson::PathTranslation::parseProtocol(Json::Value rules, std::string lfn) +{ + for( const auto& rule : rules) + { + Json::Value new_rule; + std::string pfn_init = matchLFN(rule, lfn); + // the rule is chained and the lfn can be resolved (upstream) -> go deeper + if (!rule["chain"].empty() && !pfn_init.empty()) + { + std::string name_chain = rule["chain"].asString(); + new_rule = parseProtocol(m_json[name_chain]["rules"], lfn); + } + if (!new_rule["pfn_chain"].empty()) + { + lfn = new_rule["pfn_chain"].asString(); + } + + std::string pfn_result = matchLFN(rule, lfn); + + //std::cout << rule << "\n" << new_rule << " " << lfn << "\n" << new_rule["pfn_chain"] << "<->" << pfn_result << std::endl; + + if (!new_rule["pfn_chain"].empty() and pfn_result.empty()){ + Json::Value rule_with_chain = rule; + rule_with_chain["pfn_chain"] = rule["pfn"]; + return rule_with_chain; + } + + if (!pfn_result.empty()) + { + Json::Value rule_with_chain = rule; + rule_with_chain["pfn_chain"] = pfn_result; + return rule_with_chain; + } + } + Json::Value exit_value; + return exit_value; + +} + + +int XrdCmsJson::PathTranslation::parseUrl() +{ + eDest->Say("Conecting to the catalog ", m_url.c_str()); + m_filename = m_url.substr(5, m_url.find("?")-5); + m_protocol = m_url.substr(m_url.find("protocol=")+9 ,m_url.length()); + m_volume = m_url.substr(m_url.find("volume=")+7 ,m_url.find("&protocol=")-(m_url.find("volume=")+7) ); + + return XRDCMSJSON_OK; +} + +int XrdCmsJson::PathTranslation::verifyFormatURL() +{ + + if (m_filename.empty() or m_protocol.empty()) + { + eDest->Say("PathTranslation::connect: Malformed url for file catalog configuration"); + return XRDCMSJSON_ERR_URL; + } + return XRDCMSJSON_OK; +} + +// Reformat json to use protocol name as key +int XrdCmsJson::PathTranslation::reformatJson(Json::Value original_storage) +{ + for (const auto& volume_json : original_storage) + { + if (volume_json["volume"] == m_volume){ + + for(const auto& prot : volume_json["protocols"]) + { + std::string protocol_name = prot["protocol"].asString(); + m_json[protocol_name] = prot; + } + return XRDCMSJSON_OK; + } + } + eDest->Say("None Volume has matched with the existing ones"); + return XRDCMSJSON_ERR_JSON; +} + + +int XrdCmsJson::PathTranslation::parseStorageJson() +{ + // Load json + std::ifstream file(m_filename); + Json::Value storageJson; + Json::CharReaderBuilder jsonReader; + std::string errs; + Json::parseFromStream(jsonReader, file, &storageJson, &errs); + reformatJson(storageJson); + return XRDCMSJSON_OK; +} + +int XrdCmsJson::PathTranslation::verifyFormatJson() +{ + if (m_json.empty()) + { + eDest->Say("The storage.json is empty or the path is incorrect. Information has not ben loaded"); + return XRDCMSJSON_ERR_JSON; + } + + return XRDCMSJSON_OK; +} + +// Parse and verify protocol data and store clean information inside m_rules +int XrdCmsJson::PathTranslation::parse() +{ + parseUrl(); + verifyFormatURL(); + parseStorageJson(); + verifyFormatJson(); + verifyFormatProtocol(m_json[m_protocol]); + + // If it is a prefix, we transform it to a rule format + if (!m_json[m_protocol]["prefix"].empty()) + { + Json::Value rule_pfx = parsePrefix(m_json[m_protocol]["prefix"].asString()); + m_rules.append(rule_pfx); + } else + { + m_rules = m_json[m_protocol]["rules"]; + } + + //std::cout << "active rules " << m_rules << std::endl; + return XRDCMSJSON_OK; +} + +int XrdCmsJson::PathTranslation::lfn2pfn(const char *lfn, char *buff, int blen) +{ + std::string target_lfn = lfn; + //eDest->Say("LFN to translate: ", target_lfn.c_str()); + //std::cout << "m_rules" << m_rules <Say("No lfn2pfn mapping for: ", lfn); + strncpy(buff,lfn,blen); + return XRDCMSJSON_OK; +} + +int XrdCmsJson::PathTranslation::pfn2lfn(const char *pfn, char *buff, int blen) +{ + return XRDCMSJSON_OK; +} + + +int XrdCmsJson::PathTranslation::lfn2rfn(const char *lfn, char *buff, int blen) +{ + return lfn2pfn(lfn, buff, blen); +} \ No newline at end of file diff --git a/src/json/XrdCmsJson.hh b/src/json/XrdCmsJson.hh new file mode 100644 index 0000000..dd40386 --- /dev/null +++ b/src/json/XrdCmsJson.hh @@ -0,0 +1,128 @@ +#ifndef PATHTRANSLATION_H +#define PATHTRANSLATION_H + +#include "XrdOuc/XrdOucName2Name.hh" +#include "XrdSys/XrdSysError.hh" +#include +#include +#include + +namespace XrdCmsJson +{ +/** + * @class PathTranslation + * This class is the concrete implementation of the + * CMS Path Translation as implemented by 4Quarks + * The adoptation was then done for Xrd to be a Name2Name module. + * @Author: 4Quarks + */ + +#define XRDCMSJSON_OK 0 +#define XRDCMSJSON_ERR_DATAMISSING 1 //info is missing +#define XRDCMSJSON_ERR_FORMAT 2 // info is incorrect +#define XRDCMSJSON_ERR_URL 3 +#define XRDCMSJSON_ERR_JSON 4 +#define XRDCMSJSON_ERR_PROTOCOL 5 +#define XRDCMSJSON_ERR_RULE 6 + + +class PathTranslation : public XrdOucName2Name +{ +public: + PathTranslation (XrdSysError *lp, const char * url_translation); + + virtual ~PathTranslation (){}; + + int testCMSNamespaces(); + + int lfn2pfn(const char *lfn, char *buff, int blen); + + int pfn2lfn(const char *pfn, char *buff, int blen); + + int lfn2rfn(const char *lfn, char *buff, int blen); + + int appendRuleJson(std::string lfn, std::string pfn, Json::Value *all_rules); + + std::string resolveChain(Json::Value rule_chain, Json::Value rule_defined); + + Json::Value getStorageJson(); + + int reformatJson(Json::Value original_storage); + + int parse(); + + int parseUrl(); + + int parseStorageJson(); + + int verifyFormatJson(); + + int verifyFormatURL(); + + int verifyFormatProtocol(Json::Value prot); + + Json::Value simplifyProtocol(Json::Value prot); + + Json::Value parseProtocol(Json::Value protocol, std::string lfn); + + std::string matchLFN(Json::Value rule, std::string target_lfn); + + int verifyFormatRule(Json::Value rule); + + Json ::Value parsePrefix(std::string pfn); + + Json::Value parseChain(Json::Value rule_root, Json::Value rule_chain); + + Json::Value getMatchRule(Json::Value rule_root); + + Json::Value buildRule (std::string lfn, std::string pfn, std::string chain); + +private: + + const std::string CMS_NAMESPACE = "/store/.*"; + const std::string CMS_ALL_NAMESPACES[24] = { + "/store/data/", + "/store/hidata/", + "/store/mc/", + "/store/himc/", + "/store/relval/", + "/store/hirelval/", + "/store/express/", + "/store/results/", + "/store/unmerged/", + "/store/local/" + "/store/backfill/1/", + "/store/backfill/2/", + "/store/generator/", + "/store/mc/SAM/", + "/store/mc/HC/", + "/store/temp/", + "/store/temp/user/", + "/store/test/", + "/store/user/", + "/store/user/rucio/", + "/store/group/", + "/store/group/rucio/", + "/store/test/xrootd/", + "/store/test/loadtest/" + }; + + std::string m_filename; + std::string m_url; + std::string m_volume; + std::string m_protocol; + std::string m_destination; + Json::Value m_rules; + Json::Value m_json; + + XrdSysError *eDest; +}; + +} + +extern "C" +{ +XrdOucName2Name *XrdOucgetName2Name(XrdOucgetName2NameArgs); +} + +#endif diff --git a/src/XrdCmsTfc.cc b/src/xml/XrdCmsTfc.cc similarity index 100% rename from src/XrdCmsTfc.cc rename to src/xml/XrdCmsTfc.cc diff --git a/src/XrdCmsTfc.hh b/src/xml/XrdCmsTfc.hh similarity index 100% rename from src/XrdCmsTfc.hh rename to src/xml/XrdCmsTfc.hh diff --git a/tests/storage.json b/tests/storage.json new file mode 100644 index 0000000..8b2814d --- /dev/null +++ b/tests/storage.json @@ -0,0 +1,84 @@ +[ + { "site": "T0_CH_CERN", + "volume": "TEST_JSON", + "protocols": [ + { + "protocol": "root", + "access": "virtual", + "rules": [ + { + "lfn" : "/store/temp/(.*)", + "pfn": "/store/$1", + "prefix":"root://cern-vm//cms" + } + ] + }, + { + "protocol": "prefix", + "access": "virtual", + "comment": "path translations for CMS xrootd module", + "prefix": "root://cern-vm//cms" + } + ] + }, + { + "site": "T2_CH_CERN", + "volume": "CMSSST_TEST", + "protocols": [ + { + "protocol": "first", + "access": "virtual", + "rules": [ + { + "lfn": "/+other/(.*)", + "pfn": "/store/other/first/$1/trailer" + }, + { + "lfn": "/+store/(.*)", + "pfn": "/store/first/$1/trailer" + }, + { + "lfn": "/*store/(.*)", + "pfn": "never/first/$1/trailer" + } + ] + }, + { + "protocol": "second", + "access": "virtual", + "rules": [ + { + "lfn": "/+test/(.*)", + "pfn": "//test/$1" + }, + { + "chain": "first", + "lfn": "/+.*/mc/(.*)", + "pfn": "//store/nomc/$1" + }, + { + "chain": "first", + "lfn": "(.*)/mc/(.*)", + "pfn": "/$1/xmc/$2" + }, + { + "chain": "first", + "lfn": "(.*)", + "pfn": "/$1" + } + ] + }, + { + "protocol": "root", + "access": "virtual", + "rules": [ + { + "chain": "second", + "lfn": "(.*)", + "pfn": "root://host.domain/aaa/bbb$1" + } + ] + } + ] + } +] \ No newline at end of file diff --git a/tests/test_json.cc b/tests/test_json.cc new file mode 100644 index 0000000..fc53dd9 --- /dev/null +++ b/tests/test_json.cc @@ -0,0 +1,22 @@ +#include +#include +#include "src/json/XrdCmsJson.hh" +#include "XrdSys/XrdSysError.hh" +#include "XrdSys/XrdSysLogger.hh" + + +int main (int, const char** argv) +{ + const char* lfn = argv[1]; + const char *rf = argv[2]; + + int blen = 4096; + char* buff = (char*) malloc(blen); + XrdSysLogger myLogger; + XrdSysError eDest(&myLogger, "tfc_"); + eDest.Say("TFC Module"); + XrdCmsJson::PathTranslation *cmsJson = new XrdCmsJson::PathTranslation (&eDest, rf); + cmsJson->lfn2pfn(lfn, buff, blen); + std::cout << buff << std::endl; + return 0; +} diff --git a/tests/test_xml.cc b/tests/test_xml.cc new file mode 100644 index 0000000..46934e6 --- /dev/null +++ b/tests/test_xml.cc @@ -0,0 +1,22 @@ +#include +#include +#include "src/xml/XrdCmsTfc.hh" +#include "XrdSys/XrdSysError.hh" +#include "XrdSys/XrdSysLogger.hh" + + +int main (int, const char** argv) +{ + const char* lfn = argv[1]; + const char *rf = argv[2]; + + int blen = 4096; + char* buff = (char*) malloc(blen); + XrdSysLogger myLogger; + XrdSysError eDest(&myLogger, "tfc_"); + eDest.Say("TFC Module"); + XrdCmsTfc::TrivialFileCatalog tfc(&eDest, rf); + tfc.lfn2pfn(lfn, buff, blen); + std::cout << buff << std::endl; + return 0; +} \ No newline at end of file