public List <IComparable> GetLastRowFromTable(TableDefinition tableDefinition) { Stack <long> pointers = new Stack <long>(); long dataPosition = tableDefinition.DataAddress; pointers.Push(dataPosition); while (PageIsFull(dataPosition, tableDefinition.GetRowSizeInBytes())) { dataPosition = PageLocationHelper.GetNextPagePointer(dataPosition); pointers.Push(dataPosition); } using (FileStream fs = new FileStream(Constants.FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (BinaryReader binaryReader = new BinaryReader(fs)) { List <List <IComparable> > rowsFromLastPage = ReadDataFromPage(dataPosition, tableDefinition.ColumnDefinitions, binaryReader); if (!rowsFromLastPage.Any()) { //if there are no rows, then the last row is on the previous page pointers.Pop(); //remove last pointer, which is a pointer to an empty page long previousAddress = pointers.Pop(); rowsFromLastPage = ReadDataFromPage(previousAddress, tableDefinition.ColumnDefinitions, binaryReader); } return(rowsFromLastPage.Last()); } } }
/// <summary> /// Checks if current page is full. If so, writes a pointer to the end of the page and /// returns next available writeable address. /// Otherwise, return current address /// </summary> /// <param name="address"></param> /// <returns></returns> private void WritePointerIfLastObjectOnPage(long address, int objectSize) { long nextPageAddress = PageLocationHelper.GetNextDivisbleNumber(address, Constants.Page_Size); long load = address + (objectSize + Constants.Int64_Byte_Length); bool willBeLastObjectOnPage = load + objectSize >= nextPageAddress - Constants.Int64_Byte_Length; if (willBeLastObjectOnPage) { long nextPagePointer = GetNextUnclaimedDataPage(); using (FileStream fileStream = File.Open(Constants.FILE_NAME, FileMode.Open, FileAccess.Write, FileShare.ReadWrite)) { using (BinaryWriter binaryWriter = new BinaryWriter(fileStream)) { binaryWriter.BaseStream.Position = nextPageAddress - Constants.Int64_Byte_Length; binaryWriter.Write(nextPagePointer); binaryWriter.BaseStream.Position = nextPagePointer; binaryWriter.Write((short)0); } } } }
public long GetPointerToNextPage(long pageAddress) { long pointerToNextPage = PageLocationHelper.GetNextDivisbleNumber(pageAddress, Constants.Page_Size) - Constants.Int64_Byte_Length; using (FileStream fs = new FileStream(Constants.FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (BinaryReader binaryReader = new BinaryReader(fs)) { binaryReader.BaseStream.Position = pointerToNextPage; long nextPageAddress = binaryReader.ReadInt64(); return(nextPageAddress); } } }
public long GetFirstAvailableDataAddress(long dataStart, int objectSize) { while (PageIsFull(dataStart, objectSize)) { dataStart = PageLocationHelper.GetNextPagePointer(dataStart); } using (FileStream fileStream = new FileStream(Constants.FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { fileStream.Position = dataStart; using (BinaryReader binaryReader = new BinaryReader(fileStream)) { short numObjects = binaryReader.ReadInt16(); return(objectSize * numObjects + 2 + dataStart);//todo: use global 2 byte integer size } } }