/*---------------------------------------------------------------------------------------- Database pr ----------------------------------------------------------------------------------------*/ #include "prdatabase.h" union prTempType_ prTemp_; struct prRootType_ prRootData; uint8 prModuleID; struct prRootFields prRoots; struct prNodeFields prNodes; /*---------------------------------------------------------------------------------------- Constructor/Destructor hooks. ----------------------------------------------------------------------------------------*/ void(*prRootConstructorCallback)(prRoot); void(*prNodeConstructorCallback)(prNode); void(*prNodeDestructorCallback)(prNode); /*---------------------------------------------------------------------------------------- Default constructor wrapper for the database manager. ----------------------------------------------------------------------------------------*/ static uint64 allocRoot(void) { prRoot Root = prRootAlloc(); return prRoot2Index(Root); } /*---------------------------------------------------------------------------------------- Allocate the field arrays of Root. ----------------------------------------------------------------------------------------*/ static void allocRoots(void) { prSetAllocatedRoot(2); prSetUsedRoot(0); prRoots.NodeIndex = utNewA(uint32, (prAllocatedRoot())); prRoots.NumNode = utNewA(uint32, (prAllocatedRoot())); prSetUsedRootNode(0); prSetAllocatedRootNode(2); prSetFreeRootNode(0); prRoots.Node = utNewA(prNode, prAllocatedRootNode()); prRoots.UsedNode = utNewA(uint32, (prAllocatedRoot())); prRoots.FreeList = utNewA(prRoot, (prAllocatedRoot())); } /*---------------------------------------------------------------------------------------- Realloc the arrays of properties for class Root. ----------------------------------------------------------------------------------------*/ static void reallocRoots( uint8 newSize) { utRecordResize(prModuleID, 0, (prAllocatedRoot()), true); utResizeArray(prRoots.NodeIndex, (newSize)); utRecordResize(prModuleID, 0, (newSize), false); utRecordResize(prModuleID, 1, (prAllocatedRoot()), true); utResizeArray(prRoots.NumNode, (newSize)); utRecordResize(prModuleID, 1, (newSize), false); utRecordResize(prModuleID, 3, (prAllocatedRoot()), true); utResizeArray(prRoots.UsedNode, (newSize)); utRecordResize(prModuleID, 3, (newSize), false); utRecordResize(prModuleID, 4, (prAllocatedRoot()), true); utResizeArray(prRoots.FreeList, (newSize)); utRecordResize(prModuleID, 4, (newSize), false); prSetAllocatedRoot(newSize); } /*---------------------------------------------------------------------------------------- Allocate more Roots. ----------------------------------------------------------------------------------------*/ void prRootAllocMore(void) { reallocRoots((uint8)(prAllocatedRoot() + (prAllocatedRoot() >> 1))); } /*---------------------------------------------------------------------------------------- Compact the Root.Node heap to free memory. ----------------------------------------------------------------------------------------*/ void prCompactRootNodes(void) { uint32 elementSize = sizeof(prNode); uint32 usedHeaderSize = (sizeof(prRoot) + elementSize - 1)/elementSize; uint32 freeHeaderSize = (sizeof(prRoot) + sizeof(uint32) + elementSize - 1)/elementSize; prNode *toPtr = prRoots.Node; prNode *fromPtr = toPtr; prRoot Root; uint32 size; while(fromPtr < prRoots.Node + prUsedRootNode()) { Root = *(prRoot *)(void *)fromPtr; if(Root != prRootNull) { /* Need to move it to toPtr */ size = utMax(prRootGetNumNode(Root) + usedHeaderSize, freeHeaderSize); utRecordArray(prModuleID, 2, toPtr - prRoots.Node, size, true); memmove((void *)toPtr, (void *)fromPtr, size*elementSize); utRecordArray(prModuleID, 2, toPtr - prRoots.Node, size, false); prRootSetNodeIndex(Root, toPtr - prRoots.Node + usedHeaderSize); toPtr += size; } else { /* Just skip it */ size = *(uint32 *)(void *)(((prRoot *)(void *)fromPtr) + 1); } fromPtr += size; } prSetUsedRootNode(toPtr - prRoots.Node); prSetFreeRootNode(0); } /*---------------------------------------------------------------------------------------- Allocate more memory for the Root.Node heap. ----------------------------------------------------------------------------------------*/ static void allocMoreRootNodes( uint32 spaceNeeded) { uint32 freeSpace = prAllocatedRootNode() - prUsedRootNode(); if((prFreeRootNode() << 2) > prUsedRootNode()) { prCompactRootNodes(); freeSpace = prAllocatedRootNode() - prUsedRootNode(); } if(freeSpace < spaceNeeded) { utRecordResize(prModuleID, 2, prAllocatedRootNode(), true); prSetAllocatedRootNode(prAllocatedRootNode() + spaceNeeded - freeSpace + (prAllocatedRootNode() >> 1)); utResizeArray(prRoots.Node, prAllocatedRootNode()); utRecordResize(prModuleID, 2, prAllocatedRootNode(), false); } } /*---------------------------------------------------------------------------------------- Allocate memory for a new Root.Node array. ----------------------------------------------------------------------------------------*/ void prRootAllocNodes( prRoot Root, uint32 numNodes) { uint32 freeSpace = prAllocatedRootNode() - prUsedRootNode(); uint32 elementSize = sizeof(prNode); uint32 usedHeaderSize = (sizeof(prRoot) + elementSize - 1)/elementSize; uint32 freeHeaderSize = (sizeof(prRoot) + sizeof(uint32) + elementSize - 1)/elementSize; uint32 spaceNeeded = utMax(numNodes + usedHeaderSize, freeHeaderSize); #if defined(DD_DEBUG) utAssert(prRootGetNumNode(Root) == 0); #endif if(numNodes == 0) { return; } if(freeSpace < spaceNeeded) { allocMoreRootNodes(spaceNeeded); } prRootSetNodeIndex(Root, prUsedRootNode() + usedHeaderSize); prRootSetNumNode(Root, numNodes); utRecordArray(prModuleID, 2, prUsedRootNode(), numNodes + usedHeaderSize, true); *(prRoot *)(void *)(prRoots.Node + prUsedRootNode()) = Root; { uint8 xRoot; for(xRoot = (uint8)(prRootGetNodeIndex(Root)); xRoot < prRootGetNodeIndex(Root) + numNodes; xRoot++) { prRoots.Node[xRoot] = prNodeNull; } } utRecordArray(prModuleID, 2, prUsedRootNode(), numNodes + usedHeaderSize, false); prSetUsedRootNode(prUsedRootNode() + spaceNeeded); } /*---------------------------------------------------------------------------------------- Wrapper around prRootGetNodes for the database manager. ----------------------------------------------------------------------------------------*/ static void *getRootNodes( uint64 objectNumber, uint32 *numValues) { prRoot Root = prIndex2Root((uint8)objectNumber); *numValues = prRootGetNumNode(Root); return prRootGetNodes(Root); } /*---------------------------------------------------------------------------------------- Wrapper around prRootAllocNodes for the database manager. ----------------------------------------------------------------------------------------*/ static void *allocRootNodes( uint64 objectNumber, uint32 numValues) { prRoot Root = prIndex2Root((uint8)objectNumber); prRootSetNodeIndex(Root, 0); prRootSetNumNode(Root, 0); if(numValues == 0) { return NULL; } prRootAllocNodes(Root, numValues); return prRootGetNodes(Root); } /*---------------------------------------------------------------------------------------- Free memory used by the Root.Node array. ----------------------------------------------------------------------------------------*/ void prRootFreeNodes( prRoot Root) { uint32 elementSize = sizeof(prNode); uint32 usedHeaderSize = (sizeof(prRoot) + elementSize - 1)/elementSize; uint32 freeHeaderSize = (sizeof(prRoot) + sizeof(uint32) + elementSize - 1)/elementSize; uint32 size = utMax(prRootGetNumNode(Root) + usedHeaderSize, freeHeaderSize); prNode *dataPtr = prRootGetNodes(Root) - usedHeaderSize; if(prRootGetNumNode(Root) == 0) { return; } utRecordArray(prModuleID, 2, dataPtr - prRoots.Node, freeHeaderSize, true); *(prRoot *)(void *)(dataPtr) = prRootNull; *(uint32 *)(void *)(((prRoot *)(void *)dataPtr) + 1) = size; utRecordArray(prModuleID, 2, dataPtr - prRoots.Node, freeHeaderSize, false); prRootSetNumNode(Root, 0); prSetFreeRootNode(prFreeRootNode() + size); } /*---------------------------------------------------------------------------------------- Resize the Root.Node array. ----------------------------------------------------------------------------------------*/ void prRootResizeNodes( prRoot Root, uint32 numNodes) { uint32 freeSpace; uint32 elementSize = sizeof(prNode); uint32 usedHeaderSize = (sizeof(prRoot) + elementSize - 1)/elementSize; uint32 freeHeaderSize = (sizeof(prRoot) + sizeof(uint32) + elementSize - 1)/elementSize; uint32 newSize = utMax(numNodes + usedHeaderSize, freeHeaderSize); uint32 oldSize = utMax(prRootGetNumNode(Root) + usedHeaderSize, freeHeaderSize); prNode *dataPtr; if(numNodes == 0) { if(prRootGetNumNode(Root) != 0) { prRootFreeNodes(Root); } return; } if(prRootGetNumNode(Root) == 0) { prRootAllocNodes(Root, numNodes); return; } freeSpace = prAllocatedRootNode() - prUsedRootNode(); if(freeSpace < newSize) { allocMoreRootNodes(newSize); } dataPtr = prRootGetNodes(Root) - usedHeaderSize; utRecordArray(prModuleID, 2, prUsedRootNode(), newSize, true); utRecordArray(prModuleID, 2, dataPtr - prRoots.Node, freeHeaderSize, true); memcpy((void *)(prRoots.Node + prUsedRootNode()), dataPtr, elementSize*utMin(oldSize, newSize)); if(newSize > oldSize) { { uint8 xRoot; for(xRoot = (uint8)(prUsedRootNode() + oldSize); xRoot < prUsedRootNode() + oldSize + newSize - oldSize; xRoot++) { prRoots.Node[xRoot] = prNodeNull; } } } *(prRoot *)(void *)dataPtr = prRootNull; *(uint32 *)(void *)(((prRoot *)(void *)dataPtr) + 1) = oldSize; utRecordArray(prModuleID, 2, prUsedRootNode(), newSize, false); utRecordArray(prModuleID, 2, dataPtr - prRoots.Node, freeHeaderSize, false); prSetFreeRootNode(prFreeRootNode() + oldSize); prRootSetNodeIndex(Root, prUsedRootNode() + usedHeaderSize); prRootSetNumNode(Root, numNodes); prSetUsedRootNode(prUsedRootNode() + newSize); } /*---------------------------------------------------------------------------------------- Copy the properties of Root. ----------------------------------------------------------------------------------------*/ void prRootCopyProps( prRoot prOldRoot, prRoot prNewRoot) { } /*---------------------------------------------------------------------------------------- Add the indexed Node to the Root. ----------------------------------------------------------------------------------------*/ void prRootInsertNode( prRoot Root, uint32 x, prNode _Node) { #if defined(DD_DEBUG) if(Root == prRootNull) { utExit("Non existent Root"); } if(prNodeGetRoot(_Node) != prRootNull) { utExit("Attempting to add Node to Root twice"); } #endif prRootSetiNode(Root, x, _Node); prRootSetUsedNode(Root, utMax(prRootGetUsedNode(Root), x + 1)); prNodeSetRootIndex(_Node, x); prNodeSetRoot(_Node, Root); } /*---------------------------------------------------------------------------------------- Add the Node to the end of the RootNode array. ----------------------------------------------------------------------------------------*/ void prRootAppendNode( prRoot Root, prNode _Node) { uint32 usedNode = prRootGetUsedNode(Root); #if defined(DD_DEBUG) if(Root == prRootNull) { utExit("Non existent Root"); } #endif if(usedNode >= prRootGetNumNode(Root)) { prRootResizeNodes(Root, usedNode + (usedNode << 1) + 1); } prRootSetiNode(Root, usedNode, _Node); prRootSetUsedNode(Root, usedNode + 1); prNodeSetRootIndex(_Node, usedNode); prNodeSetRoot(_Node, Root); } /*---------------------------------------------------------------------------------------- Remove the Node from the Root. ----------------------------------------------------------------------------------------*/ void prRootRemoveNode( prRoot Root, prNode _Node) { #if defined(DD_DEBUG) if(_Node == prNodeNull) { utExit("Non-existent Node"); } if(prNodeGetRoot(_Node) != prRootNull && prNodeGetRoot(_Node) != Root) { utExit("Delete Node from non-owning Root"); } #endif prRootSetiNode(Root, prNodeGetRootIndex(_Node), prNodeNull); prNodeSetRootIndex(_Node, UINT32_MAX); prNodeSetRoot(_Node, prRootNull); } static void prRootSwapNode( prRoot Root, uint32 x, uint32 y) { prNode newY = prRootGetiNode(Root, x); prNode newX = prRootGetiNode(Root, y); prRootRemoveNode(Root, newY); prRootRemoveNode(Root, newX); prRootInsertNode(Root, x, newX); prRootInsertNode(Root, y, newY); } static void prRootHeapDownNode( prRoot Root, uint32 arg_x) { uint32 x = arg_x; uint32 leftIndex; uint32 rightIndex; prNode cur = prRootGetiNode(Root, x); prNode left = prNodeNull; prNode right = prNodeNull; prNode best; utDo { best = cur; leftIndex = (x << 1) + 1; rightIndex = leftIndex + 1; if(leftIndex < prRootGetUsedNode(Root)) { left = prRootGetiNode(Root, leftIndex); if(prRootCompareNode(best, left) > 0) { best = left; } if(rightIndex < prRootGetUsedNode(Root)) { right = prRootGetiNode(Root, rightIndex); if(prRootCompareNode(best, right) > 0) { best = right; } } } } utWhile(best != cur) { if(best == left) { prRootSwapNode(Root, x, leftIndex); x = leftIndex; } else { prRootSwapNode(Root, x, rightIndex); x = rightIndex; } } utRepeat; } static void prRootHeapUpNode( prRoot Root, uint32 arg_x) { uint32 x = arg_x; prNode cur = prRootGetiNode(Root, x); uint32 parentIndex; utDo { parentIndex = (x-1) >> 1; } utWhile(x > 0 && prRootCompareNode(prRootGetiNode(Root, parentIndex), cur) > 0) { prRootSwapNode(Root, parentIndex, x); x = parentIndex; } utRepeat prRootHeapDownNode(Root, x); } void prRootPushNode( prRoot Root, prNode Node) { uint32 index = prRootGetUsedNode(Root); prRootAppendNode(Root, Node); prRootHeapUpNode(Root, index); } prNode prRootPeekNode( prRoot Root) { if(prRootGetUsedNode(Root) == 0) { return prNodeNull; } return prRootGetiNode(Root, 0); } prNode prRootPopNode( prRoot Root) { prNode cur; prNode retval = prRootPeekNode(Root); uint32 newNum = prRootGetUsedNode(Root) - 1; if(retval == prNodeNull) { return retval; } if(newNum == 0) { prRootRemoveNode(Root, retval); prRootSetUsedNode(Root, 0); return retval; } prRootRemoveNode(Root, retval); cur = prRootGetiNode(Root, newNum); prRootRemoveNode(Root, cur); prRootInsertNode(Root, 0, cur); prRootSetUsedNode(Root, newNum); prRootHeapDownNode(Root, 0); return retval; } void prRootImproveNode( prNode Node) { prRoot Root = prNodeGetRoot(Node); uint32 _index = prNodeGetRootIndex(Node); prRootHeapUpNode(Root, _index); } #if defined(DD_DEBUG) /*---------------------------------------------------------------------------------------- Write out all the fields of an object. ----------------------------------------------------------------------------------------*/ void prShowRoot( prRoot Root) { utDatabaseShowObject("pr", "Root", prRoot2Index(Root)); } #endif /*---------------------------------------------------------------------------------------- Destroy Node including everything in it. Remove from parents. ----------------------------------------------------------------------------------------*/ void prNodeDestroy( prNode Node) { prRoot owningRoot = prNodeGetRoot(Node); if(prNodeDestructorCallback != NULL) { prNodeDestructorCallback(Node); } if(owningRoot != prRootNull) { prRootRemoveNode(owningRoot, Node); } prNodeFree(Node); } /*---------------------------------------------------------------------------------------- Default constructor wrapper for the database manager. ----------------------------------------------------------------------------------------*/ static uint64 allocNode(void) { prNode Node = prNodeAlloc(); return prNode2Index(Node); } /*---------------------------------------------------------------------------------------- Destructor wrapper for the database manager. ----------------------------------------------------------------------------------------*/ static void destroyNode( uint64 objectIndex) { prNodeDestroy(prIndex2Node((uint32)objectIndex)); } /*---------------------------------------------------------------------------------------- Allocate the field arrays of Node. ----------------------------------------------------------------------------------------*/ static void allocNodes(void) { prSetAllocatedNode(2); prSetUsedNode(0); prSetFirstFreeNode(prNodeNull); prNodes.Sym = utNewA(utSym, (prAllocatedNode())); prNodes.Root = utNewA(prRoot, (prAllocatedNode())); prNodes.RootIndex = utNewA(uint32, (prAllocatedNode())); prNodes.FreeList = utNewA(prNode, (prAllocatedNode())); } /*---------------------------------------------------------------------------------------- Realloc the arrays of properties for class Node. ----------------------------------------------------------------------------------------*/ static void reallocNodes( uint32 newSize) { utRecordResize(prModuleID, 5, (prAllocatedNode()), true); utResizeArray(prNodes.Sym, (newSize)); utRecordResize(prModuleID, 5, (newSize), false); utRecordResize(prModuleID, 6, (prAllocatedNode()), true); utResizeArray(prNodes.Root, (newSize)); utRecordResize(prModuleID, 6, (newSize), false); utRecordResize(prModuleID, 7, (prAllocatedNode()), true); utResizeArray(prNodes.RootIndex, (newSize)); utRecordResize(prModuleID, 7, (newSize), false); utRecordResize(prModuleID, 8, (prAllocatedNode()), true); utResizeArray(prNodes.FreeList, (newSize)); utRecordResize(prModuleID, 8, (newSize), false); prSetAllocatedNode(newSize); } /*---------------------------------------------------------------------------------------- Allocate more Nodes. ----------------------------------------------------------------------------------------*/ void prNodeAllocMore(void) { reallocNodes((uint32)(prAllocatedNode() + (prAllocatedNode() >> 1))); } /*---------------------------------------------------------------------------------------- Copy the properties of Node. ----------------------------------------------------------------------------------------*/ void prNodeCopyProps( prNode prOldNode, prNode prNewNode) { prNodeSetSym(prNewNode, prNodeGetSym(prOldNode)); } #if defined(DD_DEBUG) /*---------------------------------------------------------------------------------------- Write out all the fields of an object. ----------------------------------------------------------------------------------------*/ void prShowNode( prNode Node) { utDatabaseShowObject("pr", "Node", prNode2Index(Node)); } #endif /*---------------------------------------------------------------------------------------- Free memory used by the pr database. ----------------------------------------------------------------------------------------*/ void prDatabaseStop(void) { utFree(prRoots.NodeIndex); utFree(prRoots.NumNode); utFree(prRoots.Node); utFree(prRoots.UsedNode); utFree(prRoots.FreeList); utFree(prNodes.Sym); utFree(prNodes.Root); utFree(prNodes.RootIndex); utFree(prNodes.FreeList); utUnregisterModule(prModuleID); } /*---------------------------------------------------------------------------------------- Allocate memory used by the pr database. ----------------------------------------------------------------------------------------*/ void prDatabaseStart(void) { if(!utInitialized()) { utStart(); } prRootData.hash = 0xcb3f8d4b; prModuleID = utRegisterModule("pr", prHash(), 2, 9, 0, sizeof(struct prRootType_), &prRootData, prDatabaseStart, prDatabaseStop); utRegisterClass("Root", 5, &prRootData.usedRoot, &prRootData.allocatedRoot, NULL, 4, 1, allocRoot, NULL); utRegisterField("NodeIndex", &prRoots.NodeIndex, sizeof(uint32), UT_UINT, NULL); utSetFieldHidden(); utRegisterField("NumNode", &prRoots.NumNode, sizeof(uint32), UT_UINT, NULL); utSetFieldHidden(); utRegisterField("Node", &prRoots.Node, sizeof(prNode), UT_POINTER, "Node"); utRegisterArray(&prRootData.usedRootNode, &prRootData.allocatedRootNode, getRootNodes, allocRootNodes); utRegisterField("UsedNode", &prRoots.UsedNode, sizeof(uint32), UT_UINT, NULL); utRegisterField("FreeList", &prRoots.FreeList, sizeof(prRoot), UT_POINTER, "Root"); utSetFieldHidden(); utRegisterClass("Node", 4, &prRootData.usedNode, &prRootData.allocatedNode, &prRootData.firstFreeNode, 8, 4, allocNode, destroyNode); utRegisterField("Sym", &prNodes.Sym, sizeof(utSym), UT_SYM, NULL); utRegisterField("Root", &prNodes.Root, sizeof(prRoot), UT_POINTER, "Root"); utRegisterField("RootIndex", &prNodes.RootIndex, sizeof(uint32), UT_UINT, NULL); utRegisterField("FreeList", &prNodes.FreeList, sizeof(prNode), UT_POINTER, "Node"); utSetFieldHidden(); allocRoots(); allocNodes(); } #if defined(DD_DEBUG) #undef prRootGetNodeIndex uint32 prRootGetNodeIndex( prRoot _Root) { return prRoots.NodeIndex[prRoot2Index(_Root)]; } #undef prRootSetNodeIndex void prRootSetNodeIndex( prRoot _Root, uint32 value) { prRoots.NodeIndex[prRoot2Index(_Root)] = value; } #undef prRootGetNumNode uint32 prRootGetNumNode( prRoot _Root) { return prRoots.NumNode[prRoot2Index(_Root)]; } #undef prRootSetNumNode void prRootSetNumNode( prRoot _Root, uint32 value) { prRoots.NumNode[prRoot2Index(_Root)] = value; } #undef prRootGetiNode prNode prRootGetiNode( prRoot _Root, uint32 x) { return (prRoots.Node)[prRootGetNodeIndex(_Root) + x]; } #undef prRootGetNodes prNode *prRootGetNodes( prRoot Root) { return prRoots.Node + prRootGetNodeIndex(Root); } #undef prRootSetiNode void prRootSetiNode( prRoot Root, uint32 x, prNode value) { prRoots.Node[prRootGetNodeIndex(Root) + x] = value; } #undef prRootGetUsedNode uint32 prRootGetUsedNode( prRoot _Root) { return prRoots.UsedNode[prRoot2Index(_Root)]; } #undef prRootSetUsedNode void prRootSetUsedNode( prRoot _Root, uint32 value) { prRoots.UsedNode[prRoot2Index(_Root)] = value; } #undef prRootGetFreeList prRoot prRootGetFreeList( prRoot _Root) { return prRoots.FreeList[prRoot2Index(_Root)]; } #undef prRootSetFreeList void prRootSetFreeList( prRoot _Root, prRoot value) { prRoots.FreeList[prRoot2Index(_Root)] = value; } #undef prNodeGetSym utSym prNodeGetSym( prNode _Node) { return prNodes.Sym[prNode2Index(_Node)]; } #undef prNodeSetSym void prNodeSetSym( prNode _Node, utSym value) { prNodes.Sym[prNode2Index(_Node)] = value; } #undef prNodeGetRoot prRoot prNodeGetRoot( prNode _Node) { return prNodes.Root[prNode2Index(_Node)]; } #undef prNodeSetRoot void prNodeSetRoot( prNode _Node, prRoot value) { prNodes.Root[prNode2Index(_Node)] = value; } #undef prNodeGetRootIndex uint32 prNodeGetRootIndex( prNode _Node) { return prNodes.RootIndex[prNode2Index(_Node)]; } #undef prNodeSetRootIndex void prNodeSetRootIndex( prNode _Node, uint32 value) { prNodes.RootIndex[prNode2Index(_Node)] = value; } #undef prNodeGetFreeList prNode prNodeGetFreeList( prNode _Node) { return prNodes.FreeList[prNode2Index(_Node)]; } #undef prNodeSetFreeList void prNodeSetFreeList( prNode _Node, prNode value) { prNodes.FreeList[prNode2Index(_Node)] = value; } #endif