예제 #1
0
 public HeapTreeLeaf(TreeSystemTransaction transaction, NodeId nodeId, int maxCapacity)
 {
     this.nodeId      = nodeId;
     size             = 0;
     this.transaction = transaction;
     data             = new byte[maxCapacity];
 }
예제 #2
0
        public TreeBranch CreateBranch(TreeSystemTransaction tran, int maxBranchChildren)
        {
            NodeId         p    = NextNodePointer();
            HeapTreeBranch node = new HeapTreeBranch(tran, p, maxBranchChildren);

            PutInHash(node);
            return(node);
        }
예제 #3
0
        public TreeLeaf CreateLeaf(TreeSystemTransaction tran, Key key, int maxLeafSize)
        {
            NodeId       p    = NextNodePointer();
            HeapTreeLeaf node = new HeapTreeLeaf(tran, p, maxLeafSize);

            PutInHash(node);
            return(node);
        }
예제 #4
0
 public HeapTreeLeaf(TreeSystemTransaction transaction, NodeId nodeId, TreeLeaf toCopy, int capacity)
 {
     this.nodeId      = nodeId;
     size             = toCopy.Length;
     this.transaction = transaction;
     // Copy the data into an array in this leaf.
     data = new byte[capacity];
     toCopy.Read(0, data, 0, size);
 }
예제 #5
0
 public TreeSystemStack(TreeSystemTransaction ts)
 {
     this.ts        = ts;
     stackSize      = 0;
     stack          = new long[StackFrameSize * 13];
     currentLeaf    = null;
     currentLeafKey = null;
     leafOffset     = 0;
 }
예제 #6
0
        public void Commit(ITransaction tran)
        {
            CheckErrorState();
            try {
                TreeSystemTransaction transaction = (TreeSystemTransaction)tran;
                VersionInfo           topVersion;
                lock (versions) {
                    topVersion = versions[versions.Count - 1];
                }
                // Check the version is based on the must current transaction,
                if (transaction.VersionId != topVersion.VersionId)
                {
                    // ID not the same as the top version, so throw the exception
                    throw new ApplicationException("Can't commit non-sequential version.");
                }

                // Make sure the transaction is written to the store,
                // NOTE: This MUST happen outside a node store lock otherwise checking
                //   out on the cache manage function could lock up the thread
                transaction.Checkout();

                try {
                    nodeStore.LockForWrite();

                    // The new version number,
                    long newVersionNum = topVersion.VersionId + 1;

                    // Write out the versions list to the store,
                    long versionRecordId = WriteVersionsList(newVersionNum, transaction);
                    // Create a new VersionInfo object with a new id,
                    VersionInfo newVinfo = new VersionInfo(newVersionNum,
                                                           transaction.RootNodeId,
                                                           versionRecordId);
                    lock (versions) {
                        // Add this version to the end of the versions list,
                        versions.Add(newVinfo);
                    }
                } finally {
                    nodeStore.UnlockForWrite();
                }

                // Notify the transaction is committed,
                // This will stop the transaction from cleaning up newly added nodes.
                transaction.OnCommitted();
            } catch (IOException e) {
                // An IOException during this block represents a critical stopping
                // condition.
                throw SetErrorState(e);
            } catch (OutOfMemoryException e) {
                // An out-of-memory error represents a critical state that causes
                // immediate cleanup.
                throw SetErrorState(e);
            }
        }
예제 #7
0
            internal DataRange(TreeSystemTransaction transaction, Key lowerKey, Key upperKey)
            {
                stack            = new TreeSystemStack(transaction);
                this.lowerKey    = transaction.PreviousKeyOrder(lowerKey);
                this.transaction = transaction;
                this.upperKey    = upperKey;
                p = 0;

                version = -1;
                start   = -1;
                end     = -1;
            }
            internal DataFile(TreeSystemTransaction transaction, Key key, bool fileReadOnly)
            {
                stack            = new TreeSystemStack(transaction);
                this.transaction = transaction;
                this.key         = key;
                p = 0;

                version           = -1;
                this.fileReadOnly = fileReadOnly;
                start             = -1;
                end = -1;
            }
예제 #9
0
 public void Dispose(ITransaction tran)
 {
     CheckErrorState();
     try {
         TreeSystemTransaction transaction = (TreeSystemTransaction)tran;
         // Get the version id of the transaction,
         long versionId = transaction.VersionId;
         // Call the dispose method,
         transaction.Dispose();
         // Reduce the lock count for this version id,
         UnlockTransaction(versionId);
         // Check if we can clear up old versions,
         DisposeOldVersions();
     } catch (IOException e) {
         // An IOException during this block represents a critical stopping
         // condition.
         throw SetErrorState(e);
     } catch (OutOfMemoryException e) {
         // An out-of-memory error represents a critical state that causes
         // immediate cleanup.
         throw SetErrorState(e);
     }
 }
예제 #10
0
 public HeapTreeBranch(TreeSystemTransaction transaction, NodeId nodeId, TreeBranch branch, int maxChildrenCount)
     : base(nodeId, branch, maxChildrenCount)
 {
     this.transaction = transaction;
 }
예제 #11
0
        internal void FlushCache()
        {
            IList <IHashNode> toFlush = null;

            // If the memory use is above some limit then we need to flush out some
            // of the nodes,
            if (memoryUsed > maxMemoryLimit)
            {
                int allNodeCount = totalBranchNodeCount + totalLeafNodeCount;
                // The number to clean,
                int toClean = (int)(allNodeCount * 0.30);

                // Make an array of all nodes to flush,
                toFlush = new List <IHashNode>(toClean);
                // Pull them from the back of the list,
                IHashNode node = hashEnd;
                while (toClean > 0 && node != null)
                {
                    toFlush.Add(node);
                    node = node.Previous;
                    --toClean;
                }
            }

            // If there are nodes to flush,
            if (toFlush != null)
            {
                // Read each group and call the node flush routine,

                // The mapping of transaction to node list
                Dictionary <TreeSystemTransaction, List <NodeId> > tranMap = new Dictionary <TreeSystemTransaction, List <NodeId> >();
                // Read the list backwards,
                for (int i = toFlush.Count - 1; i >= 0; --i)
                {
                    IHashNode node = toFlush[i];
                    // Get the transaction of this node,
                    TreeSystemTransaction tran = node.Transaction;
                    // Find the list of this transaction,
                    List <NodeId> nodeList = tranMap[tran];
                    if (nodeList == null)
                    {
                        nodeList = new List <NodeId>(toFlush.Count);
                        tranMap.Add(tran, nodeList);
                    }
                    // Add to the list
                    nodeList.Add(node.Id);
                }

                // Now read the key and dispatch the clean up to the transaction objects,
                foreach (KeyValuePair <TreeSystemTransaction, List <NodeId> > pair in tranMap)
                {
                    TreeSystemTransaction tran     = pair.Key;
                    List <NodeId>         nodeList = pair.Value;
                    // Convert to a 'NodeId[]' array,
                    NodeId[] refs = nodeList.ToArray();

                    // Sort the references,
                    Array.Sort(refs);

                    // Tell the transaction to clean up these nodes,
                    tran.FlushNodesToStore(refs);
                }
            }
        }
예제 #12
0
        public ITreeNode Copy(ITreeNode nodeToCopy, int maxBranchSize, int maxLeafSize, TreeSystemTransaction tran)
        {
            // Create a new pointer for the copy
            NodeId    p = NextNodePointer();
            IHashNode node;

            if (nodeToCopy is TreeLeaf)
            {
                node = new HeapTreeLeaf(tran, p, (TreeLeaf)nodeToCopy, maxLeafSize);
            }
            else
            {
                node = new HeapTreeBranch(tran, p, (TreeBranch)nodeToCopy, maxBranchSize);
            }
            PutInHash(node);
            // Return pointer to node
            return(node);
        }
예제 #13
0
 public PlaceholderLeaf(TreeSystemTransaction ts, NodeId nodeId, int size)
 {
     this.ts     = ts;
     this.nodeId = nodeId;
     this.size   = size;
 }
예제 #14
0
        private long WriteVersionsList(long versionId, TreeSystemTransaction tran)
        {
            lock (this) {
                // Write the version info and the deleted refs to a new area,
                NodeId rootNodeId = tran.RootNodeId;
                if (rootNodeId.IsInMemory)
                {
                    throw new ApplicationException("Assertion failed, root_node is on heap.");
                }

                // Get the list of all nodes deleted in the transaction
                List <NodeId> deletedRefs = tran.NodeDeletes;
                // Sort it
                deletedRefs.Sort();
                // Check for any duplicate entries (we shouldn't double delete stuff).
                for (int i = 1; i < deletedRefs.Count; ++i)
                {
                    if (deletedRefs[i - 1].Equals(deletedRefs[i]))
                    {
                        // Oops, duplicated delete
                        throw new ApplicationException("PRAGMATIC_CHECK failed: duplicate records in delete list.");
                    }
                }


                long theVersionId = WriteSingleVersionInfo(versionId, rootNodeId, deletedRefs);

                // Now update the version list by copying the list and adding the new ref
                // to the end.

                // Get the current version list
                IMutableArea headerArea = nodeStore.GetMutableArea(headerId);
                headerArea.Position = 8;

                long versionListId = headerArea.ReadInt8();

                // Read information from the old version info,
                IArea versionListArea = nodeStore.GetArea(versionListId);
                versionListArea.ReadInt4();                 // The magic
                int versionCount = versionListArea.ReadInt4();

                // Create a new list,
                IAreaWriter newVersionList = nodeStore.CreateArea(8 + (8 * (versionCount + 1)));
                newVersionList.WriteInt4(0x01433);
                newVersionList.WriteInt4(versionCount + 1);
                for (int i = 0; i < versionCount; ++i)
                {
                    newVersionList.WriteInt8(versionListArea.ReadInt8());
                }
                newVersionList.WriteInt8(theVersionId);
                newVersionList.Finish();

                // Write the new area to the header,
                headerArea.Position = 8;
                headerArea.WriteInt8(newVersionList.Id);

                // Delete the old version list Area,
                nodeStore.DeleteArea(versionListId);

                // Done,
                return(theVersionId);
            }
        }