Пример #1
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();
            }
        }