27 if (e->
port == port) {
66 if (e->
port == port) {
70 else if (!firstEmpty && !e->
port)
78 entry->instanceID = instID;
102 mutex->enter(5000, __FUNCTION__);
113 if (!mutex->enter(5000, __FUNCTION__)) {
140 if (!mutex->enter(5000, __FUNCTION__))
160 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
162 uint16 res = master->nodeID;
168 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
170 uint64 res = master->createdTime;
176 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
184 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
186 uint32 res = master->dynamicShmemSerial;
192 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
194 uint32 res = master->processShmemSerial;
200 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
202 uint32 res = master->componentShmemSerial;
208 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
210 uint32 res = master->datamapsShmemSerial;
218 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
220 uint32 res = ++master->dynamicShmemSerial;
226 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
228 uint32 res = ++master->processShmemSerial;
234 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
236 uint32 res = ++master->componentShmemSerial;
242 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
244 uint32 res = ++master->datamapsShmemSerial;
251 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
253 uint64 res = master->dynamicShmemSize;
259 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
261 uint64 res = master->processShmemSize;
267 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
269 uint64 res = master->componentShmemSize;
275 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
277 uint64 res = master->datamapsShmemSize;
283 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
285 master->dynamicShmemSize = size;
291 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
293 master->processShmemSize = size;
299 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
301 master->componentShmemSize = size;
307 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
309 master->datamapsShmemSize = size;
374 psycloneIndex = NULL;
381 shouldContinue =
true;
383 isLocalMaster =
false;
384 managementThreadID = 0;
390 shouldContinue =
false;
409 delete(masterMemory);
413 delete(psycloneIndex);
414 psycloneIndex = NULL;
421 uint64 alloc = 0, usage = 0;
451 createdTime = masterMemory->getCreatedTime();
458 uint64 heartbeat = 0;
472 LogPrint(0,
LOG_MEMORY,3,
"Node starting up on port %u, please try again in a little while...", port);
476 this->isLocalMaster = isLocalMaster;
478 if (!masterMemory->open(port)) {
480 delete(masterMemory);
490 delete(masterMemory);
501 delete(masterMemory);
511 delete(masterMemory);
521 delete(masterMemory);
534bool MemoryManager::create(uint16 sysID, uint32 slotCount, uint16 binCount, uint32 minBlockSize, uint32 maxBlockSize, uint64 initSize, uint64 maxSize,
bool force) {
536 this->isLocalMaster =
true;
538 uint64 heartbeat = 0;
551 if (!psycloneIndex->init(sysID,
GetTimeNow())) {
557 if (!masterMemory->create(sysID)) {
563 if (!
temporalMemory->create(slotCount, binCount, minBlockSize, maxBlockSize, initSize, maxSize)) {
602 return masterMemory->getNodeID();
606 masterMemory->setNodeID(
id);
627 tmc = masterMemory->master->currentTMC;
628 adjust = masterMemory->master->localSyncAdjustment;
633 masterMemory->master->currentTMC = tmc;
634 masterMemory->master->localSyncAdjustment = adjust;
659 while (type[level+1])
667 else if (subtype == 0xFFFF)
682 while (context[level+1])
690 else if (subcontext == 0xFFFF)
748uint32 MemoryManager::runManager() {
754 uint64 nextPageCheck = 0;
756 while (shouldContinue) {
783 uint32 maxPageCount = 15;
784 if (!manager->
create(0)) {
792 char* data =
new char[size];
795 uint32 expectedCount = 100;
796 uint32 expectedMaxCount = (maxPageCount-10) * expectedCount;
797 uint32 count = expectedMaxCount;
798 uint64* ids =
new uint64[count];
801 msg->
setData(
"data", data, size);
809 for (n=0; n<count; n++) {
826 for (n=0; n<count; n++) {
829 unittest::fail(
"MemoryManager test: getCopyOfMessage %u failed", n);
846 if ((!msg2->
getInt(
"Test", val64)) || (val64 != n)) {
847 unittest::fail(
"MemoryManager test: getCopyOfMessage wrong data (%lld != %u)", val64, n);
860 double writeUs = (double)(t2 - t1);
861 double readUs = (double)(t3 - t2);
863 unittest::metric(
"write_throughput", (1.0*size*count)/writeUs,
"MB/s",
true);
873 count, (1.0*size*count)/writeUs, (1000000.0*count)/writeUs, (uint32)writeUs, size);
875 count, (1.0*size*count)/readUs, (1000000.0*count)/readUs, (uint32)readUs, size);
3076 "Static memory management insert/read-back throughput",
"memory");
3078 "Shared memory segment smoke check",
"memory");
Central shared-memory manager for a Psyclone node: master segment, per-subsystem shared maps and the ...
#define PSYCLONE_STATUS_ENDED
Instance has shut down (or crashed and was reaped).
#define PSYCLONE_INDEX_SIZE
Total byte size of the instance-index shared-memory segment.
#define PSYCLONE_STATUS_INIT
Instance is starting up, not yet serving.
#define PSYCLONE_INDEX_MAXCOUNT
Maximum number of concurrently tracked Psyclone instances per machine.
#define PSYCLONE_STATUS_READY
Instance is fully operational.
#define PSYCLONE_STATUS_NONE
No instance recorded in this slot.
CMSDK time: µs-resolution 64-bit timestamps and the Time Mapping Constant (TMC).
Small, dependency-free unit test harness used by all CMSDK object tests.
#define thread_ret_val(ret)
#define THREAD_FUNCTION_CALL
Accessor for the shared component registry.
Accessor for the shared name/id maps and the request map.
bool maintenance()
Periodic cleanup (e.g.
The central Psyclone data container: a self-contained binary message with typed, named user entries.
bool setEOL(uint64 eol)
setEOL(uint64 eol)
bool getInt(const char *key, int64 &value)
getInt(const char* key, int64& value)
bool setInt(const char *key, int64 value)
setInt(const char* key, int64 value)
uint32 getSize()
getSize() Get message size Many types of data of any size can be put into a message as user entries; ...
bool setData(const char *key, const char *value, uint32 size)
setData(const char* key, const char* value, uint32 size)
Handle to the node's master shared-memory segment (MemoryMasterStruct).
uint32 incrementDynamicShmemSerial()
Bump the dynamic segment serial after resize.
uint64 getProcessShmemSize()
bool create(uint16 port)
Create the master segment for the node instance listening on port.
uint32 getDataMapsShmemSerial()
uint32 incrementDataMapsShmemSerial()
Bump the data-maps segment serial after resize.
uint16 getID()
MemoryController interface:
uint64 getComponentShmemSize()
bool setComponentShmemSize(uint64 size)
Record a new component segment size.
bool setID(uint16 id)
MemoryController interface: set the node id.
uint16 port
Node port this master segment belongs to (names all related segments).
bool setDataMapsShmemSize(uint64 size)
Record a new data-maps segment size.
uint32 incrementProcessShmemSerial()
Bump the process segment serial after resize.
uint32 incrementComponentShmemSerial()
Bump the component segment serial after resize.
uint32 getComponentShmemSerial()
uint32 getProcessShmemSerial()
uint64 getDynamicShmemSize()
uint32 getDynamicShmemSerial()
bool setDynamicShmemSize(uint64 size)
Record a new dynamic segment size.
bool setNodeID(uint16 id)
Set the cluster-wide node id.
bool setProcessShmemSize(uint64 size)
Record a new process segment size.
bool open(uint16 port)
Attach to an existing master segment created by another process.
uint64 getDataMapsShmemSize()
Top-level facade of the shared-memory subsystem for one process.
ProcessMemory * processMemory
Accessor for the process table and per-process queues.
DataMessage * getCopyOfMessage(uint64 id)
Fetch a private copy of a previously published message.
ComponentMemory * componentMemory
Accessor for the component registry.
bool create(uint16 sysID, uint32 slotCount=100000, uint16 binCount=2, uint32 minBlockSize=1024, uint32 maxBlockSize=64 *1024, uint64 initSize=50000000L, uint64 maxSize=1000000000L, bool force=false)
Create all shared segments for a new node instance (master process only).
static bool UnitTest()
Self-test of the shared-memory manager.
std::string subTypeToText(uint16 subtype)
Resolve a subtype id to its registered name.
DataMessage * retrieveAllSystemIDs()
Enumerate all live Psyclone system ids/ports on this machine (via the PsycloneIndex).
uint8 getNodeStatus(uint64 &lastseen, uint64 &createdTime)
Get the node status from the master segment.
bool setNodeID(uint16 id)
Set this node's cluster-wide id.
static MemoryManager * Singleton
Per-process singleton instance, set by the constructor.
static bool ShmUnitTest()
Self-test of the raw shared-memory primitives.
bool insertMessage(DataMessage *msg, uint64 &id)
Publish a DataMessage into shared (temporal) memory.
std::string getComponentName(uint32 compID)
Resolve a component id to its name.
std::string subContextToText(uint16 subcontext)
Resolve a subcontext id to its registered name.
std::string typeToText(PsyType type)
Resolve a type id to its registered name.
bool getTimeSyncData(uint64 &tmc, int64 &adjust)
Read the cluster time-sync values from the master segment.
bool getMemoryUsage(uint64 &sysAlloc, uint64 &sysUsage, uint64 &dataAlloc, uint64 &dataUsage)
Report allocation/usage figures for the system and data segments.
DataMapsMemory * dataMapsMemory
Accessor for the type/context/tag/crank/request maps.
bool connect(uint16 sysID, bool isMaster)
Attach this process to an existing node's shared segments.
TemporalMemory * temporalMemory
Accessor for time-limited message storage.
friend THREAD_RET THREAD_FUNCTION_CALL MemoryManagement(THREAD_ARG arg)
Background maintenance thread entry point for MemoryManager / MemoryManagerX.
std::string contextToText(PsyContext context)
Resolve a context id to its registered name.
bool setTimeSyncData(uint64 tmc, int64 adjust)
Write the cluster time-sync values into the master segment.
Accessor for the shared process table and per-process queues.
Accessor for the machine-global instance index segment.
bool setStatus(uint8 status)
Update this instance's status and heartbeat in the shared index.
bool init(uint16 port, uint64 instID)
Attach to (or create) the index segment and claim/refresh the slot for this instance.
static bool GetStatus(uint16 port, uint8 &status, uint64 &heartbeat)
Look up the status of the instance registered on port.
Accessor for the temporal (dynamic) message store in shared memory.
static bool CreateThread(THREAD_FUNCTION func, void *args, uint32 &newID, uint32 reqID=0)
Create a new native thread and start it immediately.
static bool Shutdown()
Terminate all managed threads, then destroy the singleton.
static UnitTestRunner & instance()
Access the singleton (created on first use).
void registerTest(const char *name, UnitTestFunc func, const char *description="", const char *category="", bool inDefaultRun=true)
Register a test with the runner.
Recursive mutual-exclusion lock, optionally named for cross-process use.
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
bool SetCurrentTimeSyncData(uint64 tmc, int64 netTimeAdjust)
Install externally computed sync data (e.g.
std::string PrintTimeDifString(uint64 t, bool us=true, bool ms=true)
int32 GetTimeAgeMS(uint64 t)
Age of a timestamp relative to now, in milliseconds.
int64 GetTimeAge(uint64 t)
Age of a timestamp relative to now.
bool GetCurrentTimeSyncData(uint64 &tmc, int64 &netTimeAdjust)
Read the current sync data.
bool Sleep(uint32 ms)
Suspend the calling thread.
char * OpenSharedMemorySegment(const char *name, uint64 size)
Open and map an existing named shared memory segment.
char * CreateSharedMemorySegment(const char *name, uint64 size, bool force=false)
Create a named shared memory segment and map it into this process.
bool CloseSharedMemorySegment(char *data, uint64 size)
Unmap a segment previously created/opened here.
std::string StringFormat(const char *format,...)
printf into a std::string.
void fail(const char *fmt,...)
Set an explanatory reason shown on the FAIL line.
void metric(const char *name, double value, const char *unit="", bool higherIsBetter=true)
Record a performance metric.
void detail(const char *fmt,...)
Verbose-only indented diagnostic line (shown only when verbose=1).
void progress(int percent, const char *action)
Report progress with a short description of the current action.
THREAD_RET THREAD_FUNCTION_CALL MemoryManagement(THREAD_ARG arg)
Background maintenance thread entry point for MemoryManager / MemoryManagerX.
void Register_MemoryManager_Tests()
Hierarchical execution-context identifier.
Hierarchical message type identifier — the key used for publish/subscribe matching in Psyclone.
Root header of the node's master shared-memory segment.
One slot in the machine-global Psyclone instance index.
uint16 port
TCP port the instance listens on; doubles as the instance key.
uint64 heartbeat
Last heartbeat timestamp (µs since epoch); staleness implies a dead instance.
uint8 status
One of the PSYCLONE_STATUS_* values.
Header of the machine-global Psyclone instance index shared-memory segment.