// find whether there's already a record with given key in file public Tuple <bool, long, long> FindKey(long key) { Tuple <bool, long, long, long> address = FindInIndex(key); // try to find on which page could possibly be that record if (address == null || address.Item1 == false) { return(new Tuple <bool, long, long>(false, -1, -1)); } long pageAddress = address.Item3; FilePage filePage = null; while ((filePage = MainReader.ReadPage(pageAddress++)) != null) { for (int i = filePage.Entries.Count - 1; i >= 0; i--) { if (filePage.Entries[i].Item1.Key == key) // if record is found { return(new Tuple <bool, long, long>(true, filePage.Address, i)); } if (filePage.Entries[i].Item1.Key < key && filePage.Entries[i].Item2 != -1) // if some record has overflow pointer which can possibly be given record { Tuple <bool, long, long> search = FindKeyInOverflowChain(filePage.Entries[i].Item2, key); // look for the key in overflow chain if (search.Item1) { return(search); } } } } return(new Tuple <bool, long, long>(false, -1, -1)); // not found }
//todo public void Reorganize() { Console.WriteLine("###REORGANIZATION###"); var NewMainReader = new MainReader("newmain", MainPageSize, Mode.New); var NewMainWriter = new MainWriter("newmain", MainPageSize, Mode.New); TempLong = OverflowAddress; ResetVariables(); AllocateEmptyPageAtTheEnd(ref NewMainWriter); MainPages++; FilePage newPage = NewMainReader.ReadNextPage(); Tuple <Record, long> entry; MainReader.Reader.Position = 0; //MainReader._count = false; while ((entry = MainReader.ReadNextEntryWithChaining()) != null) { if (entry.Item1.Key == long.MaxValue) { continue; } if (entry.Item1.Deleted) { continue; } if (newPage.Count >= Alpha * MainPageSize) { // insert new element to index // allocate new page NewMainWriter.WritePage(newPage); AllocateEmptyPageAtTheEnd(ref NewMainWriter); newPage = NewMainReader.ReadNextPage(); MainPages++; if (entry.Item1.Key != long.MaxValue) { IndexUnit.Entries.Add(new Tuple <long, long>(entry.Item1.Key, MainPages - 1)); } } newPage.Entries[(int)newPage.Count++] = new Tuple <Record, long>(entry.Item1, -1); MainRecordCount++; } NewMainWriter.WritePage(newPage); OverflowAddress = NewMainWriter.Writer.Position; AllocateEmptyPageAtTheEnd(ref NewMainWriter); // allocate overflow OverflowPages++; IndexUnit.Sort(); IndexUnit.WriteIndex(); MetaData.Save(); MainReader.Dispose(); MainWriter.Dispose(); NewMainReader.Dispose(); NewMainWriter.Dispose(); File.Delete(_filePath); File.Move("newmain", _filePath); MainReader = new MainReader(_filePath, MainPageSize, Mode.Read); MainWriter = new MainWriter(_filePath, MainPageSize, Mode.Read); }
public void Remove(long key) { if (key <= 0) { Console.WriteLine("Cannot remove that record"); return; } Tuple <bool, long, long> found = FindKey(key); if (!found.Item1) { Console.WriteLine("No such record"); return; } FilePage page = MainReader.ReadPage(found.Item2); for (int i = 0; i < page.Count; i++) { if (page.Entries[i].Item1.Key == key) { page.Entries[i].Item1.Deleted = true; MainWriter.WritePage(page); MetaData.Save(); break; } } }
private FilePage PageFromBytes(byte[] arr) { var page = new FilePage { Count = BitConverter.ToInt64(arr, 0) }; var recList = new List <Tuple <Record, long> >(); for (int i = 8; i < arr.Length; i += 41) { bool del = BitConverter.ToBoolean(arr, i); long k = BitConverter.ToInt64(arr, i + 1); long a = BitConverter.ToInt64(arr, i + 1 + 8); long b = BitConverter.ToInt64(arr, i + 1 + 8 * 2); long c = BitConverter.ToInt64(arr, i + 1 + 8 * 3); long l = BitConverter.ToInt64(arr, i + 1 + 8 * 4); recList.Add(new Tuple <Record, long>(new Record(k, a, b, c, del), l)); } for (int i = 0; i < recList.Count; ++i) { page.Entries[i] = recList[i]; } return(page); }
private void AllocateEmptyPageAtTheEnd(ref MainWriter mw) { mw.Writer.Position = mw.Writer.Length; var page = new FilePage { Address = MainReader.PageNumberFromAddress(mw.Writer.Position) }; mw.WritePage(page); }
public void WritePage(FilePage filePage) { _lastPageNumber = filePage.Address; LastPage = filePage; byte[] buffer = FilePageToBytes(filePage).ToArray(); Writer.Position = PageByteAddress(_lastPageNumber); Writer.Write(buffer, 0, _pageSizeInBytes); Writer.Flush(); if (_count) { Program.MainWrites++; } }
private IEnumerable <byte> FilePageToBytes(FilePage fp) { byte[] cnt = BitConverter.GetBytes(fp.Count); IEnumerable <byte> x = new Byte[0]; x = x.Concat(cnt); for (int i = 0; i < _pageSize; ++i) { x = x.Concat(fp.Entries[i].Item1.AsBytes()); x = x.Concat(BitConverter.GetBytes(fp.Entries[i].Item2)); } return(x); }
public FilePage ReadPage(long page) { if (_eof) { return(LastPage); } if (page == LastPageNumber) { return(LastPage); } //Reader.Position = PageByteAddress(page); var buffer = new byte[_pageSizeInBytes]; try { Reader.Position = PageByteAddress(page); int bytesRead = Reader.Read(buffer, 0, _pageSizeInBytes); if (bytesRead <= 0) { return(null); } if (bytesRead < _pageSizeInBytes) { _eof = true; //throw new PageFaultException(); } FilePage tmpPage = PageFromBytes(buffer); tmpPage.Address = page; if (_count) { Program.MainReads++; } LastPage = tmpPage; LastPageNumber = page; LastRecordNumber = -1L; NextRecordNumber = -1L; return(tmpPage); } catch (ArgumentException) { return(null); } catch (IOException) { return(null); } }
public Tuple <Record, long> ReadNextEntryWithChaining() { if (NextRecordNumber != -1) { return(ReadEntry(NextRecordNumber)); } long page = _counter / _pageSize; if (page == PageNumberFromAddress(Index.TempLong)) { return(null); } var offset = (int)(_counter++ % _pageSize); if (page == LastPageNumber) { LastRecordNumber = offset; Tuple <Record, long> ret = LastPage.Entries[offset]; if (ret.Item2 != -1) { NextRecordNumber = ret.Item2; } else { NextRecordNumber = -1; } return(ret); } FilePage newPage = ReadPage(page); if (newPage == null) { return(null); } LastRecordNumber = offset; Tuple <Record, long> returning = newPage.Entries[offset]; if (returning.Item2 != -1) { NextRecordNumber = returning.Item2; } else { NextRecordNumber = -1; } return(returning); }
public void Update(Record r) { Tuple <bool, long, long> found = FindKey(r.Key); if (!found.Item1) { Console.WriteLine("No such record"); return; } FilePage page = MainReader.ReadPage(found.Item2); page.Entries[(int)found.Item3].Item1.A = r.A; page.Entries[(int)found.Item3].Item1.B = r.B; page.Entries[(int)found.Item3].Item1.C = r.C; MainWriter.WritePage(page); MetaData.Save(); }
private void Initialize() { //fill primary area with empty pages //set overflow area address long addrI = 0L, addrM = 0L; try { File.Delete("meta"); } catch { } IndexUnit.Init(true); var firstMainPage = new FilePage { Address = addrM++, Count = 1 }; firstMainPage.Entries[0] = new Tuple <Record, long>(new Record(), -1); MainWriter.WritePage(firstMainPage); MainPages = 1; MainRecordCount = 1; OverflowAddress = MainWriter.Writer.Position; OverflowFirstPageNumber = MainReader.PageNumberFromAddress(MainWriter.Writer.Position); var newPage = new FilePage { Address = addrM }; MainWriter.WritePage(newPage); OverflowEndAddress = MainWriter.Writer.Position; OverflowPages = 1; MainWriter.Reset(); Program.MainWrites = 0L; MetaData.Save(); IndexUnit.WriteIndex(); }
public Tuple <Record, long> ReadNextEntry() { long page = _counter / _pageSize; var offset = (int)(_counter++ % _pageSize); if (page == LastPageNumber) { LastRecordNumber = offset; Tuple <Record, long> ret = LastPage.Entries[offset]; if (ret.Item2 != -1) { NextRecordNumber = ret.Item2; } else { NextRecordNumber = -1; } return(ret); } FilePage newPage = ReadPage(page); if (newPage == null) { return(null); } LastRecordNumber = offset; Tuple <Record, long> returning = newPage.Entries[offset]; if (returning.Item2 != -1) { NextRecordNumber = returning.Item2; } else { NextRecordNumber = -1; } return(returning); }
// look for a key on given page public Tuple <bool, long, long> FindInFilePage(long page, long key) { FilePage filePage = MainReader.ReadPage(page); long tmp = 0; bool flag = false; for (int i = filePage.Entries.Count; i >= 0; i--) { if (filePage.Entries[i].Item1.Key == key) { return(new Tuple <bool, long, long>(true, filePage.Address, i)); } if (filePage.Entries[i].Item1.Key < key && filePage.Entries[i].Item2 != -1) { tmp = filePage.Entries[i].Item2; flag = true; break; } } if (flag) { while (tmp != -1) { Tuple <Record, long> rec = MainReader.ReadEntry(tmp); if (rec.Item1.Key == key) { return(new Tuple <bool, long, long>(true, MainReader.LastPage.Address, MainReader.LastRecordNumber)); } if (rec.Item1.Key < key && rec.Item2 != -1) { tmp = rec.Item2; } } } return(new Tuple <bool, long, long>(false, -1, -1)); }
public void Add(Record r) { long key = r.Key; Tuple <bool, long, long> found = FindKey(key); if (found.Item1) { Console.WriteLine("Key already added"); return; } //look for a place in available pages in primary area //when there's no place, try to add in overflow area //when unable to do that, add to new page and to index Tuple <bool, long, long, long> index = FindInIndex(key); long indexPage = index.Item4; if (index.Item1 == false) { Console.WriteLine("No place"); } FilePage newPage = MainReader.ReadPage(index.Item3); //add on current page if (newPage.Count < MainPageSize) { newPage.Entries[(int)newPage.Count] = new Tuple <Record, long>(r, -1); newPage.Count++; Sort(newPage); MainRecordCount++; MainWriter.WritePage(newPage); MetaData.Save(); } else { //find a record to which link new record from overflow int linkedRecordNumber = newPage.Entries.Count - 1; long linkAddress = 0; FilePage mainPageWithLink = newPage; for (; linkedRecordNumber >= 0; linkedRecordNumber--) { if (mainPageWithLink.Entries[linkedRecordNumber].Item1.Key < key) { break; } } if (mainPageWithLink.Entries[linkedRecordNumber].Item2 != -1) // if a record in primary area already has pointer to overflow { while (true) { long id = mainPageWithLink.Entries[linkedRecordNumber].Item2; if (id == -1) { break; } Tuple <Record, long> newEntry = MainReader.ReadEntry(id); if (key > newEntry.Item1.Key) { mainPageWithLink = MainReader.LastPage; for (int i = 0; i < mainPageWithLink.Count; i++) { if (mainPageWithLink.Entries[i].Item1.Key == newEntry.Item1.Key) { linkedRecordNumber = i; } } } else { break; } } } MainReader.Reader.Position = OverflowAddress; FilePage overflowPage = MainReader.ReadNextPage(); // read next page from overflow area while (overflowPage != null && overflowPage.Count >= MainPageSize) { // find a page with enough space to place a new record overflowPage = MainReader.ReadNextPage(); } if (overflowPage == null) { AllocateEmptyPageAtTheEnd(ref MainWriter); // allocate new page for overflow area overflowPage = MainReader.ReadNextPage(); } if (overflowPage.Address == mainPageWithLink.Address) { overflowPage = mainPageWithLink; } if (overflowPage.Count < MainPageSize) { overflowPage.Entries[(int)overflowPage.Count] = new Tuple <Record, long>(r, mainPageWithLink.Entries[linkedRecordNumber].Item2); linkAddress = overflowPage.Address * MainPageSize + overflowPage.Count; overflowPage.Count++; OverflowRecordCount++; mainPageWithLink.Entries[linkedRecordNumber] = new Tuple <Record, long>(mainPageWithLink.Entries[linkedRecordNumber].Item1, linkAddress); MainWriter.WritePage(overflowPage); MetaData.Save(); } if (overflowPage.Address != mainPageWithLink.Address) { MainWriter.WritePage(mainPageWithLink); } MetaData.Save(); } if (OverflowRecordCount > 0.5 * MainRecordCount) { Reorganize(); } }
public void Reset() { LastPage = null; _lastPageNumber = -1; _eof = false; }
public void Dispose() { Writer.Dispose(); Writer = null; LastPage = null; }
private void Sort(FilePage fp) { fp.Entries.Sort((x, y) => x.Item1.Key.CompareTo(y.Item1.Key)); }
public void Dispose() { Reader.Dispose(); Reader = null; LastPage = null; }