/* * (c) Copyright, Real-Time Innovations, 2019-2024. * All rights reserved. * * No duplications, whole or partial, manual or electronic, may be made * without express written permission. Any such copies, or * revisions thereof, must display this notice unaltered. * This code contains trade secrets of Real-Time Innovations, Inc. */ #ifndef osapi_activityContext_h #define osapi_activityContext_h #include "osapi/osapi_context.h" #ifdef __cplusplus extern "C" { #endif /** @internal \ingroup RTIOsapiActivityContext * It is used mainly in two places in core and in infrastructure services. * The output string, which is the result of the context, is used by logging * and heap monitoring. It will provide extra information about the resources * and the activities when a message is logged or when memory is allocated. * - Logging: every time a message is logged, the output string of the context * will be appended. * - Heap monitoring: every time memory is allocated using the RTIOsapiHeap…() * and heap monitoring is enabled, the output string of the context will be * associated with the allocation. This information will be available when * calling RTIOsapiHeap_snapshot(). * * For example in the creation of a dataWriter, the activity context will * provide information about: * - Resource: the Publisher creating the entity. The attributes of the * publisher will be guid, name and kind. * - Activity will be “entity creation”. It will have one param which will be * the entity kind, in that case “DataWriter”. * * The output string of the activity context will be: * "[0X101A76B,0X79E5D71,0X50EE914:0X1C1:0X80000088{Entity=Pu,Domain=1}| * CREATE Writer WITH TOPIC TestTopic]" */ /** @internal \ingroup RTIOsapiActivityContext * Entry Kind */ typedef enum { RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_EMPTY, RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_RESOURCE, RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_RESOURCE_WITH_PARAMS, RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_RESOURCE_GUID_WITH_PARAMS, RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_ACTIVITY, RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_ACTIVITY_WITH_PARAMS, } RTIOsapiActivityContextEntryKind; /* ========================================= */ /* RTIOsapiActivityContextAttributeKindMask */ /* ========================================= */ /** @internal \ingroup RTIOsapiActivityContext * Activity Context's resources can have multiple associated attributes, such us * topic, type, entity kind, entity name and domain. * The attributes used can be configured through this bitmap. * * This Mask will affect the attributes of the resources used in the logging * and in heap monitoring. */ typedef unsigned int RTIOsapiActivityContextAttributeKindMask; #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_GUID_PREFIX 0x1 #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_TOPIC 0x2 #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_FORMAT_TOPIC "Topic=%s" #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_TYPE 0x4 #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_FORMAT_TYPE "Type=%s" #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_ENTITY_KIND 0x8 #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_FORMAT_ENTITY_KIND "Entity=%s" #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_DOMAIN_ID 0x10 #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_FORMAT_DOMAIN_ID "Domain=%d" #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_ENTITY_NAME 0x20 #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_FORMAT_ENTITY_NAME "Name=%s" /* Add all the possibles attributes to the resource of the Activity Context. */ #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_MASK_ALL \ (RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_GUID_PREFIX \ | RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_TOPIC \ | RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_TYPE \ | RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_ENTITY_KIND \ | RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_DOMAIN_ID \ | RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_ENTITY_NAME) #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_MASK_DEFAULT \ RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_MASK_ALL /* Not add any attribute to the resource of the Activity Context. */ #define RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_MASK_NONE 0x0 extern RTIOsapiDllVariable const RTIOsapiActivityContextAttributeKindMask RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_BIT_ARRAY[]; extern RTIOsapiDllVariable const char *RTI_OSAPI_ACTIVITY_CONTEXT_ATTRIBUTE_FORMAT_ARRAY[]; /* ========================================= */ /* ActivityContextEntry */ /* ========================================= */ /** @internal \ingroup RTIOsapiActivityContext * Entry of the activity context. */ struct RTIOsapiActivityContextStackEntry { /* * Entry kind is used for: * - Applying the skip entries functionality. * - Figuring out how to parse the params member of the structure. * - Choosing how to parse the entries to get the output string. */ RTIOsapiActivityContextEntryKind kind; /* * The format of the entry is used for: * - Identify the number of params by counting the character '%' in the * format. * - Generating the output string. */ const char *format; /* * If kind == RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_RESOURCE * params will be a a char * * If kind == * RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_RESOURCE_GUID_WITH_PARAMS * || kind == RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_RESOURCE_WITH_PARAMS * || kind == RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_ACTIVITY * || kind == RTI_OSAPI_ACTIVITY_CONTEXT_ENTRY_KIND_ACTIVITY_WITH_PARAMS: * params will be a list of void pointer (void **) * It will contain integer or guid structure or strings. */ void *params; }; /* ========================================= */ /* ActivityContextSupport */ /* ========================================= */ /** @internal \ingroup RTIOsapiActivityContextSupport * @brief Create an activity context and associate it with the TSS of the * thread. * - It should be called per thread. * - It should be called after RTIOsapiContextSupport_enable. * It is called in: * - RTIOsapiThreadFactory_onSpawned * - RTIOsapiThreadChild_onSpawned: * Here addContextTssToGlobalList is set to False, because the RTI threads * will handle the destruction as part of the thread spawn function. So, * we do not add the context thread specific storage to the global list. * * - DDS_DomainParticipantGlobals_create_worker_per_thread_with_nameI * Here addContextTssToGlobalList is set to True, the context thread * specific storage will be deleted upon * DDS_DomainParticipantGlobals destruction, which is only recommended for * non-RTI threads. * * @param addContextTssToGlobalList \b In. If true we add the context thread * specific storage to a global list. * * @return True if the context was initalized, False otherwise. */ extern RTIOsapiDllExport RTIBool RTIOsapiActivityContextSupport_assertContextTss( RTIBool addContextTssToGlobalList); /** @internal \ingroup RTIOsapiActivityContextSupport * @brief Create an activity context and associate it with the TSS of the * thread. * - It should be called per thread. * - It should be called after RTIOsapiContextSupport_enable. * It is called in: * - RTIOsapiThreadFactory_onSpawned * - RTIOsapiThreadChild_onSpawned: * Here addContextTssToGlobalList is set to False, because the RTI threads * will handle the destruction as part of the thread spawn function. So, * we do not add the context thread specific storage to the global list. * * - DDS_DomainParticipantGlobals_create_worker_per_thread_with_nameI * Here addContextTssToGlobalList is set to True, the context thread * specific storage will be deleted upon * DDS_DomainParticipantGlobals destruction, which is only recommended for * non-RTI threads. * * @param nodeOut \b Out. The node that we will assert for * the context thread. Can be NULL. * @param addContextTssToGlobalList \b In. If true we add the context thread * specific storage to a global list. * @param maxEntryCount \b In. The max size of the list of entries. * * @return True if the context was initalized, False otherwise. */ extern RTIOsapiDllExport RTIBool RTIOsapiActivityContextSupport_assertContextTssWithParams( struct RTIOsapiContextSupportNode **nodeOut, RTIBool addContextTssToGlobalList, RTI_UINT32 maxEntryCount); /** @internal \ingroup RTIOsapiActivityContext * @brief Convert the activity context into a string. Usually invoked upon log * message print (i.e., if verbosity and rest of checks passed). * Once a context is logged, it is cached. So next time the context is logged * it is not composed again. * * In the case that the size of the output string is bigger than the maximum * size (RTI_OSAPI_CONTEXT_STRING_SIZE_MAX). The output string will be cut. * * Example of the output string: * - Read operation (skip guid prefix): * [0X1010D45,0XF676000A,0X78FB808D:0X1C1{Name=testParticipantName,Domain=1}| * 0X80000003{Name=testDataReaderName,Entity=DR,Topic=test,Type=Foo,Domain=1}|Read] * - Write operation (skip guid prefix): * [0X1010D45,0XF676000A,0X78FB808D:0X1C1{Name=testParticipantName,Domain=1}| * 0X80000003{Name=testDataWriterName,Entity=DW,Topic=test,Type=Foo,Domain=1}|Write] * - Get QoS operation: * [0X1010D45,0XF676000A,0X78FB808D:0X1C1{Name=testParticipantName,Domain=1}|GET * QOS] * * @param outBuffer \b Out. The buffer with the context. * @param outBufferSize \b In. The size of the buffer. * * @return The number of character written in the buffer. */ extern RTIOsapiDllExport RTI_UINT32 RTIOsapiActivityContext_getString(char *outBuffer, RTI_UINT32 outBufferSize); /* ========================================= */ /* ActivityContextScope */ /* ========================================= */ /* * We define "scope" as a block of code which: * - Starts with a begin macro call. This macro opens the block and initializes * all the stack variables needed to support entering/leaving contexts within * the block. * - Keeps track of the context entries we enter and leave. To do so: * - Within the scope, we can enter a new context entry using the following * macros: * - RTIOsapiActivityContextScope_enterActivity * - RTIOsapiActivityContextScope_enterResource * - RTIOsapiActivityContextScope_enterActivityWithParams * - RTIOsapiActivityContextScope_enterResourceWithParams * - RTIOsapiActivityContextScope_enterResourceGuidWithParams * - Within the scope, we can leave a context entry using the following * macro: * - RTIOsapiActivityContextScope_leave * - Ends with calling RTIOsapiActivityContextScope_end. * Upon ending a scope, any remaining entered entries will leave. * * Additionally, some ContextScopes will support also "start". * Starting a scope consists of beginning the scope plus entering a Context. */ /** @internal \ingroup RTIOsapiActivityContext * @brief This function is a macro that open the scope and then initializes in * the stack: * - An index * - A list of RTIOsapiActivityContextStackEntry. * It does not create a list of Params. * The ContextScope that this macro creates can contain calls to the following * APIs: * - RTIOsapiActivityContextScope_enterActivity * - RTIOsapiActivityContextScope_enterResource * The scope should be closed calling "RTIOsapiActivityContextScope_end()". * * @param maxEntryCount \b In. Size of the list of entries. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_beginWithEntries( RTI_UINT32 maxEntryCount); /** @internal \ingroup RTIOsapiActivityContext * @brief This function is a macro that open the scope and then initializes in * the stack: * - An index * - A list of RTIOsapiActivityContextStackEntry * - A list of params * - A pointer to the position of the list of params * The ContextScope that this macro creates can contain calls to the following * APIs: * - RTIOsapiActivityContextScope_enterActivityWithParams * - RTIOsapiActivityContextScope_enterResourceWithParams * - RTIOsapiActivityContextScope_enterResourceGuidWithParams * The scope should be closed calling "RTIOsapiActivityContextScope_end()". * * @param maxEntryCount \b In. Size of the list of entries. * @param maxParamsCount \b In. Size of the list of params. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_beginWithEntriesAndParams( RTI_UINT32 maxEntryCount, RTI_UINT32 maxParamsCount); /** @internal \ingroup RTIOsapiActivityContext * @brief Enter an activity entry in the activity context. * This function is a macro that use the variables defined in the begin macro. * In order to leave this entry from the context, you can call (either or * both): * - RTIOsapiActivityContextScope_leave * - RTIOsapiActivityContextScope_end. * * Check we do not overflow the array of entries. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be got from the TSS. * @param formatTemplate \b In. The format of the entry. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_enterActivity( struct RTIOsapiContext *activityContext, const char *formatTemplate); /** @internal \ingroup RTIOsapiActivityContext * @brief Enter a resource entry in the activity context. * This function is a macro use the variables defined in the begin macro. * In order to leave this entry from the context, you can call (either or * both): * - RTIOsapiActivityContextScope_leave * - RTIOsapiActivityContextScope_end * * Check we do not overflow the array of entries. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be got from the TSS. * @param formatTemplate \b In. The format of the entry. * @param resource \b In. The resource of the entry. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_enterResource( struct RTIOsapiContext *activityContext, const char *formatTemplate, const char *resource); /** @internal \ingroup RTIOsapiActivityContext * @brief Enter an activity entry in the activity context. * This function is a macro use the variables defined in the begin macro. * In order to leave this entry from the context, you can call (either or * both): * - RTIOsapiActivityContextScope_leave * - RTIOsapiActivityContextScope_end * * Check we do not overflow the array of entries. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be got from the TSS. * @param formatTemplate \b In. The format of the entry. * @param ... \b In. List of params. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_enterActivityWithParams( struct RTIOsapiContext *activityContext, const char *formatTemplate, ...); /** @internal \ingroup RTIOsapiActivityContext * @brief Enter a resource entry in the activity context. * This function is a macro use the variables defined in the begin macro. * In order to leave this entry from the context, you can call (either or * both): * - RTIOsapiActivityContextScope_leave * - RTIOsapiActivityContextScope_end * * Check we do not overflow the array of entries. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be got from the TSS. * @param formatTemplate \b In. The format of the entry. * @param ... \b In. List of params. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_enterResourceWithParams( struct RTIOsapiContext *activityContext, const char *formatTemplate, ...); /** @internal \ingroup RTIOsapiActivityContext * @brief Enter a resource with Guid entry in the activity context. * This function is a macro use the variables defined in the begin macro. * In order to leave this entry from the context, you can call (either or * both): * - RTIOsapiActivityContextScope_leave * - RTIOsapiActivityContextScope_end * * Check we do not overflow the array of entries. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be got from the TSS. * @param formatTemplate \b In. The format of the entry. * @param ... \b In. List of params. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_enterResourceGuidWithParams( struct RTIOsapiContext *activityContext, const char *formatTemplate, ...); /** @internal \ingroup RTIOsapiActivityContext * @brief Leave the last entry of the activity context. * This function is a macro use the variables defined in the begin macro. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be got from the TSS. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_leave( struct RTIOsapiContext *activityContext); /** @internal \ingroup RTIOsapiActivityContext * @brief This function is a macro leave all the entries of the activity context * entered after calling the begin macro. * It closes the scope. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be got from the TSS. */ extern RTIOsapiDllExport void RTIOsapiActivityContextScope_end( struct RTIOsapiContext *activityContext); /* ========================================= */ /* ActivityContext enter and leave entries */ /* ========================================= */ /** @internal \ingroup RTIOsapiActivityContext * @brief Enter an entry in the activity context. * If the context is already full, the entry will not be added. * The entry memory is owned by the caller function. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be get from the TSS. * @param entry \b In. The entry to enter. */ extern RTIOsapiDllExport void RTIOsapiActivityContext_enter( struct RTIOsapiContext *activityContext, struct RTIOsapiActivityContextStackEntry *entry); /** @internal \ingroup RTIOsapiActivityContext * @brief Enter two entries in the activity context. Useful because one of the * most common use cases is to enter a resource and an activity at the same * time. If the context is already full, the entries will not be added. The * entries memory is owned by the caller function. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be get from the TSS. * @param entry1 \b In. The entry1 to enter. * @param entry2 \b In. The entry1 to enter. */ extern RTIOsapiDllExport void RTIOsapiActivityContext_enterPair( struct RTIOsapiContext *activityContext, struct RTIOsapiActivityContextStackEntry *entry1, struct RTIOsapiActivityContextStackEntry *entry2); /** @internal \ingroup RTIOsapiActivityContext * @brief Leave the last entry of the activity context. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be get from the TSS. */ extern RTIOsapiDllExport void RTIOsapiActivityContext_leave( struct RTIOsapiContext *activityContext); /** @internal \ingroup RTIOsapiActivityContext * @brief Leave the last N entries of the activity context. * * @param activityContext \b In. The activityContext itself. If it is NULL, it * will be get from the TSS. * @param groupSize \b In. The number of entries to leave from the context. */ extern RTIOsapiDllExport void RTIOsapiActivityContext_leaveGroup( struct RTIOsapiContext *activityContext, RTI_UINT32 groupSize); /* ========================================= */ /* Internal method */ /* ========================================= */ /** @internal \ingroup RTIOsapiActivityContext * @brief Return the number of entries of the activity context. * * @return number of entries of the activity context. */ extern RTIOsapiDllExport RTI_UINT32 RTIOsapiActivityContext_getDepth(void); /** @internal \ingroup RTIOsapiActivityContext * @brief Set the attribute mask for the format used in the getString. * * @param mask \n In. New mask to set. */ extern RTIOsapiDllExport void RTIOsapiActivityContext_setAttributeMask( RTIOsapiActivityContextAttributeKindMask mask); /** @internal \ingroup RTIOsapiActivityContext * @brief Save the list of param in a list. * In case we cannot fit all of the params in the list, return false and reset * paramIndex to the initial value. * * @param listParams \n In/Out. List of params. * @param paramIndex \n In/Out. Possition to add the param. * @param paramIndex \n In. Maximum number of params in the list. * @param format \n In. Format of the entry. It will be parsed to know the * number of params. * @param ... \b In. List of params. * * @return RTI_TRUE if the params were entered successfully, RTI_FALSE * otherwise. */ extern RTIOsapiDllExport RTIBool RTIOsapiActivityContext_getParamList( void **listParams, RTI_UINT32 *paramIndex, const RTI_UINT32 maxParamsCount, const char *format, ...); #ifdef __cplusplus } /* extern "C" */ #endif #include "osapi/osapi_activityContext_impl.h" #endif /* osapi_activityContext_h */