internal static int Allocate(StorageImpl db, int root, int type, BtreeKey ins) { int pageId = db.AllocatePage(); Page pg = db.PutPage(pageId); SetItemsCount(pg, 1); if (type == ClassDescriptor.tpString) { char[] sval = (char[]) ins.key.oval; int len = sval.Length; SetSize(pg, len * 2); SetKeyStrOffs(pg, 0, keySpace - len * 2); SetKeyStrSize(pg, 0, len); SetKeyStrOid(pg, 0, ins.oid); SetKeyStrOid(pg, 1, root); SetKeyStrChars(pg, keySpace - len * 2, sval); } else if (type == ClassDescriptor.tpArrayOfByte) { byte[] bval = (byte[]) ins.key.oval; int len = bval.Length; SetSize(pg, len); SetKeyStrOffs(pg, 0, keySpace - len); SetKeyStrSize(pg, 0, len); SetKeyStrOid(pg, 0, ins.oid); SetKeyStrOid(pg, 1, root); SetKeyBytes(pg, keySpace - len, bval); } else { ins.Pack(pg, 0); SetReference(pg, maxItems - 2, root); } db.pool.Unfix(pg); return pageId; }
internal static int InsertStrKey(StorageImpl db, Page pg, int r, BtreeKey ins, int height) { int nItems = GetItemsCount(pg); int size = GetSize(pg); int n = (height != 0) ? nItems + 1 : nItems; // insert before e[r] char[] sval = (char[]) ins.key.oval; int len = sval.Length; if (size + len * 2 + (n + 1) * strKeySize <= keySpace) { MemCopy(pg, r + 1, pg, r, n - r, strKeySize); size += len * 2; SetKeyStrOffs(pg, r, keySpace - size); SetKeyStrSize(pg, r, len); SetKeyStrOid(pg, r, ins.oid); SetKeyStrChars(pg, keySpace - size, sval); nItems += 1; } else { // page is full then divide page int pageId = db.AllocatePage(); Page b = db.PutPage(pageId); int moved = 0; int inserted = len * 2 + strKeySize; int prevDelta = (1 << 31) + 1; for (int bn = 0, i = 0; ; bn += 1) { int addSize, subSize; int j = nItems - i - 1; int keyLen = GetKeyStrSize(pg, i); if (bn == r) { keyLen = len; inserted = 0; addSize = len; if (height == 0) { subSize = 0; j += 1; } else { subSize = GetKeyStrSize(pg, i); } } else { addSize = subSize = keyLen; if (height != 0) { if (i + 1 != r) { subSize += GetKeyStrSize(pg, i + 1); j -= 1; } else { inserted = 0; } } } int delta = (moved + addSize * 2 + (bn + 1) * strKeySize) - (j * strKeySize + size - subSize * 2 + inserted); if (delta >= -prevDelta) { if (height == 0) { ins.GetStr(b, bn - 1); } else { Assert.That("String fits in the B-Tree page", moved + (bn + 1) * strKeySize <= keySpace); if (bn != r) { ins.GetStr(pg, i); SetKeyStrOid(b, bn, GetKeyStrOid(pg, i)); size -= keyLen * 2; i += 1; } else { SetKeyStrOid(b, bn, ins.oid); } } nItems = CompactifyStrings(pg, i); if (bn < r || (bn == r && height == 0)) { MemCopy(pg, r - i + 1, pg, r - i, n - r, strKeySize); size += len * 2; nItems += 1; Assert.That("String fits in the B-Tree page", size + (n - i + 1) * strKeySize <= keySpace); SetKeyStrOffs(pg, r - i, keySpace - size); SetKeyStrSize(pg, r - i, len); SetKeyStrOid(pg, r - i, ins.oid); SetKeyStrChars(pg, keySpace - size, sval); } SetItemsCount(b, bn); SetSize(b, moved); SetSize(pg, size); SetItemsCount(pg, nItems); ins.oid = pageId; db.pool.Unfix(b); return Btree.op_overflow; } moved += keyLen * 2; prevDelta = delta; Assert.That("String fits in the B-Tree page", moved + (bn + 1) * strKeySize <= keySpace); SetKeyStrSize(b, bn, keyLen); SetKeyStrOffs(b, bn, keySpace - moved); if (bn == r) { SetKeyStrOid(b, bn, ins.oid); SetKeyStrChars(b, keySpace - moved, sval); } else { SetKeyStrOid(b, bn, GetKeyStrOid(pg, i)); MemCopy(b, keySpace - moved, pg, GetKeyStrOffs(pg, i), keyLen * 2, 1); size -= keyLen * 2; i += 1; } } } SetItemsCount(pg, nItems); SetSize(pg, size); return size + strKeySize * (nItems + 1) < keySpace / 2 ? Btree.op_underflow : Btree.op_done; }
internal static int Insert(StorageImpl db, int pageId, Key ins, int height) { Page pg = db.GetPage(pageId); int l = 0, n = GetItemsCount(pg), r = n; int oid = ins.oid; try { if (--height != 0) { while (l < r) { int i = (l + r) >> 1; if (oid > GetItem(pg, i)) { l = i + 1; } else { r = i; } } Assert.That(l == r); /* insert before e[r] */ int result = Insert(db, GetItem(pg, maxItems - r - 1), ins, height); Assert.That(result != TenderBaseImpl.Btree.op_not_found); if (result != TenderBaseImpl.Btree.op_overflow) { return result; } n += 1; } else { while (l < r) { int i = (l + r) >> 1; if (oid > GetItem(pg, maxItems - 1 - i)) { l = i + 1; } else { r = i; } } if (r < n && oid == GetItem(pg, maxItems - 1 - r)) { db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); SetItem(pg, r, ins.key); return TenderBaseImpl.Btree.op_overwrite; } } db.pool.Unfix(pg); pg = null; pg = db.PutPage(pageId); if (n < max) { MemCopy(pg, r + 1, pg, r, n - r); MemCopy(pg, maxItems - n - 1, pg, maxItems - n, n - r); SetItem(pg, r, ins.key); SetItem(pg, maxItems - 1 - r, ins.oid); SetItemsCount(pg, GetItemsCount(pg) + 1); return TenderBaseImpl.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); MemCopy(b, r + 1, pg, r, m - r - 1); MemCopy(pg, 0, pg, m - 1, max - m + 1); MemCopy(b, maxItems - r, pg, maxItems - r, r); SetItem(b, r, ins.key); SetItem(b, maxItems - 1 - r, ins.oid); MemCopy(b, maxItems - m, pg, maxItems - m + 1, m - r - 1); MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - m + 1); } else { MemCopy(b, 0, pg, 0, m); MemCopy(pg, 0, pg, m, r - m); MemCopy(pg, r - m + 1, pg, r, max - r); MemCopy(b, maxItems - m, pg, maxItems - m, m); MemCopy(pg, maxItems - r + m, pg, maxItems - r, r - m); SetItem(pg, r - m, ins.key); SetItem(pg, maxItems - 1 - r + m, ins.oid); MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - r); } ins.oid = pageId; if (height == 0) { ins.key = GetItem(b, maxItems - m); SetItemsCount(pg, max - m + 1); SetItemsCount(b, m); } else { ins.key = GetItem(b, m - 1); SetItemsCount(pg, max - m); SetItemsCount(b, m - 1); } db.pool.Unfix(b); return TenderBaseImpl.Btree.op_overflow; } } finally { if (pg != null) { db.pool.Unfix(pg); } } }
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); } } }
internal static int Allocate(StorageImpl db, int root, Key ins) { int pageId = db.AllocatePage(); Page pg = db.PutPage(pageId); SetItemsCount(pg, 1); SetItem(pg, 0, ins.key); SetItem(pg, maxItems - 1, ins.oid); SetItem(pg, maxItems - 2, root); db.pool.Unfix(pg); return pageId; }