internal static int Remove(StorageImpl db, int pageId, Btree tree, BtreeKey rem, int height) { Page pg = db.GetPage(pageId); try { int i, n = GetItemsCount(pg), l = 0, r = n; if (tree.type == ClassDescriptor.tpString) { while (l < r) { i = (l + r) >> 1; if (CompareStr(rem.key, pg, i) > 0) { l = i + 1; } else { r = i; } } if (--height != 0) { do { switch (Remove(db, GetKeyStrOid(pg, r), tree, rem, height)) { case Btree.op_underflow: db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return HandlePageUnderflow(db, pg, r, tree.type, rem, height); case Btree.op_done: return Btree.op_done; case Btree.op_overflow: db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return InsertStrKey(db, pg, r, rem, height); } } while (++r <= n); } else { while (r < n) { if (CompareStr(rem.key, pg, r) == 0) { int oid = GetKeyStrOid(pg, r); if (oid == rem.oid || rem.oid == 0) { rem.oldOid = oid; db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return RemoveStrKey(pg, r); } } else { break; } r += 1; } } } else if (tree.type == ClassDescriptor.tpArrayOfByte) { while (l < r) { i = (l + r) >> 1; if (tree.CompareByteArrays(rem.key, pg, i) > 0) { l = i + 1; } else { r = i; } } if (--height != 0) { do { switch (Remove(db, GetKeyStrOid(pg, r), tree, rem, height)) { case Btree.op_underflow: db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return HandlePageUnderflow(db, pg, r, tree.type, rem, height); case Btree.op_done: return Btree.op_done; case Btree.op_overflow: db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return InsertByteArrayKey(db, pg, r, rem, height); } } while (++r <= n); } else { while (r < n) { if (tree.CompareByteArrays(rem.key, pg, r) == 0) { int oid = GetKeyStrOid(pg, r); if (oid == rem.oid || rem.oid == 0) { rem.oldOid = oid; db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return RemoveByteArrayKey(pg, r); } } else { break; } r += 1; } } } else { // scalar types int itemSize = ClassDescriptor.Sizeof[tree.type]; while (l < r) { i = (l + r) >> 1; if (Compare(rem.key, pg, i) > 0) { l = i + 1; } else { r = i; } } if (--height == 0) { int oid = rem.oid; while (r < n) { if (Compare(rem.key, pg, r) == 0) { if (GetReference(pg, maxItems - r - 1) == oid || oid == 0) { rem.oldOid = GetReference(pg, maxItems - r - 1); db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); MemCopy(pg, r, pg, r + 1, n - r - 1, itemSize); MemCopy(pg, maxItems - n + 1, pg, maxItems - n, n - r - 1, 4); SetItemsCount(pg, --n); return n * (itemSize + 4) < keySpace / 2 ? Btree.op_underflow : Btree.op_done; } } else { break; } r += 1; } return Btree.op_not_found; } do { switch (Remove(db, GetReference(pg, maxItems - r - 1), tree, rem, height)) { case Btree.op_underflow: db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return HandlePageUnderflow(db, pg, r, tree.type, rem, height); case Btree.op_done: return Btree.op_done; } } while (++r <= n); } return Btree.op_not_found; } finally { if (pg != null) { db.pool.Unfix(pg); } } }
internal static bool Find(StorageImpl db, int pageId, Key firstKey, Key lastKey, Btree tree, int height, ArrayList result) { Page pg = db.GetPage(pageId); int l = 0, n = GetItemsCount(pg), r = n; int oid; height -= 1; try { if (tree.type == ClassDescriptor.tpString) { if (firstKey != null) { while (l < r) { int i = (l + r) >> 1; if (CompareStr(firstKey, pg, i) >= firstKey.inclusion) { l = i + 1; } else { r = i; } } Assert.That(r == l); } if (lastKey != null) { if (height == 0) { while (l < n) { if (-CompareStr(lastKey, pg, l) >= lastKey.inclusion) { return false; } oid = GetKeyStrOid(pg, l); result.Add(db.LookupObject(oid, null)); l += 1; } } else { do { if (!Find(db, GetKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } if (l == n) { return true; } } while (CompareStr(lastKey, pg, l++) >= 0); return false; } } else { if (height == 0) { while (l < n) { oid = GetKeyStrOid(pg, l); result.Add(db.LookupObject(oid, null)); l += 1; } } else { do { if (!Find(db, GetKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } } while (++l <= n); } } } else if (tree.type == ClassDescriptor.tpArrayOfByte) { if (firstKey != null) { while (l < r) { int i = (l + r) >> 1; if (tree.CompareByteArrays(firstKey, pg, i) >= firstKey.inclusion) { l = i + 1; } else { r = i; } } Assert.That(r == l); } if (lastKey != null) { if (height == 0) { while (l < n) { if (-tree.CompareByteArrays(lastKey, pg, l) >= lastKey.inclusion) { return false; } oid = GetKeyStrOid(pg, l); result.Add(db.LookupObject(oid, null)); l += 1; } } else { do { if (!Find(db, GetKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } if (l == n) { return true; } } while (tree.CompareByteArrays(lastKey, pg, l++) >= 0); return false; } } else { if (height == 0) { while (l < n) { oid = GetKeyStrOid(pg, l); result.Add(db.LookupObject(oid, null)); l += 1; } } else { do { if (!Find(db, GetKeyStrOid(pg, l), firstKey, lastKey, tree, height, result)) { return false; } } while (++l <= n); } } } else { if (firstKey != null) { while (l < r) { int i = (l + r) >> 1; if (Compare(firstKey, pg, i) >= firstKey.inclusion) { l = i + 1; } else { r = i; } } Assert.That(r == l); } if (lastKey != null) { if (height == 0) { while (l < n) { if (-Compare(lastKey, pg, l) >= lastKey.inclusion) { return false; } oid = GetReference(pg, maxItems - 1 - l); result.Add(db.LookupObject(oid, null)); l += 1; } return true; } else { do { if (!Find(db, GetReference(pg, maxItems - 1 - l), firstKey, lastKey, tree, height, result)) { return false; } if (l == n) { return true; } } while (Compare(lastKey, pg, l++) >= 0); return false; } } if (height == 0) { while (l < n) { oid = GetReference(pg, maxItems - 1 - l); result.Add(db.LookupObject(oid, null)); l += 1; } } else { do { if (!Find(db, GetReference(pg, maxItems - 1 - l), firstKey, lastKey, tree, height, result)) { return false; } } while (++l <= n); } } } finally { db.pool.Unfix(pg); } return true; }
internal static int Insert(StorageImpl db, int pageId, Btree tree, BtreeKey ins, int height, bool unique, bool overwrite) { Page pg = db.GetPage(pageId); int result; int l = 0, n = GetItemsCount(pg), r = n; try { if (tree.type == ClassDescriptor.tpString) { while (l < r) { int i = (l + r) >> 1; if (CompareStr(ins.key, pg, i) > 0) { l = i + 1; } else { r = i; } } Assert.That(l == r); if (--height != 0) { result = Insert(db, GetKeyStrOid(pg, r), tree, ins, height, unique, overwrite); Assert.That(result != Btree.op_not_found); if (result != Btree.op_overflow) { return result; } } else if (r < n && CompareStr(ins.key, pg, r) == 0) { if (overwrite) { db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); ins.oldOid = GetKeyStrOid(pg, r); SetKeyStrOid(pg, r, ins.oid); return Btree.op_overwrite; } else if (unique) { return Btree.op_duplicate; } } db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return InsertStrKey(db, pg, r, ins, height); } else if (tree.type == ClassDescriptor.tpArrayOfByte) { while (l < r) { int i = (l + r) >> 1; if (tree.CompareByteArrays(ins.key, pg, i) > 0) { l = i + 1; } else { r = i; } } Assert.That(l == r); if (--height != 0) { result = Insert(db, GetKeyStrOid(pg, r), tree, ins, height, unique, overwrite); Assert.That(result != Btree.op_not_found); if (result != Btree.op_overflow) { return result; } } else if (r < n && tree.CompareByteArrays(ins.key, pg, r) == 0) { if (overwrite) { db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); ins.oldOid = GetKeyStrOid(pg, r); SetKeyStrOid(pg, r, ins.oid); return Btree.op_overwrite; } else if (unique) { return Btree.op_duplicate; } } db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); return InsertByteArrayKey(db, pg, r, ins, height); } else { while (l < r) { int i = (l + r) >> 1; if (Compare(ins.key, pg, i) > 0) l = i + 1; else r = i; } Assert.That(l == r); /* insert before e[r] */ if (--height != 0) { result = Insert(db, GetReference(pg, maxItems - r - 1), tree, ins, height, unique, overwrite); Assert.That(result != Btree.op_not_found); if (result != Btree.op_overflow) { return result; } n += 1; } else if (r < n && Compare(ins.key, pg, r) == 0) { if (overwrite) { db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); ins.oldOid = GetReference(pg, maxItems - r - 1); SetReference(pg, maxItems - r - 1, ins.oid); return Btree.op_overwrite; } else if (unique) { return Btree.op_duplicate; } } db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); int itemSize = ClassDescriptor.Sizeof[tree.type]; int max = keySpace / (4 + itemSize); if (n < max) { MemCopy(pg, r + 1, pg, r, n - r, itemSize); MemCopy(pg, maxItems - n - 1, pg, maxItems - n, n - r, 4); ins.Pack(pg, r); SetItemsCount(pg, GetItemsCount(pg) + 1); return Btree.op_done; } else { /* page is full then divide page */ pageId = db.AllocatePage(); Page b = db.PutPage(pageId); Assert.That(n == max); int m = max / 2; if (r < m) { MemCopy(b, 0, pg, 0, r, itemSize); MemCopy(b, r + 1, pg, r, m - r - 1, itemSize); MemCopy(pg, 0, pg, m - 1, max - m + 1, itemSize); MemCopy(b, maxItems - r, pg, maxItems - r, r, 4); ins.Pack(b, r); MemCopy(b, maxItems - m, pg, maxItems - m + 1, m - r - 1, 4); MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - m + 1, 4); } else { MemCopy(b, 0, pg, 0, m, itemSize); MemCopy(pg, 0, pg, m, r - m, itemSize); MemCopy(pg, r - m + 1, pg, r, max - r, itemSize); MemCopy(b, maxItems - m, pg, maxItems - m, m, 4); MemCopy(pg, maxItems - r + m, pg, maxItems - r, r - m, 4); ins.Pack(pg, r - m); MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - r, 4); } ins.oid = pageId; ins.Extract(b, firstKeyOffs + (m - 1) * itemSize, tree.type); if (height == 0) { SetItemsCount(pg, max - m + 1); SetItemsCount(b, m); } else { SetItemsCount(pg, max - m); SetItemsCount(b, m - 1); } db.pool.Unfix(b); return Btree.op_overflow; } } } finally { if (pg != null) { db.pool.Unfix(pg); } } }