mirror of
https://github.com/FairRootGroup/FairMQ.git
synced 2026-06-15 08:17:05 +00:00
feat(shmem): expose side-channel metadata API for unsent messages
Add two public entry points needed by the ALICE use case where shmem messages are allocated via a transport but never sent — their metadata is instead serialised into Arrow tables and delivered over a separate channel, allowing consumer devices to resolve the payload pointer without taking ownership. shmem::Message::GetMeta() returns the MetaHeader of the message, mirroring the existing positional-init pattern already used in Socket.h. shmem::GetDataAddressFromHandle(TransportFactory&, const MetaHeader&) is a free function declared in Common.h and defined in Manager.cxx. Keeping it out of the TransportFactory class body means callers only need to include Common.h (available transitively via Message.h) and do not drag in Socket.h or zmq.h. The implementation handles both managed segments and unmanaged regions, and throws SharedMemoryError with a typed message on a bad segment or region id. TransportFactory also gains a same-named member for callers that already have the concrete type. Lifetime of the returned pointer is the caller's responsibility; the cache device is expected to hold the messages alive. A SideChannel test covers the GetMeta/GetDataAddressFromHandle round-trip for both standard and expanded-metadata configurations.
This commit is contained in:
committed by
Dennis Klein
parent
a0e8271aca
commit
215c31428b
@@ -339,4 +339,13 @@ struct SegmentBufferShrink
|
||||
|
||||
} // namespace fair::mq::shmem
|
||||
|
||||
namespace fair::mq { class TransportFactory; }
|
||||
|
||||
namespace fair::mq::shmem {
|
||||
// Resolve a MetaHeader (received over a side channel) to the local data pointer.
|
||||
// The caller is responsible for ensuring the backing buffer remains alive for the
|
||||
// duration of access; FairMQ provides no refcount protection for this path.
|
||||
char* GetDataAddressFromHandle(fair::mq::TransportFactory& factory, const MetaHeader& meta);
|
||||
} // namespace fair::mq::shmem
|
||||
|
||||
#endif /* FAIR_MQ_SHMEM_COMMON_H_ */
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
********************************************************************************/
|
||||
|
||||
#include "Manager.h"
|
||||
#include "TransportFactory.h"
|
||||
|
||||
// Needed to compile-firewall the <boost/process/async.hpp> header because it
|
||||
// interferes with the <asio/buffer.hpp> header. So, let's factor
|
||||
@@ -51,4 +52,12 @@ bool Manager::SpawnShmMonitor(const std::string& id)
|
||||
return true;
|
||||
}
|
||||
|
||||
char* GetDataAddressFromHandle(fair::mq::TransportFactory& factory, const MetaHeader& meta)
|
||||
{
|
||||
if (factory.GetType() != fair::mq::Transport::SHM) {
|
||||
throw SharedMemoryError("GetDataAddressFromHandle called on a non-shmem transport");
|
||||
}
|
||||
return static_cast<TransportFactory&>(factory).GetDataAddressFromHandle(meta);
|
||||
}
|
||||
|
||||
} // namespace fair::mq::shmem
|
||||
|
||||
@@ -776,6 +776,30 @@ class Manager
|
||||
|
||||
auto GetMetadataMsgSize() const noexcept { return fMetadataMsgSize; }
|
||||
|
||||
// Resolve a MetaHeader (received over a side channel) to the local data pointer.
|
||||
// The caller is responsible for ensuring the backing buffer remains alive for the
|
||||
// duration of access; FairMQ provides no refcount protection for this path.
|
||||
char* GetDataAddressFromHandle(const MetaHeader& meta)
|
||||
{
|
||||
if (meta.fManaged) {
|
||||
if (meta.fSize == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
GetSegment(meta.fSegmentId);
|
||||
auto it = fSegments.find(meta.fSegmentId);
|
||||
if (it == fSegments.end()) {
|
||||
throw SharedMemoryError(tools::ToString("GetDataAddressFromHandle: cannot open segment with id ", meta.fSegmentId));
|
||||
}
|
||||
return ShmHeader::UserPtr(GetAddressFromHandle(meta.fHandle, meta.fSegmentId));
|
||||
} else {
|
||||
UnmanagedRegion* region = GetRegionFromCache(meta.fRegionId);
|
||||
if (!region) {
|
||||
throw SharedMemoryError(tools::ToString("GetDataAddressFromHandle: cannot get unmanaged region with id ", meta.fRegionId));
|
||||
}
|
||||
return reinterpret_cast<char*>(region->GetData()) + meta.fHandle;
|
||||
}
|
||||
}
|
||||
|
||||
~Manager()
|
||||
{
|
||||
fRegionsGen += 1; // signal TL cache invalidation
|
||||
|
||||
@@ -167,6 +167,11 @@ class Message final : public fair::mq::Message
|
||||
}
|
||||
}
|
||||
|
||||
MetaHeader GetMeta() const
|
||||
{
|
||||
return {fSize, fHint, fHandle, fShared, fRegionId, fSegmentId, fManaged};
|
||||
}
|
||||
|
||||
void* GetData() const override
|
||||
{
|
||||
if (!fLocalPtr) {
|
||||
|
||||
@@ -201,6 +201,8 @@ class TransportFactory final : public fair::mq::TransportFactory
|
||||
void Resume() override { fManager->Resume(); }
|
||||
void Reset() override { fManager->Reset(); }
|
||||
|
||||
char* GetDataAddressFromHandle(const MetaHeader& meta) { return fManager->GetDataAddressFromHandle(meta); }
|
||||
|
||||
~TransportFactory() override
|
||||
{
|
||||
LOG(debug) << "Destroying Shared Memory transport...";
|
||||
|
||||
Reference in New Issue
Block a user