internal void Read(Table obj, long row) { long rec = Data + (row - 1) * Struct.RowLength; File.BeginUpdate(); File.Read(obj, rec, Struct.RowLength); File.EndUpdate(); obj.RowNo = row; }
public void Add(DataFile fle, string key, long adr, IdxPos pos) { LastUpdate = DateTime.Now; Keys++; if (Root == 0) { IdxPage pg = new IdxPage(0, 0, 0, KeyLength); pos.Row = 0; pos.Result = IdxPos.coIxBigger; pg.Add(fle, key, adr, false, this, pos); return; } pos.Page = new IdxPage(0, 0, 0, KeyLength); pos.PageAdr = Root; ushort l = Levels; while (true) { fle.Read(pos.Page, pos.PageAdr, PageSize); pos.Page.Scan(key, pos); l--; if (l == 0) { break; } pos.PageAdr = pos.RowAdr; } pos.Page.Add(fle, key, adr, false, this, pos); }
public void LinkParent(DataFile fle, ushort kl, int pgsz) { if (Parent == 0) { return; } IdxPage pa = new IdxPage(0, 0, 0, kl); long adr = this.Buffer.Position; string key = Table[Rows - 1].Key; fle.Read(pa, Parent, pgsz); for (ushort i = 0; i < pa.Rows; i++) { if (pa.Table[i].Address == adr) { pa.Table[i].Key = key; fle.Write(pa); if (i == pa.Rows - 1) { pa.LinkParent(fle, kl, pgsz); } return; } } throw new System.InvalidOperationException("MinBase: Index file " + fle.LoFile.Name + " corrupted: tying to find record by address"); }
public Index(string nm, ushort kl, DateTime udTime) { int sz = DataFile.GetSize(Root); if (DataFile.Exists(nm, "Index")) { File = DataFile.Open(nm, "Index", FileMode.Open); File.Read(Root, DataFile.coSignatureSz, sz); if (DateTime.Compare(Root.LastUpdate, udTime) >= 0 && Root.Closed) { Root.Closed = false; File.Lock(Root); File.Write(Root); return; } File.Close(); DataFile.Delete(nm, "Index"); } File = DataFile.Open(nm, "Index", FileMode.CreateNew); DataFile.Blank(Root, sz); Root.KeyLength = kl; Root.Closed = false; Root.PageSize = (ushort)DataFile.GetSize(new IdxPage(0, 0, 0, kl)); File.Append(Root, sz); File.Lock(Root); }
public void Remove(DataFile fle, string key, long adr, IdxPos pos) { if (Root == 0) { throw new System.InvalidOperationException("MinBase: Index file " + fle.LoFile.Name + " corrupted: tying to delete key on empty index."); } LastUpdate = DateTime.Now; Keys--; pos.Page = new IdxPage(0, 0, 0, KeyLength); pos.PageAdr = Root; ushort l = Levels; while (true) { fle.Read(pos.Page, pos.PageAdr, PageSize); pos.Page.Scan(key, pos); l--; if (l == 0) { break; } pos.PageAdr = pos.RowAdr; } if (pos.Result == IdxPos.coIxFound) { if (Match(fle, key, adr, pos)) { pos.Page.Remove(fle, key, adr, false, this, pos); return; } } throw new System.InvalidOperationException("MinBase: Index file " + fle.LoFile.Name + " corrupted: tying to delete unexistent key."); }
public void Scan(DataFile fle, string key, IdxPos pos) { if (Root == 0) { pos.PageAdr = 0; pos.RowAdr = 0; pos.Row = 0; pos.Result = IdxPos.coIxBigger; return; } pos.Page = new IdxPage(0, 0, 0, KeyLength); pos.PageAdr = Root; ushort l = Levels; while (true) { fle.Read(pos.Page, pos.PageAdr, PageSize); pos.Page.Scan(key, pos); l--; if (l == 0) { return; } pos.PageAdr = pos.RowAdr; } }
public void LinkChild(DataFile fle, long chadr, ushort kl, int pgsz) { IdxPage ch = new IdxPage(0, 0, 0, kl); fle.Read(ch, chadr, pgsz); ch.Parent = this.Buffer.Position; fle.Write(ch); }
public void GetLast(DataFile fle, IdxPos pos) { if (Root == 0) { pos.PageAdr = 0; pos.RowAdr = 0; pos.Row = 0; pos.Result = IdxPos.coIxBigger; return; } pos.Page = new IdxPage(0, 0, 0, KeyLength); fle.Read(pos.Page, Last, PageSize); pos.Page.Last(pos); }
public long Position(DataFile fle, IdxPos pos) { pos.OnPage = true; long sk = 0; while (true) { sk += pos.Page.Position(pos); if (pos.PageAdr == 0) { return(sk); } fle.Read(pos.Page, pos.PageAdr, PageSize); } }
public bool Match(DataFile fle, string key, long adr, IdxPos pos) { while (true) { pos.Page.Match(key, adr, pos); if (pos.Result == IdxPos.coIxMatch) { return(true); } if (pos.Result != IdxPos.coIxFound || pos.PageAdr == 0) { return(false); } fle.Read(pos.Page, pos.PageAdr, PageSize); } }
public void KeyOnParent(DataFile fle, ushort kl, int pgsz, IdxPos pos) { IdxPage pa = new IdxPage(0, 0, 0, kl); long adr = this.Buffer.Position; fle.Read(pa, Parent, pgsz); for (ushort i = 0; i < pa.Rows; i++) { if (pa.Table[i].Address == adr) { pos.Page = pa; pos.Row = i; return; } } throw new System.InvalidOperationException("MinBase: Index file " + fle.LoFile.Name + " corrupted: tying to find record by address"); }
public bool Jump(DataFile fle, long jmp, IdxPos pos) { pos.OnPage = true; while (true) { jmp = pos.Page.Jump(jmp, pos); if (jmp == 0) { return(true); } if (pos.PageAdr == 0) { return(false); } fle.Read(pos.Page, pos.PageAdr, PageSize); } }
public void Check(DataFile fle) { if (Root == 0) { if (Keys > 0) { throw new System.InvalidOperationException("Index has no root but does contain keys."); } return; } if (Keys == 0) { throw new System.InvalidOperationException("Index is not empty while it should."); } IdxPage pg = new IdxPage(0, 0, 0, KeyLength); fle.Read(pg, Root, PageSize); pg.Check(fle, this, Levels); }
public void Check(DataFile fle, IdxRoot root, ushort lvl) { int pgsz = root.PageSize; ushort kyln = root.KeyLength; long fa, la, pa, na, xa, va; int i, j, c, ct; IdxPage fr, ls, mp, mn, pp; string ok; bool err, cr; if (Parent != 0) { throw new System.InvalidOperationException("Wrong root page."); } if (root.Root != Buffer.Position) { throw new System.InvalidOperationException("Wrong root page."); } fr = new IdxPage(0, 0, 0, kyln); ls = new IdxPage(0, 0, 0, kyln); pp = new IdxPage(0, 0, 0, kyln); cr = true; ct = 0; fa = root.First; la = root.Last; while (true) { fle.Read(fr, fa, pgsz); if (fr.Previous != 0) { throw new System.InvalidOperationException("Wrong first page."); } fle.Read(ls, la, pgsz); if (ls.Next != 0) { throw new System.InvalidOperationException("Wrong last page."); } mp = fr; mn = ls; while (true) { if (mp.Rows > coOrder || (mp.Rows < coMin && mp.Parent != 0)) { throw new System.InvalidOperationException("Wrong number of rows."); } if (mp.Parent != 0) { fle.Read(pp, mp.Parent, pgsz); err = true; for (j = 0; j < pp.Rows; j++) { if (pp.Table[j].Address == mp.Buffer.Position) { if (pp.Table[j].Key != mp.Table[mp.Rows - 1].Key) { throw new System.InvalidOperationException("Last key on this page does not match link key on parent page."); } err = false; break; } } if (err) { throw new System.InvalidOperationException("Link with parent page is wrong."); } } if (cr) { ct += mp.Rows; } ok = ""; for (i = 0; i < mp.Rows; i++) { c = string.Compare(ok, mp.Table[i].Key); if (c > 0) { throw new System.InvalidOperationException("Wrong key order."); } ok = mp.Table[i].Key; } if (mp.Next == 0) { if (mn.Previous != 0) { throw new System.InvalidOperationException("Wrong sibling link."); } break; } pa = mp.Buffer.Position; na = mn.Buffer.Position; xa = mp.Next; va = mn.Previous; mp = new IdxPage(0, 0, 0, kyln); mn = new IdxPage(0, 0, 0, kyln); fle.Read(mp, xa, pgsz); fle.Read(mn, va, pgsz); if (mp.Previous != pa) { throw new System.InvalidOperationException("Wrong next page."); } if (mn.Next != na) { throw new System.InvalidOperationException("Wrong previous page."); } c = string.Compare(ok, mp.Table[0].Key); if (c > 0) { throw new System.InvalidOperationException("Wrong page-to-page key order."); } } if (cr) { cr = false; if (ct != root.Keys) { throw new System.InvalidOperationException("Wrong parent link."); } } fa = fr.Parent; la = ls.Parent; if (fa == 0 || la == 0) { if (la != 0 || fa != 0) { throw new System.InvalidOperationException("Wrong parent link."); } break; } } }
public void Remove(DataFile fle, string key, long adr, bool branch, IdxRoot root, IdxPos pos) { ushort i; ushort row = pos.Row; int pgsz = root.PageSize; ushort kyln = root.KeyLength; if (Rows > coMin || Parent == 0) { if (Rows == 1) { root.Root = root.First = root.Last = 0; root.Levels = 0; fle.Write(root); return; } Rows--; if (row == Rows) { LinkParent(fle, kyln, pgsz); } else { for (i = row; i < Rows; i++) { Table[i].Key = Table[i + 1].Key; Table[i].Address = Table[i + 1].Address; } } fle.Write(this); fle.Write(root); return; } ushort pz, nz, f, t, dx; IdxPage pv, nx; if (Previous > 0) { pv = new IdxPage(0, 0, 0, kyln); fle.Read(pv, Previous, pgsz); pz = pv.Rows; } else { pv = null; pz = coOrder + coOrder; } if (Next > 0) { nx = new IdxPage(0, 0, 0, kyln); fle.Read(nx, Next, pgsz); nz = nx.Rows; } else { nx = null; nz = coOrder + coOrder; } Rows--; if (pz < nz) { if (pv.Rows == coMin) { t = coMin; f = 0; for (i = 0; i < Rows; i++) { if (i == row) { f++; } pv.Table[t].Key = Table[f].Key; pv.Table[t].Address = Table[f].Address; if (branch) { pv.LinkChild(fle, Table[f].Address, kyln, pgsz); } t++; f++; } pv.Rows += Rows; pv.Next = Next; if (Next == 0) { if (!branch) { root.Last = Previous; } if (pv.Previous == 0) { pv.Parent = 0; fle.Write(pv); root.Root = Previous; root.Levels--; fle.Write(root); return; } } else { nx.Previous = Previous; fle.Write(nx); } pv.LinkParent(fle, kyln, pgsz); fle.Write(pv); KeyOnParent(fle, kyln, pgsz, pos); pos.Page.Remove(fle, Table[Rows].Key, this.Buffer.Position, true, root, pos); return; } dx = (ushort)((pv.Rows - coMin) / 2); if (dx == 0) { dx = 1; } t = (ushort)(Rows + dx - 1); f = Rows; for (i = 0; i < Rows; i++) { if (f == row) { f--; } Table[t].Key = Table[f].Key; Table[t].Address = Table[f].Address; f--; t--; } f = (ushort)(pv.Rows - 1); for (i = 0; i < dx; i++) { Table[t].Key = pv.Table[f].Key; Table[t].Address = pv.Table[f].Address; if (branch) { LinkChild(fle, Table[t].Address, kyln, pgsz); } t--; f--; } pv.Rows -= dx; Rows += dx; if (row + dx == Rows) { LinkParent(fle, kyln, pgsz); } pv.LinkParent(fle, kyln, pgsz); fle.Write(pv); fle.Write(this); fle.Write(root); return; } if (nx.Rows == coMin) { f = (ushort)(nx.Rows - 1); t = (ushort)(f + Rows); for (i = 0; i < nx.Rows; i++) { nx.Table[t].Key = nx.Table[f].Key; nx.Table[t].Address = nx.Table[f].Address; t--; f--; } f = Rows; for (i = 0; i < Rows; i++) { if (f == row) { f--; } nx.Table[t].Key = Table[f].Key; nx.Table[t].Address = Table[f].Address; if (branch) { nx.LinkChild(fle, Table[f].Address, kyln, pgsz); } t--; f--; } nx.Rows += Rows; nx.Previous = Previous; if (Previous == 0) { if (!branch) { root.First = Next; } if (nx.Next == 0) { nx.Parent = 0; fle.Write(nx); root.Root = Next; root.Levels--; fle.Write(root); return; } } else { pv.Next = Next; fle.Write(pv); } fle.Write(nx); KeyOnParent(fle, kyln, pgsz, pos); pos.Page.Remove(fle, Table[Rows].Key, this.Buffer.Position, true, root, pos); return; } for (i = row; i < Rows; i++) { Table[i].Key = Table[i + 1].Key; Table[i].Address = Table[i + 1].Address; } dx = (ushort)((nx.Rows - coMin) / 2); if (dx == 0) { dx = 1; } t = Rows; f = 0; for (i = 0; i < dx; i++) { Table[t].Key = nx.Table[f].Key; Table[t].Address = nx.Table[f].Address; if (branch) { LinkChild(fle, Table[t].Address, kyln, pgsz); } f++; t++; } Rows += dx; nx.Rows -= dx; t = 0; for (i = 0; i < nx.Rows; i++) { nx.Table[t].Key = nx.Table[f].Key; nx.Table[t].Address = nx.Table[f].Address; t++; f++; } LinkParent(fle, kyln, pgsz); fle.Write(this); fle.Write(nx); fle.Write(root); }
public void Add(DataFile fle, string key, long adr, bool branch, IdxRoot root, IdxPos pos) { int i; ushort j, mx, p, q, m, dx; int pgsz = root.PageSize; ushort kyln = root.KeyLength; ushort row = pos.Row; if (pos.Result == IdxPos.coIxSmaller) { row++; } if (Rows < coOrder) { for (i = Rows; i > row; i--) { Table[i].Key = Table[i - 1].Key; Table[i].Address = Table[i - 1].Address; } Table[row].Key = key; Table[row].Address = adr; Rows++; if (row == Rows - 1) { LinkParent(fle, kyln, pgsz); } if (root.Root == 0) { fle.Append(this, pgsz); root.Levels = 1; root.Root = root.First = root.Last = this.Buffer.Position; } else { fle.Write(this); if (branch) { LinkChild(fle, adr, kyln, pgsz); } } fle.Write(root); return; } IdxPage si = new IdxPage(0, 0, 0, kyln); if (Previous > 0) { fle.Read(si, Previous, root.PageSize); if (si.Rows < coOrder) { dx = (ushort)((coOrder - si.Rows) / 2); if (dx == 0) { dx = 1; } if (row < dx) { p = (ushort)(si.Rows + row); q = coOrder + 1; if (dx == 1) { si.Table[si.Rows].Key = key; si.Table[si.Rows].Address = adr; si.Rows++; fle.Write(si); si.LinkParent(fle, kyln, pgsz); if (branch) { si.LinkChild(fle, adr, kyln, pgsz); } return; } } else { p = coOrder + 1; q = (ushort)(row - dx); } for (i = 0; i < dx; i++) { if (si.Rows == p) { si.Table[si.Rows].Key = key; si.Table[si.Rows].Address = adr; si.Rows++; if (branch) { si.LinkChild(fle, adr, kyln, pgsz); } dx--; if (dx == i) { break; } } si.Table[si.Rows].Key = Table[i].Key; si.Table[si.Rows].Address = Table[i].Address; si.Rows++; if (branch) { si.LinkChild(fle, Table[i].Address, kyln, pgsz); } } si.LinkParent(fle, kyln, pgsz); fle.Write(si); mx = (ushort)(coOrder - dx); j = dx; m = 0; for (i = 0; i < mx; i++) { if (m == q) { Table[m].Key = key; Table[m].Address = adr; if (branch) { LinkChild(fle, adr, kyln, pgsz); } m++; dx--; if (m == j) { break; } } Table[m].Key = Table[j].Key; Table[m].Address = Table[j].Address; m++; j++; } Rows -= dx; if (q == Rows) { Table[q].Key = key; Table[q].Address = adr; Rows++; if (branch) { LinkChild(fle, adr, kyln, pgsz); } } if (q == Rows - 1) { LinkParent(fle, kyln, pgsz); } fle.Write(this); fle.Write(root); return; } } if (Next > 0) { fle.Read(si, Next, pgsz); if (si.Rows < coOrder) { dx = (ushort)((coOrder - si.Rows) / 2); if (dx == 0) { dx = 1; } mx = (ushort)(Rows - dx); if (row > mx) { p = (ushort)(row - mx - 1); } else { p = coOrder + 1; } m = (ushort)(si.Rows + dx - 1); j = (ushort)(m - dx); for (i = 0; i < si.Rows; i++) { si.Table[m].Key = si.Table[j].Key; si.Table[m].Address = si.Table[j].Address; m--; j--; } si.Rows += dx; m = (ushort)(dx - 1); j = coOrder - 1; for (i = 0; i < dx; i++) { if (m == p) { si.Table[m].Key = key; si.Table[m].Address = adr; if (branch) { si.LinkChild(fle, adr, kyln, pgsz); } dx--; if (m == 0) { break; } m--; } si.Table[m].Key = Table[j].Key; si.Table[m].Address = Table[j].Address; if (branch) { si.LinkChild(fle, Table[j].Address, kyln, pgsz); } m--; j--; } Rows -= dx; if (p == coOrder + 1) { for (i = Rows; i > row; i--) { Table[i].Key = Table[i - 1].Key; Table[i].Address = Table[i - 1].Address; } Table[row].Key = key; Table[row].Address = adr; if (branch) { LinkChild(fle, adr, kyln, pgsz); } Rows++; } LinkParent(fle, kyln, pgsz); fle.Write(this); fle.Write(si); fle.Write(root); return; } } si = new IdxPage(Parent, this.Buffer.Position, Next, kyln); IdxPage pa; ushort mv = si.Rows = Rows = coMin; ushort hp, wr; long thad; string skey; if (row >= coMin) { hp = (ushort)(row - coMin); } else { hp = coOrder; } wr = 0; for (i = 0; i < coMin; i++) { if (i == hp) { si.Table[wr].Key = key; si.Table[wr].Address = adr; wr++; si.Rows++; } si.Table[wr].Key = Table[mv].Key; si.Table[wr].Address = Table[mv].Address; wr++; mv++; } if (hp == coMin) { si.Table[coMin].Key = key; si.Table[coMin].Address = adr; si.Rows++; } fle.Append(si, pgsz); Next = si.Buffer.Position; if (branch) { for (i = 0; i < si.Rows; i++) { si.LinkChild(fle, si.Table[i].Address, kyln, pgsz); } } if (si.Rows == Rows) { for (i = Rows; i > row; i--) { Table[i].Key = Table[i - 1].Key; Table[i].Address = Table[i - 1].Address; } Table[row].Key = key; Table[row].Address = adr; if (branch) { LinkChild(fle, adr, kyln, pgsz); } Rows++; } if (si.Next == 0) { if (!branch) { root.Last = Next; } if (Parent == 0) { pa = new IdxPage(0, 0, 0, kyln); pa.Rows = 2; pa.Table[0].Key = Table[Rows - 1].Key; pa.Table[0].Address = si.Previous; pa.Table[1].Key = si.Table[si.Rows - 1].Key; pa.Table[1].Address = Next; fle.Append(pa, pgsz); Parent = si.Parent = pa.Buffer.Position; fle.Write(this); fle.Write(si); root.Root = Parent; root.Levels++; fle.Write(root); return; } } else { IdxPage ss = new IdxPage(0, 0, 0, kyln); fle.Read(ss, si.Next, pgsz); ss.Previous = Next; fle.Write(ss); } LinkParent(fle, kyln, pgsz); fle.Write(this); skey = si.Table[si.Rows - 1].Key; thad = this.Buffer.Position; pa = new IdxPage(0, 0, 0, kyln); fle.Read(pa, Parent, pgsz); for (j = 0; j < pa.Rows; j++) { if (pa.Table[j].Address == thad) { pos.Row = j; pos.Result = IdxPos.coIxSmaller; pa.Add(fle, skey, Next, true, root, pos); return; } } throw new System.InvalidOperationException("MinBase: Index file " + fle.LoFile.Name + " corrupted, trying to add key."); }