diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f3d0b5a2834d8190a62ac1b73fb327b4430c456..11f6b0265082e786a478a560a336463549647998 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,9 +150,12 @@ ELSE(DEFINED PackageOnly) add_subdirectory(scheduler) add_subdirectory(tapeserver) add_subdirectory(XRootdSSiRmcd) + + add_subdirectory(statistics) add_subdirectory(continuousintegration/orchestration/tests) + #Generate version information configure_file(${PROJECT_SOURCE_DIR}/version.hpp.in ${CMAKE_BINARY_DIR}/version.h) diff --git a/catalogue/CMakeLists.txt b/catalogue/CMakeLists.txt index d928a5d174658176c86b5849e6bee87b362f82bd..186e23f91d202b5afdec26516eb925ee84ff6c0d 100644 --- a/catalogue/CMakeLists.txt +++ b/catalogue/CMakeLists.txt @@ -289,7 +289,7 @@ set_property(TARGET cta-catalogue-admin-user-create APPEND PROPERTY INSTALL_RPAT install(TARGETS cta-catalogue-admin-user-create DESTINATION /usr/bin) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-catalogue-admin-user-create.1cta DESTINATION /usr/share/man/man1) -add_executable(cta-catalogue-schema-verify +set (SCHEMA_CHECKER_LIB_SRC_FILES SQLiteSchemaInserter.cpp SchemaSqlStatementsReader.cpp SchemaComparer.cpp @@ -298,16 +298,22 @@ add_executable(cta-catalogue-schema-verify SchemaComparerResult.cpp SchemaChecker.cpp CatalogueMetadataGetter.cpp - VerifySchemaCmd.cpp - VerifySchemaCmdLineArgs.cpp - VerifySchemaCmdMain.cpp CatalogueSchema.cpp OracleCatalogueSchema.cpp SqliteCatalogueSchema.cpp PostgresCatalogueSchema.cpp - MysqlCatalogueSchema.cpp) + MysqlCatalogueSchema.cpp +) + +add_library (ctaschemachecker SHARED + ${SCHEMA_CHECKER_LIB_SRC_FILES}) + +add_executable(cta-catalogue-schema-verify + VerifySchemaCmd.cpp + VerifySchemaCmdLineArgs.cpp + VerifySchemaCmdMain.cpp) -target_link_libraries(cta-catalogue-schema-verify ctacatalogue) +target_link_libraries(cta-catalogue-schema-verify ctacatalogue ctaschemachecker) set_property(TARGET cta-catalogue-schema-verify APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH}) set_property(TARGET cta-catalogue-schema-verify APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) diff --git a/catalogue/SQLiteSchemaComparer.cpp b/catalogue/SQLiteSchemaComparer.cpp index 19047413c5d5664a0b4a51d736a50739e696f7aa..8d446750cbd9c6bf0466b2a594e9a1e5485fadbd 100644 --- a/catalogue/SQLiteSchemaComparer.cpp +++ b/catalogue/SQLiteSchemaComparer.cpp @@ -59,6 +59,15 @@ SchemaComparerResult SQLiteSchemaComparer::compareTables(){ return res; } +SchemaComparerResult SQLiteSchemaComparer::compareTablesInList(const std::list<std::string> tableNamesToCompare){ + insertSchemaInSQLite(); + std::list<std::string> catalogueTables = m_catalogueMetadataGetter.getTableNames(); + std::list<std::string> schemaTables = m_schemaMetadataGetter->getTableNames(); + SchemaComparerResult res = compareTables(catalogueTables,schemaTables); + //TODO use the list of table names to compare + return res; +} + void SQLiteSchemaComparer::insertSchemaInSQLite() { if(!m_isSchemaInserted){ if(m_schemaSqlStatementsReader != nullptr){ diff --git a/catalogue/SQLiteSchemaComparer.hpp b/catalogue/SQLiteSchemaComparer.hpp index d26da7e1ee0ebdf04fc4318c6fdd6f5d01af5867..b6c1b48b7ec1198259215a56d852df2868f9d420 100644 --- a/catalogue/SQLiteSchemaComparer.hpp +++ b/catalogue/SQLiteSchemaComparer.hpp @@ -40,7 +40,8 @@ public: SchemaComparerResult compareAll() override; SchemaComparerResult compareIndexes() override; SchemaComparerResult compareTables() override; - + SchemaComparerResult compareTablesInList(const std::list<std::string> tableNamesToCompare) override; + virtual ~SQLiteSchemaComparer(); private: diff --git a/catalogue/SchemaChecker.cpp b/catalogue/SchemaChecker.cpp index 8f9443c0ff8789a60e48db90b77dffab7b6bd1e0..0ae985e9bd2a6ddeced282e8af9ebf3a7c7c1b01 100644 --- a/catalogue/SchemaChecker.cpp +++ b/catalogue/SchemaChecker.cpp @@ -29,17 +29,6 @@ SchemaChecker::SchemaChecker(rdbms::Login::DbType dbType,cta::rdbms::Conn &conn) SchemaChecker::~SchemaChecker() { } -void SchemaChecker::useSQLiteSchemaComparer(const cta::optional<std::string> allSchemasVersionsDirectory){ - m_schemaComparer.reset(new SQLiteSchemaComparer(*m_catalogueMetadataGetter)); - std::unique_ptr<SchemaSqlStatementsReader> schemaSqlStatementsReader; - if(allSchemasVersionsDirectory){ - schemaSqlStatementsReader.reset(new DirectoryVersionsSqlStatementsReader(m_dbType,m_catalogueMetadataGetter->getCatalogueVersion().getSchemaVersion<std::string>(),allSchemasVersionsDirectory.value())); - } else { - schemaSqlStatementsReader.reset(new MapSqlStatementsReader(m_dbType,m_catalogueMetadataGetter->getCatalogueVersion().getSchemaVersion<std::string>())); - } - m_schemaComparer->setSchemaSqlStatementsReader(std::move(schemaSqlStatementsReader)); -} - SchemaChecker::Status SchemaChecker::compareSchema(){ if(m_schemaComparer == nullptr){ throw cta::exception::Exception("No schema comparer used. Please specify the schema comparer by using the methods useXXXXSchemaComparer()"); @@ -81,4 +70,40 @@ void SchemaChecker::checkSchemaNotUpgrading(){ } } +SchemaChecker::Builder::Builder(cta::rdbms::Login::DbType dbType, cta::rdbms::Conn& conn):m_dbType(dbType),m_catalogueConn(conn){ + m_catalogueMetadataGetter.reset(CatalogueMetadataGetterFactory::create(m_dbType,m_catalogueConn)); +} + +SchemaChecker::Builder & SchemaChecker::Builder::useSQLiteSchemaComparer(){ + m_schemaComparer.reset(new SQLiteSchemaComparer(*m_catalogueMetadataGetter)); + return *this; +} + +SchemaChecker::Builder& SchemaChecker::Builder::useDirectorySchemaReader(const std::string& allSchemasVersionsDirectory) { + m_schemaSqlStatementsReader.reset(new DirectoryVersionsSqlStatementsReader(m_dbType,m_catalogueMetadataGetter->getCatalogueVersion().getSchemaVersion<std::string>(),allSchemasVersionsDirectory)); + return *this; +} + +SchemaChecker::Builder& SchemaChecker::Builder::useMapStatementsReader() { + m_schemaSqlStatementsReader.reset(new MapSqlStatementsReader(m_dbType,m_catalogueMetadataGetter->getCatalogueVersion().getSchemaVersion<std::string>())); + return *this; +} + +SchemaChecker::Builder& SchemaChecker::Builder::useStringStatementsReader() { + m_schemaSqlStatementsReader.reset(new StringSqlStatementsReader()); + return *this; +} + +std::unique_ptr<SchemaChecker> SchemaChecker::Builder::build() { + std::unique_ptr<SchemaChecker> schemaChecker(new SchemaChecker(m_dbType,m_catalogueConn)); + if(m_schemaComparer != nullptr){ + schemaChecker->m_schemaComparer = std::move(m_schemaComparer); + schemaChecker->m_schemaComparer->setSchemaSqlStatementsReader(std::move(m_schemaSqlStatementsReader)); + return std::move(schemaChecker); + } + throw cta::exception::Exception("SchemaChecker::Builder::build(), a SchemaComparer should be set using the useXXXXSchemaComparer() method"); +} + + + }} \ No newline at end of file diff --git a/catalogue/SchemaChecker.hpp b/catalogue/SchemaChecker.hpp index 533e91c8aeee7a2bb6eea4f2b4d38603e31e4e0a..90a62ff58d6cc40d8187648e4a070aae41358475 100644 --- a/catalogue/SchemaChecker.hpp +++ b/catalogue/SchemaChecker.hpp @@ -45,25 +45,11 @@ public: OK, FAILURE }; - /** - * Constructor of the SchemaChecker class - * @param dbType the type of the database to check against - * @param conn the connection of the database to check - */ - SchemaChecker(rdbms::Login::DbType dbType,cta::rdbms::Conn &conn); + /** * Destructor */ virtual ~SchemaChecker(); - /** - * Set the SQLiteSchemaComparer in order to run the schema comparison. - * The SQLiteSchemaComparer creates a InMemory SQLite database with the - * statements defined in the allSchemasDirectoryPath and will compare what is in SQLite with - * what is in the catalogue database. - * - * @param allSchemaVersionsDirectoryPath the schema sql statement reader used to get the schema - */ - void useSQLiteSchemaComparer(cta::optional<std::string> allSchemaVersionsDirectoryPath); /** * Compare the schema by using a SchemaComparer * @throws Exception if no SchemaComparer has been set. @@ -81,7 +67,30 @@ public: */ void checkSchemaNotUpgrading(); + class Builder { + public: + Builder(cta::rdbms::Login::DbType dbType, cta::rdbms::Conn &conn); + Builder & useSQLiteSchemaComparer(); + Builder & useDirectorySchemaReader(const std::string &allSchemasVersionsDirectory); + Builder & useMapStatementsReader(); + Builder & useStringStatementsReader(); + std::unique_ptr<SchemaChecker> build(); + private: + cta::rdbms::Login::DbType m_dbType; + cta::rdbms::Conn &m_catalogueConn; + std::unique_ptr<SchemaComparer> m_schemaComparer; + std::unique_ptr<CatalogueMetadataGetter> m_catalogueMetadataGetter; + std::unique_ptr<SchemaSqlStatementsReader> m_schemaSqlStatementsReader; + }; + private: + /** + * Constructor of the SchemaChecker class + * @param dbType the type of the database to check against + * @param conn the connection of the database to check + */ + SchemaChecker(rdbms::Login::DbType dbType,cta::rdbms::Conn &conn); + /** * Catalogue-to-check database type */ diff --git a/catalogue/SchemaComparer.hpp b/catalogue/SchemaComparer.hpp index e607ded258554223e1177b77a02e9126e062e761..c3ad92b0ceb85bdbb31c1f88d6ad141f6daf56da 100644 --- a/catalogue/SchemaComparer.hpp +++ b/catalogue/SchemaComparer.hpp @@ -62,6 +62,13 @@ public: * @return a SchemaComparerResult that will contain the differences if there are some */ virtual SchemaComparerResult compareIndexes() = 0; + + /** + * Compare only the tables in the list given in parameter + * @param tableNamesToCompare the tables to compare between the Schema and the database + * @return a SchemaComparerResult that will contain the differences if there are some + */ + virtual SchemaComparerResult compareTablesInList(const std::list<std::string> tableNamesToCompare) = 0; /** * Sets the way the schema sql statements will be read to do the schemas comparison diff --git a/catalogue/SchemaSqlStatementsReader.cpp b/catalogue/SchemaSqlStatementsReader.cpp index 1c37a57e44f5e7e044953d8bf3a46d5809726765..ca0ee3044d6c47f144aabec26c6755d6f96190d7 100644 --- a/catalogue/SchemaSqlStatementsReader.cpp +++ b/catalogue/SchemaSqlStatementsReader.cpp @@ -34,6 +34,8 @@ namespace cta{ namespace catalogue{ ////////////////////////////////////////////////////////////////// // SchemaSqlStatementsReader ////////////////////////////////////////////////////////////////// +SchemaSqlStatementsReader::SchemaSqlStatementsReader(){} + SchemaSqlStatementsReader::SchemaSqlStatementsReader(const cta::rdbms::Login::DbType dbType):m_dbType(dbType) { } @@ -170,5 +172,15 @@ std::list<std::string> MapSqlStatementsReader::getStatements(){ } } +////////////////////////////////////////////////////////////////// +// StringSqlStatementsReader +////////////////////////////////////////////////////////////////// +StringSqlStatementsReader::StringSqlStatementsReader():SchemaSqlStatementsReader(){} + +//TODO : Refactor +std::list<std::string> StringSqlStatementsReader::getStatements(){ + return std::list<std::string>(); +} + }} diff --git a/catalogue/SchemaSqlStatementsReader.hpp b/catalogue/SchemaSqlStatementsReader.hpp index 07fd04e99e82750a15deed3043d143a49605b787..08b4ea54fcce786dcb805ac4c5a3a10da56ae271 100644 --- a/catalogue/SchemaSqlStatementsReader.hpp +++ b/catalogue/SchemaSqlStatementsReader.hpp @@ -24,6 +24,7 @@ namespace cta{ namespace catalogue { class SchemaSqlStatementsReader { public: + SchemaSqlStatementsReader(); SchemaSqlStatementsReader(const cta::rdbms::Login::DbType dbType); SchemaSqlStatementsReader(const SchemaSqlStatementsReader& orig); virtual ~SchemaSqlStatementsReader(); @@ -83,4 +84,10 @@ private: std::string m_catalogueVersion; }; +class StringSqlStatementsReader: public SchemaSqlStatementsReader{ +public: + StringSqlStatementsReader(); + virtual std::list<std::string> getStatements(); +}; + }} \ No newline at end of file diff --git a/catalogue/VerifySchemaCmd.cpp b/catalogue/VerifySchemaCmd.cpp index 79c3b54052da264a150c3a97866f87b8a59b1337..a5c1419c1df9da4f8aacd66c785e8cb603ef068c 100644 --- a/catalogue/VerifySchemaCmd.cpp +++ b/catalogue/VerifySchemaCmd.cpp @@ -74,12 +74,15 @@ int VerifySchemaCmd::exceptionThrowingMain(const int argc, char *const *const ar return 1; } - cta::catalogue::SchemaChecker schemaChecker(login.dbType,conn); - cta::optional<std::string> allSchemasDirectoryPathOpt; - schemaChecker.useSQLiteSchemaComparer(allSchemasDirectoryPathOpt); - SchemaChecker::Status comparisonStatus = schemaChecker.compareSchema(); - schemaChecker.checkNoParallelTables(); - schemaChecker.checkSchemaNotUpgrading(); + SchemaChecker::Builder schemaCheckerBuilder(login.dbType,conn); + std::unique_ptr<SchemaChecker> schemaChecker(schemaCheckerBuilder + .useMapStatementsReader() + .useSQLiteSchemaComparer() + .build()); + + SchemaChecker::Status comparisonStatus = schemaChecker->compareSchema(); + schemaChecker->checkNoParallelTables(); + schemaChecker->checkSchemaNotUpgrading(); if(comparisonStatus == SchemaChecker::Status::FAILURE){ return 1; } diff --git a/statistics/CMakeLists.txt b/statistics/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c12f71a49328205d2a48ac7d91a5b07a0ebcb687 --- /dev/null +++ b/statistics/CMakeLists.txt @@ -0,0 +1,70 @@ +# The CERN Tape Archive (CTA) project +# Copyright (C) 2015 CERN +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +cmake_minimum_required (VERSION 2.6) + +find_package(Protobuf3 REQUIRED) + +include_directories (${ORACLE-INSTANTCLIENT_INCLUDE_DIRS}) + + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow") + +set (STATISTICS_LIB_SRC_FILES + StatisticsCmd.cpp + StatisticsCmdLineArgs.cpp + StatisticsCmdMain.cpp +) + +add_library (ctastatistics + ${STATISTICS_LIB_SRC_FILES}) + +set_property(TARGET ctastatistics PROPERTY SOVERSION "${CTA_SOVERSION}") +set_property(TARGET ctastatistics PROPERTY VERSION "${CTA_LIBVERSION}") + +install (TARGETS ctastatistics DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) + +target_link_libraries (ctastatistics + ctacatalogue + ctacommon + ctaschemachecker + ctardbms) + +install (FILES ${CMAKE_SOURCE_DIR}/catalogue/cta-catalogue.conf.example + DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/cta + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + +add_executable(cta-statistics + StatisticsCmd.cpp + StatisticsCmdLineArgs.cpp + StatisticsCmdMain.cpp +) + +target_link_libraries (cta-statistics ctacatalogue ctaschemachecker) +set_property(TARGET cta-statistics APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH}) + +install (TARGETS cta-statistics DESTINATION /usr/bin) +install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-statistics.1cta DESTINATION /usr/share/man/man1) + +set (STATISTICS_CMD_LINE_UNIT_TESTS_LIB_SRC_FILES + StatisticsCmdLineArgsTest.cpp +) + +add_library (ctastatisticscmdlineunittests SHARED + ${STATISTICS_CMD_LINE_UNIT_TESTS_LIB_SRC_FILES}) +set_property(TARGET ctastatisticscmdlineunittests PROPERTY SOVERSION "${CTA_SOVERSION}") +set_property(TARGET ctastatisticscmdlineunittests PROPERTY VERSION "${CTA_LIBVERSION}") + +install (TARGETS ctastatisticscmdlineunittests DESTINATION usr/${CMAKE_INSTALL_LIBDIR}) diff --git a/statistics/StatisticsCmd.cpp b/statistics/StatisticsCmd.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca0e8e88d93e1451e20143893a56789412de4bd0 --- /dev/null +++ b/statistics/StatisticsCmd.cpp @@ -0,0 +1,94 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2019 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "rdbms/ConnPool.hpp" +#include "rdbms/AutocommitMode.hpp" +#include "StatisticsCmd.hpp" +#include "catalogue/SchemaChecker.hpp" + + +namespace cta { +namespace statistics { + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +StatisticsCmd::StatisticsCmd(std::istream &inStream, std::ostream &outStream, std::ostream &errStream): +CmdLineTool(inStream, outStream, errStream) { +} + +//------------------------------------------------------------------------------ +// destructor +//------------------------------------------------------------------------------ +StatisticsCmd::~StatisticsCmd() noexcept { +} + +//------------------------------------------------------------------------------ +// exceptionThrowingMain +//------------------------------------------------------------------------------ +int StatisticsCmd::exceptionThrowingMain(const int argc, char *const *const argv) { + const StatisticsCmdLineArgs cmdLineArgs(argc, argv); + + if(cmdLineArgs.help) { + printUsage(m_out); + return 0; + } + + std::cout << cmdLineArgs.catalogueDbConfigPath << std::endl; + std::cout << cmdLineArgs.statisticsDbConfigPath << std::endl; + + const uint64_t maxNbConns = 1; + + auto loginCatalogue = rdbms::Login::parseFile(cmdLineArgs.catalogueDbConfigPath); + rdbms::ConnPool catalogueConnPool(loginCatalogue, maxNbConns); + auto catalogueConn = catalogueConnPool.getConn(); + + auto loginStatistics = rdbms::Login::parseFile(cmdLineArgs.statisticsDbConfigPath); + rdbms::ConnPool statisticsConnPool(loginStatistics, maxNbConns); + auto statisticsConn = statisticsConnPool.getConn(); + + /*cta::catalogue::SchemaChecker catalogueSchemaChecker(loginCatalogue.dbType,catalogueConn); + cta::catalogue::SchemaChecker statisticsSchemaChecker(loginStatistics.dbType,statisticsConn);*/ + +// catalogueSchemaChecker.useSQLiteSchemaComparer(); + + return 0; +} +//------------------------------------------------------------------------------ +// tableExists +//------------------------------------------------------------------------------ +bool StatisticsCmd::tableExists(const std::string tableName, rdbms::Conn &conn) const { + const auto names = conn.getTableNames(); + for(const auto &name : names) { + if(tableName == name) { + return true; + } + } + return false; +} + +//------------------------------------------------------------------------------ +// printUsage +//------------------------------------------------------------------------------ +void StatisticsCmd::printUsage(std::ostream &os) { + StatisticsCmdLineArgs::printUsage(os); +} + + +} // namespace catalogue +} // namespace cta diff --git a/statistics/StatisticsCmd.hpp b/statistics/StatisticsCmd.hpp new file mode 100644 index 0000000000000000000000000000000000000000..654cc3e7d25ffaf5d01b7ae0445dd0752c386208 --- /dev/null +++ b/statistics/StatisticsCmd.hpp @@ -0,0 +1,83 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "catalogue/CmdLineTool.hpp" +#include "catalogue/CatalogueSchema.hpp" +#include "rdbms/Conn.hpp" +#include "rdbms/Login.hpp" +#include "StatisticsCmdLineArgs.hpp" + +namespace cta { +namespace statistics { + +/** + * Command-line tool for verifying the catalogue schema. + */ +class StatisticsCmd: public cta::catalogue::CmdLineTool { +public: + + /** + * Constructor. + * + * @param inStream Standard input stream. + * @param outStream Standard output stream. + * @param errStream Standard error stream. + */ + StatisticsCmd(std::istream &inStream, std::ostream &outStream, std::ostream &errStream); + + /** + * Destructor. + */ + ~StatisticsCmd() noexcept; + + enum class VerifyStatus { OK, INFO, ERROR, UNKNOWN }; + +private: + + /** + * An exception throwing version of main(). + * + * @param argc The number of command-line arguments including the program name. + * @param argv The command-line arguments. + * @return The exit value of the program. + */ + int exceptionThrowingMain(const int argc, char *const *const argv) override; + + /** + * Prints the usage message of the command-line tool. + * + * @param os The output stream to which the usage message is to be printed. + */ + void printUsage(std::ostream &os) override; + + /** + * Returns true if the table with the specified name exists in the database + * schema of the specified database connection. + * + * @param tableName The name of the database table. + * @param conn The database connection. + * @return True if the table exists. + */ + bool tableExists(const std::string tableName, rdbms::Conn &conn) const; + +}; // class VerifySchemaCmd + +} // namespace statistics +} // namespace cta diff --git a/statistics/StatisticsCmdLineArgs.cpp b/statistics/StatisticsCmdLineArgs.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ab649bb4faae78bf23f2b528a05d384673695a53 --- /dev/null +++ b/statistics/StatisticsCmdLineArgs.cpp @@ -0,0 +1,121 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "StatisticsCmdLineArgs.hpp" +#include "common/exception/CommandLineNotParsed.hpp" + +#include <getopt.h> +#include <ostream> +#include <iostream> + +namespace cta { +namespace statistics { + +//------------------------------------------------------------------------------ +// constructor +//------------------------------------------------------------------------------ +StatisticsCmdLineArgs::StatisticsCmdLineArgs(const int argc, char *const *const argv): + help(false) { + + static struct option longopts[] = { + {"catalogueconf",required_argument,NULL,'c'}, + {"statisticsconf",required_argument,NULL,'s'}, + {"help", no_argument, NULL, 'h'}, + {NULL , 0, NULL, 0} + }; + + // Prevent getopt() from printing an error message if it does not recognize + // an option character + opterr = 0; + + int opt = 0; + while((opt = getopt_long(argc, argv, ":hc:s:", longopts, NULL)) != -1) { + switch(opt) { + case 'h': + help = true; + break; + case 'c': + catalogueDbConfigPath = optarg; + break; + case 's': + statisticsDbConfigPath = optarg; + break; + case ':': // Missing parameter + { + exception::CommandLineNotParsed ex; + ex.getMessage() << "The -" << (char)optopt << " option requires a parameter"; + throw ex; + } + case '?': // Unknown option + { + exception::CommandLineNotParsed ex; + if(0 == optopt) { + ex.getMessage() << "Unknown command-line option"; + } else { + ex.getMessage() << "Unknown command-line option: -" << (char)optopt; + } + throw ex; + } + default: + { + exception::CommandLineNotParsed ex; + ex.getMessage() << + "getopt_long returned the following unknown value: 0x" << + std::hex << (int)opt; + throw ex; + } + } // switch(opt) + } // while getopt_long() + + // There is no need to continue parsing when the help option is set + if(help) { + return; + } + + // Calculate the number of non-option ARGV-elements + const int nbArgs = argc - 1; + + // Check the number of arguments + if(nbArgs != 4) { + exception::CommandLineNotParsed ex; + ex.getMessage() << "Wrong number of command-line arguments: expected=4 actual=" << nbArgs; + throw ex; + } +} + +//------------------------------------------------------------------------------ +// printUsage +//------------------------------------------------------------------------------ +void StatisticsCmdLineArgs::printUsage(std::ostream &os) { + os << + "Usage:" << std::endl << + " cta-statistics --catalogueconf catalogueDbConnectionFile --statisticsconf statisticsDbConnectionFile [options]" << std::endl << + "Where:" << std::endl << + " catalogueDbConnectionFile" << std::endl << + " The path to the file containing the connection details of the CTA" << std::endl << + " catalogue database" << std::endl << + " statisticsDbConnectionFile" << std::endl << + " The path to the file containing the connection details of the CTA" << std::endl << + " statistics database" << std::endl << + "Options:" << std::endl << + " -h,--help" << std::endl << + " Prints this usage message" << std::endl; +} + +} // namespace statistics +} // namespace cta diff --git a/statistics/StatisticsCmdLineArgs.hpp b/statistics/StatisticsCmdLineArgs.hpp new file mode 100644 index 0000000000000000000000000000000000000000..08b428d0f559fed55fdceabb391f9f58b389b857 --- /dev/null +++ b/statistics/StatisticsCmdLineArgs.hpp @@ -0,0 +1,66 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <string> + +namespace cta { +namespace statistics { + +/** + * Structure to store the command-line arguments of the command-line tool + * named cta-statistics + */ +struct StatisticsCmdLineArgs { + /** + * True if the usage message should be printed. + */ + bool help; + + /** + * Path to the file containing the connection details of the catalogue + * database. + */ + std::string catalogueDbConfigPath; + + /** + * Path to the file containing the connection details of the statistics + * database. + */ + std::string statisticsDbConfigPath; + + /** + * Constructor that parses the specified command-line arguments. + * + * @param argc The number of command-line arguments including the name of the + * executable. + * @param argv The vector of command-line arguments. + */ + StatisticsCmdLineArgs(const int argc, char *const *const argv); + + /** + * Prints the usage message of the command-line tool. + * + * @param os The output stream to which the usage message is to be printed. + */ + static void printUsage(std::ostream &os); +}; + +} // namespace catalogue +} // namespace cta diff --git a/statistics/StatisticsCmdLineArgsTest.cpp b/statistics/StatisticsCmdLineArgsTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5efb088a9cc83b0cce0b8604adcbadcb3bdb23a --- /dev/null +++ b/statistics/StatisticsCmdLineArgsTest.cpp @@ -0,0 +1,121 @@ +/* + * The CERN Tape Archive(CTA) project + * Copyright(C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + *(at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "common/exception/Exception.hpp" +#include "catalogue/VerifySchemaCmdLineArgs.hpp" + +#include <gtest/gtest.h> +#include <list> + +namespace unitTests { + +class cta_catalogue_VerifySchemaCmdLineArgsTest : public ::testing::Test { +protected: + + struct Argcv { + int argc; + char **argv; + Argcv(): argc(0), argv(NULL) { + } + }; + typedef std::list<Argcv*> ArgcvList; + ArgcvList m_argsList; + + /** + * Creates a duplicate string using the new operator. + */ + char *dupString(const char *str) { + const size_t len = strlen(str); + char *duplicate = new char[len+1]; + strncpy(duplicate, str, len); + duplicate[len] = '\0'; + return duplicate; + } + + virtual void SetUp() { + // Allow getopt_long to be called again + optind = 0; + } + + virtual void TearDown() { + // Allow getopt_long to be called again + optind = 0; + + for(ArgcvList::const_iterator itor = m_argsList.begin(); + itor != m_argsList.end(); itor++) { + for(int i=0; i < (*itor)->argc; i++) { + delete[] (*itor)->argv[i]; + } + delete[] (*itor)->argv; + delete *itor; + } + } +}; + +TEST_F(cta_catalogue_VerifySchemaCmdLineArgsTest, help_short) { + using namespace cta::catalogue; + + Argcv *args = new Argcv(); + m_argsList.push_back(args); + args->argc = 2; + args->argv = new char *[3]; + args->argv[0] = dupString("cta-catalogue-schema-verify"); + args->argv[1] = dupString("-h"); + args->argv[2] = NULL; + + VerifySchemaCmdLineArgs cmdLine(args->argc, args->argv); + + ASSERT_TRUE(cmdLine.help); + ASSERT_TRUE(cmdLine.dbConfigPath.empty()); +} + +TEST_F(cta_catalogue_VerifySchemaCmdLineArgsTest, help_long) { + using namespace cta::catalogue; + + Argcv *args = new Argcv(); + m_argsList.push_back(args); + args->argc = 2; + args->argv = new char *[3]; + args->argv[0] = dupString("cta-catalogue-schema-verify"); + args->argv[1] = dupString("--help"); + args->argv[2] = NULL; + + VerifySchemaCmdLineArgs cmdLine(args->argc, args->argv); + + ASSERT_TRUE(cmdLine.help); + ASSERT_TRUE(cmdLine.dbConfigPath.empty()); +} + +TEST_F(cta_catalogue_VerifySchemaCmdLineArgsTest, dbConfigPath) { + using namespace cta::catalogue; + + Argcv *args = new Argcv(); + m_argsList.push_back(args); + args->argc = 2; + args->argv = new char *[3]; + args->argv[0] = dupString("cta-catalogue-schema-verify"); + args->argv[1] = dupString("dbConfigPath"); + args->argv[2] = NULL; + + VerifySchemaCmdLineArgs cmdLine(args->argc, args->argv); + + ASSERT_FALSE(cmdLine.help); + ASSERT_EQ(std::string("dbConfigPath"), cmdLine.dbConfigPath); +} + +} // namespace unitTests diff --git a/statistics/StatisticsCmdMain.cpp b/statistics/StatisticsCmdMain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0ef80bee2f36fe397b2e80f31576e19e00f921cc --- /dev/null +++ b/statistics/StatisticsCmdMain.cpp @@ -0,0 +1,29 @@ +/* + * The CERN Tape Archive (CTA) project + * Copyright (C) 2015 CERN + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "StatisticsCmd.hpp" + +#include <iostream> + +//------------------------------------------------------------------------------ +// main +//------------------------------------------------------------------------------ +int main(const int argc, char *const *const argv) { + cta::statistics::StatisticsCmd cmd(std::cin, std::cout, std::cerr); + return cmd.main(argc, argv); +}