예제 #1
0
        internal NodeId WriteNode(NodeId nodeId)
        {
            // Create the sequence,
            TreeWrite sequence = new TreeWrite();
            // Create the command sequence to write this tree out,
            int rootId = PopulateSequence(nodeId, sequence);

            if (rootId != -1) {
                // Write out this sequence,
                IList<NodeId> refs = treeStore.Persist(sequence);

                // Update internal structure for each node written,
                IList<ITreeNode> nodes = sequence.BranchNodes;
                int sz = nodes.Count;
                for (int i = 0; i < sz; ++i) {
                    WrittenNode(nodes[i], refs[i]);
                }
                int bnodesSz = sz;
                nodes = sequence.LeafNodes;
                sz = nodes.Count;
                for (int i = 0; i < sz; ++i) {
                    WrittenNode(nodes[i], refs[i + bnodesSz]);
                }

                // Normalize the pointer,
                if (rootId >= TreeWrite.BranchPoint) {
                    rootId = rootId - TreeWrite.BranchPoint;
                } else {
                    rootId = rootId + bnodesSz;
                }

                // Return a reference to the node written,
                return refs[rootId];
            }
            return nodeId;
        }
예제 #2
0
        private int PopulateSequence(NodeId id, TreeWrite sequence)
        {
            // If it's not a heap node, return
            if (!IsHeapNode(id))
                return -1;

            // It is a heap node, so fetch
            ITreeNode node = FetchNode(id);
            // Is it a leaf or a branch?
            if (node is TreeLeaf)
                // If it's a leaf, simply write it out
                return sequence.NodeWrite(node);

            if (node is TreeBranch) {
                // This is a branch,
                // Sequence this branch to be written out,
                int branchId = sequence.NodeWrite(node);
                // For each child in the branch,
                TreeBranch branch = (TreeBranch) node;
                int sz = branch.ChildCount;
                for (int i = 0; i < sz; ++i) {
                    NodeId child = branch.GetChild(i);
                    // Sequence the child
                    int childId = PopulateSequence(child, sequence);
                    // If something could be sequenced in the child,
                    if (childId != -1) {
                        // Make the branch command,
                        sequence.BranchLink(branchId, i, childId);
                    }
                }
                // Return the id of the branch in the sequence,
                return branchId;
            } else {
                throw new ApplicationException("Unknown node type.");
            }
        }
예제 #3
0
        public IList<long> Persist(TreeWrite write)
        {
            try {
                store.LockForWrite();

                IList<ITreeNode> branches = write.BranchNodes;
                IList<ITreeNode> leafs = write.LeafNodes;
                List<ITreeNode> nodes = new List<ITreeNode>(branches.Count + leafs.Count);
                nodes.AddRange(branches);
                nodes.AddRange(leafs);

                // The list of nodes to be allocated,
                int sz = nodes.Count;
                // The list of allocated referenced for the nodes,
                long[] refs = new long[sz];
                // The list of area writers,
                IAreaWriter[] areas = new IAreaWriter[sz];

                // Allocate the space first,
                for (int i = 0; i < sz; ++i) {
                    ITreeNode node = nodes[i];
                    if (node is TreeBranch) {
                        TreeBranch branch = (TreeBranch)node;
                        int ndsz = branch.DataSize;
                        areas[i] = store.CreateArea(4 + 4 + (ndsz * 8));
                    } else {
                        TreeLeaf leaf = (TreeLeaf)node;
                        int lfsz = leaf.Length;
                        areas[i] = store.CreateArea(12 + lfsz);
                    }
                    // Set the reference,
                    refs[i] = areas[i].Id;
                }

                // Now write out the data,
                for (int i = 0; i < sz; ++i) {
                    ITreeNode node = nodes[i];
                    // Is it a branch node?
                    if (node is TreeBranch) {
                        TreeBranch branch = (TreeBranch)node;

                        // The number of children
                        int chsz = branch.ChildCount;
                        // For each child, if it's a heap node, look up the child id and
                        // reference map in the sequence and set the reference accordingly,
                        for (int o = 0; o < chsz; ++o) {
                            long childId = branch.GetChild(o);
                            if (childId < 0) {
                                // The ref is currently on the heap, so adjust accordingly
                                int refId = write.LookupRef(i, o);
                                branch.SetChild(o, refs[refId]);
                            }
                        }

                        // Write out the branch to the store
                        long[] nodeData = branch.ChildPointers;
                        int ndsz = branch.DataSize;

                        IAreaWriter writer = areas[i];
                        writer.WriteInt2(BranchType);
                        writer.WriteInt2(1);  // version
                        writer.WriteInt4(ndsz);
                        for (int o = 0; o < ndsz; ++o) {
                            writer.WriteInt8(nodeData[o]);
                        }
                        writer.Finish();

                        // Make this into a branch node and add to the cache,
                        branch = new TreeBranch(refs[i], nodeData, ndsz);
                        // Put this branch in the cache,
                        lock (branchCache) {
                            branchCache.Set(refs[i], branch);
                        }
                    } else {
                        // Otherwise, it must be a leaf node,
                        TreeLeaf leaf = (TreeLeaf)node;

                        IAreaWriter area = areas[i];
                        area.WriteInt2(LeafType);
                        area.WriteInt2(1);  // version
                        area.WriteInt4(1);            // reference count
                        area.WriteInt4(leaf.Length);
                        leaf.WriteTo(area);
                        area.Finish();
                    }
                }

                return refs;
            } finally {
                store.UnlockForWrite();
            }
        }
예제 #4
0
        public long Create()
        {
            if (initialized)
                throw new ApplicationException("This tree store is already initialized.");

            // Temporary node heap for creating a starting database
            TreeNodeHeap nodeHeap = new TreeNodeHeap(17, 4 * 1024 * 1024);

            // Write a root node to the store,
            // Create an empty head node
            TreeLeaf headLeaf = nodeHeap.CreateLeaf(null, Key.Head, 256);
            // Insert a tree identification pattern
            headLeaf.Write(0, new byte[] { 1, 1, 1, 1 }, 0, 4);
            // Create an empty tail node
            TreeLeaf tailLeaf = nodeHeap.CreateLeaf(null, Key.Tail, 256);
            // Insert a tree identification pattern
            tailLeaf.Write(0, new byte[] { 1, 1, 1, 1 }, 0, 4);

            // The write sequence,
            TreeWrite treeWrite = new TreeWrite();
            treeWrite.NodeWrite(headLeaf);
            treeWrite.NodeWrite(tailLeaf);
            IList<long> refs = Persist(treeWrite);

            // Create a branch,
            TreeBranch rootBranch = nodeHeap.CreateBranch(null, MaxBranchSize);
            rootBranch.Set(refs[0], 4,
                           Key.Tail.GetEncoded(1),
                           Key.Tail.GetEncoded(2),
                           refs[1], 4);

            treeWrite = new TreeWrite();
            treeWrite.NodeWrite(rootBranch);
            refs = Persist(treeWrite);

            // The written root node reference,
            long rootId = refs[0];

            // Delete the head and tail leaf, and the root branch
            nodeHeap.Delete(headLeaf.Id);
            nodeHeap.Delete(tailLeaf.Id);
            nodeHeap.Delete(rootBranch.Id);

            // Write this version info to the store,
            long versionId = WriteVersionInfo(1, rootId, new List<long>(0));

            // Make a first version
            versions.Add(new VersionInfo(1, rootId, versionId));

            // Flush this to the version list
            IAreaWriter verListArea = store.CreateArea(64);
            verListArea.WriteInt4(0x01433);
            verListArea.WriteInt4(1);
            verListArea.WriteInt8(versionId);
            verListArea.Finish();
            // Get the versions id
            long versionListId = verListArea.Id;

            // The final header
            IAreaWriter header = store.CreateArea(64);
            header.WriteInt4(0x09391);   // The magic value,
            header.WriteInt4(1);         // The version
            header.WriteInt8(versionListId);
            header.Finish();

            // Set up the internal variables,
            headerId = header.Id;

            initialized = true;
            // And return the header reference
            return headerId;
        }
예제 #5
0
        public IList <NodeId> Persist(TreeWrite write)
        {
            try {
                nodeStore.LockForWrite();

                IList <ITreeNode> allBranches = write.BranchNodes;
                IList <ITreeNode> allLeafs    = write.LeafNodes;
                List <ITreeNode>  nodes       = new List <ITreeNode>(allBranches.Count + allLeafs.Count);
                nodes.AddRange(allBranches);
                nodes.AddRange(allLeafs);

                // The list of nodes to be allocated,
                int sz = nodes.Count;
                // The list of allocated referenced for the nodes,
                NodeId[] refs = new NodeId[sz];
                // The list of area writers,
                IAreaWriter[] writers = new IAreaWriter[sz];

                // Allocate the space first,
                for (int i = 0; i < sz; ++i)
                {
                    ITreeNode node = nodes[i];
                    // Is it a branch node?
                    if (node is TreeBranch)
                    {
                        TreeBranch branch = (TreeBranch)node;
                        int        ndsz   = branch.NodeDataSize;
                        writers[i] = nodeStore.CreateArea(4 + 4 + (ndsz * 8));
                    }
                    // Otherwise, it must be a leaf node,
                    else
                    {
                        TreeLeaf leaf = (TreeLeaf)node;
                        int      lfsz = leaf.Length;
                        writers[i] = nodeStore.CreateArea(12 + lfsz);
                    }
                    // Set the reference,
                    refs[i] = FromInt64StoreAddress(writers[i].Id);
                }

                // Now write out the data,
                for (int i = 0; i < sz; ++i)
                {
                    ITreeNode node = nodes[i];
                    // Is it a branch node?
                    if (node is TreeBranch)
                    {
                        TreeBranch branch = (TreeBranch)node;

                        // The number of children
                        int chsz = branch.ChildCount;
                        // For each child, if it's a heap node, look up the child id and
                        // reference map in the sequence and set the reference accordingly,
                        for (int o = 0; o < chsz; ++o)
                        {
                            NodeId childId = branch.GetChild(o);
                            if (childId.IsInMemory)
                            {
                                // The ref is currently on the heap, so adjust accordingly
                                int refId = write.LookupRef(i, o);
                                branch.SetChild(refs[refId], o);
                            }
                        }

                        // Write out the branch to the store
                        long[] nodeData = branch.NodeData;
                        int    ndsz     = branch.NodeDataSize;

                        IAreaWriter writer = writers[i];
                        writer.WriteInt2(StoreBranchType);
                        writer.WriteInt2(1);                         // version
                        writer.WriteInt4(ndsz);
                        for (int o = 0; o < ndsz; ++o)
                        {
                            writer.WriteInt8(nodeData[o]);
                        }
                        writer.Finish();

                        // Make this into a branch node and add to the cache,
                        branch = new TreeBranch(refs[i], nodeData, ndsz);
                        // Put this branch in the cache,
                        lock (branchCache) {
                            branchCache.Set(refs[i], branch);
                        }
                    }
                    // Otherwise, it must be a leaf node,
                    else
                    {
                        TreeLeaf    leaf   = (TreeLeaf)node;
                        IAreaWriter writer = writers[i];
                        writer.WriteInt2(StoreLeafType);
                        writer.WriteInt2(1);                         // version
                        writer.WriteInt4(1);                         // reference count
                        writer.WriteInt4(leaf.Length);
                        leaf.WriteTo(writer);
                        writer.Finish();
                    }
                }

                return(refs);
            } finally {
                nodeStore.UnlockForWrite();
            }
        }
예제 #6
0
        public long Create()
        {
            if (initialized)
            {
                throw new InvalidOperationException("This tree store is already initialized.");
            }

            // Temporary node heap for creating a starting database
            TreeNodeHeap nodeHeap = new TreeNodeHeap(17, 4 * 1024 * 1024);

            // Write a root node to the store,
            // Create an empty head node
            TreeLeaf headLeaf = nodeHeap.CreateLeaf(null, Key.Head, 256);

            // Insert a tree identification pattern
            headLeaf.Write(0, new byte[] { 1, 1, 1, 1 }, 0, 4);
            // Create an empty tail node
            TreeLeaf tailLeaf = nodeHeap.CreateLeaf(null, Key.Tail, 256);

            // Insert a tree identification pattern
            tailLeaf.Write(0, new byte[] { 1, 1, 1, 1 }, 0, 4);

            // The write sequence,
            TreeWrite seq = new TreeWrite();

            seq.NodeWrite(headLeaf);
            seq.NodeWrite(tailLeaf);
            IList <NodeId> refs = Persist(seq);

            // Create a branch,
            TreeBranch rootBranch = nodeHeap.CreateBranch(null, MaxBranchSize);

            rootBranch.Set(refs[0], 4, Key.Tail, refs[1], 4);

            seq = new TreeWrite();
            seq.NodeWrite(rootBranch);
            refs = Persist(seq);

            // The written root node reference,
            NodeId rootId = refs[0];

            // Delete the head and tail leaf, and the root branch
            nodeHeap.Delete(headLeaf.Id);
            nodeHeap.Delete(tailLeaf.Id);
            nodeHeap.Delete(rootBranch.Id);

            // Write this version info to the store,
            long versionId = WriteSingleVersionInfo(1, rootId, new List <NodeId>(0));

            // Make a first version
            VersionInfo versionInfo = new VersionInfo(1, rootId, versionId);

            versions.Add(versionInfo);

            // Flush this to the version list
            IAreaWriter versionList = nodeStore.CreateArea(64);

            versionList.WriteInt4(0x01433);
            versionList.WriteInt4(1);
            versionList.WriteInt8(versionId);
            versionList.Finish();

            // Get the versions id
            long versionListId = versionList.Id;

            // The final header
            IAreaWriter header = nodeStore.CreateArea(64);

            header.WriteInt4(0x09391);       // The magic value,
            header.WriteInt4(1);             // The version
            header.WriteInt8(versionListId);
            header.Finish();

            // Set up the internal variables,
            headerId = header.Id;

            initialized = true;
            // And return the header reference
            return(headerId);
        }