public static byte[] GetExternalPropertyBytes(HeapOnNode heap, SubnodeBTree subnodeBTree, HeapOrNodeID heapOrNodeID)
 {
     if (heapOrNodeID.IsEmpty)
     {
         return(new byte[0]);
     }
     else if (heapOrNodeID.IsHeapID)
     {
         byte[] result = heap.GetHeapItem(heapOrNodeID.HeapID);
         return(result);
     }
     else
     {
         // indicates that the item is stored in the subnode block, and the NID is the local NID under the subnode
         Subnode subnode = subnodeBTree.GetSubnode(heapOrNodeID.NodeID);
         if (subnode != null)
         {
             if (subnode.DataTree == null)
             {
                 return(new byte[0]);
             }
             else
             {
                 return(subnode.DataTree.GetData());
             }
         }
         else
         {
             throw new MissingSubnodeException();
         }
     }
 }
Esempio n. 2
0
        // We no longer create new TCs, we simply use the template and modify to another data tree
        public static TableContext CreateNewTableContext(PSTFile file, List <TableColumnDescriptor> columns)
        {
            HeapOnNode heap = HeapOnNode.CreateNewHeap(file);

            TableContextInfo tcInfo = new TableContextInfo();

            tcInfo.rgTCOLDESC = columns;
            tcInfo.UpdateDataLayout();

            HeapID newUserRoot = heap.AddItemToHeap(tcInfo.GetBytes());
            // The heap header may have just been updated
            HeapOnNodeHeader header = heap.HeapHeader;

            header.bClientSig  = OnHeapTypeName.bTypeTC;
            header.hidUserRoot = newUserRoot;
            heap.UpdateHeapHeader(header);

            BTreeOnHeapHeader bTreeHeader = new BTreeOnHeapHeader();

            bTreeHeader.cbKey = TableContextRowID.RecordKeyLength;
            bTreeHeader.cbEnt = TableContextRowID.RecordDataLength;

            tcInfo.hidRowIndex = heap.AddItemToHeap(bTreeHeader.GetBytes());
            // this will replace the item in place (as they have the same size since number of columns was not modified)
            heap.ReplaceHeapItem(header.hidUserRoot, tcInfo.GetBytes());

            return(new TableContext(heap, null));
        }
Esempio n. 3
0
 public BTreeOnHeap(HeapOnNode heap, HeapID bTreeHeaderHeapID)
 {
     m_heap = heap;
     m_bTreeHeaderHeapID = bTreeHeaderHeapID;
     byte[] headerBytes = m_heap.GetHeapItem(bTreeHeaderHeapID);
     BTreeHeader = new BTreeOnHeapHeader(headerBytes);
 }
        /// <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));
            }
        }
Esempio n. 5
0
        public static HeapOnNode CreateNewHeap(PSTFile file)
        {
            DataTree dataTree = new DataTree(file);
            HeapOnNodeFirstBlockData blockData = new HeapOnNodeFirstBlockData();

            dataTree.UpdateDataBlock(0, blockData.GetBytes());
            // now the data tree contains a valid HN
            HeapOnNode heap = new HeapOnNode(dataTree);

            return(heap);
        }
Esempio n. 6
0
        private Subnode m_subnodeRows; // for buffering purposes

        public TableContext(HeapOnNode heap, SubnodeBTree subnodeBTree)
        {
            m_heap         = heap;
            m_subnodeBTree = subnodeBTree;
            m_tcInfo       = new TableContextInfo(m_heap.GetHeapItem(m_heap.HeapHeader.hidUserRoot));

            BTreeOnHeap <TableContextRowID> bTreeOnHeap = new BTreeOnHeap <TableContextRowID>(m_heap, m_tcInfo.hidRowIndex);

            if (bTreeOnHeap.BTreeHeader.hidRoot.hidIndex > 0) // hidRoot is set to zero if the BTH is empty.
            {
                m_rowIndex = bTreeOnHeap.GetAll();
                m_rowIndex.Sort(TableContextRowID.CompareByRowIndex);
            }

            m_rowsPerBlock = (int)Math.Floor((double)DataBlock.MaximumDataLength / RowLength);
        }
 public static void RemoveExternalProperty(HeapOnNode heap, SubnodeBTree subnodeBTree, HeapOrNodeID heapOrNodeID)
 {
     if (!heapOrNodeID.IsEmpty)
     {
         if (heapOrNodeID.IsHeapID)
         {
             heap.RemoveItemFromHeap(heapOrNodeID.HeapID);
         }
         else
         {
             DataTree dataTree = subnodeBTree.GetSubnode(heapOrNodeID.NodeID).DataTree;
             dataTree.Delete();
             subnodeBTree.DeleteSubnodeEntry(heapOrNodeID.NodeID);
         }
     }
 }
        /// <param name="subnodeBTree">Subnode BTree that will be associated with the new PC</param>
        public static PropertyContext CreateNewPropertyContext(PSTFile file, SubnodeBTree subnodeBTree)
        {
            HeapOnNode heap = HeapOnNode.CreateNewHeap(file);

            BTreeOnHeapHeader bTreeHeader = new BTreeOnHeapHeader();

            bTreeHeader.cbKey = PropertyContextRecord.RecordKeyLength;
            bTreeHeader.cbEnt = PropertyContextRecord.RecordDataLength;

            HeapID newUserRoot = heap.AddItemToHeap(bTreeHeader.GetBytes());
            // The heap header may have just been updated
            HeapOnNodeHeader header = heap.HeapHeader;

            header.bClientSig  = OnHeapTypeName.bTypePC;
            header.hidUserRoot = newUserRoot;
            heap.UpdateHeapHeader(header);
            heap.FlushToDataTree();

            return(new PropertyContext(heap, subnodeBTree));
        }
 public RecipientsTable(HeapOnNode heap, SubnodeBTree subnodeBTree) : base(heap, subnodeBTree)
 {
 }
Esempio n. 10
0
 public NamedTableContext(HeapOnNode heap, SubnodeBTree subnodeBTree, PropertyNameToIDMap map)
     : base(heap, subnodeBTree)
 {
     m_map = map;
 }
Esempio n. 11
0
 public HierarchyTable(HeapOnNode heap, SubnodeBTree subnodeBTree) : base(heap, subnodeBTree)
 {
 }
Esempio n. 12
0
 public BTreeOnHeap(HeapOnNode heap) : this(heap, heap.HeapHeader.hidUserRoot)
 {
 }
 public PropertyContext(HeapOnNode heap, SubnodeBTree subnodeBTree) : base(heap)
 {
     m_subnodeBTree = subnodeBTree;
 }
 public static HeapOrNodeID StoreExternalProperty(PSTFile file, HeapOnNode heap, ref SubnodeBTree subnodeBTree, byte[] propertyBytes)
 {
     return(StoreExternalProperty(file, heap, ref subnodeBTree, new HeapOrNodeID(HeapID.EmptyHeapID), propertyBytes));
 }
 public AttachmentTable(HeapOnNode heap, SubnodeBTree subnodeBTree) : base(heap, subnodeBTree)
 {
 }