CMSDK 2.0.1
Cross-platform C++ base library and SDK for the Psyclone AIOS platform
Loading...
Searching...
No Matches
MemoryManager.cpp
Go to the documentation of this file.
1
9
10#include "MemoryManager.h"
11#include "PsyTime.h"
12#include "UnitTestFramework.h"
13
14namespace cmlabs {
15
17
18
19bool PsycloneIndex::GetStatus(uint16 port, uint8& status, uint64& heartbeat) {
21 if (!index) {
22 // LogPrint(0,0,0,"Couldn't open shared PsycloneIndex memory segment...");
23 return false;
24 }
25 PsycloneIndexEntry* e = (PsycloneIndexEntry*)(((char*)index)+sizeof(PsycloneIndexStruct));
26 for (uint32 n=0; n<PSYCLONE_INDEX_MAXCOUNT; n++, e++) {
27 if (e->port == port) {
28 status = e->status;
29 heartbeat = e->heartbeat;
30 return true;
31 }
32 }
33 //LogPrint(0,0,0,"Couldn't find Psyclone port %u in shared PsycloneIndex memory segment...", port);
34 status = PSYCLONE_STATUS_NONE;
35 heartbeat = 0;
36 return false;
37}
38
40 index = NULL;
41 entry = NULL;
42}
43
45 if (!index)
47 entry = NULL;
49 index = NULL;
50}
51
52bool PsycloneIndex::init(uint16 port, uint64 instID) {
54 if (!index) {
56 if (!index)
57 return false;
58 memset(index, 0, PSYCLONE_INDEX_SIZE);
59 index->size = PSYCLONE_INDEX_SIZE;
60 index->cid = PSYCLONEINDEXID;
61 }
62
63 PsycloneIndexEntry* firstEmpty = NULL;
64 PsycloneIndexEntry* e = (PsycloneIndexEntry*)(((char*)index)+sizeof(PsycloneIndexStruct));
65 for (uint32 n=0; n<PSYCLONE_INDEX_MAXCOUNT; n++, e++) {
66 if (e->port == port) {
67 entry = e;
68 break;
69 }
70 else if (!firstEmpty && !e->port)
71 firstEmpty = e;
72 }
73 if (!entry) {
74 if (!firstEmpty)
75 return false;
76 entry = firstEmpty;
77 entry->port = port;
78 entry->instanceID = instID;
79 }
80
81 return true;
82}
83
84bool PsycloneIndex::setStatus(uint8 status) {
85 if (!entry)
86 return false;
87 entry->status = status;
88 entry->heartbeat = GetTimeNow();
89 return true;
90}
91
92
93
95 mutex = NULL;
96 master = NULL;
97 port = 0;
98}
99
101 if (mutex)
102 mutex->enter(5000, __FUNCTION__);
104 master = NULL;
105 if (mutex)
106 mutex->leave();
107 delete(mutex);
108 mutex = NULL;
109}
110
112 mutex = new utils::Mutex(utils::StringFormat("PsycloneNodeMutex_%u", port).c_str(), true);
113 if (!mutex->enter(5000, __FUNCTION__)) {
114 return false;
115 }
116
117 //master = (MemoryMasterStruct*) utils::OpenSharedMemorySegment(utils::StringFormat("PsycloneNode_%u", port).c_str(), sizeof(MemoryMasterStruct));
118 //if (master) {
119 // utils::CloseSharedMemorySegment((char*)master, sizeof(MemoryMasterStruct));
120 // LogPrint(0,LOG_MEMORY,2,"MemoryManager removing stale shared memory (%u)...", port);
121 //}
122
123 master = (MemoryMasterStruct*) utils::CreateSharedMemorySegment(utils::StringFormat("PsycloneNode_%u", port).c_str(), sizeof(MemoryMasterStruct), true);
124 if (!master) {
125 mutex->leave();
126 return false;
127 }
128 memset(master, 0, sizeof(MemoryMasterStruct));
129 master->size = sizeof(MemoryMasterStruct);
130 master->cid = PSYCLONEMASTERID;
131 master->status = 1; // init
132 master->createdTime = GetTimeNow();
133 this->port = port;
134 mutex->leave();
135 return true;
136}
137
139 mutex = new utils::Mutex(utils::StringFormat("PsycloneNodeMutex_%u", port).c_str());
140 if (!mutex->enter(5000, __FUNCTION__))
141 return false;
142
143 master = (MemoryMasterStruct*) utils::OpenSharedMemorySegment(utils::StringFormat("PsycloneNode_%u", port).c_str(), sizeof(MemoryMasterStruct));
144 if (!master) {
145 mutex->leave();
146 return false;
147 }
148 if (master->cid != PSYCLONEMASTERID) {
150 mutex->leave();
151 return false;
152 }
153 this->port = port;
154 mutex->leave();
155 return true;
156}
157
158
160 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
161 return 0;
162 uint16 res = master->nodeID;
163 mutex->leave();
164 return res;
165}
166
168 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
169 return 0;
170 uint64 res = master->createdTime;
171 mutex->leave();
172 return res;
173}
174
175bool MasterMemory::setNodeID(uint16 id) {
176 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
177 return 0;
178 master->nodeID = id;
179 mutex->leave();
180 return true;
181}
182
184 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
185 return 0;
186 uint32 res = master->dynamicShmemSerial;
187 mutex->leave();
188 return res;
189}
190
192 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
193 return 0;
194 uint32 res = master->processShmemSerial;
195 mutex->leave();
196 return res;
197}
198
200 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
201 return 0;
202 uint32 res = master->componentShmemSerial;
203 mutex->leave();
204 return res;
205}
206
208 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
209 return 0;
210 uint32 res = master->datamapsShmemSerial;
211 mutex->leave();
212 return res;
213}
214
215
216
218 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
219 return 0;
220 uint32 res = ++master->dynamicShmemSerial;
221 mutex->leave();
222 return res;
223}
224
226 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
227 return 0;
228 uint32 res = ++master->processShmemSerial;
229 mutex->leave();
230 return res;
231}
232
234 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
235 return 0;
236 uint32 res = ++master->componentShmemSerial;
237 mutex->leave();
238 return res;
239}
240
242 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
243 return 0;
244 uint32 res = ++master->datamapsShmemSerial;
245 mutex->leave();
246 return res;
247}
248
249
251 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
252 return 0;
253 uint64 res = master->dynamicShmemSize;
254 mutex->leave();
255 return res;
256}
257
259 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
260 return 0;
261 uint64 res = master->processShmemSize;
262 mutex->leave();
263 return res;
264}
265
267 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
268 return 0;
269 uint64 res = master->componentShmemSize;
270 mutex->leave();
271 return res;
272}
273
275 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
276 return 0;
277 uint64 res = master->datamapsShmemSize;
278 mutex->leave();
279 return res;
280}
281
283 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
284 return false;
285 master->dynamicShmemSize = size;
286 mutex->leave();
287 return true;
288}
289
291 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
292 return false;
293 master->processShmemSize = size;
294 mutex->leave();
295 return true;
296}
297
299 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
300 return false;
301 master->componentShmemSize = size;
302 mutex->leave();
303 return true;
304}
305
307 if (!mutex || !master || !mutex->enter(5000, __FUNCTION__))
308 return false;
309 master->datamapsShmemSize = size;
310 mutex->leave();
311 return true;
312}
313
314bool MasterMemory::setID(uint16 id) {
315 port = id;
316 return true;
317}
318
320 return port;
321}
322
323
324
325
326
327
328
329
330
331
332// static
333//bool MemoryManager::GetMemoryUsage(uint32& total, uint32& usage, uint32& sysTotal, uint32& sysUsage, uint32& staticTotal, uint32& staticUsage, uint32& dynamicTotal, uint32& dynamicUsage) {
334// if (!MemoryManager::Singleton)
335// return false;
336// //if (!MemoryManager::Singleton->pageMasterMutex->enter())
337// // return false;
338// //sysTotal = MemoryManager::Singleton->pageMaster->dataSize[MP_SYSTEMPAGE];
339// //sysUsage = MemoryManager::Singleton->pageMaster->dataUsage[MP_SYSTEMPAGE];
340// //staticTotal = MemoryManager::Singleton->pageMaster->dataSize[MP_STATICPAGE];
341// //staticUsage = MemoryManager::Singleton->pageMaster->dataUsage[MP_STATICPAGE];
342// //dynamicTotal = MemoryManager::Singleton->pageMaster->dataSize[MP_DYNAMICPAGE];
343// //dynamicUsage = MemoryManager::Singleton->pageMaster->dataUsage[MP_DYNAMICPAGE];
344// //total = sysTotal + staticTotal + dynamicTotal;
345// //usage = sysUsage + staticUsage + dynamicUsage;
346// //MemoryManager::Singleton->pageMasterMutex->leave();
347// return true;
348//}
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
374 psycloneIndex = NULL;
375 masterMemory = NULL;
376 temporalMemory = NULL;
377 processMemory = NULL;
378 componentMemory = NULL;
379 dataMapsMemory = NULL;
380
381 shouldContinue = true;
382 isRunning = false;
383 isLocalMaster = false;
384 managementThreadID = 0;
385 thisInstance = 0;
386}
387
389// MemoryManager::Singleton = NULL;
390 shouldContinue = false;
391 uint32 c = 0;
392 while (isRunning) {
393 utils::Sleep(50);
394 if (c++ > 10)
395 break;
396 }
397 if (isLocalMaster) {
399 }
400
401 delete(temporalMemory);
402 temporalMemory = NULL;
403 delete(processMemory);
404 processMemory = NULL;
405 delete(componentMemory);
406 componentMemory = NULL;
407 delete(dataMapsMemory);
408 dataMapsMemory = NULL;
409 delete(masterMemory);
410 masterMemory = NULL;
411 if (psycloneIndex)
412 psycloneIndex->setStatus(PSYCLONE_STATUS_ENDED);
413 delete(psycloneIndex);
414 psycloneIndex = NULL;
415}
416
417bool MemoryManager::getMemoryUsage(uint64& sysAlloc, uint64& sysUsage, uint64& dataAlloc, uint64& dataUsage) {
418 if (!masterMemory)
419 return false;
420
421 uint64 alloc = 0, usage = 0;
422 if (temporalMemory && temporalMemory->getMemoryUsage(alloc, usage)) {
423 dataAlloc = alloc;
424 dataUsage = usage;
425 }
426
427 sysAlloc = sysUsage = sizeof(MemoryMasterStruct);
428
429 if (processMemory && processMemory->getMemoryUsage(alloc, usage)) {
430 sysAlloc += alloc;
431 sysUsage += usage;
432 }
433 if (componentMemory && processMemory->getMemoryUsage(alloc, usage)) {
434 sysAlloc += alloc;
435 sysUsage += usage;
436 }
437 if (dataMapsMemory && dataMapsMemory->getMemoryUsage(alloc, usage)) {
438 sysAlloc += alloc;
439 sysUsage += usage;
440 }
441 return true;
442}
443
444
445uint8 MemoryManager::getNodeStatus(uint64& lastseen, uint64& createdTime) {
446 lastseen = 0;
447 if (!masterMemory)
449 uint8 status = 0;
450 PsycloneIndex::GetStatus(masterMemory->port, status, lastseen);
451 createdTime = masterMemory->getCreatedTime();
452 return status;
453}
454
455// Connect to existing PageMaster in shared memory
456bool MemoryManager::connect(uint16 port, bool isLocalMaster) {
457 uint8 status = 0;
458 uint64 heartbeat = 0;
459 if ((!PsycloneIndex::GetStatus(port, status, heartbeat)) || (status == PSYCLONE_STATUS_NONE) || (!heartbeat)) {
460 LogPrint(0,LOG_MEMORY,3,"Cannot find node running on port %u...", port);
461 return false;
462 }
463 else if (status <= PSYCLONE_STATUS_ENDED) {
464 LogPrint(0,LOG_MEMORY,3,"Node no longer running on port %u...", port);
465 return false;
466 }
467 else if (GetTimeAgeMS(heartbeat) > 5000) {
468 LogPrint(0,LOG_MEMORY,3,"Node on port %u is no longer responding...", port);
469 return false;
470 }
471 else if (status == PSYCLONE_STATUS_INIT) {
472 LogPrint(0,LOG_MEMORY,3,"Node starting up on port %u, please try again in a little while...", port);
473 return false;
474 }
475
476 this->isLocalMaster = isLocalMaster;
477 masterMemory = new MasterMemory();
478 if (!masterMemory->open(port)) {
479 LogPrint(0,LOG_MEMORY,0,"Cannot open MasterMemory on port %u...", port);
480 delete(masterMemory);
481 masterMemory = NULL;
482 return false;
483 }
484
485 temporalMemory = new TemporalMemory(masterMemory);
486 if (!temporalMemory->open()) {
487 LogPrint(0,LOG_MEMORY,0,"Cannot open TemporalMemory on port %u...", port);
488 delete(temporalMemory);
489 temporalMemory = NULL;
490 delete(masterMemory);
491 masterMemory = NULL;
492 return false;
493 }
494 temporalMemory->setNodeID(masterMemory->getNodeID());
495
496 componentMemory = new ComponentMemory(masterMemory);
497 if (!componentMemory->open()) {
498 LogPrint(0,LOG_MEMORY,0,"Cannot open ComponentMemory on port %u...", port);
499 delete(componentMemory);
500 componentMemory = NULL;
501 delete(masterMemory);
502 masterMemory = NULL;
503 return false;
504 }
505
506 dataMapsMemory = new DataMapsMemory(masterMemory);
507 if (!dataMapsMemory->open()) {
508 LogPrint(0,LOG_MEMORY,0,"Cannot open DataMapsMemory on port %u...", port);
509 delete(dataMapsMemory);
510 dataMapsMemory = NULL;
511 delete(masterMemory);
512 masterMemory = NULL;
513 return false;
514 }
515
516 processMemory = new ProcessMemory(masterMemory);
517 if (!processMemory->open()) {
518 LogPrint(0,LOG_MEMORY,0,"Cannot open ProcessMemory on port %u...", port);
519 delete(processMemory);
520 processMemory = NULL;
521 delete(masterMemory);
522 masterMemory = NULL;
523 return false;
524 }
525
526 if (!ThreadManager::CreateThread(MemoryManagement, this, managementThreadID)) {
527 return false;
528 }
529
530 return true;
531}
532
533// Create a new PageMaster in shared memory
534bool MemoryManager::create(uint16 sysID, uint32 slotCount, uint16 binCount, uint32 minBlockSize, uint32 maxBlockSize, uint64 initSize, uint64 maxSize, bool force) {
535
536 this->isLocalMaster = true;
537 uint8 status = 0;
538 uint64 heartbeat = 0;
539 if (PsycloneIndex::GetStatus(sysID, status, heartbeat) && (GetTimeAgeMS(heartbeat) < 500)) {
540 if (status == PSYCLONE_STATUS_INIT) {
541 LogPrint(0,LOG_MEMORY,0,"Another node is currently (%ums ago) starting up on port %u...", GetTimeAgeMS(heartbeat), sysID);
542 return false;
543 }
544 else if (status == PSYCLONE_STATUS_READY) {
545 LogPrint(0,LOG_MEMORY,0,"Another node is currently running or crashed %s ago on port %u...", PrintTimeDifString(GetTimeAge(heartbeat)).c_str(), sysID);
546 return false;
547 }
548 }
549
550 psycloneIndex = new PsycloneIndex();
551 if (!psycloneIndex->init(sysID, GetTimeNow())) {
552 LogPrint(0, LOG_MEMORY, 0, "Cannot init index memory on port %u...", sysID);
553 return false;
554 }
555
556 masterMemory = new MasterMemory();
557 if (!masterMemory->create(sysID)) {
558 LogPrint(0, LOG_MEMORY, 0, "Cannot create MasterMemory...");
559 return false;
560 }
561
562 temporalMemory = new TemporalMemory(masterMemory);
563 if (!temporalMemory->create(slotCount, binCount, minBlockSize, maxBlockSize, initSize, maxSize)) {
564 LogPrint(0, LOG_MEMORY, 0, "Cannot create TemporalMemory...");
565 return false;
566 }
567
568 componentMemory = new ComponentMemory(masterMemory);
569 // Create initial room for 1024 average components
570 // Will expand as needed
571 if (!componentMemory->create(1024)) {
572 LogPrint(0, LOG_MEMORY, 0, "Cannot create ComponentMemory...");
573 return false;
574 }
575
576 dataMapsMemory = new DataMapsMemory(masterMemory);
577 // Create initial room for 1024 typelevels, contextlevels, tags, cranks, requests
578 // Will expand as needed
579 if (!dataMapsMemory->create(1024, 1024, 1024, 1024, 1024)) {
580 LogPrint(0, LOG_MEMORY, 0, "Cannot create DataMapsMemory...");
581 return false;
582 }
583
584 processMemory = new ProcessMemory(masterMemory);
585 // Create initial room for 16 processes
586 // Will expand as needed
587 if (!processMemory->create(16)) {
588 LogPrint(0, LOG_MEMORY, 0, "Cannot create ProcessMemory...");
589 return false;
590 }
591
592 psycloneIndex->setStatus(PSYCLONE_STATUS_READY);
593
594 if (!ThreadManager::CreateThread(MemoryManagement, this, managementThreadID)) {
595 return false;
596 }
597
598 return true;
599}
600
602 return masterMemory->getNodeID();
603}
604
606 masterMemory->setNodeID(id);
607 temporalMemory->setNodeID(id);
608 return true;
609}
610
612 DataMessage* msg = new DataMessage();
613 if (!this->componentMemory->writeComponentNamesToMsg(msg)) {
614 delete msg;
615 return NULL;
616 }
617 if (!this->dataMapsMemory->writeIDsToMsg(msg)) {
618 delete msg;
619 return NULL;
620 }
621 return msg;
622}
623
624
625
626bool MemoryManager::getTimeSyncData(uint64& tmc, int64& adjust) {
627 tmc = masterMemory->master->currentTMC;
628 adjust = masterMemory->master->localSyncAdjustment;
629 return true;
630}
631
632bool MemoryManager::setTimeSyncData(uint64 tmc, int64 adjust) {
633 masterMemory->master->currentTMC = tmc;
634 masterMemory->master->localSyncAdjustment = adjust;
635 return true;
636}
637
638// Insert new block of memory and return full id
640 if (!temporalMemory)
641 return false;
642 return temporalMemory->insertMessage(msg, id);
643}
644
645// Get copy of block of memory
647 if (!temporalMemory)
648 return NULL;
649 return temporalMemory->getCopyOfMessage(id);
650}
651
653 if (!type[0])
654 return "NOTYPE";
655 if (type[0] == 1)
656 return utils::StringFormat("PsyControlMessage %u.%u", type[1], type[2]);
657 std::string str = subTypeToText(type[0]);
658 uint8 level = 0;
659 while (type[level+1])
660 str += std::string(".") + subTypeToText(type[++level]);
661 return str;
662}
663
664std::string MemoryManager::subTypeToText(uint16 subtype) {
665 if (!subtype)
666 return "-";
667 else if (subtype == 0xFFFF)
668 return "*";
669 std::string str;
670 char* data = new char[MAXKEYNAMELEN+1];
671 if (dataMapsMemory->getTypeLevelName(subtype, data, MAXKEYNAMELEN))
672 str = data;
673 delete [] data;
674 return str;
675}
676
678 if (!context[0])
679 return "NOCONTEXT";
680 std::string str = subContextToText(context[0]);
681 uint8 level = 0;
682 while (context[level+1])
683 str += std::string(".") + subContextToText(context[++level]);
684 return str;
685}
686
687std::string MemoryManager::subContextToText(uint16 subcontext) {
688 if (!subcontext)
689 return "-";
690 else if (subcontext == 0xFFFF)
691 return "*";
692 std::string str;
693 char* data = new char[MAXKEYNAMELEN+1];
694 if (dataMapsMemory->getContextLevelName(subcontext, data, MAXKEYNAMELEN))
695 str = data;
696 delete [] data;
697 return str;
698}
699
700std::string MemoryManager::getComponentName(uint32 compID) {
701 std::string str;
702 char* data = new char[MAXKEYNAMELEN+1];
703 if (componentMemory->getComponentName(compID, data, MAXKEYNAMELEN))
704 str = data;
705 delete [] data;
706 return str;
707}
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
746
747// Continuous management of eol pages
748uint32 MemoryManager::runManager() {
749 //LogPrint(0, LOG_SYSTEM, 0, "Memory Management (%p) running...\n\n", this);
750 isRunning = true;
751 uint64 tmc;
752 int64 netTimeSync;
753
754 uint64 nextPageCheck = 0; //, now;
755
756 while (shouldContinue) {
757 if (isLocalMaster) {
758 if (GetCurrentTimeSyncData(tmc, netTimeSync))
759 setTimeSyncData(tmc, netTimeSync);
761 if (psycloneIndex)
762 psycloneIndex->setStatus(PSYCLONE_STATUS_READY);
763 }
764 else {
765 // Update Sync Time
766 if (getTimeSyncData(tmc, netTimeSync) )
767 SetCurrentTimeSyncData(tmc, netTimeSync);
768 }
769
770 utils::Sleep(100);
771 }
772
773 isRunning = false;
774 //LogPrint(0, LOG_SYSTEM, 0, "Memory Management (%p) stopped running...\n\n", this);
775 return 0;
776}
777
779
780 // Create and initialise the MemoryManager (static memory management)
781 unittest::progress(5, "create manager");
782 MemoryManager* manager = new MemoryManager();
783 uint32 maxPageCount = 15;
784 if (!manager->create(0)) {
785 unittest::fail("MemoryManager test: create() failed");
786 delete(manager);
787 return false;
788 }
789
790 uint64 eol = GetTimeNow() + 100000000; // +100sec
791 uint32 size = 4096;
792 char* data = new char[size];
793
794 // we should be able to add this many blocks
795 uint32 expectedCount = 100; // CalcBlockTableSize(size);
796 uint32 expectedMaxCount = (maxPageCount-10) * expectedCount;
797 uint32 count = expectedMaxCount;
798 uint64* ids = new uint64[count];
799
800 DataMessage* msg = new DataMessage();
801 msg->setData("data", data, size);
802 msg->setEOL(eol);
803 uint32 n;
804 uint64 id;
805
806 // Write phase
807 unittest::progress(20, "insert messages");
808 uint64 t1 = GetTimeNow();
809 for (n=0; n<count; n++) {
810 msg->setInt("Test", n);
811 if (!manager->insertMessage(msg, id)) {
812 unittest::fail("MemoryManager test: insert %u failed", n);
813 delete [] ids;
814 delete [] data;
815 delete(msg);
816 delete(manager);
817 return false;
818 }
819 ids[n] = id;
820 }
821 uint64 t2 = GetTimeNow();
822
823 // Read-back phase
824 unittest::progress(60, "read back messages");
825 DataMessage* msg2;
826 for (n=0; n<count; n++) {
827 msg2 = manager->getCopyOfMessage(ids[n]);
828 if (msg2 == NULL) {
829 unittest::fail("MemoryManager test: getCopyOfMessage %u failed", n);
830 delete [] ids;
831 delete [] data;
832 delete(msg);
833 delete(manager);
834 return false;
835 }
836 if (msg->getSize() != msg2->getSize()) {
837 unittest::fail("MemoryManager test: getCopyOfMessage wrong size (%u != %u)", msg->getSize(), msg2->getSize());
838 delete [] ids;
839 delete [] data;
840 delete(msg);
841 delete(msg2);
842 delete(manager);
843 return false;
844 }
845 int64 val64;
846 if ((!msg2->getInt("Test", val64)) || (val64 != n)) {
847 unittest::fail("MemoryManager test: getCopyOfMessage wrong data (%lld != %u)", val64, n);
848 delete [] ids;
849 delete [] data;
850 delete(msg);
851 delete(msg2);
852 delete(manager);
853 return false;
854 }
855 delete(msg2);
856 }
857 uint64 t3 = GetTimeNow();
858
859 unittest::progress(90, "record metrics");
860 double writeUs = (double)(t2 - t1);
861 double readUs = (double)(t3 - t2);
862 if (writeUs > 0.0) {
863 unittest::metric("write_throughput", (1.0*size*count)/writeUs, "MB/s", true);
864 unittest::metric("write_rate", (1000000.0*count)/writeUs, "msg/s", true);
865 unittest::metric("avg_write_latency", writeUs/count, "us", false);
866 }
867 if (readUs > 0.0) {
868 unittest::metric("read_throughput", (1.0*size*count)/readUs, "MB/s", true);
869 unittest::metric("read_rate", (1000000.0*count)/readUs, "msg/s", true);
870 unittest::metric("avg_read_latency", readUs/count, "us", false);
871 }
872 unittest::detail("Writing %u: %.3f MB/s / %.3f msg/s (%u us) [%u b]",
873 count, (1.0*size*count)/writeUs, (1000000.0*count)/writeUs, (uint32)writeUs, size);
874 unittest::detail("Reading %u: %.3f MB/s / %.3f msg/s (%u us) [%u b]",
875 count, (1.0*size*count)/readUs, (1000000.0*count)/readUs, (uint32)readUs, size);
876
877 delete [] ids;
878 delete [] data;
879 delete(msg);
880 delete(manager);
881
882 unittest::progress(100, "done");
883 return true;
884}
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904//bool MemoryManagerX::GetMemoryUsage(uint32& total, uint32& usage, uint32& sysTotal, uint32& sysUsage, uint32& staticTotal, uint32& staticUsage, uint32& dynamicTotal, uint32& dynamicUsage) {
905// if (!MemoryManagerX::Singleton)
906// return false;
907// if (!MemoryManagerX::Singleton->pageMasterMutex->enter())
908// return false;
909// sysTotal = MemoryManagerX::Singleton->pageMaster->dataSize[MP_SYSTEMPAGE];
910// sysUsage = MemoryManagerX::Singleton->pageMaster->dataUsage[MP_SYSTEMPAGE];
911// staticTotal = MemoryManagerX::Singleton->pageMaster->dataSize[MP_STATICPAGE];
912// staticUsage = MemoryManagerX::Singleton->pageMaster->dataUsage[MP_STATICPAGE];
913// dynamicTotal = MemoryManagerX::Singleton->pageMaster->dataSize[MP_DYNAMICPAGE];
914// dynamicUsage = MemoryManagerX::Singleton->pageMaster->dataUsage[MP_DYNAMICPAGE];
915// total = sysTotal + staticTotal + dynamicTotal;
916// usage = sysUsage + staticUsage + dynamicUsage;
917// MemoryManagerX::Singleton->pageMasterMutex->leave();
918// return true;
919//}
920//
921//
922//MemoryManagerX::MemoryManagerX() {
923// shouldContinue = true;
924// isRunning = false;
925// isMaster = false;
926// pageMaster = NULL;
927// pageMasterMutex = NULL;
928// pageCache = NULL;
929//
930//}
931//
932//MemoryManagerX::~MemoryManagerX() {
933// if (pageMaster == NULL)
934// return;
935// pageMasterMutex->enter();
936// MemoryManagerX::Singleton = NULL;
937// shouldContinue = false;
938// uint32 c = 0;
939// while (isRunning) {
940// utils::Sleep(50);
941// if (c++ > 10)
942// break;
943// }
944// ThreadManager::Shutdown();
945// destroyAllPages();
946//
947// utils::DestroySharedMemorySegment((char*)pageMaster, pageMaster->size);
948// pageMaster = NULL;
949// pageMasterMutex->leave();
950// delete(pageMasterMutex);
951// pageMaster = NULL;
952// pageMasterMutex = NULL;
953// free(pageCache);
954//}
955//
957//bool MemoryManagerX::connect(uint16 sysID) {
959// uint32 size = sizeof(MemoryPageMaster);
960// isMaster = false;
961//
962// utils::SetSharedSystemInstance(sysID);
963//
964// pageMasterMutex = new utils::Mutex("PageMaster");
965// if (!pageMasterMutex->enter())
966// return false;
967//
968// pageMaster = (MemoryPageMaster*) utils::OpenSharedMemorySegment("CMSysMemory", size);
969// if (pageMaster == NULL) {
970// fprintf(stderr, "MemoryManager could not open shared memory id '%u'\n", sysID);
971// pageMasterMutex->leave();
972// return false;
973// }
974//
975// MemoryManagerX::Singleton = this;
976//
977// LocalSyncAdjustment = pageMaster->timesync;
978//
979// if (!ThreadManager::CreateThread(MemoryManagement, NULL, managementThreadID)) {
980// pageMasterMutex->leave();
981// return false;
982// }
983//
984// // Unlock the Mutex
985// pageMasterMutex->leave();
986// return true;
987//}
988//
990//bool MemoryManagerX::create(uint16 sysID, uint32 staticPageTableSize, uint32 slotCount, uint32 slotDuration, uint32 bufferSlots, uint32 pagesPerSlot, bool force) {
991// isMaster = true;
992//
993// utils::SetSharedSystemInstance(sysID);
994//
995// uint32 size = sizeof(MemoryPageMaster);
996//
997// char* data;
998// if (force) {
999// // Destroy CMSysMemory first...
1000// if ( (data = utils::OpenSharedMemorySegment("CMSysMemory", size)) != NULL)
1001// utils::DestroySharedMemorySegment(data, size);
1002// }
1003//
1004// pageMasterMutex = new utils::Mutex("PageMaster");
1005// if (!pageMasterMutex->enter())
1006// return false;
1007//
1008// uint32 maxPageCount = staticPageTableSize + ( (slotCount+bufferSlots) * pagesPerSlot );
1009//
1011// // Add the bitfield size = max count / 32
1012// uint32 bitFieldSize = (uint32)ceil((double)maxPageCount / 8);
1013// // Add the table size
1014// uint32 datasize = maxPageCount * sizeof(MemoryPageEntry);
1015// size += bitFieldSize + datasize;
1016//
1017// pageMaster = (MemoryPageMaster*) utils::CreateSharedMemorySegment("CMSysMemory", size);
1018// if (pageMaster == NULL) {
1019// fprintf(stderr, "MemoryManager could not create shared memory\n");
1020// pageMasterMutex->leave();
1021// pageMasterMutex->destroy();
1022// return false;
1023// }
1024//
1025// // Initialise the PageMaster structure
1026// pageMaster->status = 1; // 10 means fully initialised
1028//
1029// pageMaster->size = size; // total size of PageMaster in bytes
1030// pageMaster->sysID = sysID; // global node id
1031// pageMaster->dataSize[MP_SYSTEMPAGE] = 0; // total size of data space in bytes
1032// pageMaster->dataSize[MP_STATICPAGE] = 0; // total size of data space in bytes
1033// pageMaster->dataSize[MP_DYNAMICPAGE] = 0; // total size of data space in bytes
1034// pageMaster->dataUsage[MP_SYSTEMPAGE] = 0; // current usage of all pages in bytes, for info only
1035// pageMaster->dataUsage[MP_STATICPAGE] = 0; // current usage of all pages in bytes, for info only
1036// pageMaster->dataUsage[MP_DYNAMICPAGE] = 0; // current usage of all pages in bytes, for info only
1037// pageMaster->count[MP_SYSTEMPAGE] = 0; // current number of pages in use, for info only
1038// pageMaster->count[MP_STATICPAGE] = 0; // current number of pages in use, for info only
1039// pageMaster->count[MP_DYNAMICPAGE] = 0; // current number of pages in use, for info only
1040// pageMaster->bitFieldSize = bitFieldSize; // number of bytes in the bitfield
1041// pageMaster->pageTableSize = maxPageCount; // maximum entries in page table and number of bits in bit field
1042// memset((void*)MP_GetBitFieldLoc(pageMaster), 255, bitFieldSize);
1043// memset((void*)MP_GetPageTableLoc(pageMaster), 0, datasize);
1044//
1045// MemoryManagerX::Singleton = this;
1046//
1047// pageMaster->status = 2; // 10 means fully initialised
1049//
1050// pageMaster->timesync = LocalSyncAdjustment;
1051//
1052// pageMaster->createdTime = GetTimeNow();
1053//
1054// pageMaster->status = 3; // 10 means fully initialised
1056//
1057// // Create and initialise the EOL Page
1058// if (!resizeEOLPage(slotCount, pagesPerSlot, slotDuration, bufferSlots)) {
1059// fprintf(stderr, "MemoryManager could not resize EOL page\n");
1060// pageMasterMutex->leave();
1061// return false;
1062// }
1063//
1064// pageMaster->status = 4; // 10 means fully initialised
1066//
1067// if (!createSystemPages()) {
1068// fprintf(stderr, "MemoryManager could not create system pages\n");
1069// pageMasterMutex->leave();
1070// return false;
1071// }
1072//
1073// pageMaster->status = 5; // 10 means fully initialised
1075//
1076// pageMaster->lastCreatedStaticPage = RESERVEDPAGECOUNT-1; // id of last created static page
1077// // printBitFieldAsString("Initial Bitfield");
1078//
1079// pageMaster->status = 6; // 10 means fully initialised
1081//
1082// if (!ThreadManager::CreateThread(MemoryManagement, NULL, managementThreadID)) {
1083// pageMasterMutex->leave();
1084// return false;
1085// }
1086//
1087// pageMaster->status = 7; // 10 means fully initialised
1089//
1090// pageMaster->status = 10; // 10 means fully initialised
1091// // Unlock the Mutex
1092// pageMasterMutex->leave();
1093// return true;
1094//}
1095//
1096//
1097//
1098//
1099//
1100//
1101//
1102//
1103//
1104//
1105//
1106//
1107//
1108//
1109//
1110//
1111//
1112//
1113//
1114//
1115//
1234//
1236//char* MemoryManagerX::createSystemPage(uint32 id, uint32 size, uint64& memID) {
1237//
1238// // Mutex is still locked from callar
1239// uint32 pageID = id;
1240// MemoryPage* page = createPage(size+sizeof(MemoryBlock), 1, 0, pageID);
1241// if (page == NULL)
1242// return NULL;
1243// if (pageID != id) {
1244// destroyPage(pageID);
1245// return NULL;
1246// }
1247//
1248// if (!insertMemoryBlockIntoPage(pageID, NULL, size, 0, memID))
1249// return NULL;
1250//
1251// return getSystemBlock(pageID, size);
1252//}
1253//
1254//
1256//char* MemoryManagerX::getSystemBlock(uint32 pageID, uint32& size) {
1257// char* data = NULL;
1258// // We assume manager already locked
1260// MemoryPage* page = getCachedPage(pageID);
1261// if (page == NULL)
1262// return NULL;
1263// MemoryBlock* block = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1264// if (block == NULL)
1265// return NULL;
1266// size = block->size - sizeof(MemoryBlock);
1267// return (char*)(block + sizeof(MemoryBlock));
1268//}
1269//
1270//
1271//
1272//
1274//char* MemoryManagerX::getAndLockSystemBlock(uint32 pageID, uint32& size) {
1275// // Lock Manager
1276// if (!pageMasterMutex->enter())
1277// return NULL;
1278// MemoryPageEntry* entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1279// if (!lockPage(entry)) {
1280// pageMasterMutex->leave();
1281// return NULL;
1282// }
1283//
1284// MemoryPage* page = getCachedPage(entry);
1285// if (page == NULL) {
1286// // Unlock Manager
1287// pageMasterMutex->leave();
1288// return NULL;
1289// }
1290// char* data = getLockedSystemBlock(page, size);
1291// pageMasterMutex->leave();
1292// return data;
1293//}
1294//
1295//char* MemoryManagerX::getLockedSystemBlock(uint32 pageID, uint32& size) {
1296// // Manager should be locked
1298// MemoryPage* page = getCachedPage(pageID);
1299// if (page == NULL)
1300// return NULL;
1301// return getLockedSystemBlock(page, size);
1302//}
1303//
1304//char* MemoryManagerX::getLockedSystemBlock(MemoryPage* page, uint32& size) {
1305// MemoryBlock* block = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1306// if (block == NULL)
1307// return NULL;
1308// size = block->size - sizeof(MemoryBlock);
1309// return (char*)(block + sizeof(MemoryBlock));
1310//}
1311//
1312//bool MemoryManagerX::unlockSystemBlock(uint32 pageID) {
1313// unlockPage(pageID);
1314// return true;
1315//}
1316//
1317//
1318//
1320//char* MemoryManagerX::createAndLockNewSystemPage(uint32 size, uint32& pageID) {
1321//
1322// // Lock Manager
1323// if (!pageMasterMutex->enter())
1324// return NULL;
1325// pageID = 0; // provide new id
1326// MemoryPage* page = createPage(size+sizeof(MemoryBlock), 1, 0, pageID);
1327// if (page == NULL) {
1328// pageMasterMutex->leave();
1329// return NULL;
1330// }
1331//
1332// // createPage now keeps the page locked
1333// //if (!lockPage(pageID)) {
1334// // pageMasterMutex->leave();
1335// // return NULL;
1336// //}
1337//
1338// uint64 memID; // not required for full page memory blocks, but required for function call
1339// if (!insertMemoryBlockIntoPage(pageID, NULL, size, 0, memID))
1340// return NULL;
1341//
1342// char* data = getLockedSystemBlock(pageID, size);
1343// // Unlock Manager
1344// pageMasterMutex->leave();
1345// return data;
1346//}
1347//
1349//char* MemoryManagerX::resizeSystemPage(uint32 pageID, uint32 newSize) {
1350//
1351// uint32 oldSize = 0;
1352// char* oldData = getAndLockSystemBlock(pageID, oldSize);
1353// if (oldData == NULL)
1354// return NULL;
1355//
1356// int32 difSize = newSize - oldSize;
1357// if (difSize <= 0) {
1358// // Unlock Manager
1359// pageMasterMutex->leave();
1360// return oldData;
1361// }
1362//
1363// char* tempData = new char[oldSize];
1364// memcpy(tempData, oldData, oldSize);
1365//
1366// UnlockSystemBlock(pageID);
1367// destroyPage(pageID);
1368//
1369// uint32 newPageID = pageID;
1370// char* newData = createAndLockNewSystemPage(newSize, newPageID);
1371// if (newData == NULL) {
1372// delete [] tempData;
1373// return NULL;
1374// }
1375//
1376// memcpy(newData, tempData, oldSize);
1377// delete [] tempData;
1378// return newData;
1379//}
1380//
1381//bool MemoryManagerX::InsertMemoryBlock(const char* data, uint32 size, uint64 eol, uint64& id) {
1382// if (!MemoryManagerX::Singleton)
1383// return 0;
1384// return MemoryManagerX::Singleton->insertMemoryBlock(data, size, eol, id);
1385//}
1386//
1387//bool MemoryManagerX::OverwriteMemoryBlock(uint64 id, const char* data, uint32 size, uint64 eol) {
1388// if (!MemoryManagerX::Singleton)
1389// return 0;
1390// return MemoryManagerX::Singleton->overwriteMemoryBlock(id, data, size, eol);
1391//}
1392//
1393//char* MemoryManagerX::GetAndLockMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1394// if (!MemoryManagerX::Singleton)
1395// return 0;
1396// return MemoryManagerX::Singleton->getAndLockMemoryBlock(id, size, eol);
1397//}
1398//
1399//bool MemoryManagerX::UnlockMemoryBlock(uint64 id) {
1400// if (!MemoryManagerX::Singleton)
1401// return 0;
1402// return MemoryManagerX::Singleton->unlockMemoryBlock(id);
1403//}
1404//
1405//char* MemoryManagerX::GetCopyMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1406// if (!MemoryManagerX::Singleton)
1407// return 0;
1408// return MemoryManagerX::Singleton->getCopyMemoryBlock(id, size, eol);
1409//}
1410//
1411//
1412//
1415//char* MemoryManagerX::GetAndLockSystemBlock(uint32 pageID, uint32& size) {
1416// if (!MemoryManagerX::Singleton)
1417// return 0;
1418// return MemoryManagerX::Singleton->getAndLockSystemBlock(pageID, size);
1419//}
1420//
1423//bool MemoryManagerX::UnlockSystemBlock(uint32 pageID) {
1424// if (!MemoryManagerX::Singleton)
1425// return 0;
1426// return MemoryManagerX::Singleton->unlockSystemBlock(pageID);
1427//}
1428//
1431//char* MemoryManagerX::CreateAndLockNewSystemPage(uint32 size, uint32& id) {
1432// if (!MemoryManagerX::Singleton)
1433// return 0;
1434// return MemoryManagerX::Singleton->createAndLockNewSystemPage(size, id);
1435//}
1436//
1439//char* MemoryManagerX::ResizeSystemPage(uint32 pageID, uint32 size) {
1440// if (!MemoryManagerX::Singleton)
1441// return 0;
1442// return MemoryManagerX::Singleton->resizeSystemPage(pageID, size);
1443//}
1444//
1447//bool MemoryManagerX::DestroySystemPage(uint32 pageID) {
1448// if (!MemoryManagerX::Singleton)
1449// return 0;
1450// return MemoryManagerX::Singleton->destroyPage(pageID);
1451//}
1452//
1453//
1455//bool MemoryManagerX::createSystemPages() {
1456//
1457// // Create main system page
1458// char* data;
1459// uint32 size = 1024*512; // ############# Need better size calc
1460// uint64 memID;
1461// // Create and initialise the System Page
1462// if ( (data = createSystemPage(ID_SYSPAGE, size, memID)) == NULL) {
1463// fprintf(stderr, "MemoryManager could not create the System page\n");
1464// return false;
1465// }
1466// initSystemPage(data, size);
1467// unlockSystemBlock(ID_SYSPAGE);
1468//
1469// // Create and initialise the Page Pool
1470// size = 1024*512; // ############# Need better size calc
1471// if ( (data = createSystemPage(ID_PAGEPOOL, size, memID)) == NULL) {
1472// fprintf(stderr, "MemoryManager could not create the Page Pool page\n");
1473// return false;
1474// }
1475// initPagePool(data, size);
1476// unlockSystemBlock(ID_PAGEPOOL);
1477//
1478// // Create and initialise the Queue Page
1479// size = 1024*512; // ############# Need better size calc
1480// if ( (data = createSystemPage(ID_QUEUEPAGE, size, memID)) == NULL) {
1481// fprintf(stderr, "MemoryManager could not create the Queue page\n");
1482// return false;
1483// }
1484// initQueuePage(data, size);
1485// unlockSystemBlock(ID_QUEUEPAGE);
1486//
1487// // Create and initialise the Component Map Page
1488// uint32 count = 0xFFFF;
1489// uint32 bitFieldSize = (uint32)ceil((double)count / 8);
1490// size = sizeof(ComponentMapHeader) + bitFieldSize + count*sizeof(ComponentMapEntry);
1491// if ( (data = createSystemPage(ID_COMPMAPPAGE, size, memID)) == NULL) {
1492// fprintf(stderr, "MemoryManager could not create the Component page\n");
1493// return false;
1494// }
1495// ComponentMapHeader* cmHeader = (ComponentMapHeader*)data;
1496// cmHeader->size = size;
1497// cmHeader->bitFieldSize = bitFieldSize;
1498// cmHeader->count = count;
1499// memset(data+sizeof(ComponentMapHeader), 255, bitFieldSize);
1500// memset(data+sizeof(ComponentMapHeader)+bitFieldSize, 0, size-sizeof(ComponentMapHeader)-bitFieldSize);
1501// // Position 0 is not allowed, used to indicate error or unused
1502// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)cmHeader + sizeof(ComponentMapHeader)), cmHeader->bitFieldSize);
1503// unlockSystemBlock(ID_COMPMAPPAGE);
1504//
1505// // Create and initialise the Type Map Page
1506// count = 0xFFFF;
1507// bitFieldSize = (uint32)ceil((double)count / 8);
1508// size = sizeof(TypeMapHeader) + bitFieldSize + count*sizeof(TypeMapEntry);
1509// if ( (data = createSystemPage(ID_TYPEMAPPAGE, size, memID)) == NULL) {
1510// fprintf(stderr, "MemoryManager could not create the TypeMap page\n");
1511// return false;
1512// }
1513// TypeMapHeader* typeHeader = (TypeMapHeader*)data;
1514// typeHeader->size = size;
1515// typeHeader->bitFieldSize = bitFieldSize;
1516// typeHeader->count = count;
1517// memset((char*)typeHeader+sizeof(TypeMapHeader), 255, bitFieldSize);
1518// memset((char*)typeHeader+sizeof(TypeMapHeader)+bitFieldSize, 0, size-sizeof(TypeMapHeader)-bitFieldSize);
1519// // Position 0 is not allowed, used to indicate error or unused
1520// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)typeHeader + sizeof(TypeMapHeader)), typeHeader->bitFieldSize);
1521// unlockSystemBlock(ID_TYPEMAPPAGE);
1522//
1523// // Create and initialise the Context Map Page
1524// count = 0xFFFF;
1525// bitFieldSize = (uint32)ceil((double)count / 8);
1526// size = sizeof(ContextMapHeader) + bitFieldSize + count*sizeof(ContextMapEntry);
1527// if ( (data = createSystemPage(ID_CONTEXTMAPPAGE, size, memID)) == NULL) {
1528// fprintf(stderr, "MemoryManager could not create the ContextMap page\n");
1529// return false;
1530// }
1531// ContextMapHeader* contextHeader = (ContextMapHeader*)data;
1532// contextHeader->size = size;
1533// contextHeader->bitFieldSize = bitFieldSize;
1534// contextHeader->count = count;
1535// memset((char*)contextHeader+sizeof(ContextMapHeader), 255, bitFieldSize);
1536// memset((char*)contextHeader+sizeof(ContextMapHeader)+bitFieldSize, 0, size-sizeof(ContextMapHeader)-bitFieldSize);
1537// // Position 0 is not allowed, used to indicate error or unused
1538// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)contextHeader + sizeof(ContextMapHeader)), contextHeader->bitFieldSize);
1539// unlockSystemBlock(ID_CONTEXTMAPPAGE);
1540//
1541// //// Create and initialise the Tag Map Page
1542// //count = 4096;
1543// //bitFieldSize = (uint32)ceil((double)count / 8);
1544// //size = sizeof(TagMapHeader) + bitFieldSize + count*sizeof(TagMapEntry);
1545// //if ( (data = createSystemPage(ID_TAGMAPPAGE, size, memID)) == NULL) {
1546// // fprintf(stderr, "MemoryManager could not create the TagMap page\n");
1547// // return false;
1548// //}
1549// //TagMapHeader* tagHeader = (TagMapHeader*)data;
1550// //tagHeader->size = size;
1551// //tagHeader->bitFieldSize = bitFieldSize;
1552// //tagHeader->count = count;
1553// //memset((char*)tagHeader+sizeof(TagMapHeader), 255, bitFieldSize);
1554// //memset((char*)tagHeader+sizeof(TagMapHeader)+bitFieldSize, 0, size-sizeof(TagMapHeader)-bitFieldSize);
1555// //// Position 0 is not allowed, used to indicate error or unused
1556// //utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)tagHeader + sizeof(TagMapHeader)), tagHeader->bitFieldSize);
1557// //unlockSystemBlock(ID_TAGMAPPAGE);
1558//
1559// //// Create and initialise the Node Map Page
1560// //count = 4096;
1561// //bitFieldSize = (uint32)ceil((double)count / 8);
1562// //size = sizeof(NodeMapHeader) + bitFieldSize + count*sizeof(NodeMapEntry);
1563// //if ( (data = createSystemPage(ID_NODEMAPPAGE, size, memID)) == NULL) {
1564// // fprintf(stderr, "MemoryManager could not create the NodeMap page\n");
1565// // return false;
1566// //}
1567// //NodeMapHeader* nodeHeader = (NodeMapHeader*)data;
1568// //nodeHeader->size = size;
1569// //nodeHeader->bitFieldSize = bitFieldSize;
1570// //nodeHeader->count = count;
1571// //memset((char*)nodeHeader+sizeof(NodeMapHeader), 255, bitFieldSize);
1572// //memset((char*)nodeHeader+sizeof(NodeMapHeader)+bitFieldSize, 0, size-sizeof(NodeMapHeader)-bitFieldSize);
1573// //// Position 0 is not allowed, used to indicate error or unused
1574// //utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)nodeHeader + sizeof(NodeMapHeader)), nodeHeader->bitFieldSize);
1575// //unlockSystemBlock(ID_NODEMAPPAGE);
1576//
1577// // Create and initialise the Crank Map Page
1578// count = 0xFFFF;
1579// bitFieldSize = (uint32)ceil((double)count / 8);
1580// size = sizeof(CrankMapHeader) + bitFieldSize + count*sizeof(CrankMapEntry);
1581// if ( (data = createSystemPage(ID_CRANKMAPPAGE, size, memID)) == NULL) {
1582// fprintf(stderr, "MemoryManager could not create the CrankMap page\n");
1583// return false;
1584// }
1585// CrankMapHeader* crankHeader = (CrankMapHeader*)data;
1586// crankHeader->size = size;
1587// crankHeader->bitFieldSize = bitFieldSize;
1588// crankHeader->count = count;
1589// memset((char*)crankHeader+sizeof(CrankMapHeader), 255, bitFieldSize);
1590// memset((char*)crankHeader+sizeof(CrankMapHeader)+bitFieldSize, 0, size-sizeof(CrankMapHeader)-bitFieldSize);
1591// // Position 0 is not allowed, used to indicate error or unused
1592// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)crankHeader + sizeof(CrankMapHeader)), crankHeader->bitFieldSize);
1593// unlockSystemBlock(ID_CRANKMAPPAGE);
1594//
1595// // Create and initialise the Queue Map Page
1596// count = 0xFFFF;
1597// bitFieldSize = (uint32)ceil((double)count / 8);
1598// size = sizeof(QueueMapHeader) + bitFieldSize + count*sizeof(QueueMapEntry);
1599// if ( (data = createSystemPage(ID_QUEUEMAPPAGE, size, memID)) == NULL) {
1600// fprintf(stderr, "MemoryManager could not create the QueueMap page\n");
1601// return false;
1602// }
1603// QueueMapHeader* queueHeader = (QueueMapHeader*)data;
1604// queueHeader->size = size;
1605// queueHeader->bitFieldSize = bitFieldSize;
1606// queueHeader->count = count;
1607// memset((char*)queueHeader+sizeof(QueueMapHeader), 255, bitFieldSize);
1608// memset((char*)queueHeader+sizeof(QueueMapHeader)+bitFieldSize, 0, size-sizeof(QueueMapHeader)-bitFieldSize);
1609// // Position 0 is not allowed, used to indicate error or unused
1610// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)queueHeader + sizeof(QueueMapHeader)), queueHeader->bitFieldSize);
1611// unlockSystemBlock(ID_QUEUEMAPPAGE);
1612//
1613// // Create and initialise the Process Map Page
1614// count = 256;
1615// bitFieldSize = (uint32)ceil((double)count / 8);
1616// size = sizeof(ProcessMapHeader) + bitFieldSize + count*sizeof(ProcessMapEntry);
1617// if ( (data = createSystemPage(ID_PROCESSMAPPAGE, size, memID)) == NULL) {
1618// fprintf(stderr, "MemoryManager could not create the ProcessMap page\n");
1619// return false;
1620// }
1621// ProcessMapHeader* processHeader = (ProcessMapHeader*)data;
1622// processHeader->size = size;
1623// processHeader->bitFieldSize = bitFieldSize;
1624// processHeader->count = count;
1625// memset((char*)processHeader+sizeof(ProcessMapHeader), 0, size-sizeof(ProcessMapHeader));
1626// memset((char*)processHeader+sizeof(ProcessMapHeader), 255, bitFieldSize);
1627// // Position 0 is not allowed, used to indicate error or unused
1628// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)processHeader + sizeof(ProcessMapHeader)), processHeader->bitFieldSize);
1629// unlockSystemBlock(ID_PROCESSMAPPAGE);
1630//
1631// // Create and initialise the Request Map Page
1632// count = 256;
1633// bitFieldSize = (uint32)ceil((double)count / 8);
1634// size = sizeof(RequestMapHeader) + bitFieldSize + count*sizeof(RequestMapEntry);
1635// if ( (data = createSystemPage(ID_REQUESTMAPPAGE, size, memID)) == NULL) {
1636// fprintf(stderr, "MemoryManager could not create the RequestMap page\n");
1637// return false;
1638// }
1639// RequestMapHeader* requestHeader = (RequestMapHeader*)data;
1640// requestHeader->size = size;
1641// requestHeader->bitFieldSize = bitFieldSize;
1642// requestHeader->count = count;
1643// memset((char*)requestHeader+sizeof(RequestMapHeader), 0, size-sizeof(RequestMapHeader));
1644// memset((char*)requestHeader+sizeof(RequestMapHeader), 255, bitFieldSize);
1645// // Position 0 is not allowed, used to indicate error or unused
1646// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)requestHeader + sizeof(RequestMapHeader)), requestHeader->bitFieldSize);
1647// unlockSystemBlock(ID_REQUESTMAPPAGE);
1648//
1649// uint16 pid;
1650// if ( (!MemoryMaps::CreateNewProcess("Node Process", pid)) || (pid != NODE_PROCESS_ID) ) {
1651// fprintf(stderr, "MemoryManager could not register own process (%u != %u)\n", pid, NODE_PROCESS_ID);
1652// return false;
1653// }
1654//
1655// return true;
1656//}
1657//
1659//bool MemoryManagerX::insertMemoryBlock(const char* data, uint32 size, uint64 eol, uint64& id) {
1661// // Lock Manager
1662// if (!pageMasterMutex->enter())
1663// return false;
1664// uint32 pageID = 0;
1665// // First find an appropriate page
1666// MemoryPage* page = findPageForBlock(size, eol, pageID);
1667// if (page == NULL) {
1668// // Create a new page
1669// uint16 blockTableSize = CalcBlockTableSize(size);
1670// if (blockTableSize == 0) {
1671// pageMasterMutex->leave();
1672// return false;
1673// }
1674// page = createPage((size+sizeof(MemoryBlock))*blockTableSize, blockTableSize, eol, pageID);
1675// if (page == NULL) {
1676// pageMasterMutex->leave();
1677// return false;
1678// }
1679// unlockPage(pageID);
1680// }
1681// // printf(">>>>>> Inserting block into page ID %u...\n", pageID);
1682// if (!insertMemoryBlockIntoPage(pageID, data, size, eol, id)) {
1683// pageMasterMutex->leave();
1684// return false;
1685// }
1686// pageMasterMutex->leave();
1689// return true;
1690//}
1691//
1693//bool MemoryManagerX::insertMemoryBlockIntoPage(uint32 pageID, const char* data, uint32 size, uint64 eol, uint64& id) {
1694// // Assume page and Manager locked
1696// MemoryPage* page = getCachedPage(pageID);
1697// if (page == NULL)
1698// return false;
1699// pageMasterMutex->leave();
1700//
1701// // printf("PageID %u EOL %lu {%p}...\n", pageID, page->eol, page);
1702//
1703// uint32 totalSize = sizeof(MemoryBlock) + size;
1704//
1705// // Now we have a page, check for room
1706// if (page->count >= page->blockTableSize) {
1707// return false;
1708// }
1709// if ( (int64)page->dataSize - (int64)page->dataUsage < (int64)totalSize ) {
1710// return false;
1711// }
1712// // Find location of first available byte
1713// MemoryBlock* newBlock, *lastBlock;
1714// uint32 offset;
1715// uint16 blockID;
1716// uint32* offsetTable = (uint32*)MP_GetBlockIndexStartLoc(page);
1717// MemoryBlock* dataTable = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1718// if (page->count == 0) {
1719// newBlock = dataTable;
1720// blockID = 0;
1721// offset = 0;
1722// }
1723// else {
1724// lastBlock = (MemoryBlock*) ( (char*)dataTable + offsetTable[page->count-1] );
1725// // insert memory block
1726// newBlock = (MemoryBlock*) ( (char*)lastBlock + lastBlock->size );
1727// blockID = page->count;
1728// //offsetLoc = MP_GetBlockOffsetLoc(page, page->count-1);
1729// //offsetLoc = (uint32*)MP_GetBlockIndexStartLoc(page) + ((page->count-1) * sizeof(uint32));
1730// offset = (uint32) ((char*)newBlock - (char*)dataTable);
1731// }
1732// newBlock->size = totalSize;
1733// if (data != NULL)
1734// memcpy((char*)newBlock + sizeof(MemoryBlock), data, size);
1735// else
1736// memset((char*)newBlock + sizeof(MemoryBlock), 0, size);
1737// page->count++;
1738// page->dataUsage += newBlock->size;
1739// offsetTable[page->count-1] = offset;
1740// // Lock Manager
1741// if (!pageMasterMutex->enter())
1742// return false;
1743// pageMaster->dataUsage[MP_GetPageType(pageID, eol)] += newBlock->size;
1744// MemoryID* mid = (MemoryID*) &id;
1745// mid->blockID = blockID;
1746// mid->sysID = pageMaster->sysID;
1747// mid->pageID = pageID;
1750// // Leave Manager locked
1751// return true;
1752//}
1753//
1754//char* MemoryManagerX::getAndLockMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1755// // Lock Manager
1756// if (!pageMasterMutex->enter())
1757// return NULL;
1758// uint32 pageID = MP_GetPageID(id);
1759// //printf(">>>>>> Getting block from page ID %u...\n", pageID);
1760//
1761// MemoryPageEntry* entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1762// if (!lockPage(entry)) {
1763// pageMasterMutex->leave();
1764// return NULL;
1765// }
1766//
1767// MemoryPage* page = getCachedPage(entry);
1768// if (page == NULL) {
1769// pageMasterMutex->leave();
1770// return NULL;
1771// }
1772// // printf("PageID %u EOL %lu {%p}...\n", pageID, entry->page->eol, entry->page);
1773// pageMasterMutex->leave();
1774// return getLockedMemoryBlock(page, id, size, eol);
1775//}
1776//
1777//char* MemoryManagerX::getLockedMemoryBlock(MemoryPage* page, uint64 id, uint32& size, uint64& eol) {
1778// char* data = NULL;
1779// uint32* offsetTable = (uint32*)MP_GetBlockIndexStartLoc(page);
1780// MemoryBlock* dataTable = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1781//
1782// uint16 blockID = MP_GetBlockID(id);
1783// MemoryBlock* block = (MemoryBlock*) ( (char*)dataTable + offsetTable[blockID] );
1784// if (block == NULL) {
1785// // Unlock page
1786// unlockPage(MP_GetPageID(id));
1787// return NULL;
1788// }
1789// size = block->size - sizeof(MemoryBlock);
1790// eol = page->eol;
1791// return ((char*)block + sizeof(MemoryBlock));
1792//}
1793//
1794//bool MemoryManagerX::unlockMemoryBlock(uint64 id) {
1795// uint32 pageID = MP_GetPageID(id);
1796// unlockPage(pageID);
1797// return true;
1798//}
1799//
1800//char* MemoryManagerX::getCopyMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1801// char* data = getAndLockMemoryBlock(id, size, eol);
1802// if (data == NULL)
1803// return false;
1804// char* output = new char[size];
1805// memcpy(output, data, size);
1806// unlockMemoryBlock(id);
1807// return output;
1808//}
1809//
1811//bool MemoryManagerX::overwriteMemoryBlock(uint64 id, const char* data, uint32 size, uint64 eol) {
1812// uint32 existingSize;
1813// uint64 existingEOL;
1814// char* existingData = getAndLockMemoryBlock(id, existingSize, existingEOL);
1815// if ((existingData == NULL) || (existingSize != size) || (existingEOL != eol) )
1816// return false;
1817// memcpy(existingData, data, size);
1818// unlockMemoryBlock(id);
1819// return true;
1820//}
1821//
1823//MemoryPage* MemoryManagerX::createPage(uint32 size, uint16 tableSize, uint64 eol, uint32& pageID) {
1825// // Lock Manager
1826// if (!pageMasterMutex->enter())
1827// return NULL;
1828//
1829// // First calculate total size
1830// uint32 pageSize = sizeof(MemoryPage) + (tableSize*sizeof(uint32)) + size;
1831//
1832// MemoryPageEntry* entry = NULL;
1833// // Now check if caller is requesting a particular id
1834// if (pageID > 0) {
1835// entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1836// if ((entry == NULL) || (entry->pageSize != 0))
1837// return NULL;
1838// }
1839// else {
1840// // Get a page from the pool with the right data size
1841// if (getPageFromPool(size, pageID)) {
1842// //printf("CreateFromPool %u...\n", pageID);
1843// // We have a valid page from the pool
1844// }
1845// // Find first available Page Entry
1846// else if (!utils::GetFirstFreeBitLoc((uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->pageTableSize, pageID)) {
1847// pageMasterMutex->leave();
1848// return NULL;
1849// }
1850// }
1851//
1852// if (pageID >= pageMaster->pageTableSize) {
1853// // ############## should resize pagetable ##############
1854// LogPrint(0,0,0,"Page Table needs resizing!");
1855// pageMasterMutex->leave();
1856// return NULL;
1857// }
1858//
1859// entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1860// if (entry->pageSize == 0)
1861// entry->pageID = pageID;
1862// if (!lockPage(entry)) {
1863// pageMasterMutex->leave();
1864// return NULL;
1865// }
1866//
1867// MemoryPage* page = NULL;
1868// // If the page already exists, use it
1869// // if not, create it
1870// if (entry->pageSize == 0) {
1871// char* pageName = new char[MAXKEYNAMELEN];
1872// sprintf(pageName, "Page_%u", pageID);
1873// // Allocate from shared memory
1874// page = (MemoryPage*) utils::CreateSharedMemorySegment(pageName, pageSize);
1875// delete [] pageName;
1876// if (page == NULL) {
1877// unlockPage(entry);
1878// pageMasterMutex->leave();
1879// return NULL;
1880// }
1881// entry->cacheSerial = 1;
1882// page->blockTableSize = tableSize;
1883// page->size = pageSize;
1884// page->dataSize = size;
1885// entry->pageSize = pageSize;
1886// // entry->pageID = pageID;
1887// page->eol = 0;
1888// // printf("CreateFromNew %u EOL %lu...\n", pageID, entry->page->eol);
1889// }
1890// else {
1891// page = getCachedPage(entry);
1892// if (page == NULL) {
1893// unlockPage(entry);
1894// pageMasterMutex->leave();
1895// return NULL;
1896// }
1897// }
1898//
1899// utils::SetBit(pageID, BITOCCUPIED, (uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->bitFieldSize);
1900// if (eol == 0)
1901// pageMaster->lastCreatedStaticPage = pageID;
1902// else
1903// insertPageIntoEOL(pageID, eol, page->eol);
1904//
1905// // Initialise page
1906// page->count = 0;
1907// page->dataUsage = 0;
1909// memset((void*)MP_GetBlockIndexStartLoc(page), 0, (tableSize*sizeof(uint32)));
1910//
1911// entry->pageSerial++;
1912// pageMaster->count[MP_GetPageType(pageID, eol)]++;
1913// pageMaster->pagesSize += page->size;
1914// pageMaster->dataSize[MP_GetPageType(pageID, eol)] += page->dataSize;
1915//
1916// updateCachedPage(entry, page);
1917//
1918// // Unlock page mutex
1920// // Unlock Manager
1921// pageMasterMutex->leave();
1924// return page;
1925//}
1926//
1928//bool MemoryManagerX::freePageIntoPool(uint32 pageID) {
1929// uint32 dataSize = 0;
1930// if (!removePageFromStats(pageID, dataSize))
1931// return false;
1932// if (!insertPageIntoPool(pageID, dataSize))
1933// return false;
1934// return true;
1935//}
1936//
1938//bool MemoryManagerX::removePageFromStats(uint32 pageID, uint32& dataSize) {
1939// // Lock Manager
1940// if (!pageMasterMutex->enter())
1941// return false;
1942// MemoryPageEntry* entry = (MemoryPageEntry*) MP_GetPageEntryLoc(pageMaster, pageID);
1943// // Lock page
1944// if (!lockPage(entry)) {
1945// pageMasterMutex->leave();
1946// return false;
1947// }
1948//
1949// MemoryPage* page = getCachedPage(entry);
1950// if (page == NULL) {
1951// pageMasterMutex->leave();
1952// return true;
1953// }
1954//
1956//
1957// dataSize = page->dataSize;
1958// pageMaster->count[MP_GetPageType(pageID, page->eol)]--;
1959// pageMaster->dataSize[MP_GetPageType(pageID, page->eol)] -= page->dataSize;
1960// pageMaster->dataUsage[MP_GetPageType(pageID, page->eol)] -= page->dataUsage;
1961// pageMaster->pagesSize -= page->size;
1962// // Do not destroy shared memory segment at entry->page
1963// // and leave page link in there
1964// // entry->page = NULL;
1965// // Unlock page
1966// unlockPage(entry);
1967// // destroyPageMutex(pageID);
1968// // Page location remains in use
1969// // utils::SetBit(pageID, BITFREE, (uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->bitFieldSize);
1970// // Unlock Manager
1971// pageMasterMutex->leave();
1972// return true;
1973//}
1974//
1976//bool MemoryManagerX::insertPageIntoPool(uint32 pageID, uint32 dataSize) {
1977// uint32 sbSize = 0;
1978// PagePoolHeader* header = (PagePoolHeader*) getSystemBlock(ID_PAGEPOOL, sbSize);
1979// // Find empty spot
1980// PagePoolEntry* entry = (PagePoolEntry*) ((char*)header + sizeof(PagePoolHeader));
1981// while ((char*)entry < (char*)header + header->size) {
1982// if (entry->dataSize == 0) {
1983// //printf("Freeing to pool page id %d\n", pageID);
1984// //fflush(stdout);
1985// entry->dataSize = dataSize;
1986// entry->time = GetTimeNow();
1987// entry->pageID = pageID;
1988// return true;
1989// }
1990// else
1991// entry += 1;
1992// //entry += sizeof(PagePoolEntry);
1993// }
1994//
1995// // no free entry was found, remove the oldest one, then...
1996// entry = (PagePoolEntry*) ((char*)header + sizeof(PagePoolHeader));
1997// //printf("No free Pool Entries available for id %d, destroying id %d first\n", pageID, entry->pageID);
1998// //fflush(stdout);
1999// // Delete actual page
2000// destroyPage(entry->pageID, false);
2001// // Put in new one
2002// entry->dataSize = dataSize;
2003// entry->time = GetTimeNow();
2004// entry->pageID = pageID;
2005// return true;
2006//}
2007//
2009//bool MemoryManagerX::getPageFromPool(uint32 size, uint32& pageID) {
2010// uint32 sbSize = 0;
2011// PagePoolHeader* header = (PagePoolHeader*) getSystemBlock(ID_PAGEPOOL, sbSize);
2012// if (header == NULL)
2013// return false;
2014// // Find empty spot
2015// PagePoolEntry* entry = (PagePoolEntry*) ((char*)header + sizeof(PagePoolHeader));
2016// while ((char*)entry < (char*)header + header->size) {
2017// if (entry->dataSize >= size) {
2018// pageID = entry->pageID;
2019// //printf("Got from pool page id %d\n", pageID);
2020// //fflush(stdout);
2021// // Remove from pool
2022// memset(entry, 0, sizeof(PagePoolEntry));
2023// return true;
2024// }
2025// else
2026// entry += 1;
2027// //entry += sizeof(PagePoolEntry);
2028// }
2029// return false;
2030//}
2031//
2033//bool MemoryManagerX::destroyAllPages() {
2034// // Lock Manager
2035// if (!pageMasterMutex->enter())
2036// return false;
2037// if (pageMaster == NULL) {
2038// pageMasterMutex->leave();
2039// return true;
2040// }
2041//
2042// // MemoryPageEntry* entry = (MemoryPageEntry*) MP_GetPageTableLoc(pageMaster);
2043// for (uint32 n=0; n<pageMaster->pageTableSize; n++)
2044// destroyPage(n);
2045// // Unlock Manager
2046// pageMasterMutex->leave();
2047// return true;
2048//}
2049//
2051//bool MemoryManagerX::destroyPage(uint32 pageID, bool updateStats) {
2052// // Lock Manager
2053// if (!pageMasterMutex->enter())
2054// return false;
2055// MemoryPageEntry* entry = (MemoryPageEntry*) MP_GetPageEntryLoc(pageMaster, pageID);
2056// // Lock page
2057// if (!lockPage(entry)) {
2058// pageMasterMutex->leave();
2059// return false;
2060// }
2061//
2062// MemoryPage* page = getCachedPage(entry);
2063// if (page == NULL) {
2064// pageMasterMutex->leave();
2065// return true;
2066// }
2067//
2068// if (updateStats) {
2069// pageMaster->count[MP_GetPageType(pageID, page->eol)]--;
2070// pageMaster->dataSize[MP_GetPageType(pageID, page->eol)] -= page->dataSize;
2071// pageMaster->dataUsage[MP_GetPageType(pageID, page->eol)] -= page->dataUsage;
2072// pageMaster->pagesSize -= page->size;
2073// }
2074// // Destroy shared memory segment at entry->page
2075// //printf("Closing cached page %d...\n", pageID);
2076// //fflush(stdout);
2077// utils::DestroySharedMemorySegment((char*)(page), page->size);
2078// page = NULL;
2079// entry->cacheSerial = 0;
2080// entry->pageSize = 0;
2081// updateCachedPage(entry, NULL);
2082// // Unlock page
2083// unlockPage(entry);
2084// utils::SetBit(pageID, BITFREE, (uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->bitFieldSize);
2085// // Unlock Manager
2086// pageMasterMutex->leave();
2087// return true;
2088//}
2089//
2096//
2103//
2110//
2119//
2127//
2128//bool MemoryManagerX::lockPage(uint32 pageID) {
2129// if (!utils::EnterMutex(pageID, 5000)) {
2130// LogPrint(0,0,0,"Mutex lock timeout for memory page %u", pageID);
2131// return false;
2132// }
2133// return true;
2134//
2136//}
2137//
2138//bool MemoryManagerX::unlockPage(uint32 pageID) {
2139// return utils::LeaveMutex(pageID);
2141//}
2142//
2145//
2148//
2149//bool MemoryManagerX::lockPage(MemoryPageEntry* entry) {
2150// // Assume that pageMasterMutex is locked
2151// if (entry == NULL)
2152// return false;
2153//
2154// if (!utils::EnterMutex(entry->pageID, 5000)) {
2155// LogPrint(0,0,0,"Mutex lock timeout for memory page %u", entry->pageID);
2156// return false;
2157// }
2158// return true;
2159//
2160// //uint64 t1, t2;
2161// //uint32 myID = 0;
2162// //if (!utils::GetCurrentThreadOSID(myID) || !myID)
2163// // return false;
2164//
2165// //// wait until it reaches 0
2166// //utils::Semaphore* sem;
2167// //while ( (entry->lockCount > 0) && (entry->lockID != myID) ) {
2168// //// printf("[%u] Waiting for page %u locked by %u\n", myID, entry->pageID, entry->lockID);
2169// // // if we are waiting the page semaphore exists
2170// // if (!(sem = getPageSemaphore(entry->pageID)))
2171// // return false;
2172// // pageMasterMutex->leave();
2173// // t1 = GetTimeNow();
2174// // if (!sem->wait(1000)) {
2175// // t2 = GetTimeNow();
2176// // delete(sem);
2177// // return false;
2178// // }
2179// // else
2180// // delete(sem);
2181// // if (!pageMasterMutex->enter())
2182// // return false;
2183// //}
2184//
2185// ////if (entry->lockCount)
2186// //// printf("[%u] Locked page %u AGAIN: %u\n", myID, entry->pageID, entry->lockCount);
2187// ////else
2188// //// printf("[%u] Locked page %u\n", myID, entry->pageID);
2189//
2190// //entry->lockCount++;
2191// //entry->lockTime = GetTimeNow();
2192// //entry->lockID = myID;
2193// //return true;
2194//}
2195//
2196//bool MemoryManagerX::unlockPage(MemoryPageEntry* entry) {
2197// if (entry == NULL)
2198// return false;
2199//
2200// return utils::LeaveMutex(entry->pageID);
2201//
2228//}
2229//
2230//
2231//
2233//MemoryPage* MemoryManagerX::findPageForBlock(uint32 size, uint64 eol, uint32& id) {
2234// MemoryPage* page = NULL;
2235// if (eol > 0) {
2236// // search only in eol pages
2237// uint32 sbSize = 0;
2238// EOLHeader* header = (EOLHeader*) getSystemBlock(ID_EOLPAGE, sbSize);
2239// if (header == NULL)
2240// return NULL;
2241//
2242// EOLEntry* entry = NULL;
2243// // Find the appropriate slot
2244// uint64 now = GetTimeNow();
2245// uint64 difTime = 0;
2246// if (eol - now > 0)
2247// difTime = eol - header->startTime;
2248// uint32 difSlot = (uint32)(difTime / header->slotDuration);
2249// // If too far in the future, choose end slot - buffer slot
2250// if (difSlot >= (header->slotCount - header->bufferSlots))
2251// difSlot = header->slotCount - 1 - header->bufferSlots;
2252// // Find actual slot...
2253// uint32 actualSlot = header->startSlot + difSlot;
2254// if (actualSlot >= header->slotCount)
2255// actualSlot -= header->slotCount;
2256// entry = (EOLEntry*)((char*)header + sizeof(EOLHeader) +
2257// (actualSlot * header->pagesPerSlot * sizeof(EOLEntry)));
2258// char* endEntry = (char*) entry + header->pagesPerSlot*sizeof(EOLEntry);
2259// while ((char*) entry <= endEntry) {
2260// if (entry->eol > 0) {
2261// // page = MP_GetPageLoc(pageMaster, entry->pageID);
2262// page = getCachedPage(entry->pageID);
2263// if ((page != NULL) && ( (int64)page->dataSize - (int64)page->dataUsage >= (int64)(size+sizeof(MemoryBlock)) ) ) {
2264// id = entry->pageID;
2265// return page;
2266// }
2267// }
2268// entry += 1;
2269// //entry += sizeof(EOLEntry);
2270// }
2271// }
2272// else {
2273// // search in non-eol pages
2274// // First check the last created page
2275// //page = MP_GetPageLoc(pageMaster, pageMaster->lastCreatedStaticPage);
2276// page = getCachedPage(pageMaster->lastCreatedStaticPage);
2277// if ((page != NULL) && ( (int64)page->dataSize - (int64)page->dataUsage >= (int64)(size+sizeof(MemoryBlock)) ) ) {
2278// id = pageMaster->lastCreatedStaticPage;
2279// return page;
2280// }
2281// // Since we don't (yet) support deletion of memory within static pages,
2282// // there is no need to look further
2283// }
2284//
2285// return NULL;
2286//}
2287//
2288//
2290//uint16 MemoryManagerX::CalcBlockTableSize(uint32 size) {
2291// if (size >= 10*1024*1024) // 10 MB
2292// return 10;
2293// else if (size >= 1024*1024) // 1 MB
2294// return 100;
2295// else if (size >= 256*1024) // 256 kB
2296// return 512;
2297// else if (size >= 16*1024) // 16 kB
2298// return 1024;
2299// else
2300// return 4096;
2301//
2302//}
2303//
2305//char* MemoryManagerX::getBitFieldAsString(uint32& size) {
2306// size = this->pageMaster->bitFieldSize * 16;
2307// char* str = new char[size];
2308//
2309// char* src = (char*)MP_GetBitFieldLoc(pageMaster);
2310// uint32 bfsize = pageMaster->bitFieldSize;
2311//
2312// uint32 n=0, p=0,i,j;
2313// for(i=0;i<bfsize;i++) {
2314// for(j=0;j<8;j++) {
2315// str[n++] = (src[i] & (1<<j)) ? '_' : '0' + (uint8)(getPageUsage(p)*10);
2316// if (++p >= pageMaster->pageTableSize)
2317// break;
2318// }
2319// str[n++] = ' ';
2320// };
2321// str[n] = 0;
2322// return str;
2323//}
2324//
2326//bool MemoryManagerX::printBitFieldAsString(char* title) {
2327// uint32 size = 0;
2328// char* str = getBitFieldAsString(size);
2329// if (str == NULL)
2330// return false;
2331// if (size < 73) {
2332// if (title != NULL)
2333// printf("%s [%u]: %s\n", title, pageMaster->pageTableSize, str);
2334// else
2335// printf("%s\n", str);
2336// }
2337// else {
2338// if (title != NULL)
2339// printf("%s [%u]:\n", title, pageMaster->pageTableSize);
2340// uint32 loc = 35;
2341// while (loc < size-1) {
2342// str[loc] = '\n';
2343// loc += 36;
2344// }
2345// printf("%s\n", str);
2346// }
2347// delete [] str;
2348// return true;
2349//}
2350//
2352//bool MemoryManagerX::getPageUsage(uint32 pageID, double& val) {
2354// MemoryPage* page = getCachedPage(pageID);
2355// if (page == NULL)
2356// return false;
2357// val = ((double)page->dataUsage)/page->dataSize;
2358// return true;
2359//}
2360//
2362//double MemoryManagerX::getPageUsage(uint32 pageID) {
2364// MemoryPage* page = getCachedPage(pageID);
2365// if (page == NULL)
2366// return 0;
2367// return ((double)page->dataUsage)/page->dataSize;
2368//}
2369//
2371//bool MemoryManagerX::getPageFree(uint32 pageID, uint32& bytes) {
2373// MemoryPage* page = getCachedPage(pageID);
2374// if (page == NULL)
2375// return false;
2376// bytes = page->dataSize - page->dataUsage;
2377// return true;
2378//}
2379//
2381//bool MemoryManagerX::getPageSize(uint32 pageID, uint32& bytes) {
2383// MemoryPage* page = getCachedPage(pageID);
2384// if (page == NULL)
2385// return false;
2386// bytes = page->dataSize;
2387// return true;
2388//}
2389//
2391//bool MemoryManagerX::initSystemPage(char* data, uint32 size) {
2392// memset(data, 0, size);
2393// return true;
2394//}
2395//
2397//bool MemoryManagerX::initPagePool(char* data, uint32 size) {
2398// PagePoolHeader* header = (PagePoolHeader*) data;
2399// header->size = size;
2400// memset(data+sizeof(PagePoolHeader), 0, size-sizeof(PagePoolHeader));
2401// return true;
2402//}
2403//
2405//bool MemoryManagerX::resizeEOLPage(uint32 slotCount, uint32 pagesPerSlot, uint32 slotDuration, uint32 bufferSlots) {
2406//
2407// if ( (slotCount < 5) || (pagesPerSlot < 5) || (slotDuration < 100000) || (bufferSlots < 1) )
2408// return false;
2409//
2410// uint32 oldSize = 0, newSize = (slotCount+bufferSlots)*pagesPerSlot*sizeof(EOLEntry) + sizeof(EOLHeader);
2411// MemoryPageEntry* oldEntry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, ID_EOLPAGE);
2413// char* oldData = NULL;
2414// if ((oldEntry != NULL) && (oldEntry->pageSize != 0)) {
2415// // Make copy...
2416// char* eolData = getSystemBlock(ID_EOLPAGE, oldSize);
2417// if (newSize <= oldSize)
2418// return false;
2419// oldData = new char[oldSize];
2420// memcpy(eolData, oldData, oldSize);
2421// destroyPage(ID_EOLPAGE);
2422// }
2423// uint64 memID;
2424// char* data = createSystemPage(ID_EOLPAGE, newSize, memID);
2425// if (data == NULL)
2426// return false;
2428// memset(data, 0, newSize);
2429// EOLHeader* header = (EOLHeader*) data;
2430// header->slotCount = slotCount+bufferSlots;
2431// header->pagesPerSlot = pagesPerSlot;
2432// header->slotDuration = slotDuration;
2433// header->startSlot = 0;
2434// header->startTime = GetTimeNow();
2435// header->bufferSlots = bufferSlots;
2436//
2437// uint64 slotEOL = 0;
2438// if (oldData != NULL) {
2439// EOLHeader* oldHeader = (EOLHeader*) oldData;
2440// // Copy old data back in...
2441// EOLEntry* entry = (EOLEntry*) oldHeader + sizeof(EOLHeader);
2442// uint64 endHeader = (uint64) oldHeader + (oldHeader->slotCount*oldHeader->pagesPerSlot*sizeof(EOLEntry)) + sizeof(EOLHeader);
2443// while ((uint64) entry <= endHeader) {
2444// if (entry->eol > 0) {
2445// // Insert entry in new structure
2446// insertPageIntoEOL(entry->pageID, entry->eol, slotEOL);
2447// }
2448// entry += 1;
2449// //entry += sizeof(EOLEntry);
2450// }
2451// // Delete copy
2452// delete [] oldData;
2453// }
2454// return true;
2455//}
2456//
2458//bool MemoryManagerX::insertPageIntoEOL(uint32 pageID, uint64 eol, uint64& slotEOL) {
2459// uint32 sbSize = 0;
2460// EOLHeader* header = (EOLHeader*) getSystemBlock(ID_EOLPAGE, sbSize);
2461// if (header == NULL)
2462// return false;
2463//
2464// EOLEntry* entry = NULL;
2465// // Find the appropriate slot
2466// uint64 now = GetTimeNow();
2467// uint64 difTime = 0;
2468// if (eol - now > 0)
2469// difTime = eol - now;
2470// // If too far in the future, choose end slot
2471// uint32 difSlot = (uint32)(difTime / header->slotDuration);
2472// // If too far in the future, choose end slot - buffer slot
2473// if (difSlot >= (header->slotCount - header->bufferSlots))
2474// difSlot = header->slotCount - 1 - header->bufferSlots;
2475// // Calc end time of actual slot
2476// slotEOL = difSlot * header->slotDuration;
2477// // Find actual slot, possible wrap-around...
2478// uint32 actualSlot = header->startSlot + difSlot;
2479// if (actualSlot >= header->slotCount)
2480// actualSlot -= header->slotCount;
2481//
2483//
2484// entry = (EOLEntry*)((char*)header + sizeof(EOLHeader) +
2485// (actualSlot * header->pagesPerSlot * sizeof(EOLEntry)));
2486// char* endEntry = (char*) entry + header->pagesPerSlot*sizeof(EOLEntry);
2487// while ((char*) entry < endEntry) {
2488// if (entry->eol == 0) {
2489// entry->eol = eol;
2490// entry->pageID = pageID;
2491// return true;
2492// }
2493// else
2494// entry += 1;
2495// //entry += sizeof(EOLEntry);
2496// }
2497// // Out of room in current slot, try the next slot
2498// if (difSlot < header->slotCount - 1)
2499// return insertPageIntoEOL(pageID, eol+header->slotDuration, slotEOL);
2500// else {
2501// // we need to resize the EOL structure
2502// resizeEOLPage(header->slotCount, header->pagesPerSlot * 4, header->slotDuration, header->bufferSlots);
2503// return insertPageIntoEOL(pageID, eol, slotEOL);
2504// }
2505//}
2506//
2507//
2509//bool MemoryManagerX::initQueuePage(char* data, uint32 size) {
2510// memset(data, 0, size);
2511// return true;
2512//}
2513//
2514//
2515//MemoryPage* MemoryManagerX::getCachedPage(uint32 pageID) {
2516// return getCachedPage((MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID));
2517//}
2518//
2519//MemoryPage* MemoryManagerX::getCachedPage(MemoryPageEntry *entry) {
2520// if (entry == NULL)
2521// return NULL;
2522//
2523// if (pageCache == NULL) {
2524// uint32 size = sizeof(MemoryPageCache) + pageMaster->pageTableSize*sizeof(MemoryPageCacheEntry);
2525// pageCache = (MemoryPageCache*) malloc(size);
2526// pageCache->size = size;
2527// pageCache->count = pageMaster->pageTableSize;
2528// memset((char*)pageCache + sizeof(MemoryPageCache), 0, size - sizeof(MemoryPageCache));
2529// }
2530//
2531// // Find CachedEntry
2532// MemoryPageCacheEntry* cEntry = (MemoryPageCacheEntry*) ((char*)pageCache + sizeof(MemoryPageCache) + (entry->pageID * sizeof(MemoryPageCacheEntry)));
2533// if (cEntry == NULL)
2534// return NULL;
2535// else if ( (cEntry->page == NULL) || (cEntry->cacheSerial != entry->cacheSerial) || (cEntry->pageSerial != entry->pageSerial) ) {
2536// // Cache needs updating
2537// if (cEntry->page != NULL)
2538// utils::DestroySharedMemorySegment((char*)cEntry->page, cEntry->pageSize);
2539// // Map page memory location
2540//
2541// char* pageName = new char[MAXKEYNAMELEN];
2542// sprintf(pageName, "Page_%u", entry->pageID);
2543// cEntry->page = (MemoryPage*) utils::OpenSharedMemorySegment(pageName, entry->pageSize);
2544// delete [] pageName;
2545// if (cEntry->page == NULL)
2546// return NULL;
2547// cEntry->cacheSerial = entry->cacheSerial;
2548// cEntry->pageID = entry->pageID;
2549// cEntry->pageSerial = entry->pageSerial;
2550// cEntry->pageSize = entry->pageSize;
2551// }
2552// //printf("Got cached page id %d: %p\n", entry->pageID, cEntry->page);
2553// //fflush(stdout);
2554// return cEntry->page;
2555//}
2556//
2557//bool MemoryManagerX::updateCachedPage(MemoryPageEntry *entry, MemoryPage *page) {
2558// if (entry == NULL)
2559// return false;
2560//
2561// if (pageCache == NULL) {
2562// uint32 size = sizeof(MemoryPageCache) + pageMaster->pageTableSize*sizeof(MemoryPageCacheEntry);
2563// pageCache = (MemoryPageCache*)malloc(size);
2564// pageCache->size = size;
2565// pageCache->count = pageMaster->pageTableSize;
2566// memset((char*)pageCache + sizeof(MemoryPageCache), 0, size - sizeof(MemoryPageCache));
2567// }
2568//
2569// // Find CachedEntry
2570// MemoryPageCacheEntry* cEntry = (MemoryPageCacheEntry*) ((char*)pageCache + sizeof(MemoryPageCache) + (entry->pageID * sizeof(MemoryPageCacheEntry)));
2571// if (cEntry == NULL)
2572// return NULL;
2573//
2574// // Should existing page be removed?
2575// if ( (cEntry->page != NULL) && (cEntry->page != page) && ( (page != NULL) || (entry->pageSize == 0) ) ) {
2576// utils::DestroySharedMemorySegment((char*)cEntry->page, cEntry->pageSize);
2577// cEntry->page = NULL;
2578// }
2579// if (page != NULL)
2580// cEntry->page = page;
2581// cEntry->cacheSerial = entry->cacheSerial;
2582// cEntry->pageID = entry->pageID;
2583// cEntry->pageSerial = entry->pageSerial;
2584// cEntry->pageSize = entry->pageSize;
2585//
2586// return true;
2587//}
2588//
2589//
2590//
2591//
2592//
2593//
2594//
2595//
2596//
2597//
2598//
2599//
2600//
2601//
2602//
2603//
2604//
2605//
2606//
2607//
2613//
2615//uint32 MemoryManagerX::runManager() {
2616// LogPrint(0, LOG_SYSTEM, 5, "Memory Management running...\n\n");
2617// isRunning = true;
2618//
2619// uint64 nextPageCheck = 0, now;
2620//
2621// while (shouldContinue) {
2622// if (!pageMasterMutex->enter())
2623// break;
2624//
2625// if (isMaster)
2626// pageMaster->timesync = LocalSyncAdjustment;
2627// else
2628// LocalSyncAdjustment = pageMaster->timesync;
2629//
2630// now = GetTimeNow();
2631//
2632// if (!nextPageCheck || (now >= nextPageCheck) ) {
2633//
2634// uint32 sbSize = 0;
2635// EOLHeader* header = (EOLHeader*) getSystemBlock(ID_EOLPAGE, sbSize);
2636// if (header == NULL) {
2637// pageMasterMutex->leave();
2638// break;
2639// }
2640//
2641// EOLEntry* entry;
2642// char* endEntry;
2643// int32 delSlot;
2644// // Check if we should tick the current EOL startSlot to the next slot
2645// while ( now - header->startTime > header->slotDuration) {
2646// // Move the current slot one forward
2647// header->startSlot++;
2648// if (header->startSlot > header->slotCount)
2649// header->startSlot -= header->slotCount;
2650// header->startTime += header->slotDuration;
2651// // printf("New startSlot: %u (%d)...\n", header->startSlot, GetTimeNow() - header->startTime);
2652// // Find the slot minus bufferSlots
2653// delSlot = header->startSlot - header->bufferSlots;
2654// if (delSlot < 0)
2655// delSlot += header->slotCount;
2656//
2657// // Free all pages in the slot
2658// entry = (EOLEntry*)((char*)header + sizeof(EOLHeader) +
2659// (delSlot * header->pagesPerSlot * sizeof(EOLEntry)));
2660// endEntry = (char*) entry + header->pagesPerSlot*sizeof(EOLEntry);
2661// while ((char*) entry < endEntry) {
2662// if (entry->eol > 0) {
2663// // printf("--------- Freeing page ID %u, slot %u, eol %llu...\n", entry->pageID, delSlot, entry->eol);
2664// freePageIntoPool(entry->pageID);
2665// entry->eol = 0;
2666// entry->pageID = 0;
2667// }
2668// entry += 1;
2669// }
2670//
2671// }
2672// nextPageCheck = header->startTime + header->slotDuration + 20000;
2673// // sleep = header->startTime + header->slotDuration - GetTimeNow() + 20000;
2674// pageMasterMutex->leave();
2675// }
2676// else {
2677// pageMasterMutex->leave();
2678// utils::Sleep(20);
2679// }
2680// }
2681//
2682// isRunning = false;
2683// return 0;
2684//}
2685//
2686//bool MemoryManagerX::UnitTest() {
2687// printf("Testing Static Memory Management...\n\n");
2688//
2689// // First create and initialise the MemoryManager
2690// MemoryManagerX* manager = new MemoryManagerX();
2691// uint32 maxPageCount = 15;
2692// // fprintf(stderr, "MemoryManager init() 0...\n");
2693// if (!manager->create(0, maxPageCount)) {
2694// fprintf(stderr, "MemoryManager init() failed...\n");
2695// delete(manager);
2696// return false;
2697// }
2698// // fprintf(stderr, "MemoryManager init() success...\n");
2699//
2700// uint64 eol = 0;
2701// uint32 size = 4096;
2702// char* data = new char[size];
2703//
2704// // we should be able to add
2705// uint32 expectedCount = CalcBlockTableSize(size);
2706// uint32 expectedMaxCount = (maxPageCount-RESERVEDPAGECOUNT) * expectedCount;
2707// uint32 count = expectedMaxCount;
2708// uint64* ids = new uint64[count];
2709//
2710// // printf("\n\n>>>>>> Inserting %lu blocks ...\n\n", count);
2711//
2712// uint32 n;
2713// uint64 id;
2714// uint64 t1 = GetTimeNow();
2715// for (n=0; n<count; n++) {
2716// strcpy(data, "Test");
2717// utils::Int2Ascii(n, data+4, size-4, 10);
2718// if (!manager->insertMemoryBlock(data, size, eol, id)) {
2719// fprintf(stderr, "MemoryManager insert %d failed...\n", n);
2720// delete [] ids;
2721// delete [] data;
2722// delete(manager);
2723// return false;
2724// }
2725// ids[n] = id;
2726// }
2727// uint64 t2 = GetTimeNow();
2728//
2729// uint32 size2 = 0;
2730// uint64 eol2 = 0;
2731// char* data2;
2732//
2733// // printf("\n\n>>>>>> Getting %lu blocks ...\n\n", count);
2734// for (n=0; n<count; n++) {
2735// data2 = manager->getCopyMemoryBlock(ids[n], size2, eol2);
2736// if (data2 == NULL) {
2737// fprintf(stderr, "MemoryManager getcopy failed...\n");
2738// delete [] ids;
2739// delete [] data;
2740// delete(manager);
2741// return false;
2742// }
2743// if (size2 != size) {
2744// fprintf(stderr, "MemoryManager getcopy got wrong size back...\n");
2745// delete [] ids;
2746// delete [] data;
2747// delete [] data2;
2748// delete(manager);
2749// return false;
2750// }
2751// strcpy(data, "Test");
2752// utils::Int2Ascii(n, data+4, size-4, 10);
2753// if (strcmp(data2, data) != 0) {
2754// fprintf(stderr, "MemoryManager getcopy got wrong data back...\n");
2755// delete [] ids;
2756// delete [] data;
2757// delete [] data2;
2758// delete(manager);
2759// return false;
2760// }
2761// if (eol2 != eol) {
2762// fprintf(stderr, "MemoryManager getcopy got wrong eol back (%llu != %llu) [%u]...\n", eol2, eol, n);
2763// delete [] ids;
2764// delete [] data;
2765// delete [] data2;
2766// delete(manager);
2767// return false;
2768// }
2769// delete [] data2;
2770// }
2771// uint64 t3 = GetTimeNow();
2772//
2773// printf("Performance:\n Writing %u: %.3f MB/s / %.3f entries/s (%u us) [%u b]\n",
2774// count, (1.0*size*count)/(t2-t1), (1000000.0*count)/(t2-t1), (uint32)(t2-t1), size);
2775// printf(" Reading %u: %.3f MB/s / %.3f entries/s (%u us) [%u b]\n\n",
2776// count, (1.0*size*count)/(t3-t2), (1000000.0*count)/(t3-t2), (uint32)(t3-t2), size);
2777//
2778// delete [] ids;
2779// delete [] data;
2780// delete(manager);
2781// fprintf(stdout, "*** Static Memory Management test ran successfully ***\n\n\n");
2782//
2784//
2785// printf("Testing Dynamic Memory Management...\n\n");
2786//
2787// manager = new MemoryManagerX();
2788// // Initialise for 10 slots of 1 sec each, 0 buffer = 10 second max keep
2789// // fprintf(stderr, "MemoryManager init() 0...\n");
2790// if (!manager->create(0, 100, 10, 100000, 1)) {
2791// fprintf(stderr, "MemoryManager init() failed...\n");
2792// delete(manager);
2793// return false;
2794// }
2795// // fprintf(stderr, "MemoryManager init() success...\n");
2796//
2797// uint64 now = GetTimeNow();
2798//
2799// uint32 total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage;
2800// if (GetMemoryUsage(total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage))
2801// printf("Dynamic Memory in use before test: %u (%u allocated))\n", dynamicUsage, dynamicTotal);
2802//
2803// char* mem;
2804// for (n=0; n<30; n++) {
2805// mem = new char[1024];
2806// if (!manager->insertMemoryBlock(mem, 1024, now+1000000, id)) {
2807// fprintf(stderr, "MemoryManager insert memory failed...\n");
2808// delete(manager);
2809// return false;
2810// }
2811// delete [] mem;
2812// if (GetMemoryUsage(total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage))
2813// printf("Dynamic Memory in use add %u: %u (%u allocated))\n", n, dynamicUsage, dynamicTotal);
2814// utils::Sleep(100);
2815// now = GetTimeNow();
2816// }
2817//
2818// for (n=0; n<20; n++) {
2819// if (GetMemoryUsage(total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage))
2820// printf("Dynamic Memory in use idle %u: %u (%u allocated))\n", n, dynamicUsage, dynamicTotal);
2821// utils::Sleep(100);
2822// }
2823//
2824//
2825// delete(manager);
2826// fprintf(stdout, "*** Dynamic Memory Management test ran successfully ***\n\n\n");
2827//
2828// return true;
2829//}
2830
2831//#define SEGSIZE ((size_t)1024)
2832//
2833//int server() {
2834//
2835// int shmFD;
2836// void *shmAdd;
2837// int i, useMode=1; /* 1=use segment, not create it. */
2838//
2839// /* We get "open" a shared memory segment with the given name. The
2840// flags work just as they do with open: O_CREAT creates the segment
2841// if it doesn't exist, O_EXCL errors out if the segment already
2842// exists, and O_RDRW opens it for read and write. The perms are as
2843// with chmod. Normally, things opened with shm_open do now appear
2844// in the filesystem; however, it is best to specify a path to a
2845// file you can write to! */
2846// shmFD = shm_open("foobar", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
2847// if(shmFD < 0) {
2848// /* I have a case for all of the interesting cases, even the ones
2849// that can not happen in this situation... */
2850// switch(errno) {
2851// case EACCES: printf("shm_open failed: The requested permissions were denied or create denied .\n");
2852// break;
2853// case EEXIST: printf("shm_open failed: Object already exists and O_CREAT and O_EXCL were specified.\n");
2854// useMode=1;
2855// break;
2856// case EINTR: printf("shm_open failed: The operation was interrupted by a signal.\n");
2857// break;
2858// case EINVAL: printf("shm_open failed: The operation is not supported.\n");
2859// break;
2860// case EMFILE: printf("shm_open failed: Too many file descriptors were already open.\n");
2861// break;
2862// case ENAMETOOLONG: printf("shm_open failed: Name was too long (longer than SHM_NAME_MAX chars).\n");
2863// break;
2864// case ENFILE: printf("shm_open failed: The system file table is full.\n");
2865// break;
2866// case ENOENT: printf("shm_open failed: Object doesn't exist (O_CREAT was not specified).\n");
2867// break;
2868// case ENOSPC: printf("shm_open failed: No memory to create object (O_CREAT was specified).\n");
2869// break;
2870// default: printf("shm_open failed: Duno why...\n");
2871// break;
2872// } /* end switch */
2873//
2874// exit(1);
2875// } /* end if */
2876//
2877//
2878// /* Use ftruncate() to size the region -- IMO an only semi-intuitive
2879// choice on the part of the POSIX committee. */
2880// if(ftruncate(shmFD, SEGSIZE) < 0) {
2881// /* I have included all typically supported error cases below, even
2882// if they don't apply here. */
2883// switch(errno) {
2884// case EBADF: printf("ftruncate failed: The fd is not a valid descriptor.\n");
2885// break;
2886// case EINVAL: printf("ftruncate failed: Not open for writing, or references a socket, not a file.\n");
2887// break;
2888// default: printf("ftruncate failed: Duno why...\n");
2889// break;
2890// } /* end switch */
2891// exit(1);
2892// } /* end if */
2893//
2894// shmAdd = (char *)mmap(NULL, // Almost always not used
2895// SEGSIZE, // Length of the mapped space
2896// PROT_READ | PROT_WRITE, // Access type
2897// MAP_SHARED, // Write changes to device (see: MAP_PRIVATE)
2898// shmFD, // FD of the shared memory segment
2899// 0); // Offset into segment.
2900//
2901// /* For more info on the strange return and possible error conditions
2902// of mmap(), see the mmap.c example program. */
2903// if(shmAdd == MAP_FAILED) {
2904// switch(errno) {
2905// case EACCES: printf("mmap failed: The FD was not open for read, or for write with (PROT_WRITE or MAP_SHARED)\n");
2906// break;
2907// case EAGAIN: printf("mmap failed: The mapping could not be locked in memory\n");
2908// break;
2909// case EBADF: printf("mmap failed: The FD not a valid open file descriptor.\n");
2910// break;
2911// case EINVAL: printf("mmap failed: The value of len is zero, addr is not valid, bad combination of args\n");
2912// break;
2913// case EMFILE: printf("mmap failed: The too many regions mapped already\n");
2914// break;
2915// case ENODEV: printf("mmap failed: The FD file type is not supported by mmap().\n");
2916// break;
2917// case ENOMEM: printf("mmap failed: Not enough memory\n");
2918// break;
2919// case ENOTSUP: printf("mmap failed: Options not supported on this platform\n");
2920// break;
2921// case ENXIO: printf("mmap failed: Range [off,off+len) are invalid for the FD, MAP_FIXED & invalid addresses, or FD not accessible\n");
2922// break;
2923// case EOVERFLOW: printf("mmap failed: File is too big!\n");
2924// break;
2925// default: printf("mmap failed: Duno why! (errno: %d)\n", errno);
2926// break;
2927// } /* end switch */
2928// exit(1);
2929// } /* end if */
2930//
2931// /* We copy some stuff into the segment so that we can read it out later... */
2932// printf("Write 'Hello' into the segment.\n");
2933// strcpy((char*)shmAdd, "Hello");
2934//
2935// return 0;
2936//} /* end func main() */
2937//
2938//
2939//int client() {
2940// int shmFD;
2941// void *shmAdd;
2942// int i, useMode=0; /* 1=use segment, not create it. */
2943//
2944// /* If we failed before because the segment already existed, then we try to open it
2945// up and use it -- thus combining the "make" and "use" example programs. */
2946// shmFD = shm_open("foobar", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
2947// if(shmFD < 0) {
2948// switch(errno) {
2949// case EACCES: printf("shm_open failed: The requested permissions were denied or create denied .\n");
2950// break;
2951// case EEXIST: printf("shm_open failed: Object already exists and O_CREAT and O_EXCL were specified.\n");
2952// useMode=1;
2953// break;
2954// case EINTR: printf("shm_open failed: The operation was interrupted by a signal.\n");
2955// break;
2956// case EINVAL: printf("shm_open failed: The operation is not supported.\n");
2957// break;
2958// case EMFILE: printf("shm_open failed: Too many file descriptors were already open.\n");
2959// break;
2960// case ENAMETOOLONG: printf("shm_open failed: Name was too long (longer than SHM_NAME_MAX chars).\n");
2961// break;
2962// case ENFILE: printf("shm_open failed: The system file table is full.\n");
2963// break;
2964// case ENOENT: printf("shm_open failed: Object doesn't exist (O_CREAT was not specified).\n");
2965// break;
2966// case ENOSPC: printf("shm_open failed: No memory to create object (O_CREAT was specified).\n");
2967// break;
2968// default: printf("shm_open failed: Duno why...\n");
2969// break;
2970// } /* end switch */
2971// exit(1);
2972// } /* end if */
2973//
2974//
2975// shmAdd = (char *)mmap(NULL, // Almost always not used
2976// SEGSIZE, // Length of the mapped space
2977// PROT_READ | PROT_WRITE, // Access type
2978// MAP_SHARED, // Write changes to device (see: MAP_PRIVATE)
2979// shmFD, // FD of the shared memory segment
2980// 0); // Offset into segment.
2981//
2982// /* For more info on the strange return and possible error conditions
2983// of mmap(), see the mmap.c example program. */
2984// if(shmAdd == MAP_FAILED) {
2985// switch(errno) {
2986// case EACCES: printf("mmap failed: The FD was not open for read, or for write with (PROT_WRITE or MAP_SHARED)\n");
2987// break;
2988// case EAGAIN: printf("mmap failed: The mapping could not be locked in memory\n");
2989// break;
2990// case EBADF: printf("mmap failed: The FD not a valid open file descriptor.\n");
2991// break;
2992// case EINVAL: printf("mmap failed: The value of len is zero, addr is not valid, bad combination of args\n");
2993// break;
2994// case EMFILE: printf("mmap failed: The too many regions mapped already\n");
2995// break;
2996// case ENODEV: printf("mmap failed: The FD file type is not supported by mmap().\n");
2997// break;
2998// case ENOMEM: printf("mmap failed: Not enough memory\n");
2999// break;
3000// case ENOTSUP: printf("mmap failed: Options not supported on this platform\n");
3001// break;
3002// case ENXIO: printf("mmap failed: Range [off,off+len) are invalid for the FD, MAP_FIXED & invalid addresses, or FD not accessible\n");
3003// break;
3004// case EOVERFLOW: printf("mmap failed: File is too big!\n");
3005// break;
3006// default: printf("mmap failed: Duno why! (errno: %d)\n", errno);
3007// break;
3008// } /* end switch */
3009// exit(1);
3010// } /* end if */
3011//
3012// /* The segment already existed, so we print out it's contents and change them. */
3013// /* Just print the printable chars in case the segment has binary junk in it... */
3014// printf("The segment content: \n");
3015// for(i=0;(i<SEGSIZE)&&(((char *)shmAdd)[i]!=0);i++)
3016// if(isalpha(((char *)shmAdd)[i]) || isdigit(((char *)shmAdd)[i]))
3017// printf("%c", ((char *)shmAdd)[i]);
3018// printf("\n");
3019//
3020// /* Now we change the data to "Goodbye" */
3021// printf("Change the contents to: 'Goodbye'..\n");
3022// strcpy((char*)shmAdd, "Goodbye");
3023//
3024// /* While not required, one should unmap from segments when done with them. */
3025// if(munmap(shmAdd, SEGSIZE) < 0) {
3026// switch(errno) {
3027// case EINVAL: printf("munmap failed: The address range [addr,addr+len) is invalid.\n"
3028// " munmap failed: The len argument is 0.\n"
3029// " munmap failed: The addr argument is not a multiple of page size.\n");
3030// break;
3031// default: printf("munmap failed: Duno why! (errno %d).\n", errno);
3032// break;
3033// } /* end switch */
3034// exit(1);
3035// } /* end if */
3036//
3037// /* One should also close FDs opened with shm_open (again, not
3038// necessarily required, but good practice). */
3039// if(close(shmFD) < 0) {
3040// switch(errno) {
3041// case EBADF: printf("close failed: The FD is not an active descriptor.\n");
3042// break;
3043// case EINTR: printf("close failed: An interrupt was received.\n"); // Should try again... :)
3044// break;
3045// } /* end switch */
3046// } /* end if */
3047//
3048// return 0;
3049//} /* end func main() */
3050
3052
3053 // NOTE: the original shared-memory exercise (CreateSharedMemorySegment /
3054 // OpenSharedMemorySegment / server() / client()) is disabled in this build,
3055 // so this test is currently a smoke check that the entry point is callable.
3056 unittest::progress(10, "shared memory smoke check");
3057
3058 //char *data = utils::CreateSharedMemorySegment("foobar", 1024);
3059 //if (!data)
3060 // unittest::detail("Couldn't create test shared memory segment...");
3061
3062 //char* data2 = utils::OpenSharedMemorySegment("foobar", 1024);
3063 //if (!data2)
3064 // unittest::detail("Couldn't open test shared memory segment...");
3065
3066 unittest::progress(100, "done");
3067 return true;
3068
3069// server();
3070// client();
3071}
3072
3073
3076 "Static memory management insert/read-back throughput", "memory");
3078 "Shared memory segment smoke check", "memory");
3079}
3080
3081
3082} // namespace cmlabs
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
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.
#define PSYCLONEINDEXID
Definition ObjectIDs.h:46
#define PSYCLONEMASTERID
Definition ObjectIDs.h:47
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 MAXKEYNAMELEN
Definition Utils.h:85
#define thread_ret_val(ret)
Definition Utils.h:131
#define THREAD_RET
Definition Utils.h:127
#define THREAD_FUNCTION_CALL
Definition Utils.h:129
#define LOG_MEMORY
Definition Utils.h:199
#define LogPrint
Definition Utils.h:313
#define THREAD_ARG
Definition Utils.h:130
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.
bool create(uint16 port)
Create the master segment for the node instance listening on port.
uint32 incrementDataMapsShmemSerial()
Bump the data-maps segment serial after resize.
uint16 getID()
MemoryController interface:
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.
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.
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.
Definition Utils.h:463
uint64 GetTimeNow()
Return the current absolute time (µs since year 0) according to the TMC.
Definition PsyTime.cpp:69
bool SetCurrentTimeSyncData(uint64 tmc, int64 netTimeAdjust)
Install externally computed sync data (e.g.
Definition PsyTime.cpp:140
std::string PrintTimeDifString(uint64 t, bool us=true, bool ms=true)
Definition PsyTime.cpp:722
int32 GetTimeAgeMS(uint64 t)
Age of a timestamp relative to now, in milliseconds.
Definition PsyTime.cpp:35
int64 GetTimeAge(uint64 t)
Age of a timestamp relative to now.
Definition PsyTime.cpp:25
bool GetCurrentTimeSyncData(uint64 &tmc, int64 &netTimeAdjust)
Read the current sync data.
Definition PsyTime.cpp:147
bool Sleep(uint32 ms)
Suspend the calling thread.
Definition Utils.cpp:2802
char * OpenSharedMemorySegment(const char *name, uint64 size)
Open and map an existing named shared memory segment.
Definition Utils.cpp:2259
char * CreateSharedMemorySegment(const char *name, uint64 size, bool force=false)
Create a named shared memory segment and map it into this process.
Definition Utils.cpp:2156
bool CloseSharedMemorySegment(char *data, uint64 size)
Unmap a segment previously created/opened here.
Definition Utils.cpp:2374
std::string StringFormat(const char *format,...)
printf into a std::string.
Definition Utils.cpp:6626
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.
Definition Types.h:284
Hierarchical message type identifier — the key used for publish/subscribe matching in Psyclone.
Definition Types.h:123
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.