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 // No live node on this port (verified above): reclaim any stale OS segments
551 // (shmem + named semaphores) left by a previous crashed/killed node.
553
554 psycloneIndex = new PsycloneIndex();
555 if (!psycloneIndex->init(sysID, GetTimeNow())) {
556 LogPrint(0, LOG_MEMORY, 0, "Cannot init index memory on port %u...", sysID);
557 return false;
558 }
559
560 masterMemory = new MasterMemory();
561 if (!masterMemory->create(sysID)) {
562 LogPrint(0, LOG_MEMORY, 0, "Cannot create MasterMemory...");
563 return false;
564 }
565
566 temporalMemory = new TemporalMemory(masterMemory);
567 if (!temporalMemory->create(slotCount, binCount, minBlockSize, maxBlockSize, initSize, maxSize)) {
568 LogPrint(0, LOG_MEMORY, 0, "Cannot create TemporalMemory...");
569 return false;
570 }
571
572 componentMemory = new ComponentMemory(masterMemory);
573 // Create initial room for 1024 average components
574 // Will expand as needed
575 if (!componentMemory->create(1024)) {
576 LogPrint(0, LOG_MEMORY, 0, "Cannot create ComponentMemory...");
577 return false;
578 }
579
580 dataMapsMemory = new DataMapsMemory(masterMemory);
581 // Create initial room for 1024 typelevels, contextlevels, tags, cranks, requests
582 // Will expand as needed
583 if (!dataMapsMemory->create(1024, 1024, 1024, 1024, 1024)) {
584 LogPrint(0, LOG_MEMORY, 0, "Cannot create DataMapsMemory...");
585 return false;
586 }
587
588 processMemory = new ProcessMemory(masterMemory);
589 // Create initial room for 16 processes
590 // Will expand as needed
591 if (!processMemory->create(16)) {
592 LogPrint(0, LOG_MEMORY, 0, "Cannot create ProcessMemory...");
593 return false;
594 }
595
596 psycloneIndex->setStatus(PSYCLONE_STATUS_READY);
597
598 if (!ThreadManager::CreateThread(MemoryManagement, this, managementThreadID)) {
599 return false;
600 }
601
602 return true;
603}
604
606 return masterMemory->getNodeID();
607}
608
610 masterMemory->setNodeID(id);
611 temporalMemory->setNodeID(id);
612 return true;
613}
614
616 DataMessage* msg = new DataMessage();
617 if (!this->componentMemory->writeComponentNamesToMsg(msg)) {
618 delete msg;
619 return NULL;
620 }
621 if (!this->dataMapsMemory->writeIDsToMsg(msg)) {
622 delete msg;
623 return NULL;
624 }
625 return msg;
626}
627
628
629
630bool MemoryManager::getTimeSyncData(uint64& tmc, int64& adjust) {
631 tmc = masterMemory->master->currentTMC;
632 adjust = masterMemory->master->localSyncAdjustment;
633 return true;
634}
635
636bool MemoryManager::setTimeSyncData(uint64 tmc, int64 adjust) {
637 masterMemory->master->currentTMC = tmc;
638 masterMemory->master->localSyncAdjustment = adjust;
639 return true;
640}
641
642// Insert new block of memory and return full id
644 if (!temporalMemory)
645 return false;
646 return temporalMemory->insertMessage(msg, id);
647}
648
649// Get copy of block of memory
651 if (!temporalMemory)
652 return NULL;
653 return temporalMemory->getCopyOfMessage(id);
654}
655
657 if (!type[0])
658 return "NOTYPE";
659 if (type[0] == 1)
660 return utils::StringFormat("PsyControlMessage %u.%u", type[1], type[2]);
661 std::string str = subTypeToText(type[0]);
662 uint8 level = 0;
663 while (type[level+1])
664 str += std::string(".") + subTypeToText(type[++level]);
665 return str;
666}
667
668std::string MemoryManager::subTypeToText(uint16 subtype) {
669 if (!subtype)
670 return "-";
671 else if (subtype == 0xFFFF)
672 return "*";
673 std::string str;
674 char* data = new char[MAXKEYNAMELEN+1];
675 if (dataMapsMemory->getTypeLevelName(subtype, data, MAXKEYNAMELEN))
676 str = data;
677 delete [] data;
678 return str;
679}
680
682 if (!context[0])
683 return "NOCONTEXT";
684 std::string str = subContextToText(context[0]);
685 uint8 level = 0;
686 while (context[level+1])
687 str += std::string(".") + subContextToText(context[++level]);
688 return str;
689}
690
691std::string MemoryManager::subContextToText(uint16 subcontext) {
692 if (!subcontext)
693 return "-";
694 else if (subcontext == 0xFFFF)
695 return "*";
696 std::string str;
697 char* data = new char[MAXKEYNAMELEN+1];
698 if (dataMapsMemory->getContextLevelName(subcontext, data, MAXKEYNAMELEN))
699 str = data;
700 delete [] data;
701 return str;
702}
703
704std::string MemoryManager::getComponentName(uint32 compID) {
705 std::string str;
706 char* data = new char[MAXKEYNAMELEN+1];
707 if (componentMemory->getComponentName(compID, data, MAXKEYNAMELEN))
708 str = data;
709 delete [] data;
710 return str;
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
743
744
745
746
750
751// Continuous management of eol pages
752uint32 MemoryManager::runManager() {
753 //LogPrint(0, LOG_SYSTEM, 0, "Memory Management (%p) running...\n\n", this);
754 isRunning = true;
755 uint64 tmc;
756 int64 netTimeSync;
757
758 uint64 nextPageCheck = 0; //, now;
759
760 while (shouldContinue) {
761 if (isLocalMaster) {
762 if (GetCurrentTimeSyncData(tmc, netTimeSync))
763 setTimeSyncData(tmc, netTimeSync);
765 if (psycloneIndex)
766 psycloneIndex->setStatus(PSYCLONE_STATUS_READY);
767 }
768 else {
769 // Update Sync Time
770 if (getTimeSyncData(tmc, netTimeSync) )
771 SetCurrentTimeSyncData(tmc, netTimeSync);
772 }
773
774 utils::Sleep(100);
775 }
776
777 isRunning = false;
778 //LogPrint(0, LOG_SYSTEM, 0, "Memory Management (%p) stopped running...\n\n", this);
779 return 0;
780}
781
783
784 // Create and initialise the MemoryManager (static memory management)
785 unittest::progress(5, "create manager");
786 MemoryManager* manager = new MemoryManager();
787 uint32 maxPageCount = 15;
788 if (!manager->create(0)) {
789 unittest::fail("MemoryManager test: create() failed");
790 delete(manager);
791 return false;
792 }
793
794 uint64 eol = GetTimeNow() + 100000000; // +100sec
795 uint32 size = 4096;
796 char* data = new char[size];
797
798 // we should be able to add this many blocks
799 uint32 expectedCount = 100; // CalcBlockTableSize(size);
800 uint32 expectedMaxCount = (maxPageCount-10) * expectedCount;
801 uint32 count = expectedMaxCount;
802 uint64* ids = new uint64[count];
803
804 DataMessage* msg = new DataMessage();
805 msg->setData("data", data, size);
806 msg->setEOL(eol);
807 uint32 n;
808 uint64 id;
809
810 // Write phase
811 unittest::progress(20, "insert messages");
812 uint64 t1 = GetTimeNow();
813 for (n=0; n<count; n++) {
814 msg->setInt("Test", n);
815 if (!manager->insertMessage(msg, id)) {
816 unittest::fail("MemoryManager test: insert %u failed", n);
817 delete [] ids;
818 delete [] data;
819 delete(msg);
820 delete(manager);
821 return false;
822 }
823 ids[n] = id;
824 }
825 uint64 t2 = GetTimeNow();
826
827 // Read-back phase
828 unittest::progress(60, "read back messages");
829 DataMessage* msg2;
830 for (n=0; n<count; n++) {
831 msg2 = manager->getCopyOfMessage(ids[n]);
832 if (msg2 == NULL) {
833 unittest::fail("MemoryManager test: getCopyOfMessage %u failed", n);
834 delete [] ids;
835 delete [] data;
836 delete(msg);
837 delete(manager);
838 return false;
839 }
840 if (msg->getSize() != msg2->getSize()) {
841 unittest::fail("MemoryManager test: getCopyOfMessage wrong size (%u != %u)", msg->getSize(), msg2->getSize());
842 delete [] ids;
843 delete [] data;
844 delete(msg);
845 delete(msg2);
846 delete(manager);
847 return false;
848 }
849 int64 val64;
850 if ((!msg2->getInt("Test", val64)) || (val64 != n)) {
851 unittest::fail("MemoryManager test: getCopyOfMessage wrong data (%lld != %u)", val64, n);
852 delete [] ids;
853 delete [] data;
854 delete(msg);
855 delete(msg2);
856 delete(manager);
857 return false;
858 }
859 delete(msg2);
860 }
861 uint64 t3 = GetTimeNow();
862
863 unittest::progress(90, "record metrics");
864 double writeUs = (double)(t2 - t1);
865 double readUs = (double)(t3 - t2);
866 if (writeUs > 0.0) {
867 unittest::metric("write_throughput", (1.0*size*count)/writeUs, "MB/s", true);
868 unittest::metric("write_rate", (1000000.0*count)/writeUs, "msg/s", true);
869 unittest::metric("avg_write_latency", writeUs/count, "us", false);
870 }
871 if (readUs > 0.0) {
872 unittest::metric("read_throughput", (1.0*size*count)/readUs, "MB/s", true);
873 unittest::metric("read_rate", (1000000.0*count)/readUs, "msg/s", true);
874 unittest::metric("avg_read_latency", readUs/count, "us", false);
875 }
876 unittest::detail("Writing %u: %.3f MB/s / %.3f msg/s (%u us) [%u b]",
877 count, (1.0*size*count)/writeUs, (1000000.0*count)/writeUs, (uint32)writeUs, size);
878 unittest::detail("Reading %u: %.3f MB/s / %.3f msg/s (%u us) [%u b]",
879 count, (1.0*size*count)/readUs, (1000000.0*count)/readUs, (uint32)readUs, size);
880
881 delete [] ids;
882 delete [] data;
883 delete(msg);
884 delete(manager);
885
886 unittest::progress(100, "done");
887 return true;
888}
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908//bool MemoryManagerX::GetMemoryUsage(uint32& total, uint32& usage, uint32& sysTotal, uint32& sysUsage, uint32& staticTotal, uint32& staticUsage, uint32& dynamicTotal, uint32& dynamicUsage) {
909// if (!MemoryManagerX::Singleton)
910// return false;
911// if (!MemoryManagerX::Singleton->pageMasterMutex->enter())
912// return false;
913// sysTotal = MemoryManagerX::Singleton->pageMaster->dataSize[MP_SYSTEMPAGE];
914// sysUsage = MemoryManagerX::Singleton->pageMaster->dataUsage[MP_SYSTEMPAGE];
915// staticTotal = MemoryManagerX::Singleton->pageMaster->dataSize[MP_STATICPAGE];
916// staticUsage = MemoryManagerX::Singleton->pageMaster->dataUsage[MP_STATICPAGE];
917// dynamicTotal = MemoryManagerX::Singleton->pageMaster->dataSize[MP_DYNAMICPAGE];
918// dynamicUsage = MemoryManagerX::Singleton->pageMaster->dataUsage[MP_DYNAMICPAGE];
919// total = sysTotal + staticTotal + dynamicTotal;
920// usage = sysUsage + staticUsage + dynamicUsage;
921// MemoryManagerX::Singleton->pageMasterMutex->leave();
922// return true;
923//}
924//
925//
926//MemoryManagerX::MemoryManagerX() {
927// shouldContinue = true;
928// isRunning = false;
929// isMaster = false;
930// pageMaster = NULL;
931// pageMasterMutex = NULL;
932// pageCache = NULL;
933//
934//}
935//
936//MemoryManagerX::~MemoryManagerX() {
937// if (pageMaster == NULL)
938// return;
939// pageMasterMutex->enter();
940// MemoryManagerX::Singleton = NULL;
941// shouldContinue = false;
942// uint32 c = 0;
943// while (isRunning) {
944// utils::Sleep(50);
945// if (c++ > 10)
946// break;
947// }
948// ThreadManager::Shutdown();
949// destroyAllPages();
950//
951// utils::DestroySharedMemorySegment((char*)pageMaster, pageMaster->size);
952// pageMaster = NULL;
953// pageMasterMutex->leave();
954// delete(pageMasterMutex);
955// pageMaster = NULL;
956// pageMasterMutex = NULL;
957// free(pageCache);
958//}
959//
961//bool MemoryManagerX::connect(uint16 sysID) {
963// uint32 size = sizeof(MemoryPageMaster);
964// isMaster = false;
965//
966// utils::SetSharedSystemInstance(sysID);
967//
968// pageMasterMutex = new utils::Mutex("PageMaster");
969// if (!pageMasterMutex->enter())
970// return false;
971//
972// pageMaster = (MemoryPageMaster*) utils::OpenSharedMemorySegment("CMSysMemory", size);
973// if (pageMaster == NULL) {
974// fprintf(stderr, "MemoryManager could not open shared memory id '%u'\n", sysID);
975// pageMasterMutex->leave();
976// return false;
977// }
978//
979// MemoryManagerX::Singleton = this;
980//
981// LocalSyncAdjustment = pageMaster->timesync;
982//
983// if (!ThreadManager::CreateThread(MemoryManagement, NULL, managementThreadID)) {
984// pageMasterMutex->leave();
985// return false;
986// }
987//
988// // Unlock the Mutex
989// pageMasterMutex->leave();
990// return true;
991//}
992//
994//bool MemoryManagerX::create(uint16 sysID, uint32 staticPageTableSize, uint32 slotCount, uint32 slotDuration, uint32 bufferSlots, uint32 pagesPerSlot, bool force) {
995// isMaster = true;
996//
997// utils::SetSharedSystemInstance(sysID);
998//
999// uint32 size = sizeof(MemoryPageMaster);
1000//
1001// char* data;
1002// if (force) {
1003// // Destroy CMSysMemory first...
1004// if ( (data = utils::OpenSharedMemorySegment("CMSysMemory", size)) != NULL)
1005// utils::DestroySharedMemorySegment(data, size);
1006// }
1007//
1008// pageMasterMutex = new utils::Mutex("PageMaster");
1009// if (!pageMasterMutex->enter())
1010// return false;
1011//
1012// uint32 maxPageCount = staticPageTableSize + ( (slotCount+bufferSlots) * pagesPerSlot );
1013//
1015// // Add the bitfield size = max count / 32
1016// uint32 bitFieldSize = (uint32)ceil((double)maxPageCount / 8);
1017// // Add the table size
1018// uint32 datasize = maxPageCount * sizeof(MemoryPageEntry);
1019// size += bitFieldSize + datasize;
1020//
1021// pageMaster = (MemoryPageMaster*) utils::CreateSharedMemorySegment("CMSysMemory", size);
1022// if (pageMaster == NULL) {
1023// fprintf(stderr, "MemoryManager could not create shared memory\n");
1024// pageMasterMutex->leave();
1025// pageMasterMutex->destroy();
1026// return false;
1027// }
1028//
1029// // Initialise the PageMaster structure
1030// pageMaster->status = 1; // 10 means fully initialised
1032//
1033// pageMaster->size = size; // total size of PageMaster in bytes
1034// pageMaster->sysID = sysID; // global node id
1035// pageMaster->dataSize[MP_SYSTEMPAGE] = 0; // total size of data space in bytes
1036// pageMaster->dataSize[MP_STATICPAGE] = 0; // total size of data space in bytes
1037// pageMaster->dataSize[MP_DYNAMICPAGE] = 0; // total size of data space in bytes
1038// pageMaster->dataUsage[MP_SYSTEMPAGE] = 0; // current usage of all pages in bytes, for info only
1039// pageMaster->dataUsage[MP_STATICPAGE] = 0; // current usage of all pages in bytes, for info only
1040// pageMaster->dataUsage[MP_DYNAMICPAGE] = 0; // current usage of all pages in bytes, for info only
1041// pageMaster->count[MP_SYSTEMPAGE] = 0; // current number of pages in use, for info only
1042// pageMaster->count[MP_STATICPAGE] = 0; // current number of pages in use, for info only
1043// pageMaster->count[MP_DYNAMICPAGE] = 0; // current number of pages in use, for info only
1044// pageMaster->bitFieldSize = bitFieldSize; // number of bytes in the bitfield
1045// pageMaster->pageTableSize = maxPageCount; // maximum entries in page table and number of bits in bit field
1046// memset((void*)MP_GetBitFieldLoc(pageMaster), 255, bitFieldSize);
1047// memset((void*)MP_GetPageTableLoc(pageMaster), 0, datasize);
1048//
1049// MemoryManagerX::Singleton = this;
1050//
1051// pageMaster->status = 2; // 10 means fully initialised
1053//
1054// pageMaster->timesync = LocalSyncAdjustment;
1055//
1056// pageMaster->createdTime = GetTimeNow();
1057//
1058// pageMaster->status = 3; // 10 means fully initialised
1060//
1061// // Create and initialise the EOL Page
1062// if (!resizeEOLPage(slotCount, pagesPerSlot, slotDuration, bufferSlots)) {
1063// fprintf(stderr, "MemoryManager could not resize EOL page\n");
1064// pageMasterMutex->leave();
1065// return false;
1066// }
1067//
1068// pageMaster->status = 4; // 10 means fully initialised
1070//
1071// if (!createSystemPages()) {
1072// fprintf(stderr, "MemoryManager could not create system pages\n");
1073// pageMasterMutex->leave();
1074// return false;
1075// }
1076//
1077// pageMaster->status = 5; // 10 means fully initialised
1079//
1080// pageMaster->lastCreatedStaticPage = RESERVEDPAGECOUNT-1; // id of last created static page
1081// // printBitFieldAsString("Initial Bitfield");
1082//
1083// pageMaster->status = 6; // 10 means fully initialised
1085//
1086// if (!ThreadManager::CreateThread(MemoryManagement, NULL, managementThreadID)) {
1087// pageMasterMutex->leave();
1088// return false;
1089// }
1090//
1091// pageMaster->status = 7; // 10 means fully initialised
1093//
1094// pageMaster->status = 10; // 10 means fully initialised
1095// // Unlock the Mutex
1096// pageMasterMutex->leave();
1097// return true;
1098//}
1099//
1100//
1101//
1102//
1103//
1104//
1105//
1106//
1107//
1108//
1109//
1110//
1111//
1112//
1113//
1114//
1115//
1116//
1117//
1118//
1119//
1238//
1240//char* MemoryManagerX::createSystemPage(uint32 id, uint32 size, uint64& memID) {
1241//
1242// // Mutex is still locked from callar
1243// uint32 pageID = id;
1244// MemoryPage* page = createPage(size+sizeof(MemoryBlock), 1, 0, pageID);
1245// if (page == NULL)
1246// return NULL;
1247// if (pageID != id) {
1248// destroyPage(pageID);
1249// return NULL;
1250// }
1251//
1252// if (!insertMemoryBlockIntoPage(pageID, NULL, size, 0, memID))
1253// return NULL;
1254//
1255// return getSystemBlock(pageID, size);
1256//}
1257//
1258//
1260//char* MemoryManagerX::getSystemBlock(uint32 pageID, uint32& size) {
1261// char* data = NULL;
1262// // We assume manager already locked
1264// MemoryPage* page = getCachedPage(pageID);
1265// if (page == NULL)
1266// return NULL;
1267// MemoryBlock* block = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1268// if (block == NULL)
1269// return NULL;
1270// size = block->size - sizeof(MemoryBlock);
1271// return (char*)(block + sizeof(MemoryBlock));
1272//}
1273//
1274//
1275//
1276//
1278//char* MemoryManagerX::getAndLockSystemBlock(uint32 pageID, uint32& size) {
1279// // Lock Manager
1280// if (!pageMasterMutex->enter())
1281// return NULL;
1282// MemoryPageEntry* entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1283// if (!lockPage(entry)) {
1284// pageMasterMutex->leave();
1285// return NULL;
1286// }
1287//
1288// MemoryPage* page = getCachedPage(entry);
1289// if (page == NULL) {
1290// // Unlock Manager
1291// pageMasterMutex->leave();
1292// return NULL;
1293// }
1294// char* data = getLockedSystemBlock(page, size);
1295// pageMasterMutex->leave();
1296// return data;
1297//}
1298//
1299//char* MemoryManagerX::getLockedSystemBlock(uint32 pageID, uint32& size) {
1300// // Manager should be locked
1302// MemoryPage* page = getCachedPage(pageID);
1303// if (page == NULL)
1304// return NULL;
1305// return getLockedSystemBlock(page, size);
1306//}
1307//
1308//char* MemoryManagerX::getLockedSystemBlock(MemoryPage* page, uint32& size) {
1309// MemoryBlock* block = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1310// if (block == NULL)
1311// return NULL;
1312// size = block->size - sizeof(MemoryBlock);
1313// return (char*)(block + sizeof(MemoryBlock));
1314//}
1315//
1316//bool MemoryManagerX::unlockSystemBlock(uint32 pageID) {
1317// unlockPage(pageID);
1318// return true;
1319//}
1320//
1321//
1322//
1324//char* MemoryManagerX::createAndLockNewSystemPage(uint32 size, uint32& pageID) {
1325//
1326// // Lock Manager
1327// if (!pageMasterMutex->enter())
1328// return NULL;
1329// pageID = 0; // provide new id
1330// MemoryPage* page = createPage(size+sizeof(MemoryBlock), 1, 0, pageID);
1331// if (page == NULL) {
1332// pageMasterMutex->leave();
1333// return NULL;
1334// }
1335//
1336// // createPage now keeps the page locked
1337// //if (!lockPage(pageID)) {
1338// // pageMasterMutex->leave();
1339// // return NULL;
1340// //}
1341//
1342// uint64 memID; // not required for full page memory blocks, but required for function call
1343// if (!insertMemoryBlockIntoPage(pageID, NULL, size, 0, memID))
1344// return NULL;
1345//
1346// char* data = getLockedSystemBlock(pageID, size);
1347// // Unlock Manager
1348// pageMasterMutex->leave();
1349// return data;
1350//}
1351//
1353//char* MemoryManagerX::resizeSystemPage(uint32 pageID, uint32 newSize) {
1354//
1355// uint32 oldSize = 0;
1356// char* oldData = getAndLockSystemBlock(pageID, oldSize);
1357// if (oldData == NULL)
1358// return NULL;
1359//
1360// int32 difSize = newSize - oldSize;
1361// if (difSize <= 0) {
1362// // Unlock Manager
1363// pageMasterMutex->leave();
1364// return oldData;
1365// }
1366//
1367// char* tempData = new char[oldSize];
1368// memcpy(tempData, oldData, oldSize);
1369//
1370// UnlockSystemBlock(pageID);
1371// destroyPage(pageID);
1372//
1373// uint32 newPageID = pageID;
1374// char* newData = createAndLockNewSystemPage(newSize, newPageID);
1375// if (newData == NULL) {
1376// delete [] tempData;
1377// return NULL;
1378// }
1379//
1380// memcpy(newData, tempData, oldSize);
1381// delete [] tempData;
1382// return newData;
1383//}
1384//
1385//bool MemoryManagerX::InsertMemoryBlock(const char* data, uint32 size, uint64 eol, uint64& id) {
1386// if (!MemoryManagerX::Singleton)
1387// return 0;
1388// return MemoryManagerX::Singleton->insertMemoryBlock(data, size, eol, id);
1389//}
1390//
1391//bool MemoryManagerX::OverwriteMemoryBlock(uint64 id, const char* data, uint32 size, uint64 eol) {
1392// if (!MemoryManagerX::Singleton)
1393// return 0;
1394// return MemoryManagerX::Singleton->overwriteMemoryBlock(id, data, size, eol);
1395//}
1396//
1397//char* MemoryManagerX::GetAndLockMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1398// if (!MemoryManagerX::Singleton)
1399// return 0;
1400// return MemoryManagerX::Singleton->getAndLockMemoryBlock(id, size, eol);
1401//}
1402//
1403//bool MemoryManagerX::UnlockMemoryBlock(uint64 id) {
1404// if (!MemoryManagerX::Singleton)
1405// return 0;
1406// return MemoryManagerX::Singleton->unlockMemoryBlock(id);
1407//}
1408//
1409//char* MemoryManagerX::GetCopyMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1410// if (!MemoryManagerX::Singleton)
1411// return 0;
1412// return MemoryManagerX::Singleton->getCopyMemoryBlock(id, size, eol);
1413//}
1414//
1415//
1416//
1419//char* MemoryManagerX::GetAndLockSystemBlock(uint32 pageID, uint32& size) {
1420// if (!MemoryManagerX::Singleton)
1421// return 0;
1422// return MemoryManagerX::Singleton->getAndLockSystemBlock(pageID, size);
1423//}
1424//
1427//bool MemoryManagerX::UnlockSystemBlock(uint32 pageID) {
1428// if (!MemoryManagerX::Singleton)
1429// return 0;
1430// return MemoryManagerX::Singleton->unlockSystemBlock(pageID);
1431//}
1432//
1435//char* MemoryManagerX::CreateAndLockNewSystemPage(uint32 size, uint32& id) {
1436// if (!MemoryManagerX::Singleton)
1437// return 0;
1438// return MemoryManagerX::Singleton->createAndLockNewSystemPage(size, id);
1439//}
1440//
1443//char* MemoryManagerX::ResizeSystemPage(uint32 pageID, uint32 size) {
1444// if (!MemoryManagerX::Singleton)
1445// return 0;
1446// return MemoryManagerX::Singleton->resizeSystemPage(pageID, size);
1447//}
1448//
1451//bool MemoryManagerX::DestroySystemPage(uint32 pageID) {
1452// if (!MemoryManagerX::Singleton)
1453// return 0;
1454// return MemoryManagerX::Singleton->destroyPage(pageID);
1455//}
1456//
1457//
1459//bool MemoryManagerX::createSystemPages() {
1460//
1461// // Create main system page
1462// char* data;
1463// uint32 size = 1024*512; // ############# Need better size calc
1464// uint64 memID;
1465// // Create and initialise the System Page
1466// if ( (data = createSystemPage(ID_SYSPAGE, size, memID)) == NULL) {
1467// fprintf(stderr, "MemoryManager could not create the System page\n");
1468// return false;
1469// }
1470// initSystemPage(data, size);
1471// unlockSystemBlock(ID_SYSPAGE);
1472//
1473// // Create and initialise the Page Pool
1474// size = 1024*512; // ############# Need better size calc
1475// if ( (data = createSystemPage(ID_PAGEPOOL, size, memID)) == NULL) {
1476// fprintf(stderr, "MemoryManager could not create the Page Pool page\n");
1477// return false;
1478// }
1479// initPagePool(data, size);
1480// unlockSystemBlock(ID_PAGEPOOL);
1481//
1482// // Create and initialise the Queue Page
1483// size = 1024*512; // ############# Need better size calc
1484// if ( (data = createSystemPage(ID_QUEUEPAGE, size, memID)) == NULL) {
1485// fprintf(stderr, "MemoryManager could not create the Queue page\n");
1486// return false;
1487// }
1488// initQueuePage(data, size);
1489// unlockSystemBlock(ID_QUEUEPAGE);
1490//
1491// // Create and initialise the Component Map Page
1492// uint32 count = 0xFFFF;
1493// uint32 bitFieldSize = (uint32)ceil((double)count / 8);
1494// size = sizeof(ComponentMapHeader) + bitFieldSize + count*sizeof(ComponentMapEntry);
1495// if ( (data = createSystemPage(ID_COMPMAPPAGE, size, memID)) == NULL) {
1496// fprintf(stderr, "MemoryManager could not create the Component page\n");
1497// return false;
1498// }
1499// ComponentMapHeader* cmHeader = (ComponentMapHeader*)data;
1500// cmHeader->size = size;
1501// cmHeader->bitFieldSize = bitFieldSize;
1502// cmHeader->count = count;
1503// memset(data+sizeof(ComponentMapHeader), 255, bitFieldSize);
1504// memset(data+sizeof(ComponentMapHeader)+bitFieldSize, 0, size-sizeof(ComponentMapHeader)-bitFieldSize);
1505// // Position 0 is not allowed, used to indicate error or unused
1506// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)cmHeader + sizeof(ComponentMapHeader)), cmHeader->bitFieldSize);
1507// unlockSystemBlock(ID_COMPMAPPAGE);
1508//
1509// // Create and initialise the Type Map Page
1510// count = 0xFFFF;
1511// bitFieldSize = (uint32)ceil((double)count / 8);
1512// size = sizeof(TypeMapHeader) + bitFieldSize + count*sizeof(TypeMapEntry);
1513// if ( (data = createSystemPage(ID_TYPEMAPPAGE, size, memID)) == NULL) {
1514// fprintf(stderr, "MemoryManager could not create the TypeMap page\n");
1515// return false;
1516// }
1517// TypeMapHeader* typeHeader = (TypeMapHeader*)data;
1518// typeHeader->size = size;
1519// typeHeader->bitFieldSize = bitFieldSize;
1520// typeHeader->count = count;
1521// memset((char*)typeHeader+sizeof(TypeMapHeader), 255, bitFieldSize);
1522// memset((char*)typeHeader+sizeof(TypeMapHeader)+bitFieldSize, 0, size-sizeof(TypeMapHeader)-bitFieldSize);
1523// // Position 0 is not allowed, used to indicate error or unused
1524// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)typeHeader + sizeof(TypeMapHeader)), typeHeader->bitFieldSize);
1525// unlockSystemBlock(ID_TYPEMAPPAGE);
1526//
1527// // Create and initialise the Context Map Page
1528// count = 0xFFFF;
1529// bitFieldSize = (uint32)ceil((double)count / 8);
1530// size = sizeof(ContextMapHeader) + bitFieldSize + count*sizeof(ContextMapEntry);
1531// if ( (data = createSystemPage(ID_CONTEXTMAPPAGE, size, memID)) == NULL) {
1532// fprintf(stderr, "MemoryManager could not create the ContextMap page\n");
1533// return false;
1534// }
1535// ContextMapHeader* contextHeader = (ContextMapHeader*)data;
1536// contextHeader->size = size;
1537// contextHeader->bitFieldSize = bitFieldSize;
1538// contextHeader->count = count;
1539// memset((char*)contextHeader+sizeof(ContextMapHeader), 255, bitFieldSize);
1540// memset((char*)contextHeader+sizeof(ContextMapHeader)+bitFieldSize, 0, size-sizeof(ContextMapHeader)-bitFieldSize);
1541// // Position 0 is not allowed, used to indicate error or unused
1542// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)contextHeader + sizeof(ContextMapHeader)), contextHeader->bitFieldSize);
1543// unlockSystemBlock(ID_CONTEXTMAPPAGE);
1544//
1545// //// Create and initialise the Tag Map Page
1546// //count = 4096;
1547// //bitFieldSize = (uint32)ceil((double)count / 8);
1548// //size = sizeof(TagMapHeader) + bitFieldSize + count*sizeof(TagMapEntry);
1549// //if ( (data = createSystemPage(ID_TAGMAPPAGE, size, memID)) == NULL) {
1550// // fprintf(stderr, "MemoryManager could not create the TagMap page\n");
1551// // return false;
1552// //}
1553// //TagMapHeader* tagHeader = (TagMapHeader*)data;
1554// //tagHeader->size = size;
1555// //tagHeader->bitFieldSize = bitFieldSize;
1556// //tagHeader->count = count;
1557// //memset((char*)tagHeader+sizeof(TagMapHeader), 255, bitFieldSize);
1558// //memset((char*)tagHeader+sizeof(TagMapHeader)+bitFieldSize, 0, size-sizeof(TagMapHeader)-bitFieldSize);
1559// //// Position 0 is not allowed, used to indicate error or unused
1560// //utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)tagHeader + sizeof(TagMapHeader)), tagHeader->bitFieldSize);
1561// //unlockSystemBlock(ID_TAGMAPPAGE);
1562//
1563// //// Create and initialise the Node Map Page
1564// //count = 4096;
1565// //bitFieldSize = (uint32)ceil((double)count / 8);
1566// //size = sizeof(NodeMapHeader) + bitFieldSize + count*sizeof(NodeMapEntry);
1567// //if ( (data = createSystemPage(ID_NODEMAPPAGE, size, memID)) == NULL) {
1568// // fprintf(stderr, "MemoryManager could not create the NodeMap page\n");
1569// // return false;
1570// //}
1571// //NodeMapHeader* nodeHeader = (NodeMapHeader*)data;
1572// //nodeHeader->size = size;
1573// //nodeHeader->bitFieldSize = bitFieldSize;
1574// //nodeHeader->count = count;
1575// //memset((char*)nodeHeader+sizeof(NodeMapHeader), 255, bitFieldSize);
1576// //memset((char*)nodeHeader+sizeof(NodeMapHeader)+bitFieldSize, 0, size-sizeof(NodeMapHeader)-bitFieldSize);
1577// //// Position 0 is not allowed, used to indicate error or unused
1578// //utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)nodeHeader + sizeof(NodeMapHeader)), nodeHeader->bitFieldSize);
1579// //unlockSystemBlock(ID_NODEMAPPAGE);
1580//
1581// // Create and initialise the Crank Map Page
1582// count = 0xFFFF;
1583// bitFieldSize = (uint32)ceil((double)count / 8);
1584// size = sizeof(CrankMapHeader) + bitFieldSize + count*sizeof(CrankMapEntry);
1585// if ( (data = createSystemPage(ID_CRANKMAPPAGE, size, memID)) == NULL) {
1586// fprintf(stderr, "MemoryManager could not create the CrankMap page\n");
1587// return false;
1588// }
1589// CrankMapHeader* crankHeader = (CrankMapHeader*)data;
1590// crankHeader->size = size;
1591// crankHeader->bitFieldSize = bitFieldSize;
1592// crankHeader->count = count;
1593// memset((char*)crankHeader+sizeof(CrankMapHeader), 255, bitFieldSize);
1594// memset((char*)crankHeader+sizeof(CrankMapHeader)+bitFieldSize, 0, size-sizeof(CrankMapHeader)-bitFieldSize);
1595// // Position 0 is not allowed, used to indicate error or unused
1596// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)crankHeader + sizeof(CrankMapHeader)), crankHeader->bitFieldSize);
1597// unlockSystemBlock(ID_CRANKMAPPAGE);
1598//
1599// // Create and initialise the Queue Map Page
1600// count = 0xFFFF;
1601// bitFieldSize = (uint32)ceil((double)count / 8);
1602// size = sizeof(QueueMapHeader) + bitFieldSize + count*sizeof(QueueMapEntry);
1603// if ( (data = createSystemPage(ID_QUEUEMAPPAGE, size, memID)) == NULL) {
1604// fprintf(stderr, "MemoryManager could not create the QueueMap page\n");
1605// return false;
1606// }
1607// QueueMapHeader* queueHeader = (QueueMapHeader*)data;
1608// queueHeader->size = size;
1609// queueHeader->bitFieldSize = bitFieldSize;
1610// queueHeader->count = count;
1611// memset((char*)queueHeader+sizeof(QueueMapHeader), 255, bitFieldSize);
1612// memset((char*)queueHeader+sizeof(QueueMapHeader)+bitFieldSize, 0, size-sizeof(QueueMapHeader)-bitFieldSize);
1613// // Position 0 is not allowed, used to indicate error or unused
1614// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)queueHeader + sizeof(QueueMapHeader)), queueHeader->bitFieldSize);
1615// unlockSystemBlock(ID_QUEUEMAPPAGE);
1616//
1617// // Create and initialise the Process Map Page
1618// count = 256;
1619// bitFieldSize = (uint32)ceil((double)count / 8);
1620// size = sizeof(ProcessMapHeader) + bitFieldSize + count*sizeof(ProcessMapEntry);
1621// if ( (data = createSystemPage(ID_PROCESSMAPPAGE, size, memID)) == NULL) {
1622// fprintf(stderr, "MemoryManager could not create the ProcessMap page\n");
1623// return false;
1624// }
1625// ProcessMapHeader* processHeader = (ProcessMapHeader*)data;
1626// processHeader->size = size;
1627// processHeader->bitFieldSize = bitFieldSize;
1628// processHeader->count = count;
1629// memset((char*)processHeader+sizeof(ProcessMapHeader), 0, size-sizeof(ProcessMapHeader));
1630// memset((char*)processHeader+sizeof(ProcessMapHeader), 255, bitFieldSize);
1631// // Position 0 is not allowed, used to indicate error or unused
1632// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)processHeader + sizeof(ProcessMapHeader)), processHeader->bitFieldSize);
1633// unlockSystemBlock(ID_PROCESSMAPPAGE);
1634//
1635// // Create and initialise the Request Map Page
1636// count = 256;
1637// bitFieldSize = (uint32)ceil((double)count / 8);
1638// size = sizeof(RequestMapHeader) + bitFieldSize + count*sizeof(RequestMapEntry);
1639// if ( (data = createSystemPage(ID_REQUESTMAPPAGE, size, memID)) == NULL) {
1640// fprintf(stderr, "MemoryManager could not create the RequestMap page\n");
1641// return false;
1642// }
1643// RequestMapHeader* requestHeader = (RequestMapHeader*)data;
1644// requestHeader->size = size;
1645// requestHeader->bitFieldSize = bitFieldSize;
1646// requestHeader->count = count;
1647// memset((char*)requestHeader+sizeof(RequestMapHeader), 0, size-sizeof(RequestMapHeader));
1648// memset((char*)requestHeader+sizeof(RequestMapHeader), 255, bitFieldSize);
1649// // Position 0 is not allowed, used to indicate error or unused
1650// utils::SetBit(0, BITOCCUPIED, (uint32*)((char*)requestHeader + sizeof(RequestMapHeader)), requestHeader->bitFieldSize);
1651// unlockSystemBlock(ID_REQUESTMAPPAGE);
1652//
1653// uint16 pid;
1654// if ( (!MemoryMaps::CreateNewProcess("Node Process", pid)) || (pid != NODE_PROCESS_ID) ) {
1655// fprintf(stderr, "MemoryManager could not register own process (%u != %u)\n", pid, NODE_PROCESS_ID);
1656// return false;
1657// }
1658//
1659// return true;
1660//}
1661//
1663//bool MemoryManagerX::insertMemoryBlock(const char* data, uint32 size, uint64 eol, uint64& id) {
1665// // Lock Manager
1666// if (!pageMasterMutex->enter())
1667// return false;
1668// uint32 pageID = 0;
1669// // First find an appropriate page
1670// MemoryPage* page = findPageForBlock(size, eol, pageID);
1671// if (page == NULL) {
1672// // Create a new page
1673// uint16 blockTableSize = CalcBlockTableSize(size);
1674// if (blockTableSize == 0) {
1675// pageMasterMutex->leave();
1676// return false;
1677// }
1678// page = createPage((size+sizeof(MemoryBlock))*blockTableSize, blockTableSize, eol, pageID);
1679// if (page == NULL) {
1680// pageMasterMutex->leave();
1681// return false;
1682// }
1683// unlockPage(pageID);
1684// }
1685// // printf(">>>>>> Inserting block into page ID %u...\n", pageID);
1686// if (!insertMemoryBlockIntoPage(pageID, data, size, eol, id)) {
1687// pageMasterMutex->leave();
1688// return false;
1689// }
1690// pageMasterMutex->leave();
1693// return true;
1694//}
1695//
1697//bool MemoryManagerX::insertMemoryBlockIntoPage(uint32 pageID, const char* data, uint32 size, uint64 eol, uint64& id) {
1698// // Assume page and Manager locked
1700// MemoryPage* page = getCachedPage(pageID);
1701// if (page == NULL)
1702// return false;
1703// pageMasterMutex->leave();
1704//
1705// // printf("PageID %u EOL %lu {%p}...\n", pageID, page->eol, page);
1706//
1707// uint32 totalSize = sizeof(MemoryBlock) + size;
1708//
1709// // Now we have a page, check for room
1710// if (page->count >= page->blockTableSize) {
1711// return false;
1712// }
1713// if ( (int64)page->dataSize - (int64)page->dataUsage < (int64)totalSize ) {
1714// return false;
1715// }
1716// // Find location of first available byte
1717// MemoryBlock* newBlock, *lastBlock;
1718// uint32 offset;
1719// uint16 blockID;
1720// uint32* offsetTable = (uint32*)MP_GetBlockIndexStartLoc(page);
1721// MemoryBlock* dataTable = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1722// if (page->count == 0) {
1723// newBlock = dataTable;
1724// blockID = 0;
1725// offset = 0;
1726// }
1727// else {
1728// lastBlock = (MemoryBlock*) ( (char*)dataTable + offsetTable[page->count-1] );
1729// // insert memory block
1730// newBlock = (MemoryBlock*) ( (char*)lastBlock + lastBlock->size );
1731// blockID = page->count;
1732// //offsetLoc = MP_GetBlockOffsetLoc(page, page->count-1);
1733// //offsetLoc = (uint32*)MP_GetBlockIndexStartLoc(page) + ((page->count-1) * sizeof(uint32));
1734// offset = (uint32) ((char*)newBlock - (char*)dataTable);
1735// }
1736// newBlock->size = totalSize;
1737// if (data != NULL)
1738// memcpy((char*)newBlock + sizeof(MemoryBlock), data, size);
1739// else
1740// memset((char*)newBlock + sizeof(MemoryBlock), 0, size);
1741// page->count++;
1742// page->dataUsage += newBlock->size;
1743// offsetTable[page->count-1] = offset;
1744// // Lock Manager
1745// if (!pageMasterMutex->enter())
1746// return false;
1747// pageMaster->dataUsage[MP_GetPageType(pageID, eol)] += newBlock->size;
1748// MemoryID* mid = (MemoryID*) &id;
1749// mid->blockID = blockID;
1750// mid->sysID = pageMaster->sysID;
1751// mid->pageID = pageID;
1754// // Leave Manager locked
1755// return true;
1756//}
1757//
1758//char* MemoryManagerX::getAndLockMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1759// // Lock Manager
1760// if (!pageMasterMutex->enter())
1761// return NULL;
1762// uint32 pageID = MP_GetPageID(id);
1763// //printf(">>>>>> Getting block from page ID %u...\n", pageID);
1764//
1765// MemoryPageEntry* entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1766// if (!lockPage(entry)) {
1767// pageMasterMutex->leave();
1768// return NULL;
1769// }
1770//
1771// MemoryPage* page = getCachedPage(entry);
1772// if (page == NULL) {
1773// pageMasterMutex->leave();
1774// return NULL;
1775// }
1776// // printf("PageID %u EOL %lu {%p}...\n", pageID, entry->page->eol, entry->page);
1777// pageMasterMutex->leave();
1778// return getLockedMemoryBlock(page, id, size, eol);
1779//}
1780//
1781//char* MemoryManagerX::getLockedMemoryBlock(MemoryPage* page, uint64 id, uint32& size, uint64& eol) {
1782// char* data = NULL;
1783// uint32* offsetTable = (uint32*)MP_GetBlockIndexStartLoc(page);
1784// MemoryBlock* dataTable = (MemoryBlock*)MP_GetBlockDataStartLoc(page);
1785//
1786// uint16 blockID = MP_GetBlockID(id);
1787// MemoryBlock* block = (MemoryBlock*) ( (char*)dataTable + offsetTable[blockID] );
1788// if (block == NULL) {
1789// // Unlock page
1790// unlockPage(MP_GetPageID(id));
1791// return NULL;
1792// }
1793// size = block->size - sizeof(MemoryBlock);
1794// eol = page->eol;
1795// return ((char*)block + sizeof(MemoryBlock));
1796//}
1797//
1798//bool MemoryManagerX::unlockMemoryBlock(uint64 id) {
1799// uint32 pageID = MP_GetPageID(id);
1800// unlockPage(pageID);
1801// return true;
1802//}
1803//
1804//char* MemoryManagerX::getCopyMemoryBlock(uint64 id, uint32& size, uint64& eol) {
1805// char* data = getAndLockMemoryBlock(id, size, eol);
1806// if (data == NULL)
1807// return false;
1808// char* output = new char[size];
1809// memcpy(output, data, size);
1810// unlockMemoryBlock(id);
1811// return output;
1812//}
1813//
1815//bool MemoryManagerX::overwriteMemoryBlock(uint64 id, const char* data, uint32 size, uint64 eol) {
1816// uint32 existingSize;
1817// uint64 existingEOL;
1818// char* existingData = getAndLockMemoryBlock(id, existingSize, existingEOL);
1819// if ((existingData == NULL) || (existingSize != size) || (existingEOL != eol) )
1820// return false;
1821// memcpy(existingData, data, size);
1822// unlockMemoryBlock(id);
1823// return true;
1824//}
1825//
1827//MemoryPage* MemoryManagerX::createPage(uint32 size, uint16 tableSize, uint64 eol, uint32& pageID) {
1829// // Lock Manager
1830// if (!pageMasterMutex->enter())
1831// return NULL;
1832//
1833// // First calculate total size
1834// uint32 pageSize = sizeof(MemoryPage) + (tableSize*sizeof(uint32)) + size;
1835//
1836// MemoryPageEntry* entry = NULL;
1837// // Now check if caller is requesting a particular id
1838// if (pageID > 0) {
1839// entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1840// if ((entry == NULL) || (entry->pageSize != 0))
1841// return NULL;
1842// }
1843// else {
1844// // Get a page from the pool with the right data size
1845// if (getPageFromPool(size, pageID)) {
1846// //printf("CreateFromPool %u...\n", pageID);
1847// // We have a valid page from the pool
1848// }
1849// // Find first available Page Entry
1850// else if (!utils::GetFirstFreeBitLoc((uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->pageTableSize, pageID)) {
1851// pageMasterMutex->leave();
1852// return NULL;
1853// }
1854// }
1855//
1856// if (pageID >= pageMaster->pageTableSize) {
1857// // ############## should resize pagetable ##############
1858// LogPrint(0,0,0,"Page Table needs resizing!");
1859// pageMasterMutex->leave();
1860// return NULL;
1861// }
1862//
1863// entry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID);
1864// if (entry->pageSize == 0)
1865// entry->pageID = pageID;
1866// if (!lockPage(entry)) {
1867// pageMasterMutex->leave();
1868// return NULL;
1869// }
1870//
1871// MemoryPage* page = NULL;
1872// // If the page already exists, use it
1873// // if not, create it
1874// if (entry->pageSize == 0) {
1875// char* pageName = new char[MAXKEYNAMELEN];
1876// sprintf(pageName, "Page_%u", pageID);
1877// // Allocate from shared memory
1878// page = (MemoryPage*) utils::CreateSharedMemorySegment(pageName, pageSize);
1879// delete [] pageName;
1880// if (page == NULL) {
1881// unlockPage(entry);
1882// pageMasterMutex->leave();
1883// return NULL;
1884// }
1885// entry->cacheSerial = 1;
1886// page->blockTableSize = tableSize;
1887// page->size = pageSize;
1888// page->dataSize = size;
1889// entry->pageSize = pageSize;
1890// // entry->pageID = pageID;
1891// page->eol = 0;
1892// // printf("CreateFromNew %u EOL %lu...\n", pageID, entry->page->eol);
1893// }
1894// else {
1895// page = getCachedPage(entry);
1896// if (page == NULL) {
1897// unlockPage(entry);
1898// pageMasterMutex->leave();
1899// return NULL;
1900// }
1901// }
1902//
1903// utils::SetBit(pageID, BITOCCUPIED, (uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->bitFieldSize);
1904// if (eol == 0)
1905// pageMaster->lastCreatedStaticPage = pageID;
1906// else
1907// insertPageIntoEOL(pageID, eol, page->eol);
1908//
1909// // Initialise page
1910// page->count = 0;
1911// page->dataUsage = 0;
1913// memset((void*)MP_GetBlockIndexStartLoc(page), 0, (tableSize*sizeof(uint32)));
1914//
1915// entry->pageSerial++;
1916// pageMaster->count[MP_GetPageType(pageID, eol)]++;
1917// pageMaster->pagesSize += page->size;
1918// pageMaster->dataSize[MP_GetPageType(pageID, eol)] += page->dataSize;
1919//
1920// updateCachedPage(entry, page);
1921//
1922// // Unlock page mutex
1924// // Unlock Manager
1925// pageMasterMutex->leave();
1928// return page;
1929//}
1930//
1932//bool MemoryManagerX::freePageIntoPool(uint32 pageID) {
1933// uint32 dataSize = 0;
1934// if (!removePageFromStats(pageID, dataSize))
1935// return false;
1936// if (!insertPageIntoPool(pageID, dataSize))
1937// return false;
1938// return true;
1939//}
1940//
1942//bool MemoryManagerX::removePageFromStats(uint32 pageID, uint32& dataSize) {
1943// // Lock Manager
1944// if (!pageMasterMutex->enter())
1945// return false;
1946// MemoryPageEntry* entry = (MemoryPageEntry*) MP_GetPageEntryLoc(pageMaster, pageID);
1947// // Lock page
1948// if (!lockPage(entry)) {
1949// pageMasterMutex->leave();
1950// return false;
1951// }
1952//
1953// MemoryPage* page = getCachedPage(entry);
1954// if (page == NULL) {
1955// pageMasterMutex->leave();
1956// return true;
1957// }
1958//
1960//
1961// dataSize = page->dataSize;
1962// pageMaster->count[MP_GetPageType(pageID, page->eol)]--;
1963// pageMaster->dataSize[MP_GetPageType(pageID, page->eol)] -= page->dataSize;
1964// pageMaster->dataUsage[MP_GetPageType(pageID, page->eol)] -= page->dataUsage;
1965// pageMaster->pagesSize -= page->size;
1966// // Do not destroy shared memory segment at entry->page
1967// // and leave page link in there
1968// // entry->page = NULL;
1969// // Unlock page
1970// unlockPage(entry);
1971// // destroyPageMutex(pageID);
1972// // Page location remains in use
1973// // utils::SetBit(pageID, BITFREE, (uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->bitFieldSize);
1974// // Unlock Manager
1975// pageMasterMutex->leave();
1976// return true;
1977//}
1978//
1980//bool MemoryManagerX::insertPageIntoPool(uint32 pageID, uint32 dataSize) {
1981// uint32 sbSize = 0;
1982// PagePoolHeader* header = (PagePoolHeader*) getSystemBlock(ID_PAGEPOOL, sbSize);
1983// // Find empty spot
1984// PagePoolEntry* entry = (PagePoolEntry*) ((char*)header + sizeof(PagePoolHeader));
1985// while ((char*)entry < (char*)header + header->size) {
1986// if (entry->dataSize == 0) {
1987// //printf("Freeing to pool page id %d\n", pageID);
1988// //fflush(stdout);
1989// entry->dataSize = dataSize;
1990// entry->time = GetTimeNow();
1991// entry->pageID = pageID;
1992// return true;
1993// }
1994// else
1995// entry += 1;
1996// //entry += sizeof(PagePoolEntry);
1997// }
1998//
1999// // no free entry was found, remove the oldest one, then...
2000// entry = (PagePoolEntry*) ((char*)header + sizeof(PagePoolHeader));
2001// //printf("No free Pool Entries available for id %d, destroying id %d first\n", pageID, entry->pageID);
2002// //fflush(stdout);
2003// // Delete actual page
2004// destroyPage(entry->pageID, false);
2005// // Put in new one
2006// entry->dataSize = dataSize;
2007// entry->time = GetTimeNow();
2008// entry->pageID = pageID;
2009// return true;
2010//}
2011//
2013//bool MemoryManagerX::getPageFromPool(uint32 size, uint32& pageID) {
2014// uint32 sbSize = 0;
2015// PagePoolHeader* header = (PagePoolHeader*) getSystemBlock(ID_PAGEPOOL, sbSize);
2016// if (header == NULL)
2017// return false;
2018// // Find empty spot
2019// PagePoolEntry* entry = (PagePoolEntry*) ((char*)header + sizeof(PagePoolHeader));
2020// while ((char*)entry < (char*)header + header->size) {
2021// if (entry->dataSize >= size) {
2022// pageID = entry->pageID;
2023// //printf("Got from pool page id %d\n", pageID);
2024// //fflush(stdout);
2025// // Remove from pool
2026// memset(entry, 0, sizeof(PagePoolEntry));
2027// return true;
2028// }
2029// else
2030// entry += 1;
2031// //entry += sizeof(PagePoolEntry);
2032// }
2033// return false;
2034//}
2035//
2037//bool MemoryManagerX::destroyAllPages() {
2038// // Lock Manager
2039// if (!pageMasterMutex->enter())
2040// return false;
2041// if (pageMaster == NULL) {
2042// pageMasterMutex->leave();
2043// return true;
2044// }
2045//
2046// // MemoryPageEntry* entry = (MemoryPageEntry*) MP_GetPageTableLoc(pageMaster);
2047// for (uint32 n=0; n<pageMaster->pageTableSize; n++)
2048// destroyPage(n);
2049// // Unlock Manager
2050// pageMasterMutex->leave();
2051// return true;
2052//}
2053//
2055//bool MemoryManagerX::destroyPage(uint32 pageID, bool updateStats) {
2056// // Lock Manager
2057// if (!pageMasterMutex->enter())
2058// return false;
2059// MemoryPageEntry* entry = (MemoryPageEntry*) MP_GetPageEntryLoc(pageMaster, pageID);
2060// // Lock page
2061// if (!lockPage(entry)) {
2062// pageMasterMutex->leave();
2063// return false;
2064// }
2065//
2066// MemoryPage* page = getCachedPage(entry);
2067// if (page == NULL) {
2068// pageMasterMutex->leave();
2069// return true;
2070// }
2071//
2072// if (updateStats) {
2073// pageMaster->count[MP_GetPageType(pageID, page->eol)]--;
2074// pageMaster->dataSize[MP_GetPageType(pageID, page->eol)] -= page->dataSize;
2075// pageMaster->dataUsage[MP_GetPageType(pageID, page->eol)] -= page->dataUsage;
2076// pageMaster->pagesSize -= page->size;
2077// }
2078// // Destroy shared memory segment at entry->page
2079// //printf("Closing cached page %d...\n", pageID);
2080// //fflush(stdout);
2081// utils::DestroySharedMemorySegment((char*)(page), page->size);
2082// page = NULL;
2083// entry->cacheSerial = 0;
2084// entry->pageSize = 0;
2085// updateCachedPage(entry, NULL);
2086// // Unlock page
2087// unlockPage(entry);
2088// utils::SetBit(pageID, BITFREE, (uint32*)MP_GetBitFieldLoc(pageMaster), pageMaster->bitFieldSize);
2089// // Unlock Manager
2090// pageMasterMutex->leave();
2091// return true;
2092//}
2093//
2100//
2107//
2114//
2123//
2131//
2132//bool MemoryManagerX::lockPage(uint32 pageID) {
2133// if (!utils::EnterMutex(pageID, 5000)) {
2134// LogPrint(0,0,0,"Mutex lock timeout for memory page %u", pageID);
2135// return false;
2136// }
2137// return true;
2138//
2140//}
2141//
2142//bool MemoryManagerX::unlockPage(uint32 pageID) {
2143// return utils::LeaveMutex(pageID);
2145//}
2146//
2149//
2152//
2153//bool MemoryManagerX::lockPage(MemoryPageEntry* entry) {
2154// // Assume that pageMasterMutex is locked
2155// if (entry == NULL)
2156// return false;
2157//
2158// if (!utils::EnterMutex(entry->pageID, 5000)) {
2159// LogPrint(0,0,0,"Mutex lock timeout for memory page %u", entry->pageID);
2160// return false;
2161// }
2162// return true;
2163//
2164// //uint64 t1, t2;
2165// //uint32 myID = 0;
2166// //if (!utils::GetCurrentThreadOSID(myID) || !myID)
2167// // return false;
2168//
2169// //// wait until it reaches 0
2170// //utils::Semaphore* sem;
2171// //while ( (entry->lockCount > 0) && (entry->lockID != myID) ) {
2172// //// printf("[%u] Waiting for page %u locked by %u\n", myID, entry->pageID, entry->lockID);
2173// // // if we are waiting the page semaphore exists
2174// // if (!(sem = getPageSemaphore(entry->pageID)))
2175// // return false;
2176// // pageMasterMutex->leave();
2177// // t1 = GetTimeNow();
2178// // if (!sem->wait(1000)) {
2179// // t2 = GetTimeNow();
2180// // delete(sem);
2181// // return false;
2182// // }
2183// // else
2184// // delete(sem);
2185// // if (!pageMasterMutex->enter())
2186// // return false;
2187// //}
2188//
2189// ////if (entry->lockCount)
2190// //// printf("[%u] Locked page %u AGAIN: %u\n", myID, entry->pageID, entry->lockCount);
2191// ////else
2192// //// printf("[%u] Locked page %u\n", myID, entry->pageID);
2193//
2194// //entry->lockCount++;
2195// //entry->lockTime = GetTimeNow();
2196// //entry->lockID = myID;
2197// //return true;
2198//}
2199//
2200//bool MemoryManagerX::unlockPage(MemoryPageEntry* entry) {
2201// if (entry == NULL)
2202// return false;
2203//
2204// return utils::LeaveMutex(entry->pageID);
2205//
2232//}
2233//
2234//
2235//
2237//MemoryPage* MemoryManagerX::findPageForBlock(uint32 size, uint64 eol, uint32& id) {
2238// MemoryPage* page = NULL;
2239// if (eol > 0) {
2240// // search only in eol pages
2241// uint32 sbSize = 0;
2242// EOLHeader* header = (EOLHeader*) getSystemBlock(ID_EOLPAGE, sbSize);
2243// if (header == NULL)
2244// return NULL;
2245//
2246// EOLEntry* entry = NULL;
2247// // Find the appropriate slot
2248// uint64 now = GetTimeNow();
2249// uint64 difTime = 0;
2250// if (eol - now > 0)
2251// difTime = eol - header->startTime;
2252// uint32 difSlot = (uint32)(difTime / header->slotDuration);
2253// // If too far in the future, choose end slot - buffer slot
2254// if (difSlot >= (header->slotCount - header->bufferSlots))
2255// difSlot = header->slotCount - 1 - header->bufferSlots;
2256// // Find actual slot...
2257// uint32 actualSlot = header->startSlot + difSlot;
2258// if (actualSlot >= header->slotCount)
2259// actualSlot -= header->slotCount;
2260// entry = (EOLEntry*)((char*)header + sizeof(EOLHeader) +
2261// (actualSlot * header->pagesPerSlot * sizeof(EOLEntry)));
2262// char* endEntry = (char*) entry + header->pagesPerSlot*sizeof(EOLEntry);
2263// while ((char*) entry <= endEntry) {
2264// if (entry->eol > 0) {
2265// // page = MP_GetPageLoc(pageMaster, entry->pageID);
2266// page = getCachedPage(entry->pageID);
2267// if ((page != NULL) && ( (int64)page->dataSize - (int64)page->dataUsage >= (int64)(size+sizeof(MemoryBlock)) ) ) {
2268// id = entry->pageID;
2269// return page;
2270// }
2271// }
2272// entry += 1;
2273// //entry += sizeof(EOLEntry);
2274// }
2275// }
2276// else {
2277// // search in non-eol pages
2278// // First check the last created page
2279// //page = MP_GetPageLoc(pageMaster, pageMaster->lastCreatedStaticPage);
2280// page = getCachedPage(pageMaster->lastCreatedStaticPage);
2281// if ((page != NULL) && ( (int64)page->dataSize - (int64)page->dataUsage >= (int64)(size+sizeof(MemoryBlock)) ) ) {
2282// id = pageMaster->lastCreatedStaticPage;
2283// return page;
2284// }
2285// // Since we don't (yet) support deletion of memory within static pages,
2286// // there is no need to look further
2287// }
2288//
2289// return NULL;
2290//}
2291//
2292//
2294//uint16 MemoryManagerX::CalcBlockTableSize(uint32 size) {
2295// if (size >= 10*1024*1024) // 10 MB
2296// return 10;
2297// else if (size >= 1024*1024) // 1 MB
2298// return 100;
2299// else if (size >= 256*1024) // 256 kB
2300// return 512;
2301// else if (size >= 16*1024) // 16 kB
2302// return 1024;
2303// else
2304// return 4096;
2305//
2306//}
2307//
2309//char* MemoryManagerX::getBitFieldAsString(uint32& size) {
2310// size = this->pageMaster->bitFieldSize * 16;
2311// char* str = new char[size];
2312//
2313// char* src = (char*)MP_GetBitFieldLoc(pageMaster);
2314// uint32 bfsize = pageMaster->bitFieldSize;
2315//
2316// uint32 n=0, p=0,i,j;
2317// for(i=0;i<bfsize;i++) {
2318// for(j=0;j<8;j++) {
2319// str[n++] = (src[i] & (1<<j)) ? '_' : '0' + (uint8)(getPageUsage(p)*10);
2320// if (++p >= pageMaster->pageTableSize)
2321// break;
2322// }
2323// str[n++] = ' ';
2324// };
2325// str[n] = 0;
2326// return str;
2327//}
2328//
2330//bool MemoryManagerX::printBitFieldAsString(char* title) {
2331// uint32 size = 0;
2332// char* str = getBitFieldAsString(size);
2333// if (str == NULL)
2334// return false;
2335// if (size < 73) {
2336// if (title != NULL)
2337// printf("%s [%u]: %s\n", title, pageMaster->pageTableSize, str);
2338// else
2339// printf("%s\n", str);
2340// }
2341// else {
2342// if (title != NULL)
2343// printf("%s [%u]:\n", title, pageMaster->pageTableSize);
2344// uint32 loc = 35;
2345// while (loc < size-1) {
2346// str[loc] = '\n';
2347// loc += 36;
2348// }
2349// printf("%s\n", str);
2350// }
2351// delete [] str;
2352// return true;
2353//}
2354//
2356//bool MemoryManagerX::getPageUsage(uint32 pageID, double& val) {
2358// MemoryPage* page = getCachedPage(pageID);
2359// if (page == NULL)
2360// return false;
2361// val = ((double)page->dataUsage)/page->dataSize;
2362// return true;
2363//}
2364//
2366//double MemoryManagerX::getPageUsage(uint32 pageID) {
2368// MemoryPage* page = getCachedPage(pageID);
2369// if (page == NULL)
2370// return 0;
2371// return ((double)page->dataUsage)/page->dataSize;
2372//}
2373//
2375//bool MemoryManagerX::getPageFree(uint32 pageID, uint32& bytes) {
2377// MemoryPage* page = getCachedPage(pageID);
2378// if (page == NULL)
2379// return false;
2380// bytes = page->dataSize - page->dataUsage;
2381// return true;
2382//}
2383//
2385//bool MemoryManagerX::getPageSize(uint32 pageID, uint32& bytes) {
2387// MemoryPage* page = getCachedPage(pageID);
2388// if (page == NULL)
2389// return false;
2390// bytes = page->dataSize;
2391// return true;
2392//}
2393//
2395//bool MemoryManagerX::initSystemPage(char* data, uint32 size) {
2396// memset(data, 0, size);
2397// return true;
2398//}
2399//
2401//bool MemoryManagerX::initPagePool(char* data, uint32 size) {
2402// PagePoolHeader* header = (PagePoolHeader*) data;
2403// header->size = size;
2404// memset(data+sizeof(PagePoolHeader), 0, size-sizeof(PagePoolHeader));
2405// return true;
2406//}
2407//
2409//bool MemoryManagerX::resizeEOLPage(uint32 slotCount, uint32 pagesPerSlot, uint32 slotDuration, uint32 bufferSlots) {
2410//
2411// if ( (slotCount < 5) || (pagesPerSlot < 5) || (slotDuration < 100000) || (bufferSlots < 1) )
2412// return false;
2413//
2414// uint32 oldSize = 0, newSize = (slotCount+bufferSlots)*pagesPerSlot*sizeof(EOLEntry) + sizeof(EOLHeader);
2415// MemoryPageEntry* oldEntry = (MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, ID_EOLPAGE);
2417// char* oldData = NULL;
2418// if ((oldEntry != NULL) && (oldEntry->pageSize != 0)) {
2419// // Make copy...
2420// char* eolData = getSystemBlock(ID_EOLPAGE, oldSize);
2421// if (newSize <= oldSize)
2422// return false;
2423// oldData = new char[oldSize];
2424// memcpy(eolData, oldData, oldSize);
2425// destroyPage(ID_EOLPAGE);
2426// }
2427// uint64 memID;
2428// char* data = createSystemPage(ID_EOLPAGE, newSize, memID);
2429// if (data == NULL)
2430// return false;
2432// memset(data, 0, newSize);
2433// EOLHeader* header = (EOLHeader*) data;
2434// header->slotCount = slotCount+bufferSlots;
2435// header->pagesPerSlot = pagesPerSlot;
2436// header->slotDuration = slotDuration;
2437// header->startSlot = 0;
2438// header->startTime = GetTimeNow();
2439// header->bufferSlots = bufferSlots;
2440//
2441// uint64 slotEOL = 0;
2442// if (oldData != NULL) {
2443// EOLHeader* oldHeader = (EOLHeader*) oldData;
2444// // Copy old data back in...
2445// EOLEntry* entry = (EOLEntry*) oldHeader + sizeof(EOLHeader);
2446// uint64 endHeader = (uint64) oldHeader + (oldHeader->slotCount*oldHeader->pagesPerSlot*sizeof(EOLEntry)) + sizeof(EOLHeader);
2447// while ((uint64) entry <= endHeader) {
2448// if (entry->eol > 0) {
2449// // Insert entry in new structure
2450// insertPageIntoEOL(entry->pageID, entry->eol, slotEOL);
2451// }
2452// entry += 1;
2453// //entry += sizeof(EOLEntry);
2454// }
2455// // Delete copy
2456// delete [] oldData;
2457// }
2458// return true;
2459//}
2460//
2462//bool MemoryManagerX::insertPageIntoEOL(uint32 pageID, uint64 eol, uint64& slotEOL) {
2463// uint32 sbSize = 0;
2464// EOLHeader* header = (EOLHeader*) getSystemBlock(ID_EOLPAGE, sbSize);
2465// if (header == NULL)
2466// return false;
2467//
2468// EOLEntry* entry = NULL;
2469// // Find the appropriate slot
2470// uint64 now = GetTimeNow();
2471// uint64 difTime = 0;
2472// if (eol - now > 0)
2473// difTime = eol - now;
2474// // If too far in the future, choose end slot
2475// uint32 difSlot = (uint32)(difTime / header->slotDuration);
2476// // If too far in the future, choose end slot - buffer slot
2477// if (difSlot >= (header->slotCount - header->bufferSlots))
2478// difSlot = header->slotCount - 1 - header->bufferSlots;
2479// // Calc end time of actual slot
2480// slotEOL = difSlot * header->slotDuration;
2481// // Find actual slot, possible wrap-around...
2482// uint32 actualSlot = header->startSlot + difSlot;
2483// if (actualSlot >= header->slotCount)
2484// actualSlot -= header->slotCount;
2485//
2487//
2488// entry = (EOLEntry*)((char*)header + sizeof(EOLHeader) +
2489// (actualSlot * header->pagesPerSlot * sizeof(EOLEntry)));
2490// char* endEntry = (char*) entry + header->pagesPerSlot*sizeof(EOLEntry);
2491// while ((char*) entry < endEntry) {
2492// if (entry->eol == 0) {
2493// entry->eol = eol;
2494// entry->pageID = pageID;
2495// return true;
2496// }
2497// else
2498// entry += 1;
2499// //entry += sizeof(EOLEntry);
2500// }
2501// // Out of room in current slot, try the next slot
2502// if (difSlot < header->slotCount - 1)
2503// return insertPageIntoEOL(pageID, eol+header->slotDuration, slotEOL);
2504// else {
2505// // we need to resize the EOL structure
2506// resizeEOLPage(header->slotCount, header->pagesPerSlot * 4, header->slotDuration, header->bufferSlots);
2507// return insertPageIntoEOL(pageID, eol, slotEOL);
2508// }
2509//}
2510//
2511//
2513//bool MemoryManagerX::initQueuePage(char* data, uint32 size) {
2514// memset(data, 0, size);
2515// return true;
2516//}
2517//
2518//
2519//MemoryPage* MemoryManagerX::getCachedPage(uint32 pageID) {
2520// return getCachedPage((MemoryPageEntry*)MP_GetPageEntryLoc(pageMaster, pageID));
2521//}
2522//
2523//MemoryPage* MemoryManagerX::getCachedPage(MemoryPageEntry *entry) {
2524// if (entry == NULL)
2525// return NULL;
2526//
2527// if (pageCache == NULL) {
2528// uint32 size = sizeof(MemoryPageCache) + pageMaster->pageTableSize*sizeof(MemoryPageCacheEntry);
2529// pageCache = (MemoryPageCache*) malloc(size);
2530// pageCache->size = size;
2531// pageCache->count = pageMaster->pageTableSize;
2532// memset((char*)pageCache + sizeof(MemoryPageCache), 0, size - sizeof(MemoryPageCache));
2533// }
2534//
2535// // Find CachedEntry
2536// MemoryPageCacheEntry* cEntry = (MemoryPageCacheEntry*) ((char*)pageCache + sizeof(MemoryPageCache) + (entry->pageID * sizeof(MemoryPageCacheEntry)));
2537// if (cEntry == NULL)
2538// return NULL;
2539// else if ( (cEntry->page == NULL) || (cEntry->cacheSerial != entry->cacheSerial) || (cEntry->pageSerial != entry->pageSerial) ) {
2540// // Cache needs updating
2541// if (cEntry->page != NULL)
2542// utils::DestroySharedMemorySegment((char*)cEntry->page, cEntry->pageSize);
2543// // Map page memory location
2544//
2545// char* pageName = new char[MAXKEYNAMELEN];
2546// sprintf(pageName, "Page_%u", entry->pageID);
2547// cEntry->page = (MemoryPage*) utils::OpenSharedMemorySegment(pageName, entry->pageSize);
2548// delete [] pageName;
2549// if (cEntry->page == NULL)
2550// return NULL;
2551// cEntry->cacheSerial = entry->cacheSerial;
2552// cEntry->pageID = entry->pageID;
2553// cEntry->pageSerial = entry->pageSerial;
2554// cEntry->pageSize = entry->pageSize;
2555// }
2556// //printf("Got cached page id %d: %p\n", entry->pageID, cEntry->page);
2557// //fflush(stdout);
2558// return cEntry->page;
2559//}
2560//
2561//bool MemoryManagerX::updateCachedPage(MemoryPageEntry *entry, MemoryPage *page) {
2562// if (entry == NULL)
2563// return false;
2564//
2565// if (pageCache == NULL) {
2566// uint32 size = sizeof(MemoryPageCache) + pageMaster->pageTableSize*sizeof(MemoryPageCacheEntry);
2567// pageCache = (MemoryPageCache*)malloc(size);
2568// pageCache->size = size;
2569// pageCache->count = pageMaster->pageTableSize;
2570// memset((char*)pageCache + sizeof(MemoryPageCache), 0, size - sizeof(MemoryPageCache));
2571// }
2572//
2573// // Find CachedEntry
2574// MemoryPageCacheEntry* cEntry = (MemoryPageCacheEntry*) ((char*)pageCache + sizeof(MemoryPageCache) + (entry->pageID * sizeof(MemoryPageCacheEntry)));
2575// if (cEntry == NULL)
2576// return NULL;
2577//
2578// // Should existing page be removed?
2579// if ( (cEntry->page != NULL) && (cEntry->page != page) && ( (page != NULL) || (entry->pageSize == 0) ) ) {
2580// utils::DestroySharedMemorySegment((char*)cEntry->page, cEntry->pageSize);
2581// cEntry->page = NULL;
2582// }
2583// if (page != NULL)
2584// cEntry->page = page;
2585// cEntry->cacheSerial = entry->cacheSerial;
2586// cEntry->pageID = entry->pageID;
2587// cEntry->pageSerial = entry->pageSerial;
2588// cEntry->pageSize = entry->pageSize;
2589//
2590// return true;
2591//}
2592//
2593//
2594//
2595//
2596//
2597//
2598//
2599//
2600//
2601//
2602//
2603//
2604//
2605//
2606//
2607//
2608//
2609//
2610//
2611//
2617//
2619//uint32 MemoryManagerX::runManager() {
2620// LogPrint(0, LOG_SYSTEM, 5, "Memory Management running...\n\n");
2621// isRunning = true;
2622//
2623// uint64 nextPageCheck = 0, now;
2624//
2625// while (shouldContinue) {
2626// if (!pageMasterMutex->enter())
2627// break;
2628//
2629// if (isMaster)
2630// pageMaster->timesync = LocalSyncAdjustment;
2631// else
2632// LocalSyncAdjustment = pageMaster->timesync;
2633//
2634// now = GetTimeNow();
2635//
2636// if (!nextPageCheck || (now >= nextPageCheck) ) {
2637//
2638// uint32 sbSize = 0;
2639// EOLHeader* header = (EOLHeader*) getSystemBlock(ID_EOLPAGE, sbSize);
2640// if (header == NULL) {
2641// pageMasterMutex->leave();
2642// break;
2643// }
2644//
2645// EOLEntry* entry;
2646// char* endEntry;
2647// int32 delSlot;
2648// // Check if we should tick the current EOL startSlot to the next slot
2649// while ( now - header->startTime > header->slotDuration) {
2650// // Move the current slot one forward
2651// header->startSlot++;
2652// if (header->startSlot > header->slotCount)
2653// header->startSlot -= header->slotCount;
2654// header->startTime += header->slotDuration;
2655// // printf("New startSlot: %u (%d)...\n", header->startSlot, GetTimeNow() - header->startTime);
2656// // Find the slot minus bufferSlots
2657// delSlot = header->startSlot - header->bufferSlots;
2658// if (delSlot < 0)
2659// delSlot += header->slotCount;
2660//
2661// // Free all pages in the slot
2662// entry = (EOLEntry*)((char*)header + sizeof(EOLHeader) +
2663// (delSlot * header->pagesPerSlot * sizeof(EOLEntry)));
2664// endEntry = (char*) entry + header->pagesPerSlot*sizeof(EOLEntry);
2665// while ((char*) entry < endEntry) {
2666// if (entry->eol > 0) {
2667// // printf("--------- Freeing page ID %u, slot %u, eol %llu...\n", entry->pageID, delSlot, entry->eol);
2668// freePageIntoPool(entry->pageID);
2669// entry->eol = 0;
2670// entry->pageID = 0;
2671// }
2672// entry += 1;
2673// }
2674//
2675// }
2676// nextPageCheck = header->startTime + header->slotDuration + 20000;
2677// // sleep = header->startTime + header->slotDuration - GetTimeNow() + 20000;
2678// pageMasterMutex->leave();
2679// }
2680// else {
2681// pageMasterMutex->leave();
2682// utils::Sleep(20);
2683// }
2684// }
2685//
2686// isRunning = false;
2687// return 0;
2688//}
2689//
2690//bool MemoryManagerX::UnitTest() {
2691// printf("Testing Static Memory Management...\n\n");
2692//
2693// // First create and initialise the MemoryManager
2694// MemoryManagerX* manager = new MemoryManagerX();
2695// uint32 maxPageCount = 15;
2696// // fprintf(stderr, "MemoryManager init() 0...\n");
2697// if (!manager->create(0, maxPageCount)) {
2698// fprintf(stderr, "MemoryManager init() failed...\n");
2699// delete(manager);
2700// return false;
2701// }
2702// // fprintf(stderr, "MemoryManager init() success...\n");
2703//
2704// uint64 eol = 0;
2705// uint32 size = 4096;
2706// char* data = new char[size];
2707//
2708// // we should be able to add
2709// uint32 expectedCount = CalcBlockTableSize(size);
2710// uint32 expectedMaxCount = (maxPageCount-RESERVEDPAGECOUNT) * expectedCount;
2711// uint32 count = expectedMaxCount;
2712// uint64* ids = new uint64[count];
2713//
2714// // printf("\n\n>>>>>> Inserting %lu blocks ...\n\n", count);
2715//
2716// uint32 n;
2717// uint64 id;
2718// uint64 t1 = GetTimeNow();
2719// for (n=0; n<count; n++) {
2720// strcpy(data, "Test");
2721// utils::Int2Ascii(n, data+4, size-4, 10);
2722// if (!manager->insertMemoryBlock(data, size, eol, id)) {
2723// fprintf(stderr, "MemoryManager insert %d failed...\n", n);
2724// delete [] ids;
2725// delete [] data;
2726// delete(manager);
2727// return false;
2728// }
2729// ids[n] = id;
2730// }
2731// uint64 t2 = GetTimeNow();
2732//
2733// uint32 size2 = 0;
2734// uint64 eol2 = 0;
2735// char* data2;
2736//
2737// // printf("\n\n>>>>>> Getting %lu blocks ...\n\n", count);
2738// for (n=0; n<count; n++) {
2739// data2 = manager->getCopyMemoryBlock(ids[n], size2, eol2);
2740// if (data2 == NULL) {
2741// fprintf(stderr, "MemoryManager getcopy failed...\n");
2742// delete [] ids;
2743// delete [] data;
2744// delete(manager);
2745// return false;
2746// }
2747// if (size2 != size) {
2748// fprintf(stderr, "MemoryManager getcopy got wrong size back...\n");
2749// delete [] ids;
2750// delete [] data;
2751// delete [] data2;
2752// delete(manager);
2753// return false;
2754// }
2755// strcpy(data, "Test");
2756// utils::Int2Ascii(n, data+4, size-4, 10);
2757// if (strcmp(data2, data) != 0) {
2758// fprintf(stderr, "MemoryManager getcopy got wrong data back...\n");
2759// delete [] ids;
2760// delete [] data;
2761// delete [] data2;
2762// delete(manager);
2763// return false;
2764// }
2765// if (eol2 != eol) {
2766// fprintf(stderr, "MemoryManager getcopy got wrong eol back (%llu != %llu) [%u]...\n", eol2, eol, n);
2767// delete [] ids;
2768// delete [] data;
2769// delete [] data2;
2770// delete(manager);
2771// return false;
2772// }
2773// delete [] data2;
2774// }
2775// uint64 t3 = GetTimeNow();
2776//
2777// printf("Performance:\n Writing %u: %.3f MB/s / %.3f entries/s (%u us) [%u b]\n",
2778// count, (1.0*size*count)/(t2-t1), (1000000.0*count)/(t2-t1), (uint32)(t2-t1), size);
2779// printf(" Reading %u: %.3f MB/s / %.3f entries/s (%u us) [%u b]\n\n",
2780// count, (1.0*size*count)/(t3-t2), (1000000.0*count)/(t3-t2), (uint32)(t3-t2), size);
2781//
2782// delete [] ids;
2783// delete [] data;
2784// delete(manager);
2785// fprintf(stdout, "*** Static Memory Management test ran successfully ***\n\n\n");
2786//
2788//
2789// printf("Testing Dynamic Memory Management...\n\n");
2790//
2791// manager = new MemoryManagerX();
2792// // Initialise for 10 slots of 1 sec each, 0 buffer = 10 second max keep
2793// // fprintf(stderr, "MemoryManager init() 0...\n");
2794// if (!manager->create(0, 100, 10, 100000, 1)) {
2795// fprintf(stderr, "MemoryManager init() failed...\n");
2796// delete(manager);
2797// return false;
2798// }
2799// // fprintf(stderr, "MemoryManager init() success...\n");
2800//
2801// uint64 now = GetTimeNow();
2802//
2803// uint32 total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage;
2804// if (GetMemoryUsage(total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage))
2805// printf("Dynamic Memory in use before test: %u (%u allocated))\n", dynamicUsage, dynamicTotal);
2806//
2807// char* mem;
2808// for (n=0; n<30; n++) {
2809// mem = new char[1024];
2810// if (!manager->insertMemoryBlock(mem, 1024, now+1000000, id)) {
2811// fprintf(stderr, "MemoryManager insert memory failed...\n");
2812// delete(manager);
2813// return false;
2814// }
2815// delete [] mem;
2816// if (GetMemoryUsage(total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage))
2817// printf("Dynamic Memory in use add %u: %u (%u allocated))\n", n, dynamicUsage, dynamicTotal);
2818// utils::Sleep(100);
2819// now = GetTimeNow();
2820// }
2821//
2822// for (n=0; n<20; n++) {
2823// if (GetMemoryUsage(total, usage, sysTotal, sysUsage, staticTotal, staticUsage, dynamicTotal, dynamicUsage))
2824// printf("Dynamic Memory in use idle %u: %u (%u allocated))\n", n, dynamicUsage, dynamicTotal);
2825// utils::Sleep(100);
2826// }
2827//
2828//
2829// delete(manager);
2830// fprintf(stdout, "*** Dynamic Memory Management test ran successfully ***\n\n\n");
2831//
2832// return true;
2833//}
2834
2835//#define SEGSIZE ((size_t)1024)
2836//
2837//int server() {
2838//
2839// int shmFD;
2840// void *shmAdd;
2841// int i, useMode=1; /* 1=use segment, not create it. */
2842//
2843// /* We get "open" a shared memory segment with the given name. The
2844// flags work just as they do with open: O_CREAT creates the segment
2845// if it doesn't exist, O_EXCL errors out if the segment already
2846// exists, and O_RDRW opens it for read and write. The perms are as
2847// with chmod. Normally, things opened with shm_open do now appear
2848// in the filesystem; however, it is best to specify a path to a
2849// file you can write to! */
2850// shmFD = shm_open("foobar", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
2851// if(shmFD < 0) {
2852// /* I have a case for all of the interesting cases, even the ones
2853// that can not happen in this situation... */
2854// switch(errno) {
2855// case EACCES: printf("shm_open failed: The requested permissions were denied or create denied .\n");
2856// break;
2857// case EEXIST: printf("shm_open failed: Object already exists and O_CREAT and O_EXCL were specified.\n");
2858// useMode=1;
2859// break;
2860// case EINTR: printf("shm_open failed: The operation was interrupted by a signal.\n");
2861// break;
2862// case EINVAL: printf("shm_open failed: The operation is not supported.\n");
2863// break;
2864// case EMFILE: printf("shm_open failed: Too many file descriptors were already open.\n");
2865// break;
2866// case ENAMETOOLONG: printf("shm_open failed: Name was too long (longer than SHM_NAME_MAX chars).\n");
2867// break;
2868// case ENFILE: printf("shm_open failed: The system file table is full.\n");
2869// break;
2870// case ENOENT: printf("shm_open failed: Object doesn't exist (O_CREAT was not specified).\n");
2871// break;
2872// case ENOSPC: printf("shm_open failed: No memory to create object (O_CREAT was specified).\n");
2873// break;
2874// default: printf("shm_open failed: Duno why...\n");
2875// break;
2876// } /* end switch */
2877//
2878// exit(1);
2879// } /* end if */
2880//
2881//
2882// /* Use ftruncate() to size the region -- IMO an only semi-intuitive
2883// choice on the part of the POSIX committee. */
2884// if(ftruncate(shmFD, SEGSIZE) < 0) {
2885// /* I have included all typically supported error cases below, even
2886// if they don't apply here. */
2887// switch(errno) {
2888// case EBADF: printf("ftruncate failed: The fd is not a valid descriptor.\n");
2889// break;
2890// case EINVAL: printf("ftruncate failed: Not open for writing, or references a socket, not a file.\n");
2891// break;
2892// default: printf("ftruncate failed: Duno why...\n");
2893// break;
2894// } /* end switch */
2895// exit(1);
2896// } /* end if */
2897//
2898// shmAdd = (char *)mmap(NULL, // Almost always not used
2899// SEGSIZE, // Length of the mapped space
2900// PROT_READ | PROT_WRITE, // Access type
2901// MAP_SHARED, // Write changes to device (see: MAP_PRIVATE)
2902// shmFD, // FD of the shared memory segment
2903// 0); // Offset into segment.
2904//
2905// /* For more info on the strange return and possible error conditions
2906// of mmap(), see the mmap.c example program. */
2907// if(shmAdd == MAP_FAILED) {
2908// switch(errno) {
2909// case EACCES: printf("mmap failed: The FD was not open for read, or for write with (PROT_WRITE or MAP_SHARED)\n");
2910// break;
2911// case EAGAIN: printf("mmap failed: The mapping could not be locked in memory\n");
2912// break;
2913// case EBADF: printf("mmap failed: The FD not a valid open file descriptor.\n");
2914// break;
2915// case EINVAL: printf("mmap failed: The value of len is zero, addr is not valid, bad combination of args\n");
2916// break;
2917// case EMFILE: printf("mmap failed: The too many regions mapped already\n");
2918// break;
2919// case ENODEV: printf("mmap failed: The FD file type is not supported by mmap().\n");
2920// break;
2921// case ENOMEM: printf("mmap failed: Not enough memory\n");
2922// break;
2923// case ENOTSUP: printf("mmap failed: Options not supported on this platform\n");
2924// break;
2925// case ENXIO: printf("mmap failed: Range [off,off+len) are invalid for the FD, MAP_FIXED & invalid addresses, or FD not accessible\n");
2926// break;
2927// case EOVERFLOW: printf("mmap failed: File is too big!\n");
2928// break;
2929// default: printf("mmap failed: Duno why! (errno: %d)\n", errno);
2930// break;
2931// } /* end switch */
2932// exit(1);
2933// } /* end if */
2934//
2935// /* We copy some stuff into the segment so that we can read it out later... */
2936// printf("Write 'Hello' into the segment.\n");
2937// strcpy((char*)shmAdd, "Hello");
2938//
2939// return 0;
2940//} /* end func main() */
2941//
2942//
2943//int client() {
2944// int shmFD;
2945// void *shmAdd;
2946// int i, useMode=0; /* 1=use segment, not create it. */
2947//
2948// /* If we failed before because the segment already existed, then we try to open it
2949// up and use it -- thus combining the "make" and "use" example programs. */
2950// shmFD = shm_open("foobar", O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
2951// if(shmFD < 0) {
2952// switch(errno) {
2953// case EACCES: printf("shm_open failed: The requested permissions were denied or create denied .\n");
2954// break;
2955// case EEXIST: printf("shm_open failed: Object already exists and O_CREAT and O_EXCL were specified.\n");
2956// useMode=1;
2957// break;
2958// case EINTR: printf("shm_open failed: The operation was interrupted by a signal.\n");
2959// break;
2960// case EINVAL: printf("shm_open failed: The operation is not supported.\n");
2961// break;
2962// case EMFILE: printf("shm_open failed: Too many file descriptors were already open.\n");
2963// break;
2964// case ENAMETOOLONG: printf("shm_open failed: Name was too long (longer than SHM_NAME_MAX chars).\n");
2965// break;
2966// case ENFILE: printf("shm_open failed: The system file table is full.\n");
2967// break;
2968// case ENOENT: printf("shm_open failed: Object doesn't exist (O_CREAT was not specified).\n");
2969// break;
2970// case ENOSPC: printf("shm_open failed: No memory to create object (O_CREAT was specified).\n");
2971// break;
2972// default: printf("shm_open failed: Duno why...\n");
2973// break;
2974// } /* end switch */
2975// exit(1);
2976// } /* end if */
2977//
2978//
2979// shmAdd = (char *)mmap(NULL, // Almost always not used
2980// SEGSIZE, // Length of the mapped space
2981// PROT_READ | PROT_WRITE, // Access type
2982// MAP_SHARED, // Write changes to device (see: MAP_PRIVATE)
2983// shmFD, // FD of the shared memory segment
2984// 0); // Offset into segment.
2985//
2986// /* For more info on the strange return and possible error conditions
2987// of mmap(), see the mmap.c example program. */
2988// if(shmAdd == MAP_FAILED) {
2989// switch(errno) {
2990// case EACCES: printf("mmap failed: The FD was not open for read, or for write with (PROT_WRITE or MAP_SHARED)\n");
2991// break;
2992// case EAGAIN: printf("mmap failed: The mapping could not be locked in memory\n");
2993// break;
2994// case EBADF: printf("mmap failed: The FD not a valid open file descriptor.\n");
2995// break;
2996// case EINVAL: printf("mmap failed: The value of len is zero, addr is not valid, bad combination of args\n");
2997// break;
2998// case EMFILE: printf("mmap failed: The too many regions mapped already\n");
2999// break;
3000// case ENODEV: printf("mmap failed: The FD file type is not supported by mmap().\n");
3001// break;
3002// case ENOMEM: printf("mmap failed: Not enough memory\n");
3003// break;
3004// case ENOTSUP: printf("mmap failed: Options not supported on this platform\n");
3005// break;
3006// case ENXIO: printf("mmap failed: Range [off,off+len) are invalid for the FD, MAP_FIXED & invalid addresses, or FD not accessible\n");
3007// break;
3008// case EOVERFLOW: printf("mmap failed: File is too big!\n");
3009// break;
3010// default: printf("mmap failed: Duno why! (errno: %d)\n", errno);
3011// break;
3012// } /* end switch */
3013// exit(1);
3014// } /* end if */
3015//
3016// /* The segment already existed, so we print out it's contents and change them. */
3017// /* Just print the printable chars in case the segment has binary junk in it... */
3018// printf("The segment content: \n");
3019// for(i=0;(i<SEGSIZE)&&(((char *)shmAdd)[i]!=0);i++)
3020// if(isalpha(((char *)shmAdd)[i]) || isdigit(((char *)shmAdd)[i]))
3021// printf("%c", ((char *)shmAdd)[i]);
3022// printf("\n");
3023//
3024// /* Now we change the data to "Goodbye" */
3025// printf("Change the contents to: 'Goodbye'..\n");
3026// strcpy((char*)shmAdd, "Goodbye");
3027//
3028// /* While not required, one should unmap from segments when done with them. */
3029// if(munmap(shmAdd, SEGSIZE) < 0) {
3030// switch(errno) {
3031// case EINVAL: printf("munmap failed: The address range [addr,addr+len) is invalid.\n"
3032// " munmap failed: The len argument is 0.\n"
3033// " munmap failed: The addr argument is not a multiple of page size.\n");
3034// break;
3035// default: printf("munmap failed: Duno why! (errno %d).\n", errno);
3036// break;
3037// } /* end switch */
3038// exit(1);
3039// } /* end if */
3040//
3041// /* One should also close FDs opened with shm_open (again, not
3042// necessarily required, but good practice). */
3043// if(close(shmFD) < 0) {
3044// switch(errno) {
3045// case EBADF: printf("close failed: The FD is not an active descriptor.\n");
3046// break;
3047// case EINTR: printf("close failed: An interrupt was received.\n"); // Should try again... :)
3048// break;
3049// } /* end switch */
3050// } /* end if */
3051//
3052// return 0;
3053//} /* end func main() */
3054
3056
3057 // NOTE: the original shared-memory exercise (CreateSharedMemorySegment /
3058 // OpenSharedMemorySegment / server() / client()) is disabled in this build,
3059 // so this test is currently a smoke check that the entry point is callable.
3060 unittest::progress(10, "shared memory smoke check");
3061
3062 //char *data = utils::CreateSharedMemorySegment("foobar", 1024);
3063 //if (!data)
3064 // unittest::detail("Couldn't create test shared memory segment...");
3065
3066 //char* data2 = utils::OpenSharedMemorySegment("foobar", 1024);
3067 //if (!data2)
3068 // unittest::detail("Couldn't open test shared memory segment...");
3069
3070 unittest::progress(100, "done");
3071 return true;
3072
3073// server();
3074// client();
3075}
3076
3077
3080 "Static memory management insert/read-back throughput", "memory");
3082 "Shared memory segment smoke check", "memory");
3083}
3084
3085
3086} // namespace cmlabs
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
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:3121
char * OpenSharedMemorySegment(const char *name, uint64 size)
Open and map an existing named shared memory segment.
Definition Utils.cpp:2489
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:2368
bool CloseSharedMemorySegment(char *data, uint64 size)
Unmap a segment previously created/opened here.
Definition Utils.cpp:2604
void ClearStaleSharedSegments(uint16 port)
Remove stale OS shared-memory/semaphore objects left by a crashed node on this port.
Definition Utils.cpp:2678
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.
std::string StringFormat(const char *format,...)
printf into a std::string.
Definition Utils.cpp:8067
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.