/// <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(); }
/// <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] + "' !"); } }