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(); } } }
// 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)); }
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)); } }
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); }
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) { }
public NamedTableContext(HeapOnNode heap, SubnodeBTree subnodeBTree, PropertyNameToIDMap map) : base(heap, subnodeBTree) { m_map = map; }
public HierarchyTable(HeapOnNode heap, SubnodeBTree subnodeBTree) : base(heap, subnodeBTree) { }
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) { }