Commit 9111e0dc authored by Cedric Caffy's avatar Cedric Caffy
Browse files

Added --json output to the cta-statistics-save tool

parent c9a76aee
......@@ -54,6 +54,7 @@ set (STATISTICS_LIB_SRC_FILES
MySQLStatisticsService.cpp
DatabaseStatisticsServiceFactory.cpp
StatisticsServiceFactory.cpp
JsonStatisticsService.cpp
)
add_library (ctastatistics SHARED
......
/*
* 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 "JsonStatisticsService.hpp"
namespace cta {
namespace statistics {
JsonStatisticsService::JsonStatisticsService(OutputStream * output):m_output(output),m_input(nullptr) {
}
JsonStatisticsService::JsonStatisticsService(OutputStream * output, InputStream * input):m_output(output),m_input(input) {
}
void JsonStatisticsService::saveStatistics(const cta::statistics::Statistics& statistics){
*m_output << statistics;
}
std::unique_ptr<cta::statistics::Statistics> JsonStatisticsService::getStatistics(){
throw cta::exception::Exception("In JsonStatisticsService::getStatistics(), method not implemented.");
}
void JsonStatisticsService::updateStatisticsPerTape(){
throw cta::exception::Exception("In JsonStatistics::updateStatisticsPerTape(), method not implemented.");
}
JsonStatisticsService::~JsonStatisticsService() {
}
}}
\ No newline at end of file
/*
* 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/>.
*/
#pragma once
#include "StatisticsService.hpp"
#include "Statistics.hpp"
namespace cta { namespace statistics {
/**
* This class is a JSON statistics service
* allowing to perform statistics operation
* to and from a JSON file
*/
class JsonStatisticsService: public StatisticsService {
public:
typedef std::ostream OutputStream;
typedef std::istream InputStream;
/**
* Constructor of the service with a OutputStream object
*/
JsonStatisticsService(OutputStream * output);
/**
* Constructor of the service with the OutputStream and InputStream objects
* @param output the OutputStream object
* @param input the InputStream object
*/
JsonStatisticsService(OutputStream * output, InputStream * input);
JsonStatisticsService(const JsonStatisticsService& orig) = delete;
virtual void saveStatistics(const cta::statistics::Statistics& statistics) override;
virtual std::unique_ptr<cta::statistics::Statistics> getStatistics() override;
virtual void updateStatisticsPerTape() override;
virtual ~JsonStatisticsService();
private:
OutputStream * m_output;
InputStream * m_input;
};
}}
\ No newline at end of file
/*
* 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/>.
*/
#pragma once
#include "common/make_unique.hpp"
#include "JsonStatisticsService.hpp"
namespace cta{
namespace statistics {
class JsonStatisticsServiceFactory {
public:
static std::unique_ptr<JsonStatisticsService> create(JsonStatisticsService::OutputStream *output, JsonStatisticsService::InputStream *input = nullptr){
return cta::make_unique<JsonStatisticsService>(output,input);
}
private:
};
}}
\ No newline at end of file
......@@ -57,30 +57,54 @@ int StatisticsSaveCmd::exceptionThrowingMain(const int argc, char *const *const
verifyCmdLineArgs(cmdLineArgs);
const uint64_t maxNbConns = 1;
bool isJsonOutput = cmdLineArgs.jsonOutput;
auto loginStatistics = rdbms::Login::parseFile(cmdLineArgs.statisticsDbConfigPath);
rdbms::ConnPool statisticsConnPool(loginStatistics, maxNbConns);
auto statisticsConn = statisticsConnPool.getConn();
const uint64_t maxNbConns = 1;
std::unique_ptr<StatisticsService> statisticsStatisticsService;
//Get the statistics schema so that we can create, drop and check the presence of the database
auto statisticsSchema = StatisticsSchemaFactory::create(loginStatistics.dbType);
std::unique_ptr<rdbms::ConnPool> statisticsConnPool;
std::unique_ptr<rdbms::Conn> statisticsConn;
if(!cmdLineArgs.statisticsDbConfigPath.empty()){
if(cmdLineArgs.buildDatabase){
//Build the database
buildStatisticsDatabase(statisticsConn,*statisticsSchema);
return EXIT_SUCCESS;
}
if(cmdLineArgs.dropDatabase){
//drop the database
if(userConfirmDropStatisticsSchemaFromDb(loginStatistics)){
dropStatisticsDatabase(statisticsConn,*statisticsSchema);
auto loginStatistics = rdbms::Login::parseFile(cmdLineArgs.statisticsDbConfigPath);
statisticsConnPool = cta::make_unique<rdbms::ConnPool>(loginStatistics, maxNbConns);
statisticsConn = cta::make_unique<rdbms::Conn>(statisticsConnPool->getConn());
//Get the statistics schema so that we can create, drop and check the presence of the database
auto statisticsSchema = StatisticsSchemaFactory::create(loginStatistics.dbType);
if(cmdLineArgs.buildDatabase){
//Build the database
buildStatisticsDatabase(*statisticsConn,*statisticsSchema);
return EXIT_SUCCESS;
}
if(cmdLineArgs.dropDatabase){
//drop the database
if(userConfirmDropStatisticsSchemaFromDb(loginStatistics)){
dropStatisticsDatabase(*statisticsConn,*statisticsSchema);
}
return EXIT_SUCCESS;
}
//Check that the statistics schema tables are in the statistics database
SchemaChecker::Builder statisticsCheckerBuilder("statistics",loginStatistics.dbType,*statisticsConn);
std::unique_ptr<SchemaChecker> statisticsChecker =
statisticsCheckerBuilder.useCppSchemaStatementsReader(*statisticsSchema)
.useSQLiteSchemaComparer()
.build();
SchemaChecker::Status compareTablesStatus = statisticsChecker->compareTablesLocatedInSchema();
if(compareTablesStatus == SchemaChecker::Status::FAILURE){
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
//Save the CTA statistics
statisticsStatisticsService = StatisticsServiceFactory::create(*statisticsConn,loginStatistics.dbType);
} else if (isJsonOutput){
statisticsStatisticsService = StatisticsServiceFactory::create(std::cout);
} else {
throw cta::exception::Exception("No --json option provided and no statistics database configuration file provided.");
}
//Connect to the catalogue database
auto loginCatalogue = rdbms::Login::parseFile(cmdLineArgs.catalogueDbConfigPath);
......@@ -108,24 +132,12 @@ int StatisticsSaveCmd::exceptionThrowingMain(const int argc, char *const *const
if(tapeTableStatus == SchemaChecker::Status::FAILURE || voTableStatus == SchemaChecker::Status::FAILURE ){
return EXIT_FAILURE;
}
//Check that the statistics schema tables are in the statistics database
SchemaChecker::Builder statisticsCheckerBuilder("statistics",loginStatistics.dbType,statisticsConn);
std::unique_ptr<SchemaChecker> statisticsChecker =
statisticsCheckerBuilder.useCppSchemaStatementsReader(*statisticsSchema)
.useSQLiteSchemaComparer()
.build();
SchemaChecker::Status compareTablesStatus = statisticsChecker->compareTablesLocatedInSchema();
if(compareTablesStatus == SchemaChecker::Status::FAILURE){
return EXIT_FAILURE;
}
//Compute the statistics
std::unique_ptr<StatisticsService> catalogueStatisticsService = StatisticsServiceFactory::create(catalogueConn,loginCatalogue.dbType);
std::unique_ptr<Statistics> statistics = catalogueStatisticsService->getStatistics();
//Insert them into the statistics database
try {
std::unique_ptr<StatisticsService> statisticsStatisticsService = StatisticsServiceFactory::create(statisticsConn,loginStatistics.dbType);
statisticsStatisticsService->saveStatistics(*statistics);
} catch (cta::exception::Exception &ex) {
std::cerr << ex.getMessageValue() << std::endl;
......@@ -158,9 +170,15 @@ void StatisticsSaveCmd::verifyCmdLineArgs(const StatisticsSaveCmdLineArgs& cmdLi
if(statisticsDbConfigPathEmpty && (cmdLineArgs.buildDatabase || cmdLineArgs.dropDatabase)){
throw cta::exception::Exception("The statistics database configuration file should be provided.");
}
if((!cmdLineArgs.buildDatabase && !cmdLineArgs.dropDatabase) && (catalogueDbConfigPathEmpty || statisticsDbConfigPathEmpty)){
if(cmdLineArgs.jsonOutput && !statisticsDbConfigPathEmpty){
throw cta::exception::Exception("The statistics database connection file should not be provided when --json flag is set.");
}
if((!cmdLineArgs.buildDatabase && !cmdLineArgs.dropDatabase && !cmdLineArgs.jsonOutput) && (catalogueDbConfigPathEmpty || statisticsDbConfigPathEmpty)){
throw cta::exception::Exception("You should provide the catalogue database and the statistics database connection files.");
}
}
if((!cmdLineArgs.buildDatabase && !cmdLineArgs.dropDatabase && cmdLineArgs.jsonOutput) && catalogueDbConfigPathEmpty){
throw cta::exception::Exception("The catalogue database connection file should be provided when --json flag is set.");
}
}
void StatisticsSaveCmd::buildStatisticsDatabase(cta::rdbms::Conn& statisticsDatabaseConn, const StatisticsSchema& statisticsSchema) {
......
......@@ -37,6 +37,7 @@ StatisticsSaveCmdLineArgs::StatisticsSaveCmdLineArgs(const int argc, char *const
{"statisticsconf",required_argument,NULL,'s'},
{"build",no_argument, NULL, 'b'},
{"drop", no_argument, NULL, 'd'},
{"json", no_argument, NULL, 'j'},
{"help", no_argument, NULL, 'h'},
{NULL , 0, NULL, 0}
};
......@@ -46,7 +47,7 @@ StatisticsSaveCmdLineArgs::StatisticsSaveCmdLineArgs(const int argc, char *const
opterr = 0;
int opt = 0;
while((opt = getopt_long(argc, argv, ":hbdc:s:", longopts, NULL)) != -1) {
while((opt = getopt_long(argc, argv, ":hbdjc:s:", longopts, NULL)) != -1) {
switch(opt) {
case 'h':
help = true;
......@@ -63,6 +64,9 @@ StatisticsSaveCmdLineArgs::StatisticsSaveCmdLineArgs(const int argc, char *const
case 'd':
dropDatabase = true;
break;
case 'j':
jsonOutput = true;
break;
case ':': // Missing parameter
{
exception::CommandLineNotParsed ex;
......@@ -112,21 +116,23 @@ StatisticsSaveCmdLineArgs::StatisticsSaveCmdLineArgs(const int argc, char *const
void StatisticsSaveCmdLineArgs::printUsage(std::ostream &os) {
os <<
"Usage:" << std::endl <<
" cta-statistics-save --catalogueconf catalogueDbConnectionFile --statisticsconf statisticsDbConnectionFile [options]" << std::endl <<
" cta-statistics-save --catalogueconf catalogueDbConnectionFile [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 <<
"Options:" << std::endl <<
" -s,--statisticsconf 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 <<
" -b, --build" << std::endl <<
" Builds the statistics database" << std::endl <<
" -d, --drop" << std::endl <<
" Drops the statistics database" << std::endl;
" Drops the statistics database" << std::endl <<
" -j, --json" << std::endl <<
" Dumps the statistics in json format on stdout" << std::endl;
}
} // namespace statistics
......
......@@ -55,6 +55,11 @@ struct StatisticsSaveCmdLineArgs {
*/
bool dropDatabase = false;
/**
* True if the --json flag has been provided
*/
bool jsonOutput = false;
/**
* Constructor that parses the specified command-line arguments.
*
......
......@@ -19,6 +19,7 @@
#include "StatisticsServiceFactory.hpp"
#include "DatabaseStatisticsServiceFactory.hpp"
#include "JsonStatisticsServiceFactory.hpp"
namespace cta { namespace statistics {
......@@ -26,4 +27,8 @@ std::unique_ptr<StatisticsService> StatisticsServiceFactory::create(cta::rdbms::
return DatabaseStatisticsServiceFactory::create(connection,dbType);
}
std::unique_ptr<StatisticsService> StatisticsServiceFactory::create(std::ostream& ostream) {
return JsonStatisticsServiceFactory::create(&ostream);
}
}}
\ No newline at end of file
......@@ -35,6 +35,8 @@ public:
* @return a unique_ptr containing the StatisticsService
*/
static std::unique_ptr<StatisticsService> create(cta::rdbms::Conn &connection, cta::rdbms::Login::DbType dbType);
static std::unique_ptr<StatisticsService> create(std::ostream & ostream);
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment