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; }
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."); } }
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(); } }
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; }
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(); } }
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); }