Exemple #1
0
 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();
        }
Exemple #3
0
 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);
            }
Exemple #6
0
 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);
        }
Exemple #12
0
 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;
 }
Exemple #14
0
 public XmlExporter(DatabaseImpl db, System.IO.StreamWriter writer)
 {
     this.db = db;
     this.writer = writer;
 }
Exemple #15
0
        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;
                    }
                }
            }
        }
Exemple #16
0
        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;
        }
Exemple #17
0
 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);
     }
 }
Exemple #18
0
 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);
                    }
                }
            }
Exemple #20
0
 internal PArrayImpl(DatabaseImpl db, int initSize)
 {
     this.db = db;
     arr     = new int[initSize];
 }
Exemple #21
0
        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);
                }
            }
        }
Exemple #22
0
        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;
        }
Exemple #23
0
 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;
 }
Exemple #24
0
        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 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 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);
                    }
                }
            }
Exemple #27
0
 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);
     }
 }
Exemple #28
0
 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);
                    }
                }
            }
Exemple #30
0
 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;
 }
Exemple #31
0
        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);

                }
            }
        }
Exemple #32
0
 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);
 }
Exemple #33
0
 internal ThickIndex(DatabaseImpl db)
     : base(db)
 {
     index = db.CreateIndex <K, IPersistent>(IndexType.Unique);
 }