#ifndef TCPSTREAMJOIN_H_ #define TCPSTREAMJOIN_H_ /** * @file TCPStreamJoin.h * @brief Publishes one new stream of a TCPStreamService that merges several other * streams of the same service. * * @code * +Svc = { Class = TCPStreamService Port = 44500 } * +Join = { Class = TCPStreamJoin Service = "Svc" StreamName = "all" * Sources = "fast,slow" Master = "fast" } * @endcode * Declare the join after the service. Consumers subscribe to "all" like to any stream. * * The merged stream is emitted at the pace of the Master source: each Master DATA frame * produces one merged frame holding the Master's signals and the last values received * from every other source (sample-and-hold). Nothing is emitted until every source has * delivered one DATA frame. No thread is added: the merged frame is built and queued on * the Master producer's thread. * * @par CONFIG * Concatenation of the source descriptors in Sources order, named * "_" (at most 63 characters), time-signal indexes rebased, publish mode * Strict. All sources must share the same HRT frequency (an unknown one matches any). * * @par DATA * [master timestamp][source0 body][source1 body]... where a body is that source's last * DATA payload without its 8-byte timestamp. A held value is therefore stamped with the * Master's time unless the source carries its own time signal. * * @par Limits * Only Strict and Decimate sources are accepted (Accumulate batches have varying * length); a source whose frame size changes without a new CONFIG is ignored; the merged * frame must fit MaxPayloadSize. The output stream is registered while every source is * registered and removed as soon as one leaves; it is rebuilt when a source re-registers * or changes its CONFIG. * * @par Parameters * | Parameter | Type | Default | Description | * |----------------|--------|-------------|-------------| * | Service | string | (required) | Name of the TCPStreamService object. | * | StreamName | string | object name | Name of the merged stream. | * | Sources | string | (required) | Comma separated source stream names (1..16). | * | Master | string | first source| Source whose frames pace the merged stream. | * | MaxPayloadSize | uint32 | 60000 | Largest merged frame payload. | * * @par Locking * Producer-side: source tapMutex, then the join mutex, then the output stream mutex, then * the connection queue mutex. Service notifications run outside its topology lock and * are serialised. */ #include "FastPollingMutexSem.h" #include "Object.h" #include "ReferenceT.h" #include "StreamString.h" #include "StructuredDataI.h" #include "TCPSServiceStream.h" #include "TCPSStreamTapI.h" #include "TCPStreamService.h" namespace MARTe { class TCPStreamJoin : public Object, public TCPSStreamTapI, public TCPSStreamObserverI { public: CLASS_REGISTER_DECLARATION() /** Most source streams one join can merge. */ static const uint32 TCPSJ_MAX_SOURCES = 16u; TCPStreamJoin(); virtual ~TCPStreamJoin(); virtual bool Initialise(StructuredDataI &data); virtual void OnTapConfig(TCPSServiceStream *source, const uint8 *payload, uint32 payloadSize); virtual void OnTapData(TCPSServiceStream *source, uint32 counter, const uint8 *payload, uint32 payloadSize); virtual void OnStreamRegistered(TCPSServiceStream *stream); virtual void OnStreamUnregistered(TCPSServiceStream *stream); /** @return true while the merged stream is registered with the service. */ bool IsActive() const; /** @return true once a merged CONFIG has been published for the current sources. */ bool HasConfig() const; /** @return merged DATA frames emitted. */ uint64 GetFramesEmitted() const; uint32 GetNumSources() const; private: struct Source { Source(); ~Source(); StreamString name; TCPSServiceStream *stream; ///< non-NULL while registered and tapped bool configOk; uint8 *cfg; uint32 cfgBytes; uint32 numSigs; uint64 hrt; uint8 *body; uint32 bodyCap; uint32 bodySize; bool haveBody; }; int32 FindByName(const char8 *name) const; int32 FindByStream(const TCPSServiceStream *s) const; bool AllRegistered() const; void Evaluate(); void PublishConfigLocked(); bool ParseConfig(Source &s, const uint8 *payload, uint32 n); ReferenceT service; TCPSServiceStream *out; bool observing; StreamString outName; Source *src; uint32 numSrc; uint32 master; uint32 maxPayload; FastPollingMutexSem mtx; bool active; bool configPublished; bool sizeLogged; uint32 outCounter; volatile uint64 emitted; uint8 *scratch; uint32 scratchCap; TCPStreamJoin(const TCPStreamJoin &); TCPStreamJoin &operator=(const TCPStreamJoin &); }; } // namespace MARTe #endif // TCPSTREAMJOIN_H_