internal static int allocate(DatabaseImpl db, int root, ClassDescriptor.FieldType type, OldBtreeKey ins) { int pageId = db.allocatePage(); Page pg = db.putPage(pageId); setnItems(pg, 1); if (type == ClassDescriptor.FieldType.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.FieldType.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 OldBtreeResult insert(DatabaseImpl db, int pageId, OldBtree tree, OldBtreeKey ins, int height, bool unique, bool overwrite) { Page pg = db.getPage(pageId); OldBtreeResult result; int l = 0, n = getnItems(pg), r = n; try { if (tree.FieldType == ClassDescriptor.FieldType.tpString) { while (l < r) { int i = (l + r) >> 1; if (compareStr(ins.key, pg, i) > 0) l = i + 1; else r = i; } Debug.Assert(l == r); if (--height != 0) { result = insert(db, getKeyStrOid(pg, r), tree, ins, height, unique, overwrite); Debug.Assert(result != OldBtreeResult.NotFound); if (result != OldBtreeResult.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); setKeyStrOid(pg, r, ins.oid); return OldBtreeResult.Overwrite; } else if (unique) { return OldBtreeResult.Duplicate; } } db.pool.unfix(pg); pg = null; pg = db.putPage(pageId); return insertStrKey(db, pg, r, ins, height); } else if (tree.FieldType == ClassDescriptor.FieldType.tpArrayOfByte) { while (l < r) { int i = (l + r) >> 1; if (tree.compareByteArrays(ins.key, pg, i) > 0) l = i + 1; else r = i; } Debug.Assert(l == r); if (--height != 0) { result = insert(db, getKeyStrOid(pg, r), tree, ins, height, unique, overwrite); Debug.Assert(result != OldBtreeResult.NotFound); if (result != OldBtreeResult.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); setKeyStrOid(pg, r, ins.oid); return OldBtreeResult.Overwrite; } else if (unique) { return OldBtreeResult.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; } Debug.Assert(l == r); /* insert before e[r] */ if (--height != 0) { result = insert(db, getReference(pg, maxItems - r - 1), tree, ins, height, unique, overwrite); Debug.Assert(result != OldBtreeResult.NotFound); if (result != OldBtreeResult.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); setReference(pg, maxItems - r - 1, ins.oid); return OldBtreeResult.Overwrite; } else if (unique) { return OldBtreeResult.Duplicate; } } db.pool.unfix(pg); pg = null; pg = db.putPage(pageId); int itemSize = ClassDescriptor.Sizeof[(int)tree.FieldType]; int max = keySpace / (4 + itemSize); if (n < max) { memcpy(pg, r + 1, pg, r, n - r, itemSize); memcpy(pg, maxItems - n - 1, pg, maxItems - n, n - r, 4); ins.pack(pg, r); setnItems(pg, getnItems(pg) + 1); return OldBtreeResult.Done; } else { /* page is full then divide page */ pageId = db.allocatePage(); Page b = db.putPage(pageId); Debug.Assert(n == max); int m = max / 2; if (r < m) { memcpy(b, 0, pg, 0, r, itemSize); memcpy(b, r + 1, pg, r, m - r - 1, itemSize); memcpy(pg, 0, pg, m - 1, max - m + 1, itemSize); memcpy(b, maxItems - r, pg, maxItems - r, r, 4); ins.pack(b, r); memcpy(b, maxItems - m, pg, maxItems - m + 1, m - r - 1, 4); memcpy(pg, maxItems - max + m - 1, pg, maxItems - max, max - m + 1, 4); } else { memcpy(b, 0, pg, 0, m, itemSize); memcpy(pg, 0, pg, m, r - m, itemSize); memcpy(pg, r - m + 1, pg, r, max - r, itemSize); memcpy(b, maxItems - m, pg, maxItems - m, m, 4); memcpy(pg, maxItems - r + m, pg, maxItems - r, r - m, 4); ins.pack(pg, r - m); memcpy(pg, maxItems - max + m - 1, pg, maxItems - max, max - r, 4); } ins.oid = pageId; ins.extract(b, firstKeyOffs + (m - 1) * itemSize, tree.FieldType); if (height == 0) { setnItems(pg, max - m + 1); setnItems(b, m); } else { setnItems(pg, max - m); setnItems(b, m - 1); } db.pool.unfix(b); return OldBtreeResult.Overflow; } } } finally { if (pg != null) db.pool.unfix(pg); } }