/* * Copyright (c) 2025 Real-Time Innovations, Inc. 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 commend_srReaderService_h #define commend_srReaderService_h #ifndef reda_worker_h #include "reda/reda_worker.h" #endif #ifndef reda_weakReference_h #include "reda/reda_weakReference.h" #endif #ifndef reda_database_h #include "reda/reda_database.h" #endif #ifndef property_propertyNames_h #include "property/property_propertyNames.h" #endif #ifndef netio_common_h #include "netio/netio_common.h" #endif #ifndef mig_rtps_h #include "mig/mig_rtps.h" #endif #ifndef commend_dll_h #include "commend/commend_dll.h" #endif #ifndef commend_readerService_h #include "commend/commend_readerService.h" #endif #ifdef __cplusplus extern "C" { #endif /* Doxygen file-level documentation =====================================*/ /*e \file \brief COMMENDSrReaderService *interface*--as in no implementation. */ /*e \defgroup COMMENDSrReaderServiceModule COMMENDSrReaderService \ingroup COMMENDReaderServiceModule */ struct RTIClock; struct REDADatabase; struct COMMENDFacade; struct COMMENDSrReaderService; /* This is a testing property used to set the initial EPOCH for NACK messages. * See CORE-7133 */ #define COMMEND_READER_NACK_EPOCH \ PROPERTY_NAME_DDS_DATA_READER_INITIAL_ACK_EPOCH /*e \ingroup COMMENDSrReaderServiceReaderServiceModule * @brief Properties for a strict reliable reader endpoint. * * In addition to the standard reader endpoint properties, * a strict reliable reader endpoint also specifies an \e ackRate. * * The ackRate property can be used to have the reader periodically * send an ACK message to all its remote writers. This is helpful * if the remote writers only send occasional HEARTBEAT messages, * at a rate that is too slow for the reader. * * &&& Note: ackRate should really be called ackPeriod... &&& * * Example usage: * \code * //declare & initialize the reader properties using default values * struct COMMENDSrReaderServiceReaderProperty readerProperty = COMMEND_SR_READER_SERVICE_READER_PROPERTY_DEFAULT; * * //optionally modify the default values * readerProperty.parent.unicastEntryport[0] = ENTRYPORT; * readerProperty.parent.unicastEntryportCount = 1; * * service = (struct COMMENDReaderService *) COMMENDSrReaderService_new(db, facade, NULL, ea, worker); * * //use the property values when creating the reader * service->createReader( * service, READER_OID, * (const struct COMMENDReaderServiceReaderSampleListener *) * &readerSampleListener, * (const struct COMMENDReaderServiceReaderActivityListener *) * &readerActivityListener, * (const struct COMMENDReaderServiceReaderProperty *)&readerProperty, * ea, worker) * \endcode * * @see COMMENDReaderServiceReaderProperty * @see COMMENDSrReaderServiceRemoteWriterProperty * @see COMMEND_SR_READER_SERVICE_READER_PROPERTY_DEFAULT */ struct COMMENDSrReaderServiceReaderProperty { /*e Inherits the base reader properties. */ struct COMMENDReaderServiceReaderProperty parent; /*e The rate to send periodic ACK messages. If zero, no periodic ACKS are sent. */ struct RTINtpTime ackRate; /*e Max number of ACK retries before a remote writer is considered dead. */ int ackRetriesMax; /* Suppress HBs that would trigger redundant ACKs; necessary to avoid network storm in reboot case; Should be at least the time it takes for a writer to respond to a NACK, which would of course depend on writer's nack_response_delay. */ struct RTINtpTime heartbeatSuppressionDuration; int requestDepth; RTIBool disableAcks; /*e This member must be set to RTI_TRUE to disable the preemptive NACK */ RTIBool disablePreemptiveNack; /*e Size of reliability receive window */ int receiveWindowSize; /*e Estimate of packet round trip time */ struct RTINtpTime rtt; /*e Max number of remote writers per reader */ struct REDAFastBufferPoolGrowthProperty remoteWriterCount; /* alex TODO: rename type? */ COMMENDAppAckMode appAckMode; /*e The rate to send application-level acks. Only applies if appAckMode != PROTOCOL */ struct RTINtpTime appAckFlushRate; /*e * The following field is used only for testing purposes to set the initial * epoch for NACK messages. */ REDAEpoch initialAckEpoch; /*i * All RTPS submessages sent by this reader will be serialized by using the * endianness defined in this field. If set to MIG_GENERATOR_ENDIAN_UNKNOWN, * the ACK will be serialized using the endianness of the platform. */ MIGGeneratorEndian endianness; /*e Indicates if the reader should lazily allocate resources for batch * reception. */ RTIBool lazilyAllocateBatchResources; }; /*e \ingroup COMMENDSrReaderServiceModule * Default strict reliable reader properties. * * Inherits the default base reader properties. * Periodic ACK rate is zero by default. * * @see COMMENDSrReaderServiceReaderProperty * @see * COMMENDSrReaderServiceReaderActivityListenerOnRemoteWriterInactiveCallback */ /* clang-format off */ #define COMMEND_SR_READER_SERVICE_READER_PROPERTY_DEFAULT \ { \ COMMEND_READER_SERVICE_READER_PROPERTY_DEFAULT, { 5, 0 }, /* ackRate */ \ 10, /* ackRetriesMax */ \ { 0, 0x08000000 }, /* heartbeatSuppressionDuration, default: \ 31 ms */ \ 0, /* requestDepth */ \ RTI_FALSE, /* disableAcks */ \ RTI_FALSE, /* disablePreemptiveNack */ \ 256, /* receiveWindowSize */ \ RTI_NTP_TIME_ZERO, /* rtt */ \ REDA_FAST_BUFFER_POOL_GROWTH_PROPERTY_DEFAULT, /* maxRemoteWriters */ \ COMMEND_PROTOCOL_ACK_MODE, /* appAckMode */ \ { 5, 0 }, /* appAckFlushRate */ \ 0, /* initialAckEpoch */ \ MIG_GENERATOR_ENDIAN_UNKNOWN, /* endianness */ \ RTI_TRUE /* lazilyAllocateBatchResources */ \ } /* clang-format on */ /*e \ingroup COMMENDSrReaderServiceModule * Remote writer properties for strict reliable reader services. * * Usage example: * \code * //declare & initialize the remote writer properties using default values * struct COMMENDSrReaderServiceRemoteWriterProperty remoteWriterProperty = COMMEND_SR_READER_SERVICE_REMOTE_WRITER_PROPERTY_DEFAULT; * * //optionally modify the default values * remoteWriterProperty.ackDestination[0] = ENTRYPORT.locator; * remoteWriterProperty.ackDestinationCount = 1; * * service = (struct COMMENDReaderService *) COMMENDSrReaderService_new(db, facade, NULL, ea, worker); * * //use the property values when asserting the remote writer * service->assertRemoteWriter( * service, READER_OID, &REMOTE_WRITER_GUID, * &sampleStorage, &activityStorage, * ((const struct COMMENDReaderServiceRemoteWriterProperty *) * &remoteWriterProperty), worker); * \endcode * * @see COMMEND_SR_READER_SERVICE_REMOTE_WRITER_PROPERTY_DEFAULT * @see COMMENDSrReaderServiceReaderActivityListenerOnRemoteWriterInactiveCallback */ struct COMMENDSrReaderServiceRemoteWriterProperty { /*e immutable. Queue size of this remote writer. -1 means infinite (because the default resource limit QoS is unlimited, or -1). This is used to size the Bitmap of the samples to collect for the instance of the remote writer, so anything larger than MIG_RTPS_BITMAP_SIZE_MAX will be cutoff. */ int queueSize; /*e immutable. Max size of ACK's bitmap. This limits the number of ISSUEs or VARs that can be requested at once from the remote writer.*/ int dataToNackAtOnceMax; /*e immutable. Description of the destination where to send the ACK. */ struct RTINetioLocator ackDestination[COMMEND_COMMON_APP_IPADDRESS_COUNT_MAX]; /*e immutable. Size of destination array to send the ACK. */ int ackDestinationCount; /*e mutable. Array of locators associated with locator-filter session */ struct RTINetioLocator sessionLocatorList[COMMEND_COMMON_APP_IPADDRESS_COUNT_MAX]; /*e mutable. Size of locator array for associated session */ int sessionLocatorCount; /*e immutable. The last available sn of the remote writer. UNKNOWN if unknown */ struct REDASequenceNumber lastSn; /*e immutable. The last comitted sn for the remote writer */ struct REDASequenceNumber lastComittedSn; /*e immutable. Whether remote writer service is persistent. */ RTIBool isPersistentService; /*e immutable. Whether remote writer allows and handles ACKs */ RTIBool disableAcks; /*e Flag determining fragmentBitmap's starting SN */ RTIBool startFragmentBitmapFromZero; /*e Indicates if the shared memory transport associated to this remote * reader is incompatible with the one of the local participant. */ RTIBool incompatibleShmemTransport; /*e * SEC-82: remote writer and remote participant interceptor handle nodes * for matched list and directed list. */ struct MIGInterceptorHandlesGroup interceptorHandles; /*e * Flag that is TRUE when the remote writer is being asserted as part of * an activation event, meaning that it is regaining liveliness. */ RTIBool isActivationEvent; /*e * Flag that is TRUE when the remote writer is from RTI Connext Pro. */ RTIBool isRtiProVendor; }; #define COMMEND_SR_READER_SERVICE_REMOTE_WRITER_PROPERTY_DEFAULT \ { \ 32, /* queueSize */ \ 32, /* maxDataToNackAtOnce */ \ RTI_NETIO_RTPS_LOCATOR_LIST_DEFAULT, /* ackDestination */ \ 0, /* ackDestinationCount */ \ RTI_NETIO_RTPS_LOCATOR_LIST_DEFAULT, /* sessionLocator */ \ 0, /* sessionLocatorCount */ \ REDA_SEQUENCE_NUMBER_UNKNOWN, /* lastSn */ \ REDA_SEQUENCE_NUMBER_UNKNOWN, /* lastComittedSn */ \ RTI_FALSE, /* isPersistentService */ \ RTI_FALSE, /* disableAcks */ \ RTI_FALSE, /* startFragmentBitmapFromZero */ \ RTI_FALSE, /* incompatibleShmemTransport */ \ MIGInterceptorHandlesGroup_INITIALIZER, /* interceptorHandles \ */ \ RTI_FALSE, /* isActivationEvent */ \ RTI_TRUE /* isRtiProVendor */ \ } /*e \ingroup COMMENDSrReaderServiceModule * Create a new strict reliable reader service. * * @pre Parameters are valid, non-NULL pointers (except for \e property, which * can be a NULL pointer). * @post A new reader service is created. * * @param db \b In. Pointer to the database the reader service will use. * @param facade \b In. Pointer to the facade the reader service will use. * @param property \b In. Pointer to the desired reader service properties. * If NULL, use the default properties. * @param ea \b In. Pointer to the exclusive area the reader service will use. * @param worker \b In. Pointer to a worker that will create the reader service. * * @return A valid COMMENDSrReaderService pointer upon success, else NULL. * * @see COMMENDSrReaderService_delete * */ extern COMMENDDllExport struct COMMENDSrReaderService * COMMENDSrReaderService_new( struct REDADatabase *db, struct COMMENDFacade *facade, const struct COMMENDReaderServiceProperty *property, struct REDAExclusiveArea *ea, struct REDAWorker *worker); #ifdef __cplusplus } /* extern "C" */ #endif #include "commend/commend_srReaderService_impl.h" #endif /* commend_srReaderService_h */