/// <param name="subnodeBTree">Note: We use ref, this way we are able to create a new subnode BTree and update the subnodeBTree the caller provided</param>
        /// <param name="heapOrNodeID">Existing HeapOrNodeID</param>
        public static HeapOrNodeID StoreExternalProperty(PSTFile file, HeapOnNode heap, ref SubnodeBTree subnodeBTree, HeapOrNodeID heapOrNodeID, byte[] propertyBytes)
        {
            // We should avoid storing items with length of 0, because those are consideref freed, and could be repurposed
            if (propertyBytes.Length == 0)
            {
                RemoveExternalProperty(heap, subnodeBTree, heapOrNodeID);
                return(new HeapOrNodeID(HeapID.EmptyHeapID));
            }

            if (heapOrNodeID.IsHeapID) // if HeapOrNodeID is empty then IsHeapID == true
            {
                if (propertyBytes.Length <= HeapOnNode.MaximumAllocationLength)
                {
                    if (heapOrNodeID.IsEmpty)
                    {
                        return(new HeapOrNodeID(heap.AddItemToHeap(propertyBytes)));
                    }
                    else
                    {
                        return(new HeapOrNodeID(heap.ReplaceHeapItem(heapOrNodeID.HeapID, propertyBytes)));
                    }
                }
                else // old data (if exist) is stored on heap, but new data needs a subnode
                {
                    if (!heapOrNodeID.IsEmpty)
                    {
                        heap.RemoveItemFromHeap(heapOrNodeID.HeapID);
                    }

                    if (subnodeBTree == null)
                    {
                        subnodeBTree = new SubnodeBTree(file);
                    }
                    DataTree dataTree = new DataTree(file);
                    dataTree.AppendData(propertyBytes);
                    dataTree.SaveChanges();

                    NodeID subnodeID = file.Header.AllocateNextNodeID(NodeTypeName.NID_TYPE_LTP);
                    subnodeBTree.InsertSubnodeEntry(subnodeID, dataTree, null);

                    return(new HeapOrNodeID(subnodeID));
                }
            }
            else // old data is stored in a subnode
            {
                Subnode subnode = subnodeBTree.GetSubnode(heapOrNodeID.NodeID);
                if (subnode.DataTree != null)
                {
                    subnode.DataTree.Delete();
                }
                subnode.DataTree = new DataTree(subnodeBTree.File);
                subnode.DataTree.AppendData(propertyBytes);
                subnode.SaveChanges(subnodeBTree);
                return(new HeapOrNodeID(heapOrNodeID.NodeID));
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// The caller must update its reference to point to the new data tree and subnode B-tree
        /// </summary>
        public void SaveChanges()
        {
            if (m_subnodeRows != null)
            {
                m_subnodeRows.SaveChanges();
                m_subnodeBTree.UpdateSubnodeEntry(m_tcInfo.hnidRows.NodeID, m_subnodeRows.DataTree, m_subnodeRows.SubnodeBTree);
            }

            m_heap.SaveChanges();
            if (m_subnodeBTree != null)
            {
                m_subnodeBTree.SaveChanges();
            }
        }