This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/print_function_for_dm_info in repository https://gitbox.apache.org/repos/asf/celix.git
commit d6afb40aa1b2cf00ba9f80cf8f2e4d800b12f55f Author: Pepijn Noltes <[email protected]> AuthorDate: Sun Jun 26 19:15:18 2022 +0200 Adds print functions for dependency manager and dm cmp and refactors dm command to use these functions --- bundles/shell/shell/src/dm_shell_list_command.c | 104 +-------------------- .../gtest/src/DependencyManagerTestSuite.cc | 64 +++++++++++++ libs/framework/include/celix/dm/Component.h | 8 +- libs/framework/include/celix/dm/Component_Impl.h | 18 +++- .../framework/include/celix/dm/DependencyManager.h | 12 ++- .../include/celix/dm/DependencyManager_Impl.h | 11 +++ libs/framework/include/celix_dependency_manager.h | 59 +++++++----- libs/framework/include/celix_dm_component.h | 23 +++-- libs/framework/include/celix_dm_info.h | 6 +- libs/framework/src/dm_component_impl.c | 95 +++++++++++++++++-- libs/framework/src/dm_dependency_manager_impl.c | 27 +++++- libs/utils/include/celix/Utils.h | 32 +++++++ 12 files changed, 317 insertions(+), 142 deletions(-) diff --git a/bundles/shell/shell/src/dm_shell_list_command.c b/bundles/shell/shell/src/dm_shell_list_command.c index df1fdcac..cfe625c9 100644 --- a/bundles/shell/shell/src/dm_shell_list_command.c +++ b/bundles/shell/shell/src/dm_shell_list_command.c @@ -23,12 +23,7 @@ #include "celix_shell_constants.h" #include "celix_bundle_context.h" #include "celix_dependency_manager.h" - - -static const char * const OK_COLOR = "\033[92m"; -static const char * const WARNING_COLOR = "\033[93m"; -static const char * const NOK_COLOR = "\033[91m"; -static const char * const END_COLOR = "\033[m"; +#include "celix_dm_component.h" static void parseCommandLine(const char*line, celix_array_list_t **requestedBundleIds, bool *fullInfo, bool *wtf, FILE *err) { *fullInfo = false; @@ -54,91 +49,11 @@ static void parseCommandLine(const char*line, celix_array_list_t **requestedBund free (str); } -static void printFullInfo(FILE *out, bool colors, long bundleId, const char* bndName, dm_component_info_pt compInfo) { - const char *startColors = ""; - const char *endColors = ""; - if (colors) { - startColors = compInfo->active ? OK_COLOR : NOK_COLOR; - endColors = END_COLOR; - } - fprintf(out, "%sComponent: Name=%s%s\n", startColors, compInfo->name, endColors); - fprintf(out, "|- UUID = %s\n", compInfo->id); - fprintf(out, "|- Active = %s\n", compInfo->active ? "true" : "false"); - fprintf(out, "|- State = %s\n", compInfo->state); - fprintf(out, "|- Bundle = %li (%s)\n", bundleId, bndName); - fprintf(out, "|- Nr of times started = %i\n", (int)compInfo->nrOfTimesStarted); - fprintf(out, "|- Nr of times resumed = %i\n", (int)compInfo->nrOfTimesResumed); - - fprintf(out, "|- Interfaces (%d):\n", celix_arrayList_size(compInfo->interfaces)); - for (int interfCnt = 0; interfCnt < celix_arrayList_size(compInfo->interfaces); interfCnt++) { - dm_interface_info_pt intfInfo = celix_arrayList_get(compInfo->interfaces, interfCnt); - fprintf(out, " |- %sInterface %i: %s%s\n", startColors, (interfCnt+1), intfInfo->name, endColors); - - hash_map_iterator_t iter = hashMapIterator_construct((hash_map_pt) intfInfo->properties); - char *key = NULL; - while ((key = hashMapIterator_nextKey(&iter)) != NULL) { - fprintf(out, " | %15s = %s\n", key, celix_properties_get(intfInfo->properties, key, "!ERROR!")); - } - } - - fprintf(out, "|- Dependencies (%d):\n", celix_arrayList_size(compInfo->dependency_list)); - for (int depCnt = 0; depCnt < celix_arrayList_size(compInfo->dependency_list); ++depCnt) { - dm_service_dependency_info_pt dependency; - dependency = celix_arrayList_get(compInfo->dependency_list, depCnt); - const char *depStartColors = ""; - if (colors) { - if (dependency->required) { - depStartColors = dependency->available ? OK_COLOR : NOK_COLOR; - } else { - depStartColors = dependency->available ? OK_COLOR : WARNING_COLOR; - } - } - fprintf(out, " |- %sDependency %i: %s%s\n", depStartColors, (depCnt+1), dependency->serviceName == NULL ? "(any)" : dependency->serviceName, endColors); - fprintf(out, " | %15s = %s\n", "Available", dependency->available ? "true " : "false"); - fprintf(out, " | %15s = %s\n", "Required", dependency->required ? "true " : "false"); - fprintf(out, " | %15s = %s\n", "Version Range", dependency->versionRange == NULL ? "N/A" : dependency->versionRange); - fprintf(out, " | %15s = %s\n", "Filter", dependency->filter == NULL ? "N/A" : dependency->filter); - } - fprintf(out, "\n"); - -} - -static void printBasicInfo(FILE *out, bool colors, long bundleId, const char* bndName, dm_component_info_pt compInfo) { - const char *startColors = ""; - const char *endColors = ""; - if (colors) { - startColors = compInfo->active ? OK_COLOR : NOK_COLOR; - endColors = END_COLOR; - } - fprintf(out, "Component: Name=%s, ID=%s, %sActive=%s%s, State=%s, Bundle=%li (%s)\n", compInfo->name, compInfo->id, - startColors, compInfo->active ? "true " : "false", endColors, compInfo->state, bundleId, bndName); - -} - -static void dm_printInfo(FILE *out, bool useColors, bool fullInfo, celix_dependency_manager_info_t *info) { - if (info != NULL) { - int size = celix_arrayList_size(info->components); - if (size > 0) { - for (unsigned int cmpCnt = 0; cmpCnt < size; cmpCnt++) { - dm_component_info_pt compInfo = celix_arrayList_get(info->components, cmpCnt); - if (fullInfo) { - printFullInfo(out, useColors, info->bndId, info->bndSymbolicName, compInfo); - } else { - printBasicInfo(out, useColors, info->bndId, info->bndSymbolicName, compInfo); - } - } - fprintf(out, "\n"); - } - } -} - celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE *err) { celix_bundle_context_t *ctx = handle; celix_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(ctx); - const char *config = NULL; - bundleContext_getPropertyWithDefault(ctx, CELIX_SHELL_USE_ANSI_COLORS, CELIX_SHELL_USE_ANSI_COLORS_DEFAULT_VALUE, &config); - bool useColors = config != NULL && strncmp("true", config, 5) == 0; + bool useColors = celix_bundleContext_getPropertyAsBool(ctx, CELIX_SHELL_USE_ANSI_COLORS, CELIX_SHELL_USE_ANSI_COLORS_DEFAULT_VALUE); celix_array_list_t *bundleIds = NULL; bool fullInfo = false; @@ -157,7 +72,7 @@ celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE nrOfComponents += 1; if (!cmpInfo->active) { allActive = false; - printFullInfo(out, useColors, info->bndId, info->bndSymbolicName, cmpInfo); + celix_dmComponent_printComponentInfo(cmpInfo, true, useColors, out); } } } @@ -166,20 +81,11 @@ celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE fprintf(out, "No problem all %i dependency manager components are active\n", nrOfComponents); } } else if (celix_arrayList_size(bundleIds) == 0) { - celix_array_list_t *infos = celix_dependencyManager_createInfos(mng); - for (int i = 0; i < celix_arrayList_size(infos); ++i) { - celix_dependency_manager_info_t *info = celix_arrayList_get(infos, i); - dm_printInfo(out, useColors, fullInfo, info); - } - celix_dependencyManager_destroyInfos(mng, infos); + celix_dependencyManager_printInfo(mng, fullInfo, useColors, out); } else { for (int i = 0; i < celix_arrayList_size(bundleIds); ++i) { long bndId = celix_arrayList_getLong(bundleIds, i); - celix_dependency_manager_info_t *info = celix_dependencyManager_createInfo(mng, bndId); - if (info != NULL) { - dm_printInfo(out, useColors, fullInfo, info); - celix_dependencyManager_destroyInfo(mng, info); - } + celix_dependencyManager_printInfoForBundle(mng, fullInfo, useColors, bndId, out); } } diff --git a/libs/framework/gtest/src/DependencyManagerTestSuite.cc b/libs/framework/gtest/src/DependencyManagerTestSuite.cc index d9939fbb..dab657a7 100644 --- a/libs/framework/gtest/src/DependencyManagerTestSuite.cc +++ b/libs/framework/gtest/src/DependencyManagerTestSuite.cc @@ -1117,4 +1117,68 @@ TEST_F(DependencyManagerTestSuite, CreateInterfaceWithStaticInfo) { EXPECT_EQ(it->second, "1.2.3"); } +TEST_F(DependencyManagerTestSuite, TestPrintInfo) { + celix::dm::DependencyManager dm{ctx}; + auto& cmp = dm.createComponent<Cmp1>(); + cmp.addInterface<TestService>(); + cmp.createServiceDependency<TestInterfaceWithStaticInfo>(); + cmp.build(); + + char* buf = nullptr; + size_t bufLen = 0; + FILE* testStream = open_memstream(&buf, &bufLen); + celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), true, true, testStream); + fclose(testStream); + std::cout << buf << std::endl; + EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name + EXPECT_TRUE(strstr(buf, "TestService")); //provided service name + EXPECT_TRUE(strstr(buf, "TestName")); //service dependency name + free(buf); + + buf = nullptr; + bufLen = 0; + testStream = open_memstream(&buf, &bufLen); + celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), true, false, testStream); + fclose(testStream); + EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name + EXPECT_TRUE(strstr(buf, "TestService")); //provided service name + EXPECT_TRUE(strstr(buf, "TestName")); //service dependency name + free(buf); + + buf = nullptr; + bufLen = 0; + testStream = open_memstream(&buf, &bufLen); + celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), false, true, testStream); + fclose(testStream); + EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name + free(buf); + + buf = nullptr; + bufLen = 0; + testStream = open_memstream(&buf, &bufLen); + celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), false, false, testStream); + fclose(testStream); + EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name + free(buf); + + buf = nullptr; + bufLen = 0; + testStream = open_memstream(&buf, &bufLen); + celix_dependencyManager_printInfoForBundle(celix_bundleContext_getDependencyManager(ctx), true, true, 0, testStream); + fclose(testStream); + EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name + free(buf); + + //bundle does not exist -> empty print + celix_dependencyManager_printInfoForBundle(celix_bundleContext_getDependencyManager(ctx), true, true, 1 /*non existing*/, stdout); + + std::stringstream ss{}; + ss << dm; + EXPECT_TRUE(strstr(ss.str().c_str(), "Cmp1")); + + ss = std::stringstream{}; + ss << cmp; + EXPECT_TRUE(strstr(ss.str().c_str(), "Cmp1")); +} + #endif \ No newline at end of file diff --git a/libs/framework/include/celix/dm/Component.h b/libs/framework/include/celix/dm/Component.h index d101b35f..f3780f8d 100644 --- a/libs/framework/include/celix/dm/Component.h +++ b/libs/framework/include/celix/dm/Component.h @@ -28,7 +28,7 @@ #include <iostream> #include <type_traits> #include <algorithm> - +#include <cstdio> #include "dm_component.h" #include "celix/dm/types.h" @@ -137,6 +137,8 @@ namespace celix { namespace dm { * The underlining service registration and service tracker will be registered/created async. */ void runBuild(); + + friend std::ostream& operator<<(std::ostream& out, const BaseComponent& cmp); protected: celix_bundle_context_t* context; celix_dependency_manager_t* cDepMan; @@ -152,6 +154,10 @@ namespace celix { namespace dm { std::vector<std::shared_ptr<void>> componentContexts{}; }; + /** + * Stream outputs the full component info. + */ + inline std::ostream& operator<<(std::ostream& out, const BaseComponent& cmp); template<class T> class Component : public BaseComponent { diff --git a/libs/framework/include/celix/dm/Component_Impl.h b/libs/framework/include/celix/dm/Component_Impl.h index d860afa2..f56e2044 100644 --- a/libs/framework/include/celix/dm/Component_Impl.h +++ b/libs/framework/include/celix/dm/Component_Impl.h @@ -51,6 +51,20 @@ inline void BaseComponent::wait() const { celix_dependencyManager_wait(cDepMan); } +std::ostream& celix::dm::operator<<(std::ostream &out, const BaseComponent &cmp) { + char* buf = nullptr; + size_t bufSize = 0; + FILE* stream = open_memstream(&buf, &bufSize); + celix_dm_component_info_t* cmpInfo = nullptr; + celix_dmComponent_getComponentInfo(cmp.cComponent(), &cmpInfo); + celix_dmComponent_printComponentInfo(cmpInfo, true, true, stream); + fclose(stream); + celix_dmComponent_destroyComponentInfo(cmpInfo); + out << buf; + free(buf); + return out; +} + template<class T> Component<T>::Component( celix_bundle_context_t *context, @@ -59,7 +73,7 @@ Component<T>::Component( std::string uuid) : BaseComponent( context, cDepMan, - celix::typeName<T>(name), + celix::cmpTypeName<T>(name), std::move(uuid)) {} template<class T> @@ -167,7 +181,7 @@ Component<T>& Component<T>::remove(CServiceDependency<T,I>& dep) { template<class T> std::shared_ptr<Component<T>> Component<T>::create(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, std::string name, std::string uuid) { - std::string cmpName = celix::typeName<T>(name); + std::string cmpName = celix::cmpTypeName<T>(name); return std::shared_ptr<Component<T>>{new Component<T>(context, cDepMan, std::move(cmpName), std::move(uuid)), [](Component<T>* cmp){ //Using a callback of async destroy to ensure that the cmp instance is still exist while the //dm component is async disabled and destroyed. diff --git a/libs/framework/include/celix/dm/DependencyManager.h b/libs/framework/include/celix/dm/DependencyManager.h index d5dbaa6b..2b824c84 100644 --- a/libs/framework/include/celix/dm/DependencyManager.h +++ b/libs/framework/include/celix/dm/DependencyManager.h @@ -19,6 +19,10 @@ #pragma once +#include <cstdio> +#include <iostream> +#include <vector> + #include "celix/dm/types.h" #include "celix/dm/Component.h" #include "celix/dm/ServiceDependency.h" @@ -28,8 +32,6 @@ #include "celix_bundle_context.h" #include "celix_dependency_manager.h" -#include <vector> - namespace celix { namespace dm { /** @@ -215,6 +217,8 @@ namespace celix { namespace dm { * @return A vector of DependencyManagerInfo structs. */ std::vector<celix::dm::DependencyManagerInfo> getInfos() const; + + friend std::ostream& operator<<(std::ostream& out, const DependencyManager& mng); private: template<class T> Component<T>& createComponentInternal(std::string name, std::string uuid); @@ -225,6 +229,10 @@ namespace celix { namespace dm { std::vector<std::shared_ptr<BaseComponent>> components{}; }; + /** + * Stream outputs the full dependency manager info. + */ + inline std::ostream& operator<<(std::ostream& out, const DependencyManager& mng); }} #include "celix/dm/DependencyManager_Impl.h" diff --git a/libs/framework/include/celix/dm/DependencyManager_Impl.h b/libs/framework/include/celix/dm/DependencyManager_Impl.h index 6ff1da2e..f3e9f075 100644 --- a/libs/framework/include/celix/dm/DependencyManager_Impl.h +++ b/libs/framework/include/celix/dm/DependencyManager_Impl.h @@ -217,3 +217,14 @@ inline std::vector<celix::dm::DependencyManagerInfo> DependencyManager::getInfos celix_dependencyManager_destroyInfos(cDependencyManager(), cInfos); return result; } + +std::ostream& celix::dm::operator<<(std::ostream &out, const DependencyManager &mng) { + char* buf = nullptr; + size_t bufSize = 0; + FILE* stream = open_memstream(&buf, &bufSize); + celix_dependencyManager_printInfo(mng.cDepMan.get(), true, true, stream); + fclose(stream); + out << buf; + free(buf); + return out; +} diff --git a/libs/framework/include/celix_dependency_manager.h b/libs/framework/include/celix_dependency_manager.h index d4cf37a5..9efa3794 100644 --- a/libs/framework/include/celix_dependency_manager.h +++ b/libs/framework/include/celix_dependency_manager.h @@ -102,6 +102,30 @@ celix_status_t celix_dependencyManager_removeAllComponents(celix_dependency_mana */ celix_status_t celix_dependencyManager_removeAllComponentsAsync(celix_dependency_manager_t *manager, void *doneData, void (*doneCallback)(void *data)); +/** + * Check if all components for the bundle of the dependency manager are active (all required dependencies resolved). + */ +bool celix_dependencyManager_areComponentsActive(celix_dependency_manager_t *manager); + +/** + * Check if all components - for all bundles - are active (all required dependencies resolved). + */ +bool celix_dependencyManager_allComponentsActive(celix_dependency_manager_t *manager); + +/** + * Return the nr of components for this dependency manager + */ +size_t celix_dependencyManager_nrOfComponents(celix_dependency_manager_t *manager); + +/** + * Wait for an empty Celix event queue. + * Should not be called on the Celix event queue thread. + * + * Can be used to ensure that all created/updated components are completely processed (services registered + * and/or service trackers are created). + */ +void celix_dependencyManager_wait(celix_dependency_manager_t* manager); + /** * Create and returns a dependency manager info struct for the specified bundle. * The dependency manager info contains information about the state of the dependency manager components @@ -122,7 +146,6 @@ celix_dependency_manager_info_t* celix_dependencyManager_createInfo(celix_depend * * @param manager The dependency manager * @returns A Celix array of dependency manager infos (celix_dependency_manager_info_t*) - * for the provided bundle id or NULL if the bundle id is invalid. */ celix_array_list_t * /*celix_dependency_manager_info_t* entries*/ celix_dependencyManager_createInfos(celix_dependency_manager_t *manager); @@ -136,30 +159,24 @@ void celix_dependencyManager_destroyInfo(celix_dependency_manager_t *manager, ce */ void celix_dependencyManager_destroyInfos(celix_dependency_manager_t *manager, celix_array_list_t * infos /*entries celix_dependency_manager_info_t*/); - -/** - * Check if all components for the bundle of the dependency manager are active (all required dependencies resolved). - */ -bool celix_dependencyManager_areComponentsActive(celix_dependency_manager_t *manager); - -/** - * Check if all components - for all bundles - are active (all required dependencies resolved). - */ -bool celix_dependencyManager_allComponentsActive(celix_dependency_manager_t *manager); - /** - * Return the nr of components for this dependency manager + * Print the dependency manager info for all bundles to the provided output stream. + * @param manager The dependency manager. + * @param fullInfo Whether to print the full info or summary. + * @param useAnsiColors Whether to use ansi colors when printing info. + * @param stream The output stream (e.g. stdout) */ -size_t celix_dependencyManager_nrOfComponents(celix_dependency_manager_t *manager); +void celix_dependencyManager_printInfo(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, FILE* stream); /** - * Wait for an empty Celix event queue. - * Should not be called on the Celix event queue thread. - * - * Can be used to ensure that all created/updated components are completely processed (services registered - * and/or service trackers are created). - */ -void celix_dependencyManager_wait(celix_dependency_manager_t* manager); + * Print the dependency manager info for the provided bundle id to the provided output stream. + * @param manager The dependency manager. + * @param fullInfo whether to print the full info or summary. + * @param useAnsiColors Whether to use ansi colors when printing info. + * @param bundleId The bundle id for which the dependency manager info should be printed. + * @param stream The output stream (e.g. stdout) + */ +void celix_dependencyManager_printInfoForBundle(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, long bundleId, FILE* stream); #ifdef __cplusplus } diff --git a/libs/framework/include/celix_dm_component.h b/libs/framework/include/celix_dm_component.h index 8302dca0..29ea96d9 100644 --- a/libs/framework/include/celix_dm_component.h +++ b/libs/framework/include/celix_dm_component.h @@ -172,23 +172,34 @@ celix_status_t celix_dmComponent_setCallbacks(celix_dm_component_t *component, c celix_dmComponent_setCallbacks((dmCmp), (celix_dm_cmp_lifecycle_fpt)tmp_init, (celix_dm_cmp_lifecycle_fpt)tmp_start, (celix_dm_cmp_lifecycle_fpt)tmp_stop, (celix_dm_cmp_lifecycle_fpt)tmp_deinit); \ } while(0) + +bool celix_dmComponent_isActive(celix_dm_component_t *component); + +/** + * Returns the string value of a provided state + */ +const char* celix_dmComponent_stateToString(celix_dm_component_state_t state); + /** * Create a DM Component info struct. Containing information about the component. * Caller has ownership. */ -celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, dm_component_info_pt *info); +celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, celix_dm_component_info_t** infoOut); -bool celix_dmComponent_isActive(celix_dm_component_t *component); +/** + * Print the component info to the provided stream. + * @param info The component info to print. + * @param printFullInfo Whether to print the full info or summary. + * @param useAnsiColors Whether to use ansi colors when printing the component info. + * @param stream The stream to print to (e..g stdout). + */ +void celix_dmComponent_printComponentInfo(celix_dm_component_info_t* info, bool printFullInfo, bool useAnsiColors, FILE* stream); /** * Destroys a DM Component info struct. */ void celix_dmComponent_destroyComponentInfo(dm_component_info_pt info); -/** - * Returns the string value of a provided state - */ -const char* celix_dmComponent_stateToString(celix_dm_component_state_t state); #ifdef __cplusplus } diff --git a/libs/framework/include/celix_dm_info.h b/libs/framework/include/celix_dm_info.h index fa66d95c..2f7d2622 100644 --- a/libs/framework/include/celix_dm_info.h +++ b/libs/framework/include/celix_dm_info.h @@ -52,8 +52,10 @@ typedef struct celix_dm_service_dependency_info_struct dm_service_dependency_inf typedef struct celix_dm_service_dependency_info_struct celix_dm_service_dependency_info_t; struct celix_dm_component_info_struct { - char id[64]; - char name[128]; + long bundleId; + char* bundleSymbolicName; + char* id; + char* name; bool active; char* state; size_t nrOfTimesStarted; diff --git a/libs/framework/src/dm_component_impl.c b/libs/framework/src/dm_component_impl.c index d8838bba..d18396df 100644 --- a/libs/framework/src/dm_component_impl.c +++ b/libs/framework/src/dm_component_impl.c @@ -29,6 +29,11 @@ #include "dm_component_impl.h" #include "celix_framework.h" +static const char * const CELIX_DM_PRINT_OK_COLOR = "\033[92m"; +static const char * const CELIX_DM_PRINT_WARNING_COLOR = "\033[93m"; +static const char * const CELIX_DM_PRINT_NOK_COLOR = "\033[91m"; +static const char * const CELIX_DM_PRINT_END_COLOR = "\033[m"; + struct celix_dm_component_struct { char uuid[DM_COMPONENT_MAX_ID_LENGTH]; char name[DM_COMPONENT_MAX_NAME_LENGTH]; @@ -982,19 +987,21 @@ celix_bundle_context_t* celix_dmComponent_getBundleContext(celix_dm_component_t return result; } -celix_status_t component_getComponentInfo(celix_dm_component_t *component, dm_component_info_pt *out) { +celix_status_t component_getComponentInfo(celix_dm_component_t *component, celix_dm_component_info_t** out) { return celix_dmComponent_getComponentInfo(component, out); } -celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, dm_component_info_pt *out) { - dm_component_info_pt info = calloc(1, sizeof(*info)); +celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, celix_dm_component_info_t** out) { + celix_dm_component_info_t* info = calloc(1, sizeof(*info)); info->dependency_list = celix_arrayList_create(); celix_dmComponent_getInterfaces(component, &info->interfaces); celixThreadMutex_lock(&component->mutex); + info->bundleId = celix_bundleContext_getBundleId(component->context); + info->bundleSymbolicName = celix_bundleContext_getBundleSymbolicName(component->context, info->bundleId); info->active = false; - memcpy(info->id, component->uuid, DM_COMPONENT_MAX_ID_LENGTH); - memcpy(info->name, component->name, DM_COMPONENT_MAX_NAME_LENGTH); + info->id = celix_utils_strdup(component->uuid); + info->name = celix_utils_strdup(component->name); info->nrOfTimesStarted = component->nrOfTimesStarted; info->nrOfTimesResumed = component->nrOfTimesResumed; celix_dm_component_state_t state = celix_dmComponent_currentState(component); @@ -1012,14 +1019,88 @@ celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *componen *out = info; return CELIX_SUCCESS; } -void component_destroyComponentInfo(dm_component_info_pt info) { + + +static void celix_dmComponent_printFullInfo(FILE *out, bool colors, celix_dm_component_info_t* compInfo) { + const char *startColors = ""; + const char *endColors = ""; + if (colors) { + startColors = compInfo->active ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_NOK_COLOR; + endColors = CELIX_DM_PRINT_END_COLOR; + } + fprintf(out, "%sComponent: Name=%s%s\n", startColors, compInfo->name, endColors); + fprintf(out, "|- UUID = %s\n", compInfo->id); + fprintf(out, "|- Active = %s\n", compInfo->active ? "true" : "false"); + fprintf(out, "|- State = %s\n", compInfo->state); + fprintf(out, "|- Bundle = %li (%s)\n", compInfo->bundleId, compInfo->bundleSymbolicName); + fprintf(out, "|- Nr of times started = %i\n", (int)compInfo->nrOfTimesStarted); + fprintf(out, "|- Nr of times resumed = %i\n", (int)compInfo->nrOfTimesResumed); + + fprintf(out, "|- Interfaces (%d):\n", celix_arrayList_size(compInfo->interfaces)); + for (int interfCnt = 0; interfCnt < celix_arrayList_size(compInfo->interfaces); interfCnt++) { + dm_interface_info_pt intfInfo = celix_arrayList_get(compInfo->interfaces, interfCnt); + fprintf(out, " |- %sInterface %i: %s%s\n", startColors, (interfCnt+1), intfInfo->name, endColors); + + hash_map_iterator_t iter = hashMapIterator_construct((hash_map_pt) intfInfo->properties); + char *key = NULL; + while ((key = hashMapIterator_nextKey(&iter)) != NULL) { + fprintf(out, " | %15s = %s\n", key, celix_properties_get(intfInfo->properties, key, "!ERROR!")); + } + } + + fprintf(out, "|- Dependencies (%d):\n", celix_arrayList_size(compInfo->dependency_list)); + for (int depCnt = 0; depCnt < celix_arrayList_size(compInfo->dependency_list); ++depCnt) { + dm_service_dependency_info_pt dependency; + dependency = celix_arrayList_get(compInfo->dependency_list, depCnt); + const char *depStartColors = ""; + if (colors) { + if (dependency->required) { + depStartColors = dependency->available ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_NOK_COLOR; + } else { + depStartColors = dependency->available ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_WARNING_COLOR; + } + } + fprintf(out, " |- %sDependency %i: %s%s\n", depStartColors, (depCnt+1), dependency->serviceName == NULL ? "(any)" : dependency->serviceName, endColors); + fprintf(out, " | %15s = %s\n", "Available", dependency->available ? "true " : "false"); + fprintf(out, " | %15s = %s\n", "Required", dependency->required ? "true " : "false"); + fprintf(out, " | %15s = %s\n", "Version Range", dependency->versionRange == NULL ? "N/A" : dependency->versionRange); + fprintf(out, " | %15s = %s\n", "Filter", dependency->filter == NULL ? "N/A" : dependency->filter); + } + fprintf(out, "\n"); +} + +static void celix_dmComponent_printBasicInfo(FILE *out, bool colors, celix_dm_component_info_t* compInfo) { + const char *startColors = ""; + const char *endColors = ""; + if (colors) { + startColors = compInfo->active ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_NOK_COLOR; + endColors = CELIX_DM_PRINT_END_COLOR; + } + fprintf(out, "Component: Name=%s, ID=%s, %sActive=%s%s, State=%s, Bundle=%li (%s)\n", + compInfo->name, compInfo->id, startColors, compInfo->active ? "true " : "false", endColors, + compInfo->state, compInfo->bundleId, compInfo->bundleSymbolicName); +} + + +void celix_dmComponent_printComponentInfo(celix_dm_component_info_t* info, bool printFullInfo, bool useAnsiColors, FILE* stream) { + if (printFullInfo) { + celix_dmComponent_printFullInfo(stream, useAnsiColors, info); + } else { + celix_dmComponent_printBasicInfo(stream, useAnsiColors, info); + } +} + +void component_destroyComponentInfo(celix_dm_component_info_t* info) { return celix_dmComponent_destroyComponentInfo(info); } -void celix_dmComponent_destroyComponentInfo(dm_component_info_pt info) { +void celix_dmComponent_destroyComponentInfo(celix_dm_component_info_t* info) { int i; int size; if (info != NULL) { + free(info->bundleSymbolicName); + free(info->id); + free(info->name); free(info->state); if (info->interfaces != NULL) { diff --git a/libs/framework/src/dm_dependency_manager_impl.c b/libs/framework/src/dm_dependency_manager_impl.c index 1277a2f2..3c0be71f 100644 --- a/libs/framework/src/dm_dependency_manager_impl.c +++ b/libs/framework/src/dm_dependency_manager_impl.c @@ -373,7 +373,30 @@ celix_status_t dependencyManager_getInfo(celix_dependency_manager_t *manager, dm return status; } - void dependencyManager_destroyInfo(celix_dependency_manager_t *manager, celix_dependency_manager_info_t *info) { celix_dependencyManager_destroyInfo(manager, info); -} \ No newline at end of file +} + +static void celix_dependencyManager_printInfoForEntry(bool fullInfo, bool useAnsiColors, FILE* stream, celix_dependency_manager_info_t* mngInfo) { + for (int i = 0; i < celix_arrayList_size(mngInfo->components); ++i) { + celix_dm_component_info_t *cmpInfo = celix_arrayList_get(mngInfo->components, i); + celix_dmComponent_printComponentInfo(cmpInfo, fullInfo, useAnsiColors, stream); + } +} + +void celix_dependencyManager_printInfo(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, FILE* stream) { + celix_array_list_t *infos = celix_dependencyManager_createInfos(manager); + for (int i = 0; i< celix_arrayList_size(infos); ++i) { + celix_dependency_manager_info_t* mngInfo = celix_arrayList_get(infos, i); + celix_dependencyManager_printInfoForEntry(fullInfo, useAnsiColors, stream, mngInfo); + } + celix_dependencyManager_destroyInfos(manager, infos); +} + +void celix_dependencyManager_printInfoForBundle(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, long bundleId, FILE* stream) { + celix_dependency_manager_info_t* mngInfo = celix_dependencyManager_createInfo(manager, bundleId); + if (mngInfo != NULL) { + celix_dependencyManager_printInfoForEntry(fullInfo, useAnsiColors, stream, mngInfo); + celix_dependencyManager_destroyInfo(manager, mngInfo); + } +} diff --git a/libs/utils/include/celix/Utils.h b/libs/utils/include/celix/Utils.h index aae33bc5..5a72e36a 100644 --- a/libs/utils/include/celix/Utils.h +++ b/libs/utils/include/celix/Utils.h @@ -160,6 +160,22 @@ namespace celix { } } + /** + * @brief Returns the inferred cmp type name for the template T if the providedCmpTypeName is empty. + * + * If the a non empty providedCmpTypeName is provided this will be returned. + * Otherwise the celix::impl::typeName will be used to infer the type name. + * celix::impl::typeName uses the macro __PRETTY_FUNCTION__ to extract a type name. + */ + template<typename T> + std::string cmpTypeName(std::string_view providedCmpTypeName = "") { + if (!providedCmpTypeName.empty()) { + return std::string{providedCmpTypeName}; + } else { + return celix::impl::extractTypeName<T>(); + } + } + /** * @brief Returns the inferred type version for the template I if the providedVersion is empty. * @@ -218,6 +234,22 @@ namespace celix { } } + /** + * @brief Returns the inferred cmp type name for the template T if the providedCmpTypeName is empty. + * + * If the a non empty providedCmpTypeName is provided this will be returned. + * Otherwise the celix::impl::typeName will be used to infer the type name. + * celix::impl::typeName uses the macro __PRETTY_FUNCTION__ to extract a type name. + */ + template<typename T> + std::string cmpTypeName(const std::string &providedCmpTypeName = "") { + if (!providedCmpTypeName.empty()) { + return providedCmpTypeName; + } else { + return celix::impl::extractTypeName<T>(); + } + } + /** * @brief Returns the type version. *
