From cf2a79102d34c15b8825998c1db766210c05293c Mon Sep 17 00:00:00 2001 From: Inna Brodkin Date: Mon, 13 May 2024 17:52:24 -0500 Subject: [PATCH 1/6] python bindings: first step --- CMakeLists.txt | 7 ++++++- Client/main.cpp | 13 ------------- python_client/CMakeLists.txt | 28 +++++++++++++++++++++++++++ python_client/py_chronolog_client.cpp | 7 +++++++ spack.yaml | 3 +++ 5 files changed, 44 insertions(+), 14 deletions(-) delete mode 100644 Client/main.cpp create mode 100644 python_client/CMakeLists.txt create mode 100644 python_client/py_chronolog_client.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 27900c3e..a1f4b06f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.25) # Set a consistent MACOSX_RPATH default across all CMake versions. if(NOT DEFINED CMAKE_MACOSX_RPATH) @@ -218,3 +218,8 @@ if(CHRONOLOG_BUILD_TESTING) enable_testing() add_subdirectory(test) endif() + +if(CHRONOLOG_ENABLE_PYTHON_BINDINGS) + message("Python binding enabled") + add_subdirectory(python_client) +endif() diff --git a/Client/main.cpp b/Client/main.cpp deleted file mode 100644 index c7b9db5b..00000000 --- a/Client/main.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// -// Created by kfeng on 5/17/2022. -// - -#include -#include - -using namespace std; - -int main() -{ - return 0; -} \ No newline at end of file diff --git a/python_client/CMakeLists.txt b/python_client/CMakeLists.txt new file mode 100644 index 00000000..48dc965c --- /dev/null +++ b/python_client/CMakeLists.txt @@ -0,0 +1,28 @@ +cmake_minimum_required(VERSION 3.25) + +################################### +# Find Packages +################################### +find_package(pybind11 CONFIG REQUIRED) +message(STATUS "Found pybind11 v${pybind11_VERSION}:${pybind11_INCLUDE_DIRS}") + +#################################### +# Compile ChronoLog Python Client +#################################### + +pybind11_add_module(py_chronolog_client MODULE py_chronolog_client.cpp) + +add_dependencies(py_chronolog_client + #${chronolog_CLIENT_DEPS} + chronolog_client) +target_link_libraries(py_chronolog_client PUBLIC + #${chronolog_CLIENT_LIBRARIES} + chronolog_client pybind11::module) + +################################### +# Install targets +################################## + +#install(TARGETS py_chronolog_client +# LIBRARY_DESTINATION ${CMAKE_INSTALL_LIBDIR} +# ARCHIVE_DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/python_client/py_chronolog_client.cpp b/python_client/py_chronolog_client.cpp new file mode 100644 index 00000000..c3da61ee --- /dev/null +++ b/python_client/py_chronolog_client.cpp @@ -0,0 +1,7 @@ + +#include +#include + +#include + + diff --git a/spack.yaml b/spack.yaml index 4187cacf..55899deb 100644 --- a/spack.yaml +++ b/spack.yaml @@ -8,4 +8,7 @@ spack: - mochi-margo@0.13 ^libfabric@1.16.1 fabrics=mlx,rxd,rxm,shm,sockets,tcp,udp,verbs - mercury@2.2.0~boostsys ^libfabric@1.16.1 fabrics=mlx,rxd,rxm,shm,sockets,tcp,udp,verbs - hdf5@1.14.1-2 +cxx + - py-pybind11@2.11.1 + - python3-dev +# - py-pybind11@2.12.0 view: true From 7db371119fe4aca9eefa516670b5c99a57bca40b Mon Sep 17 00:00:00 2001 From: Inna Brodkin Date: Mon, 3 Jun 2024 14:23:44 -0500 Subject: [PATCH 2/6] Client API calls use map of attributes --- ChronoVisor/include/Chronicle.h | 2 +- ChronoVisor/include/ChronicleMetaDirectory.h | 8 +-- ChronoVisor/include/ClientPortalService.h | 4 +- ChronoVisor/include/Story.h | 3 +- ChronoVisor/include/VisorClientPortal.h | 8 +-- ChronoVisor/src/ChronicleMetaDirectory.cpp | 60 +------------------ ChronoVisor/src/VisorClientPortal.cpp | 6 +- Client/ChronoAdmin/client_admin.cpp | 6 +- Client/include/chronolog_client.h | 9 +-- Client/src/ChronologClient.cpp | 4 +- Client/src/ChronologClientImpl.cpp | 4 +- Client/src/ChronologClientImpl.h | 7 +-- Client/src/rpcVisorClient.h | 9 ++- .../Client/client_lib_metadata_rpc_test.cpp | 8 +-- .../Client/client_lib_multi_argobots_test.cpp | 9 +-- .../Client/client_lib_multi_openmp_test.cpp | 4 +- .../Client/client_lib_multi_pthread_test.cpp | 6 +- .../Client/client_lib_multi_storytellers.cpp | 4 +- 18 files changed, 43 insertions(+), 118 deletions(-) diff --git a/ChronoVisor/include/Chronicle.h b/ChronoVisor/include/Chronicle.h index 0ee2252f..86c45599 100644 --- a/ChronoVisor/include/Chronicle.h +++ b/ChronoVisor/include/Chronicle.h @@ -187,7 +187,7 @@ class Chronicle } std::pair - addStory(const std::string &story_name, const std::unordered_map &attrs) + addStory(const std::string &story_name, const std::map &attrs) { /* Check if Story exists */ std::string story_name_for_hash = name_ + story_name; diff --git a/ChronoVisor/include/ChronicleMetaDirectory.h b/ChronoVisor/include/ChronicleMetaDirectory.h index ae302711..8581bfe3 100644 --- a/ChronoVisor/include/ChronicleMetaDirectory.h +++ b/ChronoVisor/include/ChronicleMetaDirectory.h @@ -26,9 +26,7 @@ class ChronicleMetaDirectory std::unordered_map *getChronicleMap() { return chronicleMap_; } - int create_chronicle(const std::string &name); - - int create_chronicle(const std::string &name, const std::unordered_map &attrs); + int create_chronicle(const std::string &name, const std::map &attrs); int destroy_chronicle(const std::string &name); @@ -36,7 +34,7 @@ class ChronicleMetaDirectory int acquire_story(chronolog::ClientId const &client_id, const std::string &chronicle_name, const std::string &story_name - , const std::unordered_map &attrs, int &flags, StoryId &); + , const std::map &attrs, int &flags, StoryId &); int release_story(chronolog::ClientId const &client_id, const std::string &chronicle_name, const std::string &story_name @@ -54,8 +52,6 @@ class ChronicleMetaDirectory std::unordered_map *chronicleMap_; std::mutex g_chronicleMetaDirectoryMutex_; ClientRegistryManager*clientRegistryManager_ = nullptr; -// std::unordered_map *chronicleName2IdMap_; -// std::unordered_map *chronicleId2NameMap_; }; #endif //CHRONOLOG_CHRONICLEMETADIRECTORY_H diff --git a/ChronoVisor/include/ClientPortalService.h b/ChronoVisor/include/ClientPortalService.h index f4025c2b..16362942 100644 --- a/ChronoVisor/include/ClientPortalService.h +++ b/ChronoVisor/include/ClientPortalService.h @@ -53,7 +53,7 @@ class ClientPortalService: public thallium::provider } void CreateChronicle(tl::request const &request, ClientId const &client_id, std::string const &chronicle_name - , const std::unordered_map &attrs, int &flags)//old + , const std::map &attrs, int &flags) { int return_code = theVisorClientPortal.CreateChronicle(client_id, chronicle_name, attrs, flags); request.respond(return_code); @@ -66,7 +66,7 @@ class ClientPortalService: public thallium::provider } void AcquireStory(tl::request const &request, ClientId const &client_id, std::string const &chronicle_name - , std::string const &story_name, const std::unordered_map &attrs + , std::string const &story_name, const std::map &attrs , int &flags) { AcquireStoryResponseMsg acquire_response = theVisorClientPortal.AcquireStory(client_id, chronicle_name diff --git a/ChronoVisor/include/Story.h b/ChronoVisor/include/Story.h index 39cd81d9..9026379c 100644 --- a/ChronoVisor/include/Story.h +++ b/ChronoVisor/include/Story.h @@ -6,6 +6,7 @@ #define CHRONOLOG_STORY_H #include +#include #include #include #include @@ -132,7 +133,7 @@ class Story } } - void setProperty(const std::unordered_map &attrs) + void setProperty(const std::map &attrs) { for(auto const &entry: attrs) { diff --git a/ChronoVisor/include/VisorClientPortal.h b/ChronoVisor/include/VisorClientPortal.h index 034d7abc..4fddfb5c 100644 --- a/ChronoVisor/include/VisorClientPortal.h +++ b/ChronoVisor/include/VisorClientPortal.h @@ -42,25 +42,21 @@ class VisorClientPortal void ShutdownServices(); -//int ClientConnect( const std::string &uri, std::string const &client_account, uint32_t client_host_ip, ClientId &, uint64_t &clock_offset); //old - int ClientConnect(uint32_t client_account, uint32_t client_host_ip, uint32_t client_pid, ClientId & , uint64_t &clock_offset); int ClientDisconnect(ClientId const &client_id); int CreateChronicle(ClientId const &name, ChronicleName const & - , const std::unordered_map &attrs, int &flags); + , const std::map &attrs, int &flags); int DestroyChronicle(ClientId const &client_id, ChronicleName const &chronicle_name); int DestroyStory(ClientId const &client_id, std::string const &chronicle_name, std::string const &story_name); AcquireStoryResponseMsg AcquireStory(ClientId const &client_id, - //std::string const& client_id, std::string const &chronicle_name, std::string const &story_name - , const std::unordered_map &attrs, int &flags); - //, AcquireStoryResponseMsg &); + , const std::map &attrs, int &flags); int ReleaseStory(ClientId const &client_id, std::string const &chronicle_name, std::string const &story_name); diff --git a/ChronoVisor/src/ChronicleMetaDirectory.cpp b/ChronoVisor/src/ChronicleMetaDirectory.cpp index 29146b34..dca82ef6 100644 --- a/ChronoVisor/src/ChronicleMetaDirectory.cpp +++ b/ChronoVisor/src/ChronicleMetaDirectory.cpp @@ -13,28 +13,11 @@ ChronicleMetaDirectory::ChronicleMetaDirectory() LOG_DEBUG("[ChronicleMetaDirectory] Constructor is called. Object created at {} in thread PID={}" , static_cast(this), getpid()); chronicleMap_ = new std::unordered_map (); -// chronicleName2IdMap_ = new std::unordered_map(); -// chronicleId2NameMap_ = new std::unordered_map(); } ChronicleMetaDirectory::~ChronicleMetaDirectory() { delete chronicleMap_; -// delete chronicleName2IdMap_; -// delete chronicleId2NameMap_; -} - -/** - * Create a Chronicle - * @param name: name of the Chronicle - * @return CL_SUCCESS if succeed to create the Chronicle \n - * CL_ERR_CHRONICLE_EXISTS if a Chronicle with the same name already exists \n - * CL_ERR_UNKNOWN otherwise - */ -int ChronicleMetaDirectory::create_chronicle(const std::string &name) -{ - std::unordered_map attrs; - return create_chronicle(name, attrs); } /** @@ -46,7 +29,7 @@ int ChronicleMetaDirectory::create_chronicle(const std::string &name) * CL_ERR_UNKNOWN otherwise */ int ChronicleMetaDirectory::create_chronicle(const std::string &name - , const std::unordered_map &attrs) + , const std::map &attrs) { LOG_DEBUG("[ChronicleMetaDirectory] Creating Chronicle Name={}", name.c_str()); for(auto iter = attrs.begin(); iter != attrs.end(); ++iter) @@ -54,17 +37,9 @@ int ChronicleMetaDirectory::create_chronicle(const std::string &name LOG_DEBUG("[ChronicleMetaDirectory] Attribute of Chronicle {}: {}={}", name.c_str(), iter->first.c_str() , iter->second.c_str()); } - std::chrono::steady_clock::time_point t1, t2; - t1 = std::chrono::steady_clock::now(); std::lock_guard chronicleMapLock(g_chronicleMetaDirectoryMutex_); /* Check if Chronicle already exists, fail if true */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// return CL_ERR_CHRONICLE_EXISTS; -// } else { -// cid = CityHash64(name.c_str(), name.length()); -// } cid = CityHash64(name.c_str(), name.length()); auto chronicleMapRecord = chronicleMap_->find(cid); if(chronicleMapRecord != chronicleMap_->end()) @@ -76,10 +51,6 @@ int ChronicleMetaDirectory::create_chronicle(const std::string &name pChronicle->setName(name); pChronicle->setCid(cid); auto res = chronicleMap_->emplace(cid, pChronicle); -// chronicleName2IdMap_->insert_or_assign(name, cid); -// chronicleId2NameMap_->insert_or_assign(cid, name); - t2 = std::chrono::steady_clock::now(); - std::chrono::duration duration = (t2 - t1); LOG_DEBUG("[ChronicleMetaDirectory] Chronicle created in {} ns", duration.count()); if(res.second) { @@ -106,14 +77,9 @@ int ChronicleMetaDirectory::create_chronicle(const std::string &name int ChronicleMetaDirectory::destroy_chronicle(const std::string &name) { LOG_DEBUG("[ChronicleMetaDirectory] Destroying ChronicleName={}", name.c_str()); - std::chrono::steady_clock::time_point t1, t2; - t1 = std::chrono::steady_clock::now(); std::lock_guard chronicleMapLock(g_chronicleMetaDirectoryMutex_); /* First check if Chronicle exists, fail if false */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// cid = name2IdRecord->second; cid = CityHash64(name.c_str(), name.length()); auto chronicleMapRecord = chronicleMap_->find(cid); if(chronicleMapRecord != chronicleMap_->end()) @@ -148,10 +114,6 @@ int ChronicleMetaDirectory::destroy_chronicle(const std::string &name) /* No Stories in Chronicle is acquired, ready to destroy */ delete pChronicle; auto nErased = chronicleMap_->erase(cid); -// chronicleName2IdMap_->erase(name); -// chronicleId2NameMap_->erase(cid); - t2 = std::chrono::steady_clock::now(); - std::chrono::duration duration = (t2 - t1); LOG_DEBUG("[ChronicleMetaDirectory] Chronicle destroyed in {} ns", duration.count()); if(nErased == 1) { @@ -189,9 +151,6 @@ int ChronicleMetaDirectory::destroy_story(std::string const &chronicle_name, con std::lock_guard chronicleMapLock(g_chronicleMetaDirectoryMutex_); /* First check if Chronicle exists, fail if false */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(chronicle_name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// cid = name2IdRecord->second; cid = CityHash64(chronicle_name.c_str(), chronicle_name.length()); auto chronicleMapRecord = chronicleMap_->find(cid); if(chronicleMapRecord != chronicleMap_->end()) @@ -244,7 +203,7 @@ int ChronicleMetaDirectory::destroy_story(std::string const &chronicle_name, con */ int ChronicleMetaDirectory::acquire_story(chl::ClientId const &client_id, const std::string &chronicle_name , const std::string &story_name - , const std::unordered_map &attrs, int &flags + , const std::map &attrs, int &flags , StoryId &story_id) { LOG_DEBUG("[ChronicleMetaDirectory] ClientID={} acquiring StoryName={} in ChronicleName={} with Flags={}", client_id @@ -253,9 +212,6 @@ int ChronicleMetaDirectory::acquire_story(chl::ClientId const &client_id, const std::lock_guard chronicleMapLock(g_chronicleMetaDirectoryMutex_); /* First check if Chronicle exists, fail if false */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(chronicle_name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// cid = name2IdRecord->second; cid = CityHash64(chronicle_name.c_str(), chronicle_name.length()); auto chronicleMapRecord = chronicleMap_->find(cid); if(chronicleMapRecord == chronicleMap_->end()) @@ -314,9 +270,6 @@ int ChronicleMetaDirectory::release_story(chl::ClientId const &client_id, const std::lock_guard chronicleMapLock(g_chronicleMetaDirectoryMutex_); /* First check if Chronicle exists, fail if false */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(chronicle_name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// cid = name2IdRecord->second; cid = CityHash64(chronicle_name.c_str(), chronicle_name.length()); int ret = chronolog::CL_ERR_NOT_EXIST; auto chronicleRecord = chronicleMap_->find(cid); @@ -364,9 +317,6 @@ int ChronicleMetaDirectory::get_chronicle_attr(std::string const &name, const st std::lock_guard chronicleMapLock(g_chronicleMetaDirectoryMutex_); /* First check if Chronicle exists, fail if false */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// cid = name2IdRecord->second; cid = CityHash64(name.c_str(), name.length()); auto chronicleMapRecord = chronicleMap_->find(cid); if(chronicleMapRecord != chronicleMap_->end()) @@ -409,9 +359,6 @@ ChronicleMetaDirectory::edit_chronicle_attr(std::string const &name, const std:: std::lock_guard chronicleMapLock(g_chronicleMetaDirectoryMutex_); /* First check if Chronicle exists, fail if false */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// cid = name2IdRecord->second; cid = CityHash64(name.c_str(), name.length()); auto chronicleMapRecord = chronicleMap_->find(cid); if(chronicleMapRecord != chronicleMap_->end()) @@ -489,9 +436,6 @@ int ChronicleMetaDirectory::show_stories(const std::string &chronicle_name, std: /* First check if Chronicle exists, fail if false */ uint64_t cid; -// auto name2IdRecord = chronicleName2IdMap_->find(chronicle_name); -// if (name2IdRecord != chronicleName2IdMap_->end()) { -// cid = name2IdRecord->second; cid = CityHash64(chronicle_name.c_str(), chronicle_name.length()); auto chronicleMapRecord = chronicleMap_->find(cid); if(chronicleMapRecord == chronicleMap_->end()) diff --git a/ChronoVisor/src/VisorClientPortal.cpp b/ChronoVisor/src/VisorClientPortal.cpp index 0f52cd92..4fe7780e 100644 --- a/ChronoVisor/src/VisorClientPortal.cpp +++ b/ChronoVisor/src/VisorClientPortal.cpp @@ -131,7 +131,7 @@ int chronolog::VisorClientPortal::ClientDisconnect(chronolog::ClientId const &cl * Metadata APIs */ int chronolog::VisorClientPortal::CreateChronicle(chl::ClientId const &client_id, std::string const &chronicle_name - , const std::unordered_map &attrs + , const std::map &attrs , int &flags) { if(chronicle_name.empty()) @@ -140,7 +140,7 @@ int chronolog::VisorClientPortal::CreateChronicle(chl::ClientId const &client_id if(!chronicle_action_is_authorized(client_id, chronicle_name)) { return CL_ERR_NOT_AUTHORIZED; } - int return_code = chronicleMetaDirectory.create_chronicle(chronicle_name); + int return_code = chronicleMetaDirectory.create_chronicle(chronicle_name, attrs); if(return_code == CL_SUCCESS) { LOG_INFO("[VisorClientPortal] Chronicle created: PID={}, ClientID={}, Name={}", getpid(), client_id @@ -191,7 +191,7 @@ int chronolog::VisorClientPortal::DestroyStory(chl::ClientId const &client_id, s chl::AcquireStoryResponseMsg chronolog::VisorClientPortal::AcquireStory(chl::ClientId const &client_id, std::string const &chronicle_name , std::string const &story_name - , const std::unordered_map &attrs, int &flags) + , const std::map &attrs, int &flags) { chronolog::StoryId story_id{0}; std::vector recording_keepers; diff --git a/Client/ChronoAdmin/client_admin.cpp b/Client/ChronoAdmin/client_admin.cpp index 26737659..5f113270 100644 --- a/Client/ChronoAdmin/client_admin.cpp +++ b/Client/ChronoAdmin/client_admin.cpp @@ -175,7 +175,7 @@ void random_sleep() void test_create_chronicle(chronolog::Client &client, const std::string &chronicle_name) { int ret, flags = 0; - std::unordered_map chronicle_attrs; + std::map chronicle_attrs; chronicle_attrs.emplace("Priority", "High"); chronicle_attrs.emplace("IndexGranularity", "Millisecond"); chronicle_attrs.emplace("TieringPolicy", "Hot"); @@ -188,7 +188,7 @@ test_acquire_story(chronolog::Client &client, const std::string &chronicle_name, { // random_sleep(); int flags = 0; - std::unordered_map story_acquisition_attrs; + std::map story_acquisition_attrs; story_acquisition_attrs.emplace("Priority", "High"); story_acquisition_attrs.emplace("IndexGranularity", "Millisecond"); story_acquisition_attrs.emplace("TieringPolicy", "Hot"); @@ -535,4 +535,4 @@ std::vector &command_subs) MPI_Finalize(); return 0; -} \ No newline at end of file +} diff --git a/Client/include/chronolog_client.h b/Client/include/chronolog_client.h index 914d9c89..16ec22ce 100644 --- a/Client/include/chronolog_client.h +++ b/Client/include/chronolog_client.h @@ -3,14 +3,13 @@ #include #include -#include +#include #include "ConfigurationManager.h" //TODO: not sure this is a good idea , but will keep it for now ... namespace chronolog { -//Abstract StoryHandle will be returnrned to the cleitn in AcquireStory() API call class StoryHandle { public: @@ -37,14 +36,12 @@ class Client int Disconnect(); - int CreateChronicle(std::string const &chronicle_name, std::unordered_map const &attrs - , int &flags); + int CreateChronicle(std::string const &chronicle_name, std::map const &attrs , int &flags); int DestroyChronicle(std::string const &chronicle_name); -//TODO: unordered_map? how many attributes do we expect ??? std::pair AcquireStory(std::string const &chronicle_name, std::string const &story_name - , const std::unordered_map &attrs + , const std::map &attrs , int &flags); int ReleaseStory(std::string const &chronicle_name, std::string const &story_name); diff --git a/Client/src/ChronologClient.cpp b/Client/src/ChronologClient.cpp index ed8ecd05..3ae14753 100644 --- a/Client/src/ChronologClient.cpp +++ b/Client/src/ChronologClient.cpp @@ -22,7 +22,7 @@ int chronolog::Client::Disconnect() } int chronolog::Client::CreateChronicle(std::string const &chronicle_name - , std::unordered_map const &attrs, int &flags) + , std::map const &attrs, int &flags) { return chronologClientImpl->CreateChronicle(chronicle_name, attrs, flags); } @@ -34,7 +34,7 @@ int chronolog::Client::DestroyChronicle(std::string const &chronicle_name) std::pair chronolog::Client::AcquireStory(std::string const &chronicle_name, std::string const &story_name - , const std::unordered_map &attrs, int &flags) + , const std::map &attrs, int &flags) { return chronologClientImpl->AcquireStory(chronicle_name, story_name, attrs, flags); } diff --git a/Client/src/ChronologClientImpl.cpp b/Client/src/ChronologClientImpl.cpp index 9f17856f..6060e1bc 100644 --- a/Client/src/ChronologClientImpl.cpp +++ b/Client/src/ChronologClientImpl.cpp @@ -156,7 +156,7 @@ int chronolog::ChronologClientImpl::Disconnect() } int chronolog::ChronologClientImpl::CreateChronicle(std::string const &chronicle_name - , const std::unordered_map &attrs + , const std::map &attrs , int &flags) { if(chronicle_name.empty()) @@ -236,7 +236,7 @@ int chronolog::ChronologClientImpl::DestroyStory(std::string const &chronicle_na std::pair chronolog::ChronologClientImpl::AcquireStory(std::string const &chronicle_name, std::string const &story_name - , const std::unordered_map &attrs, int &flags) + , const std::map &attrs, int &flags) { // Log the attempt to acquire a story with specific details. LOG_DEBUG("[ChronoLogClientImpl] Attempting to acquire story. ChronicleName={}, StoryName={}", chronicle_name diff --git a/Client/src/ChronologClientImpl.h b/Client/src/ChronologClientImpl.h index 3fffa04d..0ec93c61 100644 --- a/Client/src/ChronologClientImpl.h +++ b/Client/src/ChronologClientImpl.h @@ -43,16 +43,15 @@ class ChronologClientImpl int Connect(); - //const std::string &server_uri, std::string const& client_id, int &flags); //uint64_t &clock_offset); - int Disconnect(); //const std::string &client_account, int &flags); + int Disconnect(); - int CreateChronicle(std::string const &chronicle_name, const std::unordered_map &attrs + int CreateChronicle(std::string const &chronicle_name, const std::map &attrs , int &flags); int DestroyChronicle(std::string const &chronicle_name); //, int &flags); std::pair AcquireStory(std::string const &chronicle_name, std::string const &story_name - , const std::unordered_map &attrs + , const std::map &attrs , int &flags); int ReleaseStory(std::string const &chronicle_name, std::string const &story_name); //, int &flags); diff --git a/Client/src/rpcVisorClient.h b/Client/src/rpcVisorClient.h index 6f2a918a..73ecbb1e 100644 --- a/Client/src/rpcVisorClient.h +++ b/Client/src/rpcVisorClient.h @@ -2,7 +2,7 @@ #define RPC_VISOR_PORTAL_CLIENT_H #include -#include +#include #include #include #include @@ -12,10 +12,9 @@ #include #include #include -#include // remove after attrs are changed +#include #include "log.h" -#include "error.h" #include "chronolog_types.h" #include "ConnectResponseMsg.h" #include "AcquireStoryResponseMsg.h" @@ -89,7 +88,7 @@ class RpcVisorClient } int CreateChronicle(ClientId const &client_id, std::string const &name - , const std::unordered_map &attrs, int &flags) + , const std::map &attrs, int &flags) { LOG_INFO("[RPCVisorClient] Initiating creation of chronicle: Name={}, Flags={}", name.c_str() , flags); @@ -142,7 +141,7 @@ class RpcVisorClient chronolog::AcquireStoryResponseMsg AcquireStory(ClientId const &client_id, std::string const &chronicle_name, std::string const &story_name - , const std::unordered_map &attrs, const int &flags) + , const std::map &attrs, const int &flags) { LOG_INFO("[RPCVisorClient] Initiating story acquisition: ChronicleName={}, StoryName={}", chronicle_name.c_str() , story_name.c_str()); diff --git a/test/integration/Client/client_lib_metadata_rpc_test.cpp b/test/integration/Client/client_lib_metadata_rpc_test.cpp index acdde7c3..1d407a2c 100644 --- a/test/integration/Client/client_lib_metadata_rpc_test.cpp +++ b/test/integration/Client/client_lib_metadata_rpc_test.cpp @@ -63,7 +63,7 @@ int main(int argc, char**argv) for(int i = 0; i < NUM_CHRONICLE; i++) { std::string attr = std::string("Priority=High"); - std::unordered_map chronicle_attrs; + std::map chronicle_attrs; chronicle_attrs.emplace("Priority", "High"); chronicle_attrs.emplace("Date", "2023-01-15"); chronicle_attrs.emplace("IndexGranularity", "Millisecond"); @@ -104,7 +104,7 @@ int main(int argc, char**argv) flags = 2; std::string story_name(gen_random(STORY_NAME_LEN)); story_names.emplace_back(story_name); - std::unordered_map story_attrs; + std::map story_attrs; story_attrs.emplace("Priority", "High"); story_attrs.emplace("IndexGranularity", "Millisecond"); story_attrs.emplace("TieringPolicy", "Hot"); @@ -170,7 +170,7 @@ int main(int argc, char**argv) for(int i = 0; i < NUM_STORY; i++) { - std::unordered_map story_attrs; + std::map story_attrs; std::string temp_str = gen_random(STORY_NAME_LEN); ret = client.AcquireStory(chronicle_names[i].append(temp_str), temp_str, story_attrs, flags).first; assert(ret == chronolog::CL_ERR_NOT_EXIST); @@ -200,7 +200,7 @@ int main(int argc, char**argv) chronicle_names.emplace_back(chronicle_name); std::string attr = std::string("Priority=High"); int ret; - std::unordered_map chronicle_attrs; + std::map chronicle_attrs; chronicle_attrs.emplace("Priority", "High"); chronicle_attrs.emplace("IndexGranularity", "Millisecond"); chronicle_attrs.emplace("TieringPolicy", "Hot"); diff --git a/test/integration/Client/client_lib_multi_argobots_test.cpp b/test/integration/Client/client_lib_multi_argobots_test.cpp index a26a3fce..ad7671e9 100644 --- a/test/integration/Client/client_lib_multi_argobots_test.cpp +++ b/test/integration/Client/client_lib_multi_argobots_test.cpp @@ -24,18 +24,13 @@ void thread_function(void*tt) { struct thread_arg*t = (struct thread_arg*)tt; - //std::string server_ip = CHRONOLOG_CONF->RPC_CONF.CLIENT_VISOR_CONF.VISOR_END_CONF.VISOR_IP.string(); - //int base_port = CHRONOLOG_CONF->RPC_CONF.CLIENT_VISOR_CONF.VISOR_END_CONF.VISOR_BASE_PORT; - /*std::string client_id = gen_random(8); - std::string server_uri = CHRONOLOG_CONF->SOCKETS_CONF.string(); - server_uri += "://"+server_ip+":"+std::to_string(base_port);*/ int flags = 0; uint64_t offset; int ret; std::string chronicle_name; if(t->tid % 2 == 0) chronicle_name = "Chronicle_1"; else chronicle_name = "Chronicle_2"; - std::unordered_map chronicle_attrs; + std::map chronicle_attrs; chronicle_attrs.emplace("Priority", "High"); chronicle_attrs.emplace("IndexGranularity", "Millisecond"); chronicle_attrs.emplace("TieringPolicy", "Hot"); @@ -46,7 +41,7 @@ void thread_function(void*tt) ret == chronolog::CL_ERR_NO_KEEPERS); flags = 1; std::string story_name = gen_random(STORY_NAME_LEN); - std::unordered_map story_attrs; + std::map story_attrs; story_attrs.emplace("Priority", "High"); story_attrs.emplace("IndexGranularity", "Millisecond"); story_attrs.emplace("TieringPolicy", "Hot"); diff --git a/test/integration/Client/client_lib_multi_openmp_test.cpp b/test/integration/Client/client_lib_multi_openmp_test.cpp index 66fe9027..57ee259c 100644 --- a/test/integration/Client/client_lib_multi_openmp_test.cpp +++ b/test/integration/Client/client_lib_multi_openmp_test.cpp @@ -54,7 +54,7 @@ int main(int argc, char**argv) std::string chronicle_name; if(i % 2 == 0) chronicle_name = "gscs5er9TcdJ9mOgUDteDVBcI0oQjozK"; else chronicle_name = "6RPkwqX2IOpR41dVCqmWauX9RfXIuTAp"; - std::unordered_map chronicle_attrs; + std::map chronicle_attrs; chronicle_attrs.emplace("Priority", "High"); chronicle_attrs.emplace("IndexGranularity", "Millisecond"); chronicle_attrs.emplace("TieringPolicy", "Hot"); @@ -66,7 +66,7 @@ int main(int argc, char**argv) std::string story_name = gen_random(STORY_NAME_LEN); LOG_INFO("[ClientLibMultiOpenMPTest] Thread {} creating story: {}", i, story_name); - std::unordered_map story_attrs; + std::map story_attrs; story_attrs.emplace("Priority", "High"); story_attrs.emplace("IndexGranularity", "Millisecond"); story_attrs.emplace("TieringPolicy", "Hot"); diff --git a/test/integration/Client/client_lib_multi_pthread_test.cpp b/test/integration/Client/client_lib_multi_pthread_test.cpp index 0e163317..fda06b19 100644 --- a/test/integration/Client/client_lib_multi_pthread_test.cpp +++ b/test/integration/Client/client_lib_multi_pthread_test.cpp @@ -18,8 +18,6 @@ chronolog::Client*client; void thread_body(struct thread_arg*t) { LOG_INFO("[ClientLibMultiPThreadTest] Thread (ID: {}) - Starting execution.", t->tid); - //std::string server_ip = CHRONOLOG_CONF->RPC_CONF.CLIENT_VISOR_CONF.VISOR_END_CONF.VISOR_IP.string(); - //int base_port = CHRONOLOG_CONF->RPC_CONF.CLIENT_VISOR_CONF.VISOR_END_CONF.VISOR_BASE_PORT; int flags = 0; uint64_t offset; int ret; @@ -28,7 +26,7 @@ void thread_body(struct thread_arg*t) else chronicle_name = "Chronicle_1"; LOG_INFO("[ClientLibMultiPThreadTest] Thread (ID: {}) - Creating Chronicle: {}", t->tid, chronicle_name); - std::unordered_map chronicle_attrs; + std::map chronicle_attrs; chronicle_attrs.emplace("Priority", "High"); chronicle_attrs.emplace("IndexGranularity", "Millisecond"); chronicle_attrs.emplace("TieringPolicy", "Hot"); @@ -40,7 +38,7 @@ void thread_body(struct thread_arg*t) std::string story_name = gen_random(STORY_NAME_LEN); LOG_INFO("[ClientLibMultiPThreadTest] Thread (ID: {}) - Generating Story: {}", t->tid, story_name); - std::unordered_map story_attrs; + std::map story_attrs; story_attrs.emplace("Priority", "High"); story_attrs.emplace("IndexGranularity", "Millisecond"); story_attrs.emplace("TieringPolicy", "Hot"); diff --git a/test/integration/Client/client_lib_multi_storytellers.cpp b/test/integration/Client/client_lib_multi_storytellers.cpp index fafd9b99..1fb59415 100644 --- a/test/integration/Client/client_lib_multi_storytellers.cpp +++ b/test/integration/Client/client_lib_multi_storytellers.cpp @@ -31,7 +31,7 @@ void thread_body(struct thread_arg*t) chronicle_name = "CHRONICLE_1"; // Create attributes for the chronicle - std::unordered_map chronicle_attrs; + std::map chronicle_attrs; chronicle_attrs.emplace("Priority", "High"); flags = 1; @@ -42,7 +42,7 @@ void thread_body(struct thread_arg*t) // Create attributes for the story std::string story_name = gen_random(STORY_NAME_LEN); - std::unordered_map story_attrs; + std::map story_attrs; flags = 2; // Acquire the story From 31bb9a1b28a773aa0ad5f70ddab34c6ea3a46b62 Mon Sep 17 00:00:00 2001 From: Inna Brodkin Date: Tue, 4 Jun 2024 17:04:10 -0500 Subject: [PATCH 3/6] added ClientPortalServiceConf to the Client API , plus functional python bindings --- ChronoVisor/src/ChronicleMetaDirectory.cpp | 2 - Client/CMakeLists.txt | 16 +-- Client/include/ClientConfiguration.h | 115 +++++++++++++++++++++ Client/include/chronolog_client.h | 9 ++ Client/src/ChronologClient.cpp | 5 + Client/src/ChronologClientImpl.cpp | 42 ++++++++ Client/src/ChronologClientImpl.h | 3 + python_client/CMakeLists.txt | 5 +- python_client/py_chronolog_client.cpp | 62 +++++++++++ python_client/test.py | 32 ++++++ 10 files changed, 273 insertions(+), 18 deletions(-) create mode 100644 Client/include/ClientConfiguration.h create mode 100644 python_client/test.py diff --git a/ChronoVisor/src/ChronicleMetaDirectory.cpp b/ChronoVisor/src/ChronicleMetaDirectory.cpp index dca82ef6..e3fae789 100644 --- a/ChronoVisor/src/ChronicleMetaDirectory.cpp +++ b/ChronoVisor/src/ChronicleMetaDirectory.cpp @@ -51,7 +51,6 @@ int ChronicleMetaDirectory::create_chronicle(const std::string &name pChronicle->setName(name); pChronicle->setCid(cid); auto res = chronicleMap_->emplace(cid, pChronicle); - LOG_DEBUG("[ChronicleMetaDirectory] Chronicle created in {} ns", duration.count()); if(res.second) { LOG_DEBUG("[ChronicleMetaDirectory] ChronicleName={} is created", name.c_str()); @@ -114,7 +113,6 @@ int ChronicleMetaDirectory::destroy_chronicle(const std::string &name) /* No Stories in Chronicle is acquired, ready to destroy */ delete pChronicle; auto nErased = chronicleMap_->erase(cid); - LOG_DEBUG("[ChronicleMetaDirectory] Chronicle destroyed in {} ns", duration.count()); if(nErased == 1) { LOG_DEBUG("[ChronicleMetaDirectory] ChronicleName={} is destroyed", name.c_str()); diff --git a/Client/CMakeLists.txt b/Client/CMakeLists.txt index 62f44461..266349bf 100644 --- a/Client/CMakeLists.txt +++ b/Client/CMakeLists.txt @@ -42,8 +42,7 @@ target_include_directories(chronolog_client PUBLIC include target_link_libraries(chronolog_client thallium) -add_subdirectory(storyteller_test) -add_subdirectory(ChronoAdmin) +################################ # install library install( @@ -52,15 +51,8 @@ install( # Install header files install( - FILES ${HEADER_FILES} - DESTINATION ${HEADER_DEST_DIR} + FILES ${HEADER_FILES} DESTINATION include ) -#include/client.h -#include/RPCClient.h -#../ChronoAPI/ChronoLog/include/macro.h -#../ChronoAPI/ChronoLog/include/rpc.h -#../ChronoAPI/ChronoLog/include/RPCFactory.h -#../ChronoAPI/ChronoLog/include/singleton.h -#../ChronoAPI/ChronoLog/src/city.cpp -#../ChronoAPI/ChronoLog/include/city.h) +add_subdirectory(storyteller_test) +add_subdirectory(ChronoAdmin) diff --git a/Client/include/ClientConfiguration.h b/Client/include/ClientConfiguration.h new file mode 100644 index 00000000..c4356e66 --- /dev/null +++ b/Client/include/ClientConfiguration.h @@ -0,0 +1,115 @@ +#ifndef CHRONOLOG_CLIENT_CONFIGURATION_H +#define CHRONOLOG_CLIENT_CONFIGURATION_H + +#include + +namespace chronolog +{ + +typedef struct RPCProviderConf_ +{ + std::string PROTO_CONF; + std::string IP; + uint16_t BASE_PORT; + uint16_t SERVICE_PROVIDER_ID; + + [[nodiscard]] std::string to_String() const + { + return "[PROTO_CONF: " + PROTO_CONF + ", IP: " + IP + ", BASE_PORT: " + std::to_string(BASE_PORT) + + ", SERVICE_PROVIDER_ID: " + std::to_string(SERVICE_PROVIDER_ID) + "]"; + } +} RPCProviderConf; + + +typedef struct LogConf_ +{ + std::string LOGTYPE; + std::string LOGFILE; + spdlog::level::level_enum LOGLEVEL; + std::string LOGNAME; + size_t LOGFILESIZE; + size_t LOGFILENUM; + spdlog::level::level_enum FLUSHLEVEL; + + // Helper function to convert spdlog::level::level_enum to string + static std::string LevelToString(spdlog::level::level_enum level) + { + switch(level) + { + case spdlog::level::trace: + return "TRACE"; + case spdlog::level::debug: + return "DEBUG"; + case spdlog::level::info: + return "INFO"; + case spdlog::level::warn: + return "WARN"; + case spdlog::level::err: + return "ERROR"; + case spdlog::level::critical: + return "CRITICAL"; + case spdlog::level::off: + return "OFF"; + default: + return "UNKNOWN"; + } + } + + [[nodiscard]] std::string to_string() const + { + return "[TYPE: " + LOGTYPE + ", FILE: " + LOGFILE + ", LEVEL: " + LevelToString(LOGLEVEL) + ", NAME: " + + LOGNAME + ", LOGFILESIZE: " + std::to_string(LOGFILESIZE) + ", LOGFILENUM: " + + std::to_string(LOGFILENUM) + ", FLUSH LEVEL: " + LevelToString(FLUSHLEVEL) + "]"; + } +} LogConf; + +struct ClientConf +{ + RPCProviderConf VISOR_CLIENT_PORTAL_SERVICE_CONF; + LogConf CLIENT_LOG_CONF; + + ClientConf() + { + VISOR_CLIENT_PORTAL_SERVICE_CONF.PROTO_CONF = "ofi+sockets"; + VISOR_CLIENT_PORTAL_SERVICE_CONF.IP = "127.0.0.1"; + VISOR_CLIENT_PORTAL_SERVICE_CONF.BASE_PORT = 5555; + VISOR_CLIENT_PORTAL_SERVICE_CONF.SERVICE_PROVIDER_ID = 55; + + CLIENT_LOG_CONF.LOGTYPE = "file"; + CLIENT_LOG_CONF.LOGFILE = "chrono_client.log"; + CLIENT_LOG_CONF.LOGLEVEL = spdlog::level::info; + CLIENT_LOG_CONF.LOGFILESIZE = 104857600; + CLIENT_LOG_CONF.LOGFILENUM = 3; + CLIENT_LOG_CONF.FLUSHLEVEL = spdlog::level::warn; + + }; + + [[nodiscard]] std::string to_string() const + { + return "[VISOR_CLIENT_PORTAL_SERVICE_CONF: " + VISOR_CLIENT_PORTAL_SERVICE_CONF.to_String() + + ", CLIENT_LOG_CONF:" + CLIENT_LOG_CONF.to_string() + "]"; + } +}; + +struct ClientPortalServiceConf +{ + ClientPortalServiceConf( const std::string & protocol, const std::string & service_ip, uint16_t service_port, uint16_t service_provider_id) + : proto_conf_(protocol) + , ip_(service_ip) + , port_(service_port) + , provider_id_(service_provider_id) + {} + + std::string const & proto_conf() const { return proto_conf_; } + std::string const & ip() const { return ip_; } + uint16_t port() const { return port_; } + uint16_t provider_id() const { return provider_id_; } + + std::string proto_conf_; + std::string ip_; + uint16_t port_; + uint16_t provider_id_; +}; + +} +#endif diff --git a/Client/include/chronolog_client.h b/Client/include/chronolog_client.h index 16ec22ce..5084c483 100644 --- a/Client/include/chronolog_client.h +++ b/Client/include/chronolog_client.h @@ -7,6 +7,13 @@ #include "ConfigurationManager.h" //TODO: not sure this is a good idea , but will keep it for now ... +#include "ClientConfiguration.h" + +//TODO: rename Client to be ChronologClient +//TODO: remove ConfigurationManager from chronolog_client include fiels , should only be in the implementation files +// if needed at all + + namespace chronolog { @@ -29,6 +36,8 @@ class Client { public: Client(ChronoLog::ConfigurationManager const &); + + Client(ClientPortalServiceConf const &); ~Client(); diff --git a/Client/src/ChronologClient.cpp b/Client/src/ChronologClient.cpp index 3ae14753..0abb0093 100644 --- a/Client/src/ChronologClient.cpp +++ b/Client/src/ChronologClient.cpp @@ -6,6 +6,11 @@ chronolog::Client::Client(ChronoLog::ConfigurationManager const &confManager) chronologClientImpl = chronolog::ChronologClientImpl::GetClientImplInstance(confManager); } +chronolog::Client::Client(chronolog::ClientPortalServiceConf const &visorClientPortalServiceConf) +{ + chronologClientImpl = chronolog::ChronologClientImpl::GetClientImplInstance(visorClientPortalServiceConf); +} + chronolog::Client::~Client() { delete chronologClientImpl; diff --git a/Client/src/ChronologClientImpl.cpp b/Client/src/ChronologClientImpl.cpp index 6060e1bc..b08dae81 100644 --- a/Client/src/ChronologClientImpl.cpp +++ b/Client/src/ChronologClientImpl.cpp @@ -22,6 +22,22 @@ chronolog::ChronologClientImpl::GetClientImplInstance(ChronoLog::ConfigurationMa return chronologClientImplInstance; } + +chronolog::ChronologClientImpl* +chronolog::ChronologClientImpl::GetClientImplInstance(chronolog::ClientPortalServiceConf const & visorClientPortalServiceConf) +{ + Logger::initialize("file", "/tmp/chrono_client.log", spdlog::level::info, "chrono_client", 1024000,3, spdlog::level::warn); + + std::lock_guard lock_client(chronologClientMutex); + + if(chronologClientImplInstance == nullptr) + { + chronologClientImplInstance = new ChronologClientImpl(visorClientPortalServiceConf); + } + + return chronologClientImplInstance; +} + //////// chronolog::ChronologClientImpl::ChronologClientImpl(const ChronoLog::ConfigurationManager &confManager): clientState( UNKNOWN), clientLogin(""), hostId(0), pid(0), clientId(0), tlEngine(nullptr), rpcVisorClient(nullptr) @@ -42,6 +58,32 @@ chronolog::ChronologClientImpl::ChronologClientImpl(const ChronoLog::Configurati rpcVisorClient = chl::RpcVisorClient::CreateRpcVisorClient(*tlEngine, CLIENT_VISOR_NA_STRING , confManager.CLIENT_CONF.VISOR_CLIENT_PORTAL_SERVICE_CONF.RPC_CONF.SERVICE_PROVIDER_ID); } +/////////////// + +chronolog::ChronologClientImpl::ChronologClientImpl(const chronolog::ClientPortalServiceConf & clientPortalServiceConf) + : clientState( + UNKNOWN) + , clientLogin("") + , hostId(0), pid(0), clientId(0) + , tlEngine(nullptr) + , rpcVisorClient(nullptr) + , storyteller(nullptr) +{ + //pClocksourceManager_ = ClocksourceManager::getInstance(); + //pClocksourceManager_->setClocksourceType(CHRONOLOG_CONF->CLOCKSOURCE_TYPE); + + defineClientIdentity(); + tlEngine = new thallium::engine(clientPortalServiceConf.proto_conf() + , THALLIUM_CLIENT_MODE, true, 1); + + std::string CLIENT_VISOR_NA_STRING = + clientPortalServiceConf.proto_conf() + "://" + + clientPortalServiceConf.ip() + ":" + + std::to_string(clientPortalServiceConf.port()); + + rpcVisorClient = chl::RpcVisorClient::CreateRpcVisorClient(*tlEngine, CLIENT_VISOR_NA_STRING + , clientPortalServiceConf.provider_id()); +} //////// diff --git a/Client/src/ChronologClientImpl.h b/Client/src/ChronologClientImpl.h index 0ec93c61..13707f0b 100644 --- a/Client/src/ChronologClientImpl.h +++ b/Client/src/ChronologClientImpl.h @@ -3,6 +3,7 @@ #include "chronolog_errcode.h" #include "ConfigurationManager.h" +#include "ClientConfiguration.h" //#include "ClocksourceManager.h" #include "chronolog_types.h" @@ -33,6 +34,7 @@ class ChronologClientImpl static ChronologClientImpl*chronologClientImplInstance; static ChronologClientImpl*GetClientImplInstance(ChronoLog::ConfigurationManager const &); + static ChronologClientImpl*GetClientImplInstance(chronolog::ClientPortalServiceConf const &); // the classs is non-copyable ChronologClientImpl(ChronologClientImpl const &) = delete; @@ -79,6 +81,7 @@ class ChronologClientImpl // ClocksourceManager *pClocksourceManager_; ChronologClientImpl(const ChronoLog::ConfigurationManager &conf_manager); + ChronologClientImpl(const chronolog::ClientPortalServiceConf &); ChronologClientImpl(std::string const &protocol, const std::string &visor_ip, int visor_port , uint16_t service_provider); diff --git a/python_client/CMakeLists.txt b/python_client/CMakeLists.txt index 48dc965c..0b028044 100644 --- a/python_client/CMakeLists.txt +++ b/python_client/CMakeLists.txt @@ -22,7 +22,4 @@ target_link_libraries(py_chronolog_client PUBLIC ################################### # Install targets ################################## - -#install(TARGETS py_chronolog_client -# LIBRARY_DESTINATION ${CMAKE_INSTALL_LIBDIR} -# ARCHIVE_DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(TARGETS py_chronolog_client DESTINATION lib) diff --git a/python_client/py_chronolog_client.cpp b/python_client/py_chronolog_client.cpp index c3da61ee..30573079 100644 --- a/python_client/py_chronolog_client.cpp +++ b/python_client/py_chronolog_client.cpp @@ -5,3 +5,65 @@ #include + +using chronolog::ClientPortalServiceConf; +using chronolog::Client; + +void BindChronologClientPortalServiceConf(pybind11::module &m) +{ + pybind11::class_(m,"ClientPortalServiceConf") + .def(pybind11::init()) + .def("proto_conf", &ClientPortalServiceConf::proto_conf) + .def("ip", &ClientPortalServiceConf::ip) + .def("port", &ClientPortalServiceConf::port) + .def("provider_id", &ClientPortalServiceConf::provider_id); +}; + +using chronolog::StoryHandle; +class PyStoryHandle : public StoryHandle +{ +public: + /* Inherit the constructors */ + using StoryHandle::StoryHandle; + + /* Trampoline (need one for each virtual function) */ + int log_event(std::string const & event_string) override { + PYBIND11_OVERRIDE_PURE( + int, /* Return type */ + StoryHandle, /* Parent class */ + log_event, /* Name of function in C++ (must match Python name) */ + event_string /* Argument(s) */ + ); + } +}; + +void BindChronologStoryHandle(pybind11::module &m) +{ + pybind11::class_(m, "StoryHandle") + .def(pybind11::init<>()) + .def("log_event",&StoryHandle::log_event, pybind11::arg("log_string") ); + +}; + +PYBIND11_MAKE_OPAQUE(std::pair); + +void BindChronologClient(pybind11::module &m) +{ + pybind11::class_(m,"Client") + .def(pybind11::init()) + .def("Connect", &Client::Connect) + .def("Disconnect", &Client::Disconnect) + .def("CreateChronicle", &Client::CreateChronicle) + .def("DestroyChronicle", &Client::DestroyChronicle) + .def("AcquireStory", &Client::AcquireStory, pybind11::return_value_policy::reference) + .def("ReleaseStory", &Client::ReleaseStory, pybind11::arg("chronicle_name"), pybind11::arg("story_name")) + .def("DestroyStory", &Client::DestroyStory, pybind11::arg("chronicle_name"), pybind11::arg("story_name")); + +}; + +PYBIND11_MODULE(py_chronolog_client, m) +{ + BindChronologClientPortalServiceConf(m); + BindChronologStoryHandle(m); + BindChronologClient(m); +} diff --git a/python_client/test.py b/python_client/test.py new file mode 100644 index 00000000..c6ac153b --- /dev/null +++ b/python_client/test.py @@ -0,0 +1,32 @@ + +//make install + +// currently CMAKE_INSTALL_LIBDIR=/home/ENV{USERNAME}/chronolog/lib + +// create symlink for py_chronolog_client.[linux_distibution_version].so +// ln -s ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.so ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.[linux_distribution_version].so + +//update LD_LIBRARY_PATH +// export LD_LIBRARY_PATH=${CMAKE_INSTALL_LIBDIR}:${LD_LIBRARY_PATH} +//update PYTHONPATH +// export PYTHONPATH=${CMAKE_INSTALL_LIBDIR}:${PYTHONPATH} + + +//using spack installed python3 version + +>>> import py_chronolog_client + +>>> attrs=dict(); +>>> clientConf = py_chronolog_client.ClientPortalServiceConf("ofi+sockets","127.0.0.1",5555,55); + +>>> client = py_chronolog_client.Client(clientConf); + +>>> client.CreateChronicle("py_chronicle", attrs, 1); +-15 +>>> client.DestroyChronicle("py_chronicle"); +-15 +>>> return_pair = client.AcquireStory("py_chronicle", "my_story", attrs, 1); +>>> print(return_pair) +(-15, None) +>>> + From ce2a100d005520ca5aa26548f5fec8d5e4bc6a9e Mon Sep 17 00:00:00 2001 From: Inna Brodkin Date: Thu, 6 Jun 2024 13:12:47 -0500 Subject: [PATCH 4/6] default logger parameters --- ChronoAPI/ChronoLog/include/log.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ChronoAPI/ChronoLog/include/log.h b/ChronoAPI/ChronoLog/include/log.h index b4124fe1..332ff827 100644 --- a/ChronoAPI/ChronoLog/include/log.h +++ b/ChronoAPI/ChronoLog/include/log.h @@ -54,7 +54,6 @@ #define LOG_ERROR(...) Logger::getInstance().error(__VA_ARGS__) #define LOG_CRITICAL(...) Logger::getInstance().critical(__VA_ARGS__) - /** * @class Logger * @brief The Logger class provides a singleton logger with customizable configuration. @@ -86,8 +85,10 @@ class Logger * and returns 1 if there was an error during initialization. */ static int initialize(const std::string &logType, const std::string &location, spdlog::level::level_enum logLevel - , const std::string &loggerName, const std::size_t &logFileSize, const std::size_t &logFileNum - , spdlog::level::level_enum flushLevel); + , const std::string &loggerName + , const std::size_t &logFileSize = 104857600 + , const std::size_t &logFileNum = 3 + , spdlog::level::level_enum flushLevel = spdlog::level::warn); /** From 1b7cf5aa1966bea1c4c52a72aa7a680553c7faae Mon Sep 17 00:00:00 2001 From: Inna Brodkin Date: Thu, 6 Jun 2024 17:07:21 -0500 Subject: [PATCH 5/6] added basic python example --- Client/include/ClientConfiguration.h | 86 ---------------------------- python_client/test.py | 60 +++++++++++++------ 2 files changed, 42 insertions(+), 104 deletions(-) diff --git a/Client/include/ClientConfiguration.h b/Client/include/ClientConfiguration.h index c4356e66..f1e18317 100644 --- a/Client/include/ClientConfiguration.h +++ b/Client/include/ClientConfiguration.h @@ -1,96 +1,10 @@ #ifndef CHRONOLOG_CLIENT_CONFIGURATION_H #define CHRONOLOG_CLIENT_CONFIGURATION_H -#include namespace chronolog { -typedef struct RPCProviderConf_ -{ - std::string PROTO_CONF; - std::string IP; - uint16_t BASE_PORT; - uint16_t SERVICE_PROVIDER_ID; - - [[nodiscard]] std::string to_String() const - { - return "[PROTO_CONF: " + PROTO_CONF + ", IP: " + IP + ", BASE_PORT: " + std::to_string(BASE_PORT) + - ", SERVICE_PROVIDER_ID: " + std::to_string(SERVICE_PROVIDER_ID) + "]"; - } -} RPCProviderConf; - - -typedef struct LogConf_ -{ - std::string LOGTYPE; - std::string LOGFILE; - spdlog::level::level_enum LOGLEVEL; - std::string LOGNAME; - size_t LOGFILESIZE; - size_t LOGFILENUM; - spdlog::level::level_enum FLUSHLEVEL; - - // Helper function to convert spdlog::level::level_enum to string - static std::string LevelToString(spdlog::level::level_enum level) - { - switch(level) - { - case spdlog::level::trace: - return "TRACE"; - case spdlog::level::debug: - return "DEBUG"; - case spdlog::level::info: - return "INFO"; - case spdlog::level::warn: - return "WARN"; - case spdlog::level::err: - return "ERROR"; - case spdlog::level::critical: - return "CRITICAL"; - case spdlog::level::off: - return "OFF"; - default: - return "UNKNOWN"; - } - } - - [[nodiscard]] std::string to_string() const - { - return "[TYPE: " + LOGTYPE + ", FILE: " + LOGFILE + ", LEVEL: " + LevelToString(LOGLEVEL) + ", NAME: " + - LOGNAME + ", LOGFILESIZE: " + std::to_string(LOGFILESIZE) + ", LOGFILENUM: " + - std::to_string(LOGFILENUM) + ", FLUSH LEVEL: " + LevelToString(FLUSHLEVEL) + "]"; - } -} LogConf; - -struct ClientConf -{ - RPCProviderConf VISOR_CLIENT_PORTAL_SERVICE_CONF; - LogConf CLIENT_LOG_CONF; - - ClientConf() - { - VISOR_CLIENT_PORTAL_SERVICE_CONF.PROTO_CONF = "ofi+sockets"; - VISOR_CLIENT_PORTAL_SERVICE_CONF.IP = "127.0.0.1"; - VISOR_CLIENT_PORTAL_SERVICE_CONF.BASE_PORT = 5555; - VISOR_CLIENT_PORTAL_SERVICE_CONF.SERVICE_PROVIDER_ID = 55; - - CLIENT_LOG_CONF.LOGTYPE = "file"; - CLIENT_LOG_CONF.LOGFILE = "chrono_client.log"; - CLIENT_LOG_CONF.LOGLEVEL = spdlog::level::info; - CLIENT_LOG_CONF.LOGFILESIZE = 104857600; - CLIENT_LOG_CONF.LOGFILENUM = 3; - CLIENT_LOG_CONF.FLUSHLEVEL = spdlog::level::warn; - - }; - - [[nodiscard]] std::string to_string() const - { - return "[VISOR_CLIENT_PORTAL_SERVICE_CONF: " + VISOR_CLIENT_PORTAL_SERVICE_CONF.to_String() + - ", CLIENT_LOG_CONF:" + CLIENT_LOG_CONF.to_string() + "]"; - } -}; - struct ClientPortalServiceConf { ClientPortalServiceConf( const std::string & protocol, const std::string & service_ip, uint16_t service_port, uint16_t service_provider_id) diff --git a/python_client/test.py b/python_client/test.py index c6ac153b..0be074ac 100644 --- a/python_client/test.py +++ b/python_client/test.py @@ -1,32 +1,56 @@ -//make install +# make install -// currently CMAKE_INSTALL_LIBDIR=/home/ENV{USERNAME}/chronolog/lib +# currently CMAKE_INSTALL_LIBDIR=/home/ENV{USERNAME}/chronolog/lib -// create symlink for py_chronolog_client.[linux_distibution_version].so -// ln -s ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.so ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.[linux_distribution_version].so +## create symlink for py_chronolog_client.[linux_distibution_version].so +## ln -s ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.so ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.[linux_distribution_version].so -//update LD_LIBRARY_PATH -// export LD_LIBRARY_PATH=${CMAKE_INSTALL_LIBDIR}:${LD_LIBRARY_PATH} -//update PYTHONPATH -// export PYTHONPATH=${CMAKE_INSTALL_LIBDIR}:${PYTHONPATH} +## update LD_LIBRARY_PATH +## export LD_LIBRARY_PATH=${CMAKE_INSTALL_LIBDIR}:${LD_LIBRARY_PATH} +## update PYTHONPATH +## export PYTHONPATH=${CMAKE_INSTALL_LIBDIR}:${PYTHONPATH} -//using spack installed python3 version +## using spack installed python3 version ->>> import py_chronolog_client +############################# ->>> attrs=dict(); ->>> clientConf = py_chronolog_client.ClientPortalServiceConf("ofi+sockets","127.0.0.1",5555,55); +import py_chronolog_client ->>> client = py_chronolog_client.Client(clientConf); +>>>attrs=dict(); +>>>clientConf = py_chronolog_client.ClientPortalServiceConf("ofi+sockets","127.0.0.1",5555,55); + +>>>client = py_chronolog_client.Client(clientConf); + +>>>return_pair = client.AcquireStory("py_chronicle", "my_story", attrs, 1); +>>>print(return_pair) +(-15, None) +>>> + +>>> client.Connect() +0 >>> client.CreateChronicle("py_chronicle", attrs, 1); --15 ->>> client.DestroyChronicle("py_chronicle"); --15 +0 >>> return_pair = client.AcquireStory("py_chronicle", "my_story", attrs, 1); >>> print(return_pair) -(-15, None) ->>> +(0, ) +>>> print(return_pair[1]) + + +>>> return_pair[1].log_event("py_event") +1 +>>> return_pair[1].log_event("py_event.2") +1 +>>> return_pair[1].log_event("py_event.3") +1 +>>> return_pair[1].log_event("py_event.4") +1 +>>> client.ReleaseStory("py_chronicle","py_story"); +-3 +>>> client.ReleaseStory("py_chronicle","my_story"); +0 +>>> client.Disconnect() +0 From 7e8c79bde395e348ecbbefba996f682d3ccbbd8f Mon Sep 17 00:00:00 2001 From: Inna Brodkin Date: Fri, 7 Jun 2024 15:30:50 -0500 Subject: [PATCH 6/6] cleaned up python_client/test.py --- CMakeLists.txt | 8 +-- python_client/test.py | 125 +++++++++++++++++++++++++++--------------- spack.yaml | 2 - 3 files changed, 85 insertions(+), 50 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a1f4b06f..d9520306 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -219,7 +219,7 @@ if(CHRONOLOG_BUILD_TESTING) add_subdirectory(test) endif() -if(CHRONOLOG_ENABLE_PYTHON_BINDINGS) - message("Python binding enabled") - add_subdirectory(python_client) -endif() +#if(CHRONOLOG_ENABLE_PYTHON_BINDINGS) +message("Python binding enabled") +add_subdirectory(python_client) +#endif() diff --git a/python_client/test.py b/python_client/test.py index 0be074ac..379c2ac9 100644 --- a/python_client/test.py +++ b/python_client/test.py @@ -1,10 +1,15 @@ -# make install +# ChronoLog project uses this default installation directory +# CMAKE_INSTALL_LIBDIR=/home/ENV{USERNAME}/chronolog/lib +# +# "make install" will build chronolog_client.so and py_chronolog_client.[python-version-linux-version].so +# and place them under ${CMAKE_INSTALL_LIBDIR} +# -# currently CMAKE_INSTALL_LIBDIR=/home/ENV{USERNAME}/chronolog/lib - -## create symlink for py_chronolog_client.[linux_distibution_version].so -## ln -s ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.so ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.[linux_distribution_version].so +## create symlink for py_chronolog_client.[python-version-linux-version].so +# so that you can import the binding module as "py_chronolog_client" in Python code +# +## ln -s ${CMAKE_INSTALL_LIBDIR}/py_chronolog_client.[python-version-linux-version].so {CMAKE_INSTALL_LIBDIR}/py_chronolog_client.so ## update LD_LIBRARY_PATH ## export LD_LIBRARY_PATH=${CMAKE_INSTALL_LIBDIR}:${LD_LIBRARY_PATH} @@ -12,45 +17,77 @@ ## export PYTHONPATH=${CMAKE_INSTALL_LIBDIR}:${PYTHONPATH} -## using spack installed python3 version - +## use ChronoLog spack installed python3 version to avoid version mismatch +# +# for example to run the basic test below +# +# ${CHRONOLOG_SOURCE_DIR}/.spack-env/view/bin/python3 ${CHRONOLOG_SOURCE_DIR}/python_client/test.py +# +# ############################# -import py_chronolog_client - ->>>attrs=dict(); - ->>>clientConf = py_chronolog_client.ClientPortalServiceConf("ofi+sockets","127.0.0.1",5555,55); - ->>>client = py_chronolog_client.Client(clientConf); - ->>>return_pair = client.AcquireStory("py_chronicle", "my_story", attrs, 1); ->>>print(return_pair) -(-15, None) ->>> - ->>> client.Connect() -0 ->>> client.CreateChronicle("py_chronicle", attrs, 1); -0 ->>> return_pair = client.AcquireStory("py_chronicle", "my_story", attrs, 1); ->>> print(return_pair) -(0, ) ->>> print(return_pair[1]) - - ->>> return_pair[1].log_event("py_event") -1 ->>> return_pair[1].log_event("py_event.2") -1 ->>> return_pair[1].log_event("py_event.3") -1 ->>> return_pair[1].log_event("py_event.4") -1 ->>> client.ReleaseStory("py_chronicle","py_story"); --3 ->>> client.ReleaseStory("py_chronicle","my_story"); -0 ->>> client.Disconnect() -0 +def main(): + + print("Basic test for py_chronolog_client") + + # NOTE: if you having issues importing py_chronolog_client + # see post installation instructions at the top of this file + + import py_chronolog_client + + #create ClientPortalServiceConf instance with the connection credentials to ChronoVisor ClientPortalService + + clientConf = py_chronolog_client.ClientPortalServiceConf("ofi+sockets","127.0.0.1",5555,55); + + # instantiate ChronoLog Client object + client = py_chronolog_client.Client(clientConf); + + #try to acquire the story + # this should fail as the connection to the ChronoVisor hasn't been established yet + attrs=dict(); + return_tuple = client.AcquireStory("py_chronicle", "my_story", attrs, 1); + print("\n Attempt to acquire story without ChronoVisor connection returns : ", return_tuple) + # (-15, None) + + + # Connect to the ChronoVisor for client authentication + # returns 0 on success and error_cde otherwise + return_code = client.Connect() + print( "\n client.Connect() call returns:", return_code) + + #create chronicle + return_code = client.CreateChronicle("py_chronicle", attrs, 1); + print("\n clientCreateCronicle() returned", return_code); + + # acquire story that is part of "py_chronicle" + # returns a tuple [0, StoryHandle] on success + # and [error_code,None] otherwise + return_tuple = client.AcquireStory("py_chronicle", "my_story", attrs, 1); + + print( "\n client.AcquireStory() returned:" , return_tuple) + + if( return_tuple[0] == 0): + + print( "\n Aquired Story = my_story within chronicle = py_chronicle"); + + print("\n logging 4 events for my_story using the StoryHandle"); + return_tuple[1].log_event("py_event"); + return_tuple[1].log_event("py_event.2"); + return_tuple[1].log_event("py_event.3"); + return_tuple[1].log_event("py_event.4"); + + + # release acquired Story + # returns 0 on success and error_code othewise + return_code = client.ReleaseStory("py_chronicle","my_story"); + print("\n client.ReleaseStory() returned:", return_code); + + + + # Disconenct the client from ChronoLog system + # returns 0 on success and error_code otherwise + return_code = client.Disconnect() + print("\n client.Disconnect() returned:", return_code); +if __name__=="__main__": + main() diff --git a/spack.yaml b/spack.yaml index 55899deb..899fbc80 100644 --- a/spack.yaml +++ b/spack.yaml @@ -9,6 +9,4 @@ spack: - mercury@2.2.0~boostsys ^libfabric@1.16.1 fabrics=mlx,rxd,rxm,shm,sockets,tcp,udp,verbs - hdf5@1.14.1-2 +cxx - py-pybind11@2.11.1 - - python3-dev -# - py-pybind11@2.12.0 view: true