/// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="ownerDb">Table that owns this row.</param>
        /// <param name="rowStartDataPage">Data page on what row starts.</param>
        internal LDB_Record(DbFile ownerDb,DataPage rowStartDataPage)
        {
            m_pOwnerDb = ownerDb;
            m_pDataPage = rowStartDataPage;

            ParseRowInfo();
        }
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="ownerDb">Table that owns this row.</param>
        /// <param name="rowStartDataPage">Data page on what row starts.</param>
        internal LDB_Record(DbFile ownerDb, DataPage rowStartDataPage)
        {
            m_pOwnerDb  = ownerDb;
            m_pDataPage = rowStartDataPage;

            ParseRowInfo();
        }
Exemple #3
0
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="dataPageDataAreaSize">Specifies how much data data page can store.</param>
        /// <param name="ownerDB">Owner DB file..</param>
        /// <param name="startOffset">Data page start offset pointer.</param>
        public DataPage(int dataPageDataAreaSize,DbFile ownerDB,long startOffset)
        {
            /* DataPage structure
               2 bytes                 - CRLF
               1 byte                  - used (f - unused,u - used)
               8 byte	               - owner object id
               8 bytes                 - owner data page pointer
               8 bytes                 - continuing data page pointer
               4 bytes                 - stored data length in data area
               2 bytes                 - CRLF
               1000 bytes              - data area
            */

            m_DataAreaSize = dataPageDataAreaSize;
            m_pOwnerDB = ownerDB;
            m_StartPointer = startOffset;

            byte[] dataPageInfo = new byte[33];
            ownerDB.SetFilePosition(startOffset);
            ownerDB.ReadFromFile(dataPageInfo,0,dataPageInfo.Length);
            m_Data = new byte[dataPageDataAreaSize];
            ownerDB.ReadFromFile(m_Data,0,dataPageDataAreaSize);

            // CRLF
            if(dataPageInfo[0] != (byte)'\r'){
                throw new Exception("Not right data page startOffset, or invalid data page <CR> is expected but is '" + (int)dataPageInfo[0] + "' !");
            }
            if(dataPageInfo[1] != (byte)'\n'){
                throw new Exception("Not right data page startOffset, or invalid data page <LF> is expected but is '" + (int)dataPageInfo[1] + "' !");
            }

            // used
            if(dataPageInfo[2] == (byte)'u'){
                m_Used = true;
            }
            else{
                m_Used = false;
            }

            // owner object id
            m_OwnerID = ldb_Utils.ByteToLong(dataPageInfo,3);

            // owner data page pointer
            m_OwnerDataPagePointer = ldb_Utils.ByteToLong(dataPageInfo,11);

            // continuing data page pointer
            m_NextDataPagePointer = ldb_Utils.ByteToLong(dataPageInfo,19);

            // stored data length in data area
            m_StoredDataLength = ldb_Utils.ByteToInt(dataPageInfo,27);

            // CRLF
            if(dataPageInfo[31] != (byte)'\r'){
                throw new Exception("Not right data page startOffset, or invalid data page <CR> is expected but is '" + (int)dataPageInfo[31] + "' !");
            }
            if(dataPageInfo[32] != (byte)'\n'){
                throw new Exception("Not right data page startOffset, or invalid data page <LF> is expected but is '" + (int)dataPageInfo[32] + "' !");
            }
        }
        /// <summary>
        /// Updates this record values.
        /// </summary>
        /// <param name="rowValues">Row new values.</param>
        private void UpdateRecord(object[] rowValues)
        {
            bool unlock = true;

            // Table is already locked, don't lock it
            if (m_pOwnerDb.TableLocked)
            {
                unlock = false;
            }
            else
            {
                m_pOwnerDb.LockTable(15);
            }

            // Create new record
            byte[] rowData = LDB_Record.CreateRecord(m_pOwnerDb, rowValues);

            DataPage[] dataPages = this.DataPages;
            // Clear old data ?? do we need that
            //	for(int i=0;i<dataPages.Length;i++){
            //		dataPages[i].Data = new byte[1000];
            //	}

            // We haven't enough room to store row, get needed data pages
            if ((int)Math.Ceiling(rowData.Length / (double)m_pOwnerDb.DataPageDataAreaSize) > dataPages.Length)
            {
                int        dataPagesNeeded     = (int)Math.Ceiling(rowData.Length / (double)m_pOwnerDb.DataPageDataAreaSize) - dataPages.Length;
                DataPage[] additionalDataPages = m_pOwnerDb.GetDataPages(dataPages[dataPages.Length - 1].Pointer, dataPagesNeeded);

                // Append new data pages to existing data pages chain
                dataPages[dataPages.Length - 1].NextDataPagePointer = additionalDataPages[0].Pointer;

                DataPage[] newVal = new DataPage[dataPages.Length + additionalDataPages.Length];
                Array.Copy(dataPages, 0, newVal, 0, dataPages.Length);
                Array.Copy(additionalDataPages, 0, newVal, dataPages.Length, additionalDataPages.Length);
                dataPages = newVal;
            }

            // Store new record
            DbFile.StoreDataToDataPages(m_pOwnerDb.DataPageDataAreaSize, rowData, dataPages);

            // Update row info
            ParseRowInfo();

            if (unlock)
            {
                m_pOwnerDb.UnlockTable();
            }
        }
        /// <summary>
        /// Creates record. Contains record info + record values.
        /// </summary>
        /// <param name="ownerDb">Roecord owner table.</param>
        /// <param name="rowValues">Row values what to store to record.</param>
        /// <returns></returns>
        internal static byte[] CreateRecord(DbFile ownerDb, object[] rowValues)
        {
            if (ownerDb.Columns.Count != rowValues.Length)
            {
                throw new Exception("LDB_Record.CreateRecord m_pOwnerDb.Columns.Count != rowValues.Length !");
            }

            // Convert values to internal store format
            ArrayList rowByteValues = new ArrayList();

            for (int i = 0; i < rowValues.Length; i++)
            {
                rowByteValues.Add(ConvertToInternalData(ownerDb.Columns[i], rowValues[i]));
            }

            /* RowInfo structure
             *      (4 bytes) * columnCount - holds column data data length
             *      xx bytes columns values
             */

            MemoryStream msRecord = new MemoryStream();

            // Write values sizes
            for (int i = 0; i < rowByteValues.Count; i++)
            {
                msRecord.Write(ldb_Utils.IntToByte(((byte[])rowByteValues[i]).Length), 0, 4);
            }

            // Write values
            for (int i = 0; i < rowByteValues.Count; i++)
            {
                byte[] val = (byte[])rowByteValues[i];
                msRecord.Write(val, 0, val.Length);
            }

            return(msRecord.ToArray());
        }
        /// <summary>
        /// Appends new record to table.
        /// </summary>
        public void AppendRecord(object[] values)
        {
            if (!this.IsDatabaseOpen)
            {
                throw new Exception("Database isn't open, please open database first !");
            }
            if (m_pColumns.Count != values.Length)
            {
                throw new Exception("Each column must have corresponding value !");
            }

            bool unlock = true;

            // Table is already locked, don't lock it
            if (this.TableLocked)
            {
                unlock = false;
            }
            else
            {
                LockTable(15);
            }

            // Construct record data
            byte[] record = LDB_Record.CreateRecord(this, values);

            // Get free data pages
            DataPage[] dataPages = GetDataPages(0, (int)Math.Ceiling(record.Length / (double)m_DataPageDataAreaSize));

            DbFile.StoreDataToDataPages(m_DataPageDataAreaSize, record, dataPages);

            if (unlock)
            {
                UnlockTable();
            }
        }
        /// <summary>
        /// Creates record. Contains record info + record values.
        /// </summary>
        /// <param name="ownerDb">Roecord owner table.</param>
        /// <param name="rowValues">Row values what to store to record.</param>
        /// <returns></returns>
        internal static byte[] CreateRecord(DbFile ownerDb,object[] rowValues)
        {
            if(ownerDb.Columns.Count != rowValues.Length){
                throw new Exception("LDB_Record.CreateRecord m_pOwnerDb.Columns.Count != rowValues.Length !");
            }

            // Convert values to internal store format
            ArrayList rowByteValues = new ArrayList();
            for(int i=0;i<rowValues.Length;i++){
                rowByteValues.Add(ConvertToInternalData(ownerDb.Columns[i],rowValues[i]));
            }

            /* RowInfo structure
                (4 bytes) * columnCount - holds column data data length
                xx bytes columns values
            */

            MemoryStream msRecord = new MemoryStream();
            // Write values sizes
            for(int i=0;i<rowByteValues.Count;i++){
                msRecord.Write(ldb_Utils.IntToByte(((byte[])rowByteValues[i]).Length),0,4);
            }

            // Write values
            for(int i=0;i<rowByteValues.Count;i++){
                byte[] val = (byte[])rowByteValues[i];
                msRecord.Write(val,0,val.Length);
            }

            return msRecord.ToArray();
        }
        /// <summary>
        /// Default constructor.
        /// </summary>
        /// <param name="dataPageDataAreaSize">Specifies how much data data page can store.</param>
        /// <param name="ownerDB">Owner DB file..</param>
        /// <param name="startOffset">Data page start offset pointer.</param>
        public DataPage(int dataPageDataAreaSize, DbFile ownerDB, long startOffset)
        {
            /* DataPage structure
             * 2 bytes                 - CRLF
             * 1 byte                  - used (f - unused,u - used)
             * 8 byte	               - owner object id
             * 8 bytes                 - owner data page pointer
             * 8 bytes                 - continuing data page pointer
             * 4 bytes                 - stored data length in data area
             * 2 bytes                 - CRLF
             * 1000 bytes              - data area
             */

            m_DataAreaSize = dataPageDataAreaSize;
            m_pOwnerDB     = ownerDB;
            m_StartPointer = startOffset;

            byte[] dataPageInfo = new byte[33];
            ownerDB.SetFilePosition(startOffset);
            ownerDB.ReadFromFile(dataPageInfo, 0, dataPageInfo.Length);
            m_Data = new byte[dataPageDataAreaSize];
            ownerDB.ReadFromFile(m_Data, 0, dataPageDataAreaSize);

            // CRLF
            if (dataPageInfo[0] != (byte)'\r')
            {
                throw new Exception("Not right data page startOffset, or invalid data page <CR> is expected but is '" + (int)dataPageInfo[0] + "' !");
            }
            if (dataPageInfo[1] != (byte)'\n')
            {
                throw new Exception("Not right data page startOffset, or invalid data page <LF> is expected but is '" + (int)dataPageInfo[1] + "' !");
            }

            // used
            if (dataPageInfo[2] == (byte)'u')
            {
                m_Used = true;
            }
            else
            {
                m_Used = false;
            }

            // owner object id
            m_OwnerID = ldb_Utils.ByteToLong(dataPageInfo, 3);

            // owner data page pointer
            m_OwnerDataPagePointer = ldb_Utils.ByteToLong(dataPageInfo, 11);

            // continuing data page pointer
            m_NextDataPagePointer = ldb_Utils.ByteToLong(dataPageInfo, 19);

            // stored data length in data area
            m_StoredDataLength = ldb_Utils.ByteToInt(dataPageInfo, 27);

            // CRLF
            if (dataPageInfo[31] != (byte)'\r')
            {
                throw new Exception("Not right data page startOffset, or invalid data page <CR> is expected but is '" + (int)dataPageInfo[31] + "' !");
            }
            if (dataPageInfo[32] != (byte)'\n')
            {
                throw new Exception("Not right data page startOffset, or invalid data page <LF> is expected but is '" + (int)dataPageInfo[32] + "' !");
            }
        }