public void SetRowBytes(int rowIndex, byte[] rowBytes)
        {
            if (rowIndex >= RowCount)
            {
                throw new ArgumentException("Invalid rowIndex");
            }

            int rowLength = this.RowLength;

            if (m_tcInfo.hnidRows.IsHeapID)
            {
                // the RowMatrix is stored in the data tree
                byte[] rows      = m_heap.GetHeapItem(m_tcInfo.hnidRows.HeapID);
                int    rowOffset = (int)rowIndex * rowLength;
                Array.Copy(rowBytes, 0, rows, rowOffset, rowLength);

                HeapID oldHeapID = m_tcInfo.hnidRows.HeapID;
                // this will replace the item in place (as they have the same size)
                m_heap.ReplaceHeapItem(oldHeapID, rows);
            }
            else
            {
                // indicates that the item is stored in the subnode block, and the NID is the local NID under the subnode BTree
                NodeID rowsNodeID = m_tcInfo.hnidRows.NodeID;
                if (m_subnodeRows == null)
                {
                    m_subnodeRows = m_subnodeBTree.GetSubnode(rowsNodeID);
                }
                int       blockIndex      = (int)(rowIndex / m_rowsPerBlock);
                int       inBlockRowIndex = (int)(rowIndex % m_rowsPerBlock);
                DataBlock block           = m_subnodeRows.DataTree.GetDataBlock(blockIndex);
                int       offset          = inBlockRowIndex * rowLength;

                Array.Copy(rowBytes, 0, block.Data, offset, rowLength);
                m_subnodeRows.DataTree.UpdateDataBlock(blockIndex, block.Data);
            }
        }
 public ModifiedAppointmentInstance(Subnode subnode)
     : base(subnode.File, subnode.SubnodeID, subnode.DataTree, subnode.SubnodeBTree)
 {
 }
        /// <summary>
        /// Add column to an empty table context.
        /// If this is a Contents Table, the caller should call UpdateMessage() afterwards.
        /// Similarly, for attachment table, the caller should call UpdateAttachment().
        /// </summary>
        public void AddPropertyColumn(PropertyID propertyID, PropertyTypeName propertyType)
        {
            TableColumnDescriptor newColumnDescriptor = new TableColumnDescriptor();

            newColumnDescriptor.PropertyID   = propertyID;
            newColumnDescriptor.PropertyType = propertyType;
            newColumnDescriptor.iBit         = (byte)m_tcInfo.ColumnCount;
            newColumnDescriptor.cbData       = (byte)GetPropertyDataLength(propertyType);

            // Set the ibData:
            // http://social.msdn.microsoft.com/Forums/en-US/os_binaryfile/thread/a5f9c653-40f5-4638-85d3-00c54607d984/
            // PidTagLtpRowId and PidTagLtpRowVer must not be relocated
            if (newColumnDescriptor.DataLengthGroup == TableContextInfo.TCI_4b)
            {
                newColumnDescriptor.ibData = m_tcInfo.rgib[TableContextInfo.TCI_4b];
            }
            else if (newColumnDescriptor.DataLengthGroup == TableContextInfo.TCI_2b)
            {
                newColumnDescriptor.ibData = m_tcInfo.rgib[TableContextInfo.TCI_2b];
            }
            else
            {
                newColumnDescriptor.ibData = m_tcInfo.rgib[TableContextInfo.TCI_1b];
            }

            // We call GetRedistributedRows() before adding the new column:
            List <byte[]> rows = GetRedistributedRows(newColumnDescriptor.ibData, newColumnDescriptor.cbData);

            // add the new column
            m_tcInfo.rgTCOLDESC.Add(newColumnDescriptor);

            // redistribute column descriptions
            ushort offset = (ushort)(newColumnDescriptor.ibData + newColumnDescriptor.cbData);

            for (int groupIndex = newColumnDescriptor.DataLengthGroup + 1; groupIndex < 3; groupIndex++)
            {
                for (int index = 0; index < m_tcInfo.rgTCOLDESC.Count; index++)
                {
                    TableColumnDescriptor descriptor = m_tcInfo.rgTCOLDESC[index];

                    if (groupIndex == descriptor.DataLengthGroup)
                    {
                        // changes to descriptor will be saved when calling UpdateTableContextInfo()
                        descriptor.ibData = offset;
                        offset           += descriptor.cbData;
                    }
                }
            }

            // update the group ending offset
            m_tcInfo.UpdateDataLayout();
            m_rowsPerBlock = (int)Math.Floor((double)DataBlock.MaximumDataLength / RowLength);

            // Update the rows data
            if (!m_tcInfo.hnidRows.IsEmpty)
            {
                if (m_tcInfo.hnidRows.IsHeapID)
                {
                    m_heap.RemoveItemFromHeap(m_tcInfo.hnidRows.HeapID);
                    CreateSubnodeForRows();
                }
                else
                {
                    if (m_subnodeRows == null)
                    {
                        m_subnodeRows = m_subnodeBTree.GetSubnode(m_tcInfo.hnidRows.NodeID);
                    }
                    m_subnodeRows.Delete(); // this will set the subnode data-tree to null
                    // New data tree will be created when the first row will be added
                    m_subnodeBTree.UpdateSubnodeEntry(m_tcInfo.hnidRows.NodeID, null, null);
                }

                for (int index = 0; index < rows.Count; index++)
                {
                    AddRowToSubnode(index, rows[index]);
                }
            }

            UpdateTableContextInfo();
        }
Example #4
0
 public AttachmentObject(Subnode subnode)
     : base(subnode.File, subnode.SubnodeID, subnode.DataTree, subnode.SubnodeBTree)
 {
 }