Commit cef7980f authored by Matthieu Dorier's avatar Matthieu Dorier
Browse files

finished API, started CppUnit testing

parent 5ff11a14
......@@ -9,7 +9,6 @@
cmake_minimum_required (VERSION 3.0)
project (hepnos CXX)
enable_testing ()
add_definitions (-g)
......@@ -46,6 +45,19 @@ xpkg_import_module (bake-server REQUIRED bake-server)
xpkg_import_module (ch-placement REQUIRED ch-placement)
find_package (yaml-cpp REQUIRED)
find_package (CppUnit)
if (CPPUNIT_FOUND)
message(STATUS "CppUnit found, unit tests will be compiled")
include_directories(${CPPUNIT_INCLUDE_DIR})
enable_testing()
else (CPPUNIT_FOUND)
message(STATUS "CppUnit not found, unit tests will not be compiled")
endif (CPPUNIT_FOUND)
add_subdirectory (src)
add_subdirectory (test)
add_subdirectory (bin)
if(CPPUNIT_FOUND AND ENABLE_TESTS)
message(STATUS "Unit tests are enabled, will be built")
add_subdirectory (test)
endif(CPPUNIT_FOUND AND ENABLE_TESTS)
add_executable(hepnos-service hepnos-service.cpp hepnos-service-util.cpp)
target_link_libraries(hepnos-service sdskv-server bake-server yaml-cpp)
add_executable(hepnos-daemon hepnos-daemon.cpp)
target_link_libraries(hepnos-daemon hepnos-service yaml-cpp margo bake-server sdskv-server)
/*
* (C) 2018 The University of Chicago
*
* See COPYRIGHT in top-level directory.
*/
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <unistd.h>
#include <mpi.h>
#include <margo.h>
#include <bake-server.h>
#include <sdskv-server.h>
#include <yaml-cpp/yaml.h>
#include "hepnos-service.h"
#define ASSERT(__cond, __msg, ...) { if(!(__cond)) { fprintf(stderr, "[%s:%d] " __msg, __FILE__, __LINE__, __VA_ARGS__); exit(-1); } }
void usage(void)
{
fprintf(stderr, "Usage: hepnos-service <addr> <config>\n");
fprintf(stderr, " <addr> the Mercury address to listen on (e.g. tcp://)\n");
fprintf(stderr, " <config> path to the YAML file to generate for clients\n");
exit(-1);
}
int main(int argc, char *argv[])
{
char* listen_addr;
char* config_file;
int rank;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if(argc != 3) {
if(rank == 0) {
usage();
}
MPI_Finalize();
exit(0);
}
listen_addr = argv[1];
config_file = argv[2];
hepnos_run_service(MPI_COMM_WORLD, listen_addr, config_file);
MPI_Finalize();
}
#include "hepnos-service-util.hpp"
int hepnos_sdskv_provider_setup(sdskv_provider_t sdskv_provider) {
}
#ifndef __HEPNOS_SERVICE_UTIL_H
#define __HEPNOS_SERVICE_UTIL_H
#include <sdskv-server.h>
int hepnos_sdskv_provider_setup(sdskv_provider_t sdskv_provider);
#endif
#
# Find the CppUnit includes and library
#
# This module defines
# CPPUNIT_INCLUDE_DIR, where to find tiff.h, etc.
# CPPUNIT_LIBRARIES, the libraries to link against to use CppUnit.
# CPPUNIT_FOUND, If false, do not try to use CppUnit.
# also defined, but not for general use are
# CPPUNIT_LIBRARY, where to find the CppUnit library.
# CPPUNIT_DEBUG_LIBRARY, where to find the CppUnit library in debug mode.
FIND_PATH(CPPUNIT_INCLUDE_DIR cppunit/TestCase.h HINTS
/usr/local/include
/usr/include
ENV CppUnit_ROOT
)
# With Win32, important to have both
IF(WIN32)
FIND_LIBRARY(CPPUNIT_LIBRARY cppunit
${CPPUNIT_INCLUDE_DIR}/../lib
/usr/local/lib
/usr/lib)
FIND_LIBRARY(CPPUNIT_DEBUG_LIBRARY cppunitd
${CPPUNIT_INCLUDE_DIR}/../lib
/usr/local/lib
/usr/lib)
ELSE(WIN32)
# On unix system, debug and release have the same name
FIND_LIBRARY(CPPUNIT_LIBRARY cppunit
${CPPUNIT_INCLUDE_DIR}/../lib
/usr/local/lib
/usr/lib)
FIND_LIBRARY(CPPUNIT_DEBUG_LIBRARY cppunit
${CPPUNIT_INCLUDE_DIR}/../lib
/usr/local/lib
/usr/lib)
ENDIF(WIN32)
IF(CPPUNIT_INCLUDE_DIR)
IF(CPPUNIT_LIBRARY)
SET(CPPUNIT_FOUND "YES")
SET(CPPUNIT_LIBRARIES ${CPPUNIT_LIBRARY} ${CMAKE_DL_LIBS})
SET(CPPUNIT_DEBUG_LIBRARIES ${CPPUNIT_DEBUG_LIBRARY}
${CMAKE_DL_LIBS})
ENDIF(CPPUNIT_LIBRARY)
ENDIF(CPPUNIT_INCLUDE_DIR)
#ifndef __HEPNOS_SERVICE_H
#define __HEPNOS_SERVICE_H
#include <mpi.h>
#ifdef __cplusplus
extern "C" {
#endif
void hepnos_run_service(MPI_Comm comm, const char* listen_addr, const char* config_file);
#ifdef __cplusplus
}
#endif
#endif
#ifndef __HEPNOS_H
#define __HEPNOS_H
#include <hepnos/DataStore.hpp>
#include <hepnos/DataSet.hpp>
#include <hepnos/Demangle.hpp>
#include <hepnos/Event.hpp>
#include <hepnos/EventNumber.hpp>
#include <hepnos/Exception.hpp>
#include <hepnos/KeyValueContainer.hpp>
#include <hepnos/Run.hpp>
#include <hepnos/RunNumber.hpp>
#include <hepnos/RunSet.hpp>
#include <hepnos/SubRun.hpp>
#include <hepnos/SubRunNumber.hpp>
#endif
......@@ -237,6 +237,11 @@ class DataStore {
*/
DataSet createDataSet(const std::string& name);
/**
* @brief Shuts down the HEPnOS service.
*/
void shutdown();
private:
/**
......
......@@ -7,11 +7,14 @@
#define __HEPNOS_EVENT_NUMBER_H
#include <cstdint>
#include <limits>
namespace hepnos {
typedef std::uint64_t EventNumber;
const EventNumber InvalidEventNumber = std::numeric_limits<EventNumber>::max();
}
#endif
......@@ -7,11 +7,14 @@
#define __HEPNOS_RUN_NUMBER_H
#include <cstdint>
#include <limits>
namespace hepnos {
typedef std::uint64_t RunNumber;
const RunNumber InvalidRunNumber = std::numeric_limits<RunNumber>::max();
}
#endif
......@@ -22,6 +22,7 @@ namespace hepnos {
class RunSet {
friend class DataSet::Impl;
friend class DataSet;
private:
......@@ -81,6 +82,18 @@ class RunSet {
class const_iterator;
class iterator;
/**
* @brief Accesses an existing Run using the ()
* operator. If no Run correspond to the provided number,
* the function returns a Run instance r such that
* r.valid() is false.
*
* @param runNumber run number of the Run to retrieve.
*
* @return a Run corresponding to the provided number.
*/
Run operator()(const RunNumber& runNumber);
/**
* @brief Searches this RunSet for a Run with
* the provided run number and returns an iterator to
......
......@@ -7,11 +7,14 @@
#define __HEPNOS_SUB_RUN_NUMBER_H
#include <cstdint>
#include <limits>
namespace hepnos {
typedef std::uint64_t SubRunNumber;
const SubRunNumber InvalidSubRunNumber = std::numeric_limits<SubRunNumber>::max();
}
#endif
......@@ -6,6 +6,8 @@ set(hepnos-src DataStore.cpp
SubRun.cpp
Event.cpp)
set(hepnos-service-src service/HEPnOSService.cpp)
# load package helper for generating cmake CONFIG packages
include (CMakePackageConfigHelpers)
......@@ -15,8 +17,8 @@ set (hepnos-pkg "share/cmake/hepnos")
#
# library version set here (e.g. for shared libs).
#
set (HEPNOS_VERSION_MAJOR 1)
set (HEPNOS_VERSION_MINOR 0)
set (HEPNOS_VERSION_MAJOR 0)
set (HEPNOS_VERSION_MINOR 1)
set (HEPNOS_VERSION_PATCH 0)
set (hepnos-vers "${HEPNOS_VERSION_MAJOR}.${HEPNOS_VERSION_MINOR}")
set (HEPNOS_VERSION "${hepnos-vers}.${HEPNOS_VERSION_PATCH}")
......@@ -35,6 +37,18 @@ set_target_properties (hepnos
PROPERTIES VERSION ${HEPNOS_VERSION}
SOVERSION ${HEPNOS_VERSION_MAJOR})
add_library(hepnos-service ${hepnos-service-src})
target_link_libraries (hepnos mercury margo yaml-cpp sdskv-client sdskv-server bake-client bake-server ch-placement)
target_include_directories (hepnos-service PUBLIC $<INSTALL_INTERFACE:include>)
# local include's BEFORE, in case old incompatable .h files in prefix/include
target_include_directories (hepnos-service BEFORE PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>)
# for shared libs, establish the lib version
set_target_properties (hepnos-service
PROPERTIES VERSION ${HEPNOS_VERSION}
SOVERSION ${HEPNOS_VERSION_MAJOR})
#
# installation stuff (packaging and install commands)
#
......@@ -49,12 +63,13 @@ configure_file (hepnos-config.cmake.in hepnos-config.cmake @ONLY)
#
# "make install" rules
#
#install (TARGETS hepnos EXPORT hepnos-targets
# ARCHIVE DESTINATION lib
# LIBRARY DESTINATION lib)
#install (EXPORT hepnos-targets
# DESTINATION ${hepnos-pkg}
# FILE "hepnos-targets.cmake")
install (TARGETS hepnos EXPORT hepnos-targets
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
install (TARGETS hepnos-service ARCHIVE DESTINATION lib LIBRARY DESTINATION lib)
install (EXPORT hepnos-targets
DESTINATION ${hepnos-pkg}
FILE "hepnos-targets.cmake")
install (FILES "${CMAKE_CURRENT_BINARY_DIR}/hepnos-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/hepnos-config-version.cmake"
"../cmake/xpkg-import.cmake"
......@@ -62,3 +77,6 @@ install (FILES "${CMAKE_CURRENT_BINARY_DIR}/hepnos-config.cmake"
install (DIRECTORY ../include/hepnos
DESTINATION include
FILES_MATCHING PATTERN "*.hpp")
install (DIRECTORY ../include/hepnos
DESTINATION include
FILES_MATCHING PATTERN "*.h")
......@@ -6,6 +6,7 @@
#include "hepnos/DataSet.hpp"
#include "hepnos/Run.hpp"
#include "hepnos/RunSet.hpp"
#include "private/RunSetImpl.hpp"
#include "private/RunImpl.hpp"
#include "private/DataSetImpl.hpp"
#include "private/DataStoreImpl.hpp"
......@@ -36,7 +37,10 @@ DataSet::DataSet(const DataSet& other)
other.m_impl->m_container,
other.m_impl->m_name)) {}
DataSet::DataSet(DataSet&&) = default;
DataSet::DataSet(DataSet&& other)
: m_impl(std::move(other.m_impl)) {
m_impl->m_runset.m_impl->m_dataset = this;
}
DataSet& DataSet::operator=(const DataSet& other) {
if(this == &other) return *this;
......@@ -48,7 +52,12 @@ DataSet& DataSet::operator=(const DataSet& other) {
return *this;
}
DataSet& DataSet::operator=(DataSet&&) = default;
DataSet& DataSet::operator=(DataSet&& other) {
if(this == &other) return *this;
m_impl = std::move(other.m_impl);
m_impl->m_runset.m_impl->m_dataset = this;
return *this;
}
DataSet::~DataSet() {}
......@@ -59,7 +68,7 @@ DataSet DataSet::next() const {
size_t s = m_impl->m_datastore->m_impl->nextKeys(
m_impl->m_level, m_impl->m_container, m_impl->m_name, keys, 1);
if(s == 0) return DataSet();
return DataSet(m_impl->m_datastore, m_impl->m_level, m_impl->m_container, keys[0]);
return DataSet(m_impl->m_datastore, m_impl->m_level, keys[0]);
}
bool DataSet::valid() const {
......@@ -111,8 +120,9 @@ std::string DataSet::fullname() const {
}
DataSet DataSet::createDataSet(const std::string& name) {
if(name.find('/') != std::string::npos) {
throw Exception("Invalid character '/' in dataset name");
if(name.find('/') != std::string::npos
|| name.find('%') != std::string::npos) {
throw Exception("Invalid character '/' or '%' in dataset name");
}
std::string parent = fullname();
m_impl->m_datastore->m_impl->store(m_impl->m_level+1, parent, name, std::vector<char>());
......@@ -120,6 +130,9 @@ DataSet DataSet::createDataSet(const std::string& name) {
}
Run DataSet::createRun(const RunNumber& runNumber) {
if(InvalidRunNumber == runNumber) {
throw Exception("Trying to create a Run with InvalidRunNumber");
}
std::string parent = fullname();
std::string runStr = Run::Impl::makeKeyStringFromRunNumber(runNumber);
m_impl->m_datastore->m_impl->store(m_impl->m_level+1, parent, runStr, std::vector<char>());
......@@ -138,8 +151,9 @@ Run DataSet::operator()(const RunNumber& runNumber) const {
DataSet::iterator DataSet::find(const std::string& datasetName) {
int ret;
if(datasetName.find('/') != std::string::npos) {
throw Exception("Invalid character '/' in dataset name");
if(datasetName.find('/') != std::string::npos
|| datasetName.find('%') != std::string::npos) {
throw Exception("Invalid character '/' or '%' in dataset name");
}
std::vector<char> data;
std::string parent = fullname();
......
......@@ -54,7 +54,7 @@ DataStore::iterator DataStore::find(const std::string& datasetName) {
if(!b) {
return m_impl->m_end;
}
return iterator(DataSet(this, 1, datasetName));
return iterator(DataSet(this, 1, "", datasetName));
}
DataSet DataStore::operator[](const std::string& datasetName) const {
......@@ -137,6 +137,12 @@ DataSet DataStore::createDataSet(const std::string& name) {
return DataSet(this, 1, "", name);
}
void DataStore::shutdown() {
for(auto addr : m_impl->m_addrs) {
margo_shutdown_remote_instance(m_impl->m_mid, addr);
}
}
////////////////////////////////////////////////////////////////////////////////////////////
// DataStore::const_iterator::Impl implementation
////////////////////////////////////////////////////////////////////////////////////////////
......
......@@ -11,7 +11,7 @@
namespace hepnos {
Run::Run()
: m_impl(std::make_unique<Run::Impl>(nullptr, 0, "", 0)) {}
: m_impl(std::make_unique<Run::Impl>(nullptr, 0, "", InvalidRunNumber)) {}
Run::Run(DataStore* ds, uint8_t level, const std::string& container, const RunNumber& rn)
: m_impl(std::make_unique<Run::Impl>(ds, level, container, rn)) { }
......
......@@ -20,10 +20,16 @@ namespace hepnos {
////////////////////////////////////////////////////////////////////////////////////////////
RunSet::RunSet(DataSet* ds)
: m_impl(std::make_unique<RunSet::Impl>(ds)) {}
: m_impl(std::make_unique<RunSet::Impl>(ds)) {
}
RunSet::~RunSet() {}
Run RunSet::operator()(const RunNumber& runNumber) {
auto it = find(runNumber);
return std::move(*it);
}
RunSet::iterator RunSet::find(const RunNumber& runNumber) {
int ret;
std::vector<char> data;
......
......@@ -12,7 +12,7 @@
namespace hepnos {
SubRun::SubRun()
: m_impl(std::make_unique<Impl>(nullptr, 0, "", 0)) {}
: m_impl(std::make_unique<Impl>(nullptr, 0, "", InvalidSubRunNumber)) {}
SubRun::SubRun(DataStore* ds, uint8_t level, const std::string& container, const SubRunNumber& rn)
: m_impl(std::make_unique<Impl>(ds, level, container, rn)) { }
......
......@@ -7,6 +7,7 @@
#define __HEPNOS_PRIVATE_DATASTORE_IMPL
#include <vector>
#include <unordered_set>
#include <functional>
#include <iostream>
#include <yaml-cpp/yaml.h>
......@@ -28,6 +29,7 @@ class DataStore::Impl {
public:
margo_instance_id m_mid; // Margo instance
std::unordered_set<hg_addr_t> m_addrs; // Addresses used by the service
sdskv_client_t m_sdskv_client; // SDSKV client
bake_client_t m_bake_client; // BAKE client
std::vector<sdskv_provider_handle_t> m_sdskv_ph; // list of SDSKV provider handlers
......@@ -81,6 +83,7 @@ class DataStore::Impl {
cleanup();
throw Exception("margo_addr_lookup failed");
}
m_addrs.insert(addr);
if(it->second.IsScalar()) {
uint16_t provider_id = it->second.as<uint16_t>();
sdskv_provider_handle_t ph;
......@@ -128,6 +131,7 @@ class DataStore::Impl {
cleanup();
throw Exception("margo_addr_lookup failed");
}
m_addrs.insert(addr);
if(it->second.IsScalar()) {
uint16_t provider_id = it->second.as<uint16_t>();
bake_provider_handle_t ph;
......
Markdown is supported
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