Example #1
0
        /// <summary>
        /// Iterates over this page's _data and populates the supplied array with structs representing the rows
        /// </summary>
        /// <param name="rows">An array of RowStruct to populate</param>
        private void IterateOverData(ref RowStruct[] rows)
        {
            var dataSpan      = new Span <byte>(_data);
            int currentOffset = DatabaseConstants.SIZE_OF_PAGE_PREAMBLE;
            int currentRowNum = 0;

            while (currentOffset < DatabaseConstants.PAGE_SIZE)
            {
                int  rowId;
                bool isLocal;
                int  sizeOfRow;

                RowPreamble.Parse(dataSpan.Slice(currentOffset, DatabaseConstants.SIZE_OF_ROW_PREAMBLE), out rowId, out isLocal);

                // check for end of data row identifier
                if (isLocal && rowId == DatabaseConstants.END_OF_ROW_DATA_ID)
                {
                    break;
                }

                if (currentRowNum >= _totalRows)
                {
                    break;
                }

                currentOffset += DatabaseConstants.SIZE_OF_ROW_PREAMBLE;

                if (isLocal)
                {
                    var values = new RowValue2[_schema.Columns.Length];

                    // we need the size of the row to parse how far along we should go in the array (span).
                    // we will however not adjust the offset since the method LocalRowBodyFromBinary includes parsing the rowSize prefix (an int32 size (4 bytes)).

                    sizeOfRow = BitConverter.ToInt32(dataSpan.Slice(currentOffset, DatabaseConstants.SIZE_OF_ROW_SIZE));
                    int rowSize; // this isn't really needed, but it's a required param of the method below
                    Row2.LocalRowBodyFromBinary(dataSpan.Slice(currentOffset, sizeOfRow), out rowSize, ref values, _schema.Columns);

                    //rows.Add(new Row2(rowId, isLocal, _schema.Columns, _process.Id.Value, values, sizeOfRow));
                    rows[currentRowNum] = new RowStruct {
                        IsLocal = isLocal, RowId = rowId, ParticipantId = Guid.Empty, RowSize = sizeOfRow, Values = values
                    };
                    currentOffset += sizeOfRow;
                    currentRowNum++;
                }
                else
                {
                    sizeOfRow = DatabaseConstants.PARTICIPANT_ID_SIZE;
                    Guid particpantId = DatabaseBinaryConverter.BinaryToGuid(dataSpan.Slice(currentOffset, sizeOfRow));
                    //rows.Add(new Row2(rowId, isLocal, particpantId, sizeOfRow, _schema.Columns));
                    rows[currentRowNum] = new RowStruct {
                        IsLocal = isLocal, ParticipantId = particpantId, RowSize = sizeOfRow, RowId = rowId, Values = null
                    };
                    currentOffset += sizeOfRow;
                    currentRowNum++;
                }
            }
        }
Example #2
0
 /// <summary>
 /// Returns the data in binary format for this row. This method takes an array reference (usually passed in from ArrayPool).
 /// This array must be sized correctly (use Size attribute + size of INT to account for row size prefix).
 /// This does not include the row preamble. If local, it will prefix with the size of the row (this does not include the Size of the Row Preamble - only the size of the fixed + variable size data).
 /// </summary>
 /// <param name="returnedArray">A source array reference (usually from ArrayPool). This must be sized correctly (use Size attribute).</param>
 /// <returns>Row values in a binary array</returns>
 public void ToBinaryFormat(ref byte[] array)
 {
     if (!IsReferenceInsert)
     {
         Row2.ValuesToBinaryFormat(ref array, Values);
     }
     else
     {
         Row2.ParticipantToBinaryFormat(ref array, ParticipantId.Value);
     }
 }
Example #3
0
        /// <summary>
        /// Attempts to add a row to this page and then reconcile the xact on disk
        /// </summary>
        /// <param name="row">The row to be added</param>
        /// <param name="rowId">The id for this row. This should be the next available rowId</param>
        /// <returns>True if succesful, otherwise false</returns>
        public bool AddRow(RowInsert row, int rowId)
        {
            bool result = false;

            if (row == null)
            {
                throw new ArgumentNullException(nameof(row));
            }

            row.OrderByByteFormat();

            // rent 1
            byte[] preamble = RentByteArrayFromPool(DatabaseConstants.SIZE_OF_ROW_PREAMBLE);
            Row2.BuildRowPreamble(ref preamble, rowId, !row.IsReferenceInsert);

            byte[] rowData = null;
            if (row.IsReferenceInsert)
            {
                // need to save off the GUID id

                // rent 2
                rowData = RentByteArrayFromPool(DatabaseConstants.PARTICIPANT_ID_SIZE);
                row.ToBinaryFormat(ref rowData);
            }
            else
            {
                // need to save off the size of the row + all the actual row data

                // rent 2
                rowData = RentByteArrayFromPool(row.Size + DatabaseConstants.SIZE_OF_ROW_SIZE);
                row.ToBinaryFormat(ref rowData);
            }

            // rent 3
            byte[] totalRowData = RentByteArrayFromPool(preamble.Length + rowData.Length);

            // combine the preamble and the row data together
            Array.Copy(preamble, 0, totalRowData, 0, preamble.Length);
            Array.Copy(rowData, 0, totalRowData, preamble.Length, rowData.Length);

            // to do: add totalRowData to this Page's data
            if (CanInsertNewRow(totalRowData.Length))
            {
                Array.Copy(totalRowData, 0, _data, GetNextAvailableRowOffset(), totalRowData.Length);
                _totalBytesUsed += totalRowData.Length;
                _totalRows++;
                SaveTotalRows();
                result = true;
            }
            else
            {
                // we need to add this row to the next page because we are out of room on this page
                // throw exception here or... ?
            }

            _pendingXacts.Add(row.XactId);

            // return 1, 2, 3
            ReturnByteArrayToPool(ref preamble);
            ReturnByteArrayToPool(ref rowData);
            ReturnByteArrayToPool(ref totalRowData);

            return(result);
        }