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; }
public void Put(T obj, int mask) { DatabaseImpl db = (DatabaseImpl)Database; if (db == null) { throw new DatabaseException(DatabaseException.ErrorCode.DELETED_OBJECT); } if (!obj.IsPersistent()) { db.MakePersistent(obj); } Key ins = new Key(mask, obj.Oid); if (root == 0) { root = BitIndexPage.allocate(db, 0, ins); height = 1; } else { OldBtreeResult result = BitIndexPage.insert(db, root, ins, height); if (result == OldBtreeResult.Overflow) { root = BitIndexPage.allocate(db, root, ins); height += 1; } } updateCounter += 1; nElems += 1; Modify(); }
internal PArrayImpl(DatabaseImpl db, int[] oids, IPersistent owner) { this.db = db; this.owner = owner; arr = oids; used = oids.Length; }
public int Get(T obj) { DatabaseImpl db = (DatabaseImpl)Database; if (root == 0) { throw new DatabaseException(DatabaseException.ErrorCode.KEY_NOT_FOUND); } return(BitIndexPage.find(db, root, obj.Oid, height)); }
internal static int allocate(DatabaseImpl db, int root, Key ins) { int pageId = db.allocatePage(); Page pg = db.putPage(pageId); setnItems(pg, 1); setItem(pg, 0, ins.key); setItem(pg, maxItems - 1, ins.oid); setItem(pg, maxItems - 2, root); db.pool.unfix(pg); return(pageId); }
internal ScalableSet(DatabaseImpl db, int initialSize) : base(db) { if (initialSize <= BTREE_THRESHOLD) { link = db.CreateLink <T>(initialSize); } else { pset = db.CreateBtreeSet <T>(); } }
internal static int find(DatabaseImpl db, int pageId, int oid, int height) { Page pg = db.getPage(pageId); try { int i, n = getnItems(pg), l = 0, r = n; if (--height == 0) { while (l < r) { i = (l + r) >> 1; if (oid > getItem(pg, maxItems - 1 - i)) { l = i + 1; } else { r = i; } } if (r < n && getItem(pg, maxItems - r - 1) == oid) { return(getItem(pg, r)); } throw new DatabaseException(DatabaseException.ErrorCode.KEY_NOT_FOUND); } else { while (l < r) { i = (l + r) >> 1; if (oid > getItem(pg, i)) { l = i + 1; } else { r = i; } } return(find(db, getItem(pg, maxItems - r - 1), oid, height)); } } finally { if (pg != null) { db.pool.unfix(pg); } } }
internal ClassDescriptor(DatabaseImpl db, Type cls) { this.cls = cls; name = getTypeName(cls); ArrayList list = new ArrayList(); buildFieldList(db, cls, list); allFields = (FieldDescriptor[])list.ToArray(typeof(FieldDescriptor)); defaultConstructor = cls.GetConstructor(BindingFlags.Instance | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly, null, defaultConstructorProfile, null); if (defaultConstructor == null && !typeof(ValueType).IsAssignableFrom(cls)) { throw new DatabaseException(DatabaseException.ErrorCode.DESCRIPTOR_FAILURE, cls); } resolved = true; }
internal void resolve() { if (resolved) { return; } DatabaseImpl classStorage = (DatabaseImpl)Database; ClassDescriptor desc = new ClassDescriptor(classStorage, cls); resolved = true; if (!desc.equals(this)) { classStorage.registerClassDescriptor(desc); } }
public override void OnLoad() { cls = lookup(Database, name); int n = allFields.Length; bool hasTransparentAttribute = cls.GetCustomAttributes(typeof(TransparentPersistenceAttribute), true).Length != 0; for (int i = n; --i >= 0;) { FieldDescriptor fd = allFields[i]; fd.Load(); fd.field = cls.GetField(fd.fieldName, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); if (hasTransparentAttribute && fd.type == FieldType.tpObject && isVolanteInternalType(fd.field.FieldType)) { fd.recursiveLoading = true; } switch (fd.type) { case FieldType.tpArrayOfOid: fd.constructor = GetConstructor(fd.field, "ConstructArray"); break; case FieldType.tpLink: fd.constructor = GetConstructor(fd.field, "ConstructLink"); break; default: break; } } defaultConstructor = cls.GetConstructor(BindingFlags.Instance | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly, null, defaultConstructorProfile, null); if (defaultConstructor == null && !typeof(ValueType).IsAssignableFrom(cls)) { throw new DatabaseException(DatabaseException.ErrorCode.DESCRIPTOR_FAILURE, cls); } DatabaseImpl s = (DatabaseImpl)Database; if (!s.classDescMap.ContainsKey(cls)) { ((DatabaseImpl)Database).classDescMap.Add(cls, this); } }
public override bool Remove(T obj) { DatabaseImpl db = (DatabaseImpl)Database; if (db == null) { throw new DatabaseException(DatabaseException.ErrorCode.DELETED_OBJECT); } if (root == 0) { return(false); } OldBtreeResult result = BitIndexPage.remove(db, root, obj.Oid, height); if (result == OldBtreeResult.NotFound) { return(false); } nElems -= 1; if (result == OldBtreeResult.Underflow) { Page pg = db.getPage(root); if (BitIndexPage.getnItems(pg) == 0) { int newRoot = 0; if (height != 1) { newRoot = BitIndexPage.getItem(pg, BitIndexPage.maxItems - 1); } db.freePage(root); root = newRoot; height -= 1; } db.pool.unfix(pg); } updateCounter += 1; Modify(); return(true); }
public XmlImporter(DatabaseImpl db, System.IO.StreamReader reader) { this.db = db; scanner = new XMLScanner(reader); classMap = new Hashtable(); }
public DatabaseServiceImpl(DatabaseImpl database, bool isSystem, SpecialMiiKeyCode miiKeyCode) { _database = database; _metadata = _database.CreateSessionMetadata(miiKeyCode); _isSystem = isSystem; }
public XmlExporter(DatabaseImpl db, System.IO.StreamWriter writer) { this.db = db; this.writer = writer; }
internal static OldBtreeResult handlePageUnderflow(DatabaseImpl db, Page pg, int r, ClassDescriptor.FieldType type, OldBtreeKey rem, int height) { int nItems = getnItems(pg); if (type == ClassDescriptor.FieldType.tpString) { Page a = db.putPage(getKeyStrOid(pg, r)); int an = getnItems(a); if (r < nItems) { // exists greater page Page b = db.getPage(getKeyStrOid(pg, r + 1)); int bn = getnItems(b); int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b); if (height != 1) { merged_size += getKeyStrSize(pg, r) * 2 + strKeySize * 2; } if (merged_size > keySpace) { // reallocation of nodes between pages a and b int i, j, k; db.pool.unfix(b); b = db.putPage(getKeyStrOid(pg, r + 1)); int size_a = getSize(a); int size_b = getSize(b); int addSize, subSize; if (height != 1) { addSize = getKeyStrSize(pg, r); subSize = getKeyStrSize(b, 0); } else { addSize = subSize = getKeyStrSize(b, 0); } i = 0; int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b); while (true) { i += 1; int delta = ((an + i) * strKeySize + size_a + addSize * 2) - ((bn - i) * strKeySize + size_b - subSize * 2); if (delta >= 0) { if (delta >= -prevDelta) i -= 1; break; } size_a += addSize * 2; size_b -= subSize * 2; prevDelta = delta; if (height != 1) { addSize = subSize; subSize = getKeyStrSize(b, i); } else { addSize = subSize = getKeyStrSize(b, i); } } OldBtreeResult result = OldBtreeResult.Done; if (i > 0) { k = i; if (height != 1) { int len = getKeyStrSize(pg, r); setSize(a, getSize(a) + len * 2); setKeyStrOffs(a, an, keySpace - getSize(a)); setKeyStrSize(a, an, len); memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), len * 2, 1); k -= 1; an += 1; setKeyStrOid(a, an + k, getKeyStrOid(b, k)); setSize(b, getSize(b) - getKeyStrSize(b, k) * 2); } for (j = 0; j < k; j++) { int len = getKeyStrSize(b, j); setSize(a, getSize(a) + len * 2); setSize(b, getSize(b) - len * 2); setKeyStrOffs(a, an, keySpace - getSize(a)); setKeyStrSize(a, an, len); setKeyStrOid(a, an, getKeyStrOid(b, j)); memcpy(a, getKeyStrOffs(a, an), b, getKeyStrOffs(b, j), len * 2, 1); an += 1; } rem.getStr(b, i - 1); result = replaceStrKey(db, pg, r, rem, height); setnItems(a, an); setnItems(b, compactifyStrings(b, i)); } db.pool.unfix(a); db.pool.unfix(b); return result; } else { // merge page b to a if (height != 1) { int r_len = getKeyStrSize(pg, r); setKeyStrSize(a, an, r_len); setSize(a, getSize(a) + r_len * 2); setKeyStrOffs(a, an, keySpace - getSize(a)); memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), r_len * 2, 1); an += 1; setKeyStrOid(a, an + bn, getKeyStrOid(b, bn)); } for (int i = 0; i < bn; i++, an++) { setKeyStrSize(a, an, getKeyStrSize(b, i)); setKeyStrOffs(a, an, getKeyStrOffs(b, i) - getSize(a)); setKeyStrOid(a, an, getKeyStrOid(b, i)); } setSize(a, getSize(a) + getSize(b)); setnItems(a, an); memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1); db.pool.unfix(a); db.pool.unfix(b); db.freePage(getKeyStrOid(pg, r + 1)); setKeyStrOid(pg, r + 1, getKeyStrOid(pg, r)); return removeStrKey(pg, r); } } else { // page b is before a Page b = db.getPage(getKeyStrOid(pg, r - 1)); int bn = getnItems(b); int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b); if (height != 1) merged_size += getKeyStrSize(pg, r - 1) * 2 + strKeySize * 2; if (merged_size > keySpace) { // reallocation of nodes between pages a and b int i, j, k, len; db.pool.unfix(b); b = db.putPage(getKeyStrOid(pg, r - 1)); int size_a = getSize(a); int size_b = getSize(b); int addSize, subSize; if (height != 1) { addSize = getKeyStrSize(pg, r - 1); subSize = getKeyStrSize(b, bn - 1); } else { addSize = subSize = getKeyStrSize(b, bn - 1); } i = 0; int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b); while (true) { i += 1; int delta = ((an + i) * strKeySize + size_a + addSize * 2) - ((bn - i) * strKeySize + size_b - subSize * 2); if (delta >= 0) { if (delta >= -prevDelta) i -= 1; break; } prevDelta = delta; size_a += addSize * 2; size_b -= subSize * 2; if (height != 1) { addSize = subSize; subSize = getKeyStrSize(b, bn - i - 1); } else { addSize = subSize = getKeyStrSize(b, bn - i - 1); } } OldBtreeResult result = OldBtreeResult.Done; if (i > 0) { k = i; Debug.Assert(i < bn); if (height != 1) { setSize(b, getSize(b) - getKeyStrSize(b, bn - k) * 2); memcpy(a, i, a, 0, an + 1, strKeySize); k -= 1; setKeyStrOid(a, k, getKeyStrOid(b, bn)); len = getKeyStrSize(pg, r - 1); setKeyStrSize(a, k, len); setSize(a, getSize(a) + len * 2); setKeyStrOffs(a, k, keySpace - getSize(a)); memcpy(a, getKeyStrOffs(a, k), pg, getKeyStrOffs(pg, r - 1), len * 2, 1); } else { memcpy(a, i, a, 0, an, strKeySize); } for (j = 0; j < k; j++) { len = getKeyStrSize(b, bn - k + j); setSize(a, getSize(a) + len * 2); setSize(b, getSize(b) - len * 2); setKeyStrOffs(a, j, keySpace - getSize(a)); setKeyStrSize(a, j, len); setKeyStrOid(a, j, getKeyStrOid(b, bn - k + j)); memcpy(a, getKeyStrOffs(a, j), b, getKeyStrOffs(b, bn - k + j), len * 2, 1); } an += i; setnItems(a, an); rem.getStr(b, bn - k - 1); result = replaceStrKey(db, pg, r - 1, rem, height); setnItems(b, compactifyStrings(b, -i)); } db.pool.unfix(a); db.pool.unfix(b); return result; } else { // merge page b to a if (height != 1) { memcpy(a, bn + 1, a, 0, an + 1, strKeySize); int len = getKeyStrSize(pg, r - 1); setKeyStrSize(a, bn, len); setSize(a, getSize(a) + len * 2); setKeyStrOffs(a, bn, keySpace - getSize(a)); setKeyStrOid(a, bn, getKeyStrOid(b, bn)); memcpy(a, getKeyStrOffs(a, bn), pg, getKeyStrOffs(pg, r - 1), len * 2, 1); an += 1; } else { memcpy(a, bn, a, 0, an, strKeySize); } for (int i = 0; i < bn; i++) { setKeyStrOid(a, i, getKeyStrOid(b, i)); setKeyStrSize(a, i, getKeyStrSize(b, i)); setKeyStrOffs(a, i, getKeyStrOffs(b, i) - getSize(a)); } an += bn; setnItems(a, an); setSize(a, getSize(a) + getSize(b)); memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1); db.pool.unfix(a); db.pool.unfix(b); db.freePage(getKeyStrOid(pg, r - 1)); return removeStrKey(pg, r - 1); } } } else if (type == ClassDescriptor.FieldType.tpArrayOfByte) { Page a = db.putPage(getKeyStrOid(pg, r)); int an = getnItems(a); if (r < nItems) { // exists greater page Page b = db.getPage(getKeyStrOid(pg, r + 1)); int bn = getnItems(b); int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b); if (height != 1) { merged_size += getKeyStrSize(pg, r) + strKeySize * 2; } if (merged_size > keySpace) { // reallocation of nodes between pages a and b int i, j, k; db.pool.unfix(b); b = db.putPage(getKeyStrOid(pg, r + 1)); int size_a = getSize(a); int size_b = getSize(b); int addSize, subSize; if (height != 1) { addSize = getKeyStrSize(pg, r); subSize = getKeyStrSize(b, 0); } else { addSize = subSize = getKeyStrSize(b, 0); } i = 0; int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b); while (true) { i += 1; int delta = ((an + i) * strKeySize + size_a + addSize) - ((bn - i) * strKeySize + size_b - subSize); if (delta >= 0) { if (delta >= -prevDelta) i -= 1; break; } size_a += addSize; size_b -= subSize; prevDelta = delta; if (height != 1) { addSize = subSize; subSize = getKeyStrSize(b, i); } else { addSize = subSize = getKeyStrSize(b, i); } } OldBtreeResult result = OldBtreeResult.Done; if (i > 0) { k = i; if (height != 1) { int len = getKeyStrSize(pg, r); setSize(a, getSize(a) + len); setKeyStrOffs(a, an, keySpace - getSize(a)); setKeyStrSize(a, an, len); memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), len, 1); k -= 1; an += 1; setKeyStrOid(a, an + k, getKeyStrOid(b, k)); setSize(b, getSize(b) - getKeyStrSize(b, k)); } for (j = 0; j < k; j++) { int len = getKeyStrSize(b, j); setSize(a, getSize(a) + len); setSize(b, getSize(b) - len); setKeyStrOffs(a, an, keySpace - getSize(a)); setKeyStrSize(a, an, len); setKeyStrOid(a, an, getKeyStrOid(b, j)); memcpy(a, getKeyStrOffs(a, an), b, getKeyStrOffs(b, j), len, 1); an += 1; } rem.getByteArray(b, i - 1); result = replaceByteArrayKey(db, pg, r, rem, height); setnItems(a, an); setnItems(b, compactifyByteArrays(b, i)); } db.pool.unfix(a); db.pool.unfix(b); return result; } else { // merge page b to a if (height != 1) { int r_len = getKeyStrSize(pg, r); setKeyStrSize(a, an, r_len); setSize(a, getSize(a) + r_len); setKeyStrOffs(a, an, keySpace - getSize(a)); memcpy(a, getKeyStrOffs(a, an), pg, getKeyStrOffs(pg, r), r_len, 1); an += 1; setKeyStrOid(a, an + bn, getKeyStrOid(b, bn)); } for (int i = 0; i < bn; i++, an++) { setKeyStrSize(a, an, getKeyStrSize(b, i)); setKeyStrOffs(a, an, getKeyStrOffs(b, i) - getSize(a)); setKeyStrOid(a, an, getKeyStrOid(b, i)); } setSize(a, getSize(a) + getSize(b)); setnItems(a, an); memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1); db.pool.unfix(a); db.pool.unfix(b); db.freePage(getKeyStrOid(pg, r + 1)); setKeyStrOid(pg, r + 1, getKeyStrOid(pg, r)); return removeByteArrayKey(pg, r); } } else { // page b is before a Page b = db.getPage(getKeyStrOid(pg, r - 1)); int bn = getnItems(b); int merged_size = (an + bn) * strKeySize + getSize(a) + getSize(b); if (height != 1) merged_size += getKeyStrSize(pg, r - 1) + strKeySize * 2; if (merged_size > keySpace) { // reallocation of nodes between pages a and b int i, j, k, len; db.pool.unfix(b); b = db.putPage(getKeyStrOid(pg, r - 1)); int size_a = getSize(a); int size_b = getSize(b); int addSize, subSize; if (height != 1) { addSize = getKeyStrSize(pg, r - 1); subSize = getKeyStrSize(b, bn - 1); } else { addSize = subSize = getKeyStrSize(b, bn - 1); } i = 0; int prevDelta = (an * strKeySize + size_a) - (bn * strKeySize + size_b); while (true) { i += 1; int delta = ((an + i) * strKeySize + size_a + addSize) - ((bn - i) * strKeySize + size_b - subSize); if (delta >= 0) { if (delta >= -prevDelta) i -= 1; break; } prevDelta = delta; size_a += addSize; size_b -= subSize; if (height != 1) { addSize = subSize; subSize = getKeyStrSize(b, bn - i - 1); } else { addSize = subSize = getKeyStrSize(b, bn - i - 1); } } OldBtreeResult result = OldBtreeResult.Done; if (i > 0) { k = i; Debug.Assert(i < bn); if (height != 1) { setSize(b, getSize(b) - getKeyStrSize(b, bn - k)); memcpy(a, i, a, 0, an + 1, strKeySize); k -= 1; setKeyStrOid(a, k, getKeyStrOid(b, bn)); len = getKeyStrSize(pg, r - 1); setKeyStrSize(a, k, len); setSize(a, getSize(a) + len); setKeyStrOffs(a, k, keySpace - getSize(a)); memcpy(a, getKeyStrOffs(a, k), pg, getKeyStrOffs(pg, r - 1), len, 1); } else { memcpy(a, i, a, 0, an, strKeySize); } for (j = 0; j < k; j++) { len = getKeyStrSize(b, bn - k + j); setSize(a, getSize(a) + len); setSize(b, getSize(b) - len); setKeyStrOffs(a, j, keySpace - getSize(a)); setKeyStrSize(a, j, len); setKeyStrOid(a, j, getKeyStrOid(b, bn - k + j)); memcpy(a, getKeyStrOffs(a, j), b, getKeyStrOffs(b, bn - k + j), len, 1); } an += i; setnItems(a, an); rem.getByteArray(b, bn - k - 1); result = replaceByteArrayKey(db, pg, r - 1, rem, height); setnItems(b, compactifyByteArrays(b, -i)); } db.pool.unfix(a); db.pool.unfix(b); return result; } else { // merge page b to a if (height != 1) { memcpy(a, bn + 1, a, 0, an + 1, strKeySize); int len = getKeyStrSize(pg, r - 1); setKeyStrSize(a, bn, len); setSize(a, getSize(a) + len); setKeyStrOffs(a, bn, keySpace - getSize(a)); setKeyStrOid(a, bn, getKeyStrOid(b, bn)); memcpy(a, getKeyStrOffs(a, bn), pg, getKeyStrOffs(pg, r - 1), len, 1); an += 1; } else { memcpy(a, bn, a, 0, an, strKeySize); } for (int i = 0; i < bn; i++) { setKeyStrOid(a, i, getKeyStrOid(b, i)); setKeyStrSize(a, i, getKeyStrSize(b, i)); setKeyStrOffs(a, i, getKeyStrOffs(b, i) - getSize(a)); } an += bn; setnItems(a, an); setSize(a, getSize(a) + getSize(b)); memcpy(a, keySpace - getSize(a), b, keySpace - getSize(b), getSize(b), 1); db.pool.unfix(a); db.pool.unfix(b); db.freePage(getKeyStrOid(pg, r - 1)); return removeByteArrayKey(pg, r - 1); } } } else { Page a = db.putPage(getReference(pg, maxItems - r - 1)); int an = getnItems(a); int itemSize = ClassDescriptor.Sizeof[(int)type]; if (r < nItems) { // exists greater page Page b = db.getPage(getReference(pg, maxItems - r - 2)); int bn = getnItems(b); Debug.Assert(bn >= an); if (height != 1) { memcpy(a, an, pg, r, 1, itemSize); an += 1; bn += 1; } int merged_size = (an + bn) * (4 + itemSize); if (merged_size > keySpace) { // reallocation of nodes between pages a and b int i = bn - ((an + bn) >> 1); db.pool.unfix(b); b = db.putPage(getReference(pg, maxItems - r - 2)); memcpy(a, an, b, 0, i, itemSize); memcpy(b, 0, b, i, bn - i, itemSize); memcpy(a, maxItems - an - i, b, maxItems - i, i, 4); memcpy(b, maxItems - bn + i, b, maxItems - bn, bn - i, 4); memcpy(pg, r, a, an + i - 1, 1, itemSize); setnItems(b, getnItems(b) - i); setnItems(a, getnItems(a) + i); db.pool.unfix(a); db.pool.unfix(b); return OldBtreeResult.Done; } else { // merge page b to a memcpy(a, an, b, 0, bn, itemSize); memcpy(a, maxItems - an - bn, b, maxItems - bn, bn, 4); db.freePage(getReference(pg, maxItems - r - 2)); memcpy(pg, maxItems - nItems, pg, maxItems - nItems - 1, nItems - r - 1, 4); memcpy(pg, r, pg, r + 1, nItems - r - 1, itemSize); setnItems(a, getnItems(a) + bn); setnItems(pg, nItems - 1); db.pool.unfix(a); db.pool.unfix(b); return nItems * (itemSize + 4) < keySpace / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done; } } else { // page b is before a Page b = db.getPage(getReference(pg, maxItems - r)); int bn = getnItems(b); Debug.Assert(bn >= an); if (height != 1) { an += 1; bn += 1; } int merged_size = (an + bn) * (4 + itemSize); if (merged_size > keySpace) { // reallocation of nodes between pages a and b int i = bn - ((an + bn) >> 1); db.pool.unfix(b); b = db.putPage(getReference(pg, maxItems - r)); memcpy(a, i, a, 0, an, itemSize); memcpy(a, 0, b, bn - i, i, itemSize); memcpy(a, maxItems - an - i, a, maxItems - an, an, 4); memcpy(a, maxItems - i, b, maxItems - bn, i, 4); if (height != 1) { memcpy(a, i - 1, pg, r - 1, 1, itemSize); } memcpy(pg, r - 1, b, bn - i - 1, 1, itemSize); setnItems(b, getnItems(b) - i); setnItems(a, getnItems(a) + i); db.pool.unfix(a); db.pool.unfix(b); return OldBtreeResult.Done; } else { // merge page b to a memcpy(a, bn, a, 0, an, itemSize); memcpy(a, 0, b, 0, bn, itemSize); memcpy(a, maxItems - an - bn, a, maxItems - an, an, 4); memcpy(a, maxItems - bn, b, maxItems - bn, bn, 4); if (height != 1) memcpy(a, bn - 1, pg, r - 1, 1, itemSize); db.freePage(getReference(pg, maxItems - r)); setReference(pg, maxItems - r, getReference(pg, maxItems - r - 1)); setnItems(a, getnItems(a) + bn); setnItems(pg, nItems - 1); db.pool.unfix(a); db.pool.unfix(b); return nItems * (itemSize + 4) < keySpace / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done; } } } }
internal static bool find(DatabaseImpl db, int pageId, Key firstKey, Key lastKey, OldBtree tree, int height, ArrayList result) { Page pg = db.getPage(pageId); int l = 0, n = getnItems(pg), r = n; int oid; height -= 1; try { if (tree.FieldType == ClassDescriptor.FieldType.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; } Debug.Assert(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.FieldType == ClassDescriptor.FieldType.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; } Debug.Assert(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; } Debug.Assert(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 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); } }
internal static int traverseForward(DatabaseImpl db, int pageId, ClassDescriptor.FieldType type, int height, IPersistent[] result, int pos) { Page pg = db.getPage(pageId); int oid; try { int i, n = getnItems(pg); if (--height != 0) { if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) { // page of strings for (i = 0; i <= n; i++) { pos = traverseForward(db, getKeyStrOid(pg, i), type, height, result, pos); } } else { for (i = 0; i <= n; i++) { pos = traverseForward(db, getReference(pg, maxItems - i - 1), type, height, result, pos); } } } else { if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) { // page of strings for (i = 0; i < n; i++) { oid = getKeyStrOid(pg, i); result[pos++] = db.lookupObject(oid, null); } } else { // page of scalars for (i = 0; i < n; i++) { oid = getReference(pg, maxItems - 1 - i); result[pos++] = db.lookupObject(oid, null); } } } return pos; } finally { db.pool.unfix(pg); } }
internal static OldBtreeResult remove(DatabaseImpl db, int pageId, int oid, int height) { Page pg = db.getPage(pageId); try { int i, n = getnItems(pg), l = 0, r = n; if (--height == 0) { while (l < r) { i = (l + r) >> 1; if (oid > getItem(pg, maxItems - 1 - i)) { l = i + 1; } else { r = i; } } if (r < n && getItem(pg, maxItems - r - 1) == oid) { db.pool.unfix(pg); pg = null; pg = db.putPage(pageId); memcpy(pg, r, pg, r + 1, n - r - 1); memcpy(pg, maxItems - n + 1, pg, maxItems - n, n - r - 1); setnItems(pg, --n); return(n < max / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done); } return(OldBtreeResult.NotFound); } else { while (l < r) { i = (l + r) >> 1; if (oid > getItem(pg, i)) { l = i + 1; } else { r = i; } } OldBtreeResult result = remove(db, getItem(pg, maxItems - r - 1), oid, height); if (result == OldBtreeResult.Underflow) { db.pool.unfix(pg); pg = null; pg = db.putPage(pageId); return(handlePageUnderflow(db, pg, r, height)); } return(result); } } finally { if (pg != null) { db.pool.unfix(pg); } } }
internal PArrayImpl(DatabaseImpl db, int initSize) { this.db = db; arr = new int[initSize]; }
internal void buildFieldList(DatabaseImpl db, System.Type cls, ArrayList list) { System.Type superclass = cls.BaseType; if (superclass != null && superclass != typeof(MarshalByRefObject)) { buildFieldList(db, superclass, list); } System.Reflection.FieldInfo[] flds = cls.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly); bool isWrapper = typeof(PersistentWrapper).IsAssignableFrom(cls); bool hasTransparentAttribute = cls.GetCustomAttributes(typeof(TransparentPersistenceAttribute), true).Length != 0; for (int i = 0; i < flds.Length; i++) { FieldInfo f = flds[i]; if (!f.IsNotSerialized && !f.IsStatic) { FieldDescriptor fd = new FieldDescriptor(); fd.field = f; fd.fieldName = f.Name; fd.className = getTypeName(cls); Type fieldType = f.FieldType; FieldType type = getTypeCode(fieldType); switch (type) { case FieldType.tpInt: if (isWrapper && isObjectProperty(cls, f)) { hasReferences = true; type = FieldType.tpOid; } break; case FieldType.tpArrayOfOid: fd.constructor = GetConstructor(f, "ConstructArray"); hasReferences = true; break; case FieldType.tpLink: fd.constructor = GetConstructor(f, "ConstructLink"); hasReferences = true; break; case FieldType.tpArrayOfObject: case FieldType.tpObject: hasReferences = true; if (hasTransparentAttribute && isVolanteInternalType(fieldType)) { fd.recursiveLoading = true; } break; case FieldType.tpValue: fd.valueDesc = db.getClassDescriptor(f.FieldType); hasReferences |= fd.valueDesc.hasReferences; break; case FieldType.tpArrayOfValue: fd.valueDesc = db.getClassDescriptor(f.FieldType.GetElementType()); hasReferences |= fd.valueDesc.hasReferences; break; } fd.type = type; list.Add(fd); } } }
internal static bool prefixSearch(DatabaseImpl db, int pageId, string key, int height, ArrayList result) { Page pg = db.getPage(pageId); int l = 0, n = getnItems(pg), r = n; int oid; height -= 1; try { while (l < r) { int i = (l + r) >> 1; if (comparePrefix(key, pg, i) > 0) l = i + 1; else r = i; } Debug.Assert(r == l); if (height == 0) { while (l < n) { if (comparePrefix(key, pg, l) < 0) return false; oid = getKeyStrOid(pg, l); result.Add(db.lookupObject(oid, null)); l += 1; } } else { do { if (!prefixSearch(db, getKeyStrOid(pg, l), key, height, result)) return false; if (l == n) return true; } while (comparePrefix(key, pg, l++) >= 0); return false; } } finally { db.pool.unfix(pg); } return true; }
internal static int markPage(DatabaseImpl db, int pageId, ClassDescriptor.FieldType type, int height) { Page pg = db.getGCPage(pageId); int nPages = 1; try { int i, n = getnItems(pg); if (--height != 0) { if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) { // page of strings for (i = 0; i <= n; i++) { nPages += markPage(db, getKeyStrOid(pg, i), type, height); } } else { for (i = 0; i <= n; i++) { nPages += markPage(db, getReference(pg, maxItems - i - 1), type, height); } } } else { if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) { // page of strings for (i = 0; i < n; i++) { db.markOid(getKeyStrOid(pg, i)); } } else { // page of scalars for (i = 0; i < n; i++) { db.markOid(getReference(pg, maxItems - 1 - i)); } } } } finally { db.pool.unfix(pg); } return nPages; }
internal static OldBtreeResult insertStrKey(DatabaseImpl db, Page pg, int r, OldBtreeKey ins, int height) { int nItems = getnItems(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) { memcpy(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 { Debug.Assert(moved + (bn + 1) * strKeySize <= keySpace, "String fits in the B-Tree page"); 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)) { memcpy(pg, r - i + 1, pg, r - i, n - r, strKeySize); size += len * 2; nItems += 1; Debug.Assert(size + (n - i + 1) * strKeySize <= keySpace, "String fits in the B-Tree page"); setKeyStrOffs(pg, r - i, keySpace - size); setKeyStrSize(pg, r - i, len); setKeyStrOid(pg, r - i, ins.oid); setKeyStrChars(pg, keySpace - size, sval); } setnItems(b, bn); setSize(b, moved); setSize(pg, size); setnItems(pg, nItems); ins.oid = pageId; db.pool.unfix(b); return OldBtreeResult.Overflow; } moved += keyLen * 2; prevDelta = delta; Debug.Assert(moved + (bn + 1) * strKeySize <= keySpace, "String fits in the B-Tree page"); 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)); memcpy(b, keySpace - moved, pg, getKeyStrOffs(pg, i), keyLen * 2, 1); size -= keyLen * 2; i += 1; } } } setnItems(pg, nItems); setSize(pg, size); return size + strKeySize * (nItems + 1) < keySpace / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done; }
internal static OldBtreeResult insert(DatabaseImpl db, int pageId, Key ins, int height) { Page pg = db.getPage(pageId); int l = 0, n = getnItems(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; } } Debug.Assert(l == r); /* insert before e[r] */ OldBtreeResult result = insert(db, getItem(pg, maxItems - r - 1), ins, height); Debug.Assert(result != OldBtreeResult.NotFound); if (result != OldBtreeResult.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(OldBtreeResult.Overwrite); } } db.pool.unfix(pg); pg = null; pg = db.putPage(pageId); if (n < max) { memcpy(pg, r + 1, pg, r, n - r); memcpy(pg, maxItems - n - 1, pg, maxItems - n, n - r); setItem(pg, r, ins.key); setItem(pg, maxItems - 1 - r, ins.oid); 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); memcpy(b, r + 1, pg, r, m - r - 1); memcpy(pg, 0, pg, m - 1, max - m + 1); memcpy(b, maxItems - r, pg, maxItems - r, r); setItem(b, r, ins.key); setItem(b, maxItems - 1 - r, ins.oid); memcpy(b, maxItems - m, pg, maxItems - m + 1, m - r - 1); memcpy(pg, maxItems - max + m - 1, pg, maxItems - max, max - m + 1); } else { memcpy(b, 0, pg, 0, m); memcpy(pg, 0, pg, m, r - m); memcpy(pg, r - m + 1, pg, r, max - r); memcpy(b, maxItems - m, pg, maxItems - m, m); memcpy(pg, maxItems - r + m, pg, maxItems - r, r - m); setItem(pg, r - m, ins.key); setItem(pg, maxItems - 1 - r + m, ins.oid); memcpy(pg, maxItems - max + m - 1, pg, maxItems - max, max - r); } ins.oid = pageId; if (height == 0) { ins.key = getItem(b, maxItems - m); setnItems(pg, max - m + 1); setnItems(b, m); } else { ins.key = getItem(b, m - 1); setnItems(pg, max - m); setnItems(b, m - 1); } db.pool.unfix(b); return(OldBtreeResult.Overflow); } } finally { if (pg != null) { db.pool.unfix(pg); } } }
internal static void exportPage(DatabaseImpl db, XmlExporter exporter, int pageId, ClassDescriptor.FieldType type, int height) { Page pg = db.getPage(pageId); try { int i, n = getnItems(pg); if (--height != 0) { if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) { // page of strings for (i = 0; i <= n; i++) { exportPage(db, exporter, getKeyStrOid(pg, i), type, height); } } else { for (i = 0; i <= n; i++) { exportPage(db, exporter, getReference(pg, maxItems - i - 1), type, height); } } } else { if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) { // page of strings for (i = 0; i < n; i++) { exporter.exportAssoc(getKeyStrOid(pg, i), pg.data, OldBtreePage.firstKeyOffs + OldBtreePage.getKeyStrOffs(pg, i), OldBtreePage.getKeyStrSize(pg, i), type); } } else { // page of scalars for (i = 0; i < n; i++) { exporter.exportAssoc(getReference(pg, maxItems - 1 - i), pg.data, OldBtreePage.firstKeyOffs + i * ClassDescriptor.Sizeof[(int)type], ClassDescriptor.Sizeof[(int)type], type); } } } } finally { db.pool.unfix(pg); } }
internal static void purge(DatabaseImpl db, int pageId, ClassDescriptor.FieldType type, int height) { if (--height != 0) { Page pg = db.getPage(pageId); int n = getnItems(pg) + 1; if (type == ClassDescriptor.FieldType.tpString || type == ClassDescriptor.FieldType.tpArrayOfByte) { // page of strings while (--n >= 0) { purge(db, getKeyStrOid(pg, n), type, height); } } else { while (--n >= 0) { purge(db, getReference(pg, maxItems - n - 1), type, height); } } db.pool.unfix(pg); } db.freePage(pageId); }
internal static OldBtreeResult handlePageUnderflow(DatabaseImpl db, Page pg, int r, int height) { int nItems = getnItems(pg); Page a = db.putPage(getItem(pg, maxItems - r - 1)); int an = getnItems(a); if (r < nItems) { // exists greater page Page b = db.getPage(getItem(pg, maxItems - r - 2)); int bn = getnItems(b); Debug.Assert(bn >= an); if (height != 1) { memcpy(a, an, pg, r, 1); an += 1; bn += 1; } if (an + bn > max) { // reallocation of nodes between pages a and b int i = bn - ((an + bn) >> 1); db.pool.unfix(b); b = db.putPage(getItem(pg, maxItems - r - 2)); memcpy(a, an, b, 0, i); memcpy(b, 0, b, i, bn - i); memcpy(a, maxItems - an - i, b, maxItems - i, i); memcpy(b, maxItems - bn + i, b, maxItems - bn, bn - i); if (height != 1) { memcpy(pg, r, a, an + i - 1, 1); } else { memcpy(pg, r, a, maxItems - an - i, 1); } setnItems(b, getnItems(b) - i); setnItems(a, getnItems(a) + i); db.pool.unfix(a); db.pool.unfix(b); return(OldBtreeResult.Done); } else { // merge page b to a memcpy(a, an, b, 0, bn); memcpy(a, maxItems - an - bn, b, maxItems - bn, bn); db.freePage(getItem(pg, maxItems - r - 2)); memcpy(pg, maxItems - nItems, pg, maxItems - nItems - 1, nItems - r - 1); memcpy(pg, r, pg, r + 1, nItems - r - 1); setnItems(a, getnItems(a) + bn); setnItems(pg, nItems - 1); db.pool.unfix(a); db.pool.unfix(b); return(nItems < max / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done); } } else { // page b is before a Page b = db.getPage(getItem(pg, maxItems - r)); int bn = getnItems(b); Debug.Assert(bn >= an); if (height != 1) { an += 1; bn += 1; } if (an + bn > max) { // reallocation of nodes between pages a and b int i = bn - ((an + bn) >> 1); db.pool.unfix(b); b = db.putPage(getItem(pg, maxItems - r)); memcpy(a, i, a, 0, an); memcpy(a, 0, b, bn - i, i); memcpy(a, maxItems - an - i, a, maxItems - an, an); memcpy(a, maxItems - i, b, maxItems - bn, i); if (height != 1) { memcpy(a, i - 1, pg, r - 1, 1); memcpy(pg, r - 1, b, bn - i - 1, 1); } else { memcpy(pg, r - 1, b, maxItems - bn + i, 1); } setnItems(b, getnItems(b) - i); setnItems(a, getnItems(a) + i); db.pool.unfix(a); db.pool.unfix(b); return(OldBtreeResult.Done); } else { // merge page b to a memcpy(a, bn, a, 0, an); memcpy(a, 0, b, 0, bn); memcpy(a, maxItems - an - bn, a, maxItems - an, an); memcpy(a, maxItems - bn, b, maxItems - bn, bn); if (height != 1) { memcpy(a, bn - 1, pg, r - 1, 1); } db.freePage(getItem(pg, maxItems - r)); setItem(pg, maxItems - r, getItem(pg, maxItems - r - 1)); setnItems(a, getnItems(a) + bn); setnItems(pg, nItems - 1); db.pool.unfix(a); db.pool.unfix(b); return(nItems < max / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done); } } }
internal ClassDescriptor(DatabaseImpl db, Type cls) { this.cls = cls; name = getTypeName(cls); ArrayList list = new ArrayList(); buildFieldList(db, cls, list); allFields = (FieldDescriptor[])list.ToArray(typeof(FieldDescriptor)); defaultConstructor = cls.GetConstructor(BindingFlags.Instance | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly, null, defaultConstructorProfile, null); if (defaultConstructor == null && !typeof(ValueType).IsAssignableFrom(cls)) throw new DatabaseException(DatabaseException.ErrorCode.DESCRIPTOR_FAILURE, cls); resolved = true; }
internal static OldBtreeResult remove(DatabaseImpl db, int pageId, OldBtree tree, OldBtreeKey rem, int height) { Page pg = db.getPage(pageId); try { int i, n = getnItems(pg), l = 0, r = n; if (tree.FieldType == ClassDescriptor.FieldType.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 OldBtreeResult.Underflow: db.pool.unfix(pg); pg = null; pg = db.putPage(pageId); return handlePageUnderflow(db, pg, r, tree.FieldType, rem, height); case OldBtreeResult.Done: return OldBtreeResult.Done; case OldBtreeResult.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.FieldType == ClassDescriptor.FieldType.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 OldBtreeResult.Underflow: db.pool.unfix(pg); pg = null; pg = db.putPage(pageId); return handlePageUnderflow(db, pg, r, tree.FieldType, rem, height); case OldBtreeResult.Done: return OldBtreeResult.Done; case OldBtreeResult.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 // scalars { int itemSize = ClassDescriptor.Sizeof[(int)tree.FieldType]; 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); memcpy(pg, r, pg, r + 1, n - r - 1, itemSize); memcpy(pg, maxItems - n + 1, pg, maxItems - n, n - r - 1, 4); setnItems(pg, --n); return n * (itemSize + 4) < keySpace / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done; } } else { break; } r += 1; } return OldBtreeResult.NotFound; } do { switch (remove(db, getReference(pg, maxItems - r - 1), tree, rem, height)) { case OldBtreeResult.Underflow: db.pool.unfix(pg); pg = db.putPage(pageId); return handlePageUnderflow(db, pg, r, tree.FieldType, rem, height); case OldBtreeResult.Done: return OldBtreeResult.Done; } } while (++r <= n); } return OldBtreeResult.NotFound; } finally { if (pg != null) { db.pool.unfix(pg); } } }
internal static OldBtreeResult replaceStrKey(DatabaseImpl db, Page pg, int r, OldBtreeKey ins, int height) { ins.oid = getKeyStrOid(pg, r); removeStrKey(pg, r); return insertStrKey(db, pg, r, ins, height); }
internal ThickIndex(DatabaseImpl db) : base(db) { index = db.CreateIndex <K, IPersistent>(IndexType.Unique); }