/******************************************************************************** * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * * * * This software is distributed under the terms of the * * GNU Lesser General Public Licence (LGPL) version 3, * * copied verbatim in the file "LICENSE" * ********************************************************************************/ #ifndef FAIR_MQ_SHMEM_COMMON_H_ #define FAIR_MQ_SHMEM_COMMON_H_ #include #include #include #include #include // std::equal_to #include #include #include #include #include #include #include #include #include #include #include #include namespace fair::mq::shmem { struct SharedMemoryError : std::runtime_error { using std::runtime_error::runtime_error; }; using SimpleSeqFitSegment = boost::interprocess::basic_managed_shared_memory, boost::interprocess::null_index>; // boost::interprocess::iset_index>; using RBTreeBestFitSegment = boost::interprocess::basic_managed_shared_memory, boost::interprocess::null_index>; // boost::interprocess::iset_index>; using SegmentManager = boost::interprocess::managed_shared_memory::segment_manager; using VoidAlloc = boost::interprocess::allocator; using CharAlloc = boost::interprocess::allocator; using Str = boost::interprocess::basic_string, CharAlloc>; using StrAlloc = boost::interprocess::allocator; using StrVector = boost::interprocess::vector; enum class AllocationAlgorithm : int { rbtree_best_fit, simple_seq_fit }; struct RegionInfo { RegionInfo(const VoidAlloc& alloc) : fPath("", alloc) , fFlags(0) , fUserFlags(0) , fDestroyed(false) {} RegionInfo(const char* path, const int flags, const uint64_t userFlags, const VoidAlloc& alloc) : fPath(path, alloc) , fFlags(flags) , fUserFlags(userFlags) , fDestroyed(false) {} Str fPath; int fFlags; uint64_t fUserFlags; bool fDestroyed; }; using Uint16RegionInfoPairAlloc = boost::interprocess::allocator, SegmentManager>; using Uint16RegionInfoMap = boost::interprocess::map, Uint16RegionInfoPairAlloc>; using Uint16RegionInfoHashMap = boost::unordered_map, std::equal_to, Uint16RegionInfoPairAlloc>; struct SegmentInfo { SegmentInfo(AllocationAlgorithm aa) : fAllocationAlgorithm(aa) {} AllocationAlgorithm fAllocationAlgorithm; }; struct SessionInfo { SessionInfo(const char* sessionName, int creatorId, const VoidAlloc& alloc) : fSessionName(sessionName, alloc) , fCreatorId(creatorId) {} Str fSessionName; int fCreatorId; }; using Uint16SegmentInfoPairAlloc = boost::interprocess::allocator, SegmentManager>; using Uint16SegmentInfoHashMap = boost::unordered_map, std::equal_to, Uint16SegmentInfoPairAlloc>; // using Uint16SegmentInfoMap = boost::interprocess::map, Uint16SegmentInfoPairAlloc>; struct DeviceCounter { DeviceCounter(unsigned int c) : fCount(c) {} std::atomic fCount; }; struct EventCounter { EventCounter(uint64_t c) : fCount(c) {} std::atomic fCount; }; struct Heartbeat { Heartbeat(uint64_t c) : fCount(c) {} std::atomic fCount; }; struct RegionCounter { RegionCounter(uint16_t c) : fCount(c) {} std::atomic fCount; }; struct MetaHeader { size_t fSize; size_t fHint; boost::interprocess::managed_shared_memory::handle_t fHandle; mutable boost::interprocess::managed_shared_memory::handle_t fShared; uint16_t fRegionId; mutable uint16_t fSegmentId; }; #ifdef FAIRMQ_DEBUG_MODE struct MsgCounter { MsgCounter() : fCount(0) {} MsgCounter(unsigned int c) : fCount(c) {} std::atomic fCount; }; using Uint16MsgCounterPairAlloc = boost::interprocess::allocator, SegmentManager>; using Uint16MsgCounterHashMap = boost::unordered_map, std::equal_to, Uint16MsgCounterPairAlloc>; struct MsgDebug { MsgDebug() : fPid(0) , fSize(0) , fCreationTime(0) {} MsgDebug(pid_t pid, size_t size, const uint64_t creationTime) : fPid(pid) , fSize(size) , fCreationTime(creationTime) {} pid_t fPid; size_t fSize; uint64_t fCreationTime; }; using SizetMsgDebugPairAlloc = boost::interprocess::allocator, SegmentManager>; // using SizetMsgDebugHashMap = boost::unordered_map, std::equal_to, SizetMsgDebugPairAlloc>; using SizetMsgDebugMap = boost::interprocess::map, SizetMsgDebugPairAlloc>; using Uint16MsgDebugMapPairAlloc = boost::interprocess::allocator, SegmentManager>; using Uint16MsgDebugMapHashMap = boost::unordered_map, std::equal_to, Uint16MsgDebugMapPairAlloc>; #endif struct RegionBlock { RegionBlock() = default; RegionBlock(boost::interprocess::managed_shared_memory::handle_t handle, size_t size, size_t hint) : fHandle(handle) , fSize(size) , fHint(hint) {} boost::interprocess::managed_shared_memory::handle_t fHandle{}; size_t fSize = 0; size_t fHint = 0; }; // find id for unique shmem name: // a hash of user id + session id, truncated to 8 characters (to accommodate for name size limit on some systems (MacOS)). inline std::string makeShmIdStr(const std::string& sessionId, const std::string& userId) { std::string seed(userId + sessionId); // generate a 8-digit hex value out of sha256 hash std::vector hash(4); picosha2::hash256(seed.begin(), seed.end(), hash.begin(), hash.end()); return picosha2::bytes_to_hex_string(hash.begin(), hash.end()); } inline std::string makeShmIdStr(const std::string& sessionId) { return makeShmIdStr(sessionId, std::to_string(geteuid())); } inline uint64_t makeShmIdUint64(const std::string& sessionId) { std::string shmId = makeShmIdStr(sessionId); uint64_t id = 0; std::stringstream ss; ss << std::hex << shmId; ss >> id; return id; } struct SegmentSize : public boost::static_visitor { template size_t operator()(S& s) const { return s.get_size(); } }; struct SegmentAddress : public boost::static_visitor { template void* operator()(S& s) const { return s.get_address(); } }; struct SegmentMemoryZeroer : public boost::static_visitor<> { template void operator()(S& s) const { s.zero_free_memory(); } }; struct SegmentFreeMemory : public boost::static_visitor { template size_t operator()(S& s) const { return s.get_free_memory(); } }; struct SegmentHandleFromAddress : public boost::static_visitor { SegmentHandleFromAddress(const void* _ptr) : ptr(_ptr) {} template boost::interprocess::managed_shared_memory::handle_t operator()(S& s) const { return s.get_handle_from_address(ptr); } const void* ptr; }; struct SegmentAddressFromHandle : public boost::static_visitor { SegmentAddressFromHandle(const boost::interprocess::managed_shared_memory::handle_t _handle) : handle(_handle) {} template char* operator()(S& s) const { return reinterpret_cast(s.get_address_from_handle(handle)); } const boost::interprocess::managed_shared_memory::handle_t handle; }; struct SegmentAllocate : public boost::static_visitor { SegmentAllocate(const size_t _size) : size(_size) {} template char* operator()(S& s) const { return reinterpret_cast(s.allocate(size)); } const size_t size; }; struct SegmentAllocateAligned : public boost::static_visitor { SegmentAllocateAligned(const size_t _size, const size_t _alignment) : size(_size), alignment(_alignment) {} template void* operator()(S& s) const { return s.allocate_aligned(size, alignment); } const size_t size; const size_t alignment; }; struct SegmentBufferShrink : public boost::static_visitor { SegmentBufferShrink(const size_t _new_size, char* _local_ptr) : new_size(_new_size) , local_ptr(_local_ptr) {} template char* operator()(S& s) const { boost::interprocess::managed_shared_memory::size_type shrunk_size = new_size; return s.template allocation_command(boost::interprocess::shrink_in_place, new_size + 128, shrunk_size, local_ptr); } const size_t new_size; mutable char* local_ptr; }; struct SegmentDeallocate : public boost::static_visitor<> { SegmentDeallocate(char* _ptr) : ptr(_ptr) {} template void operator()(S& s) const { return s.deallocate(ptr); } char* ptr; }; } // namespace fair::mq::shmem #endif /* FAIR_MQ_SHMEM_COMMON_H_ */