Inheritance: LRU, IComparable
Beispiel #1
0
 internal void close()
 {
     lock (this)
     {
         file.Close();
         hashTable = null;
         dirtyPages = null;
         lru = null;
         freePages = null;
     }
 }
Beispiel #2
0
        internal static OldBtreeResult removeStrKey(Page pg, int r)
        {
            int len = getKeyStrSize(pg, r) * 2;
            int offs = getKeyStrOffs(pg, r);
            int size = getSize(pg);
            int nItems = getnItems(pg);
            if ((nItems + 1) * strKeySize >= keySpace)
                memcpy(pg, r, pg, r + 1, nItems - r - 1, strKeySize);
            else
                memcpy(pg, r, pg, r + 1, nItems - r, strKeySize);

            if (len != 0)
            {
                memcpy(pg, keySpace - size + len, pg, keySpace - size, size - keySpace + offs, 1);
                for (int i = nItems; --i >= 0; )
                {
                    if (getKeyStrOffs(pg, i) < offs)
                        setKeyStrOffs(pg, i, getKeyStrOffs(pg, i) + len);
                }
                setSize(pg, size -= len);
            }
            setnItems(pg, nItems - 1);
            return size + strKeySize * nItems < keySpace / 2 ? OldBtreeResult.Underflow : OldBtreeResult.Done;
        }
Beispiel #3
0
        internal void open(IFile f)
        {
            file = f;
            hashTable = new Page[poolSize];
            dirtyPages = new Page[poolSize];
            nDirtyPages = 0;
            lru = new LRU();
            freePages = null;
            if (autoExtended)
                return;

            for (int i = poolSize; --i >= 0; )
            {
                Page pg = new Page();
                pg.next = freePages;
                freePages = pg;
            }
        }
Beispiel #4
0
 internal void getStr(Page pg, int i)
 {
     int len = OldBtreePage.getKeyStrSize(pg, i);
     int offs = OldBtreePage.firstKeyOffs + OldBtreePage.getKeyStrOffs(pg, i);
     char[] sval = new char[len];
     for (int j = 0; j < len; j++)
     {
         sval[j] = (char)Bytes.unpack2(pg.data, offs);
         offs += 2;
     }
     key = new Key(sval);
 }
Beispiel #5
0
        internal void extract(Page pg, int offs, ClassDescriptor.FieldType type)
        {
            byte[] data = pg.data;

            switch (type)
            {
                case ClassDescriptor.FieldType.tpBoolean:
                    key = new Key(data[offs] != 0);
                    break;

                case ClassDescriptor.FieldType.tpSByte:
                    key = new Key((sbyte)data[offs]);
                    break;
                case ClassDescriptor.FieldType.tpByte:
                    key = new Key(data[offs]);
                    break;

                case ClassDescriptor.FieldType.tpShort:
                    key = new Key(Bytes.unpack2(data, offs));
                    break;
                case ClassDescriptor.FieldType.tpUShort:
                    key = new Key((ushort)Bytes.unpack2(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpChar:
                    key = new Key((char)Bytes.unpack2(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpInt:
                    key = new Key(Bytes.unpack4(data, offs));
                    break;
                case ClassDescriptor.FieldType.tpEnum:
                case ClassDescriptor.FieldType.tpUInt:
                case ClassDescriptor.FieldType.tpObject:
                case ClassDescriptor.FieldType.tpOid:
                    key = new Key((uint)Bytes.unpack4(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpLong:
                    key = new Key(Bytes.unpack8(data, offs));
                    break;
                case ClassDescriptor.FieldType.tpDate:
                case ClassDescriptor.FieldType.tpULong:
                    key = new Key((ulong)Bytes.unpack8(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpFloat:
                    key = new Key(Bytes.unpackF4(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpDouble:
                    key = new Key(Bytes.unpackF8(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpGuid:
                    key = new Key(Bytes.unpackGuid(data, offs));
                    break;

                case ClassDescriptor.FieldType.tpDecimal:
                    key = new Key(Bytes.unpackDecimal(data, offs));
                    break;

                default:
                    Debug.Assert(false, "Invalid type");
                    break;

            }
        }
Beispiel #6
0
 internal static int getSize(Page pg)
 {
     return Bytes.unpack2(pg.data, 2);
 }
Beispiel #7
0
        internal static int compactifyByteArrays(Page pg, int m)
        {
            int i, j, offs, len, n = getnItems(pg);
            int[] size = new int[keySpace + 1];
            int[] index = new int[keySpace + 1];
            if (m == 0)
                return n;

            int nZeroLengthArrays = 0;
            if (m < 0)
            {
                m = -m;
                for (i = 0; i < n - m; i++)
                {
                    len = getKeyStrSize(pg, i);
                    if (len != 0)
                    {
                        offs = getKeyStrOffs(pg, i);
                        size[offs + len] = len;
                        index[offs + len] = i;
                    }
                    else
                    {
                        nZeroLengthArrays += 1;
                    }
                }
                for (; i < n; i++)
                {
                    len = getKeyStrSize(pg, i);
                    if (len != 0)
                    {
                        offs = getKeyStrOffs(pg, i);
                        size[offs + len] = len;
                        index[offs + len] = -1;
                    }
                }
            }
            else
            {
                for (i = 0; i < m; i++)
                {
                    len = getKeyStrSize(pg, i);
                    if (len != 0)
                    {
                        offs = getKeyStrOffs(pg, i);
                        size[offs + len] = len;
                        index[offs + len] = -1;
                    }
                }
                for (; i < n; i++)
                {
                    len = getKeyStrSize(pg, i);
                    if (len != 0)
                    {
                        offs = getKeyStrOffs(pg, i);
                        size[offs + len] = len;
                        index[offs + len] = i - m;
                    }
                    else
                    {
                        nZeroLengthArrays += 1;
                    }
                    setKeyStrOid(pg, i - m, getKeyStrOid(pg, i));
                    setKeyStrSize(pg, i - m, len);
                }
                setKeyStrOid(pg, i - m, getKeyStrOid(pg, i));
            }
            int nItems = n -= m;
            n -= nZeroLengthArrays;
            for (offs = keySpace, i = offs; n != 0; i -= len)
            {
                len = size[i];
                j = index[i];
                if (j >= 0)
                {
                    offs -= len;
                    n -= 1;
                    setKeyStrOffs(pg, j, offs);
                    if (offs != i - len)
                        memcpy(pg, offs, pg, i - len, len, 1);
                }
            }
            return nItems;
        }
Beispiel #8
0
 internal static void setKeyStrSize(Page pg, int index, int size)
 {
     Bytes.pack2(pg.data, firstKeyOffs + index * 8 + 4, (short)size);
 }
Beispiel #9
0
 internal static void setnItems(Page pg, int nItems)
 {
     Bytes.pack2(pg.data, 0, (short)nItems);
 }
Beispiel #10
0
 internal static void setKeyStrOffs(Page pg, int index, int offs)
 {
     Bytes.pack2(pg.data, firstKeyOffs + index * 8 + 6, (short)offs);
 }
Beispiel #11
0
 internal static void setKeyStrOid(Page pg, int index, int oid)
 {
     Bytes.pack4(pg.data, firstKeyOffs + index * 8, oid);
 }
Beispiel #12
0
 internal static void setKeyStrChars(Page pg, int offs, char[] str)
 {
     int len = str.Length;
     for (int i = 0; i < len; i++)
     {
         Bytes.pack2(pg.data, firstKeyOffs + offs, (short)str[i]);
         offs += 2;
     }
 }
Beispiel #13
0
 internal static void setKeyBytes(Page pg, int offs, byte[] bytes)
 {
     Array.Copy(bytes, 0, pg.data, firstKeyOffs + offs, bytes.Length);
 }
Beispiel #14
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);
 }
Beispiel #15
0
 internal static int getnItems(Page pg)
 {
     return Bytes.unpack2(pg.data, 0);
 }
Beispiel #16
0
 internal static void setReference(Page pg, int index, int oid)
 {
     Bytes.pack4(pg.data, firstKeyOffs + index * 4, oid);
 }
Beispiel #17
0
 internal static int getReference(Page pg, int index)
 {
     return Bytes.unpack4(pg.data, firstKeyOffs + index * 4);
 }
Beispiel #18
0
 internal static void setSize(Page pg, int size)
 {
     Bytes.pack2(pg.data, 2, (short)size);
 }
Beispiel #19
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;
                    }
                }
            }
        }
Beispiel #20
0
 static int comparePrefix(string key, Page pg, int i)
 {
     int alen = key.Length;
     int blen = OldBtreePage.getKeyStrSize(pg, i);
     int minlen = alen < blen ? alen : blen;
     int offs = OldBtreePage.getKeyStrOffs(pg, i) + OldBtreePage.firstKeyOffs;
     byte[] b = pg.data;
     for (int j = 0; j < minlen; j++)
     {
         char c = (char)Bytes.unpack2(b, offs);
         int diff = key[j] - c;
         if (diff != 0)
             return diff;
         offs += 2;
     }
     return minlen - alen;
 }
Beispiel #21
0
 internal void getByteArray(Page pg, int i)
 {
     int len = OldBtreePage.getKeyStrSize(pg, i);
     int offs = OldBtreePage.firstKeyOffs + OldBtreePage.getKeyStrOffs(pg, i);
     byte[] bval = new byte[len];
     Array.Copy(pg.data, offs, bval, 0, len);
     key = new Key(bval);
 }
Beispiel #22
0
        internal static int compare(Key key, Page pg, int i)
        {
            long i8;
            ulong u8;
            int i4;
            uint u4;
            float r4;
            double r8;
            switch (key.type)
            {
                case ClassDescriptor.FieldType.tpSByte:
                    return (sbyte)key.ival - (sbyte)pg.data[OldBtreePage.firstKeyOffs + i];

                case ClassDescriptor.FieldType.tpBoolean:
                case ClassDescriptor.FieldType.tpByte:
                    return (byte)key.ival - pg.data[OldBtreePage.firstKeyOffs + i];

                case ClassDescriptor.FieldType.tpShort:
                    return (short)key.ival - Bytes.unpack2(pg.data, OldBtreePage.firstKeyOffs + i * 2);
                case ClassDescriptor.FieldType.tpUShort:
                    return (ushort)key.ival - (ushort)Bytes.unpack2(pg.data, OldBtreePage.firstKeyOffs + i * 2);

                case ClassDescriptor.FieldType.tpChar:
                    return (char)key.ival - (char)Bytes.unpack2(pg.data, OldBtreePage.firstKeyOffs + i * 2);

                case ClassDescriptor.FieldType.tpObject:
                case ClassDescriptor.FieldType.tpUInt:
                case ClassDescriptor.FieldType.tpOid:
                case ClassDescriptor.FieldType.tpEnum:
                    u4 = (uint)Bytes.unpack4(pg.data, OldBtreePage.firstKeyOffs + i * 4);
                    return (uint)key.ival < u4 ? -1 : (uint)key.ival == u4 ? 0 : 1;

                case ClassDescriptor.FieldType.tpInt:
                    i4 = Bytes.unpack4(pg.data, OldBtreePage.firstKeyOffs + i * 4);
                    return key.ival < i4 ? -1 : key.ival == i4 ? 0 : 1;

                case ClassDescriptor.FieldType.tpLong:
                    i8 = Bytes.unpack8(pg.data, OldBtreePage.firstKeyOffs + i * 8);
                    return key.lval < i8 ? -1 : key.lval == i8 ? 0 : 1;

                case ClassDescriptor.FieldType.tpDate:
                case ClassDescriptor.FieldType.tpULong:
                    u8 = (ulong)Bytes.unpack8(pg.data, OldBtreePage.firstKeyOffs + i * 8);
                    return (ulong)key.lval < u8 ? -1 : (ulong)key.lval == u8 ? 0 : 1;

                case ClassDescriptor.FieldType.tpFloat:
                    r4 = Bytes.unpackF4(pg.data, OldBtreePage.firstKeyOffs + i * 4);
                    return key.dval < r4 ? -1 : key.dval == r4 ? 0 : 1;

                case ClassDescriptor.FieldType.tpDouble:
                    r8 = Bytes.unpackF8(pg.data, OldBtreePage.firstKeyOffs + i * 8);
                    return key.dval < r8 ? -1 : key.dval == r8 ? 0 : 1;

                case ClassDescriptor.FieldType.tpDecimal:
                    return key.dec.CompareTo(Bytes.unpackDecimal(pg.data, OldBtreePage.firstKeyOffs + i * 16));

                case ClassDescriptor.FieldType.tpGuid:
                    return key.guid.CompareTo(Bytes.unpackGuid(pg.data, OldBtreePage.firstKeyOffs + i * 16));
            }
            Debug.Assert(false, "Invalid type");
            return 0;
        }
Beispiel #23
0
        internal void pack(Page pg, int i)
        {
            byte[] dst = pg.data;
            switch (key.type)
            {
                case ClassDescriptor.FieldType.tpBoolean:
                case ClassDescriptor.FieldType.tpSByte:
                case ClassDescriptor.FieldType.tpByte:
                    dst[OldBtreePage.firstKeyOffs + i] = (byte)key.ival;
                    break;

                case ClassDescriptor.FieldType.tpShort:
                case ClassDescriptor.FieldType.tpUShort:
                case ClassDescriptor.FieldType.tpChar:
                    Bytes.pack2(dst, OldBtreePage.firstKeyOffs + i * 2, (short)key.ival);
                    break;

                case ClassDescriptor.FieldType.tpInt:
                case ClassDescriptor.FieldType.tpUInt:
                case ClassDescriptor.FieldType.tpEnum:
                case ClassDescriptor.FieldType.tpObject:
                case ClassDescriptor.FieldType.tpOid:
                    Bytes.pack4(dst, OldBtreePage.firstKeyOffs + i * 4, key.ival);
                    break;

                case ClassDescriptor.FieldType.tpLong:
                case ClassDescriptor.FieldType.tpULong:
                case ClassDescriptor.FieldType.tpDate:
                    Bytes.pack8(dst, OldBtreePage.firstKeyOffs + i * 8, key.lval);
                    break;

                case ClassDescriptor.FieldType.tpFloat:
                    Bytes.packF4(dst, OldBtreePage.firstKeyOffs + i * 4, (float)key.dval);
                    break;

                case ClassDescriptor.FieldType.tpDouble:
                    Bytes.packF8(dst, OldBtreePage.firstKeyOffs + i * 8, key.dval);
                    break;

                case ClassDescriptor.FieldType.tpDecimal:
                    Bytes.packDecimal(dst, OldBtreePage.firstKeyOffs + i * 16, key.dec);
                    break;

                case ClassDescriptor.FieldType.tpGuid:
                    Bytes.packGuid(dst, OldBtreePage.firstKeyOffs + i * 16, key.guid);
                    break;

                default:
                    Debug.Assert(false, "Invalid type");
                    break;

            }
            Bytes.pack4(dst, OldBtreePage.firstKeyOffs + (OldBtreePage.maxItems - i - 1) * 4, oid);
        }
Beispiel #24
0
 internal static int compareStr(Key key, Page pg, int i)
 {
     char[] chars = null;
     string s = key.oval as string;
     if (s != null)
         chars = s.ToCharArray();
     else
         chars = (char[])key.oval;
     int alen = chars.Length;
     int blen = OldBtreePage.getKeyStrSize(pg, i);
     int minlen = alen < blen ? alen : blen;
     int offs = OldBtreePage.getKeyStrOffs(pg, i) + OldBtreePage.firstKeyOffs;
     byte[] b = pg.data;
     for (int j = 0; j < minlen; j++)
     {
         int diff = chars[j] - (char)Bytes.unpack2(b, offs);
         if (diff != 0)
             return diff;
         offs += 2;
     }
     return alen - blen;
 }
Beispiel #25
0
 internal void modify(Page pg)
 {
     lock (this)
     {
         Debug.Assert(pg.accessCount > 0);
         if ((pg.state & Page.psDirty) == 0)
         {
             Debug.Assert(!flushing);
             pg.state |= Page.psDirty;
             if (nDirtyPages >= dirtyPages.Length)
             {
                 Page[] newDirtyPages = new Page[nDirtyPages * 2];
                 Array.Copy(dirtyPages, 0, newDirtyPages, 0, dirtyPages.Length);
                 dirtyPages = newDirtyPages;
             }
             dirtyPages[nDirtyPages] = pg;
             pg.writeQueueIndex = nDirtyPages++;
         }
     }
 }
Beispiel #26
0
 internal static int getKeyStrOid(Page pg, int index)
 {
     return Bytes.unpack4(pg.data, firstKeyOffs + index * 8);
 }
Beispiel #27
0
 internal void unfix(Page pg)
 {
     lock (this)
     {
         Debug.Assert(pg.accessCount > 0);
         if (--pg.accessCount == 0)
         {
             lru.link(pg);
         }
     }
 }
Beispiel #28
0
 internal static int getKeyStrSize(Page pg, int index)
 {
     return Bytes.unpack2(pg.data, firstKeyOffs + index * 8 + 4);
 }
Beispiel #29
0
        internal Page find(long addr, int state)
        {
            Debug.Assert((addr & (Page.pageSize - 1)) == 0);
            Page pg;
            int pageNo = (int)((ulong)addr >> Page.pageBits);
            int hashCode = pageNo % poolSize;

            lock (this)
            {
                int nCollisions = 0;
                for (pg = hashTable[hashCode]; pg != null; pg = pg.collisionChain)
                {
                    if (pg.offs == addr)
                    {
                        if (pg.accessCount++ == 0)
                            pg.unlink();
                        break;
                    }
                    nCollisions += 1;
                }
                if (pg == null)
                {
                    pg = freePages;
                    if (pg != null)
                        freePages = (Page)pg.next;
                    else if (autoExtended)
                    {
                        if (pageNo >= poolSize)
                        {
                            int newPoolSize = pageNo >= poolSize * 2 ? pageNo + 1 : poolSize * 2;
                            Page[] newHashTable = new Page[newPoolSize];
                            Array.Copy(hashTable, 0, newHashTable, 0, hashTable.Length);
                            hashTable = newHashTable;
                            poolSize = newPoolSize;
                        }
                        pg = new Page();
                        hashCode = pageNo;
                    }
                    else
                    {
                        Debug.Assert(lru.prev != lru, "unfixed page available");
                        pg = (Page)lru.prev;
                        pg.unlink();
                        lock (pg)
                        {
                            if ((pg.state & Page.psDirty) != 0)
                            {
                                pg.state = 0;
                                file.Write(pg.offs, pg.data);
                                if (!flushing)
                                {
                                    dirtyPages[pg.writeQueueIndex] = dirtyPages[--nDirtyPages];
                                    dirtyPages[pg.writeQueueIndex].writeQueueIndex = pg.writeQueueIndex;
                                }
                            }
                        }
                        int h = (int)(pg.offs >> Page.pageBits) % poolSize;
                        Page curr = hashTable[h], prev = null;
                        while (curr != pg)
                        {
                            prev = curr;
                            curr = curr.collisionChain;
                        }

                        if (prev == null)
                            hashTable[h] = pg.collisionChain;
                        else
                            prev.collisionChain = pg.collisionChain;
                    }
                    pg.accessCount = 1;
                    pg.offs = addr;
                    pg.state = Page.psRaw;
                    pg.collisionChain = hashTable[hashCode];
                    hashTable[hashCode] = pg;
                }
                if ((pg.state & Page.psDirty) == 0 && (state & Page.psDirty) != 0)
                {
                    Debug.Assert(!flushing);
                    if (nDirtyPages >= dirtyPages.Length)
                    {
                        Page[] newDirtyPages = new Page[nDirtyPages * 2];
                        Array.Copy(dirtyPages, 0, newDirtyPages, 0, dirtyPages.Length);
                        dirtyPages = newDirtyPages;
                    }
                    dirtyPages[nDirtyPages] = pg;
                    pg.writeQueueIndex = nDirtyPages++;
                    pg.state |= Page.psDirty;
                }

                if ((pg.state & Page.psRaw) != 0)
                {
                    if (file.Read(pg.offs, pg.data) < Page.pageSize)
                        Array.Clear(pg.data, 0, Page.pageSize);

                    pg.state &= ~Page.psRaw;
                }
            }
            return pg;
        }
Beispiel #30
0
 internal static void memcpy(Page dst_pg, int dst_idx, Page src_pg, int src_idx, int len, int itemSize)
 {
     Array.Copy(src_pg.data, firstKeyOffs + src_idx * itemSize, dst_pg.data, firstKeyOffs + dst_idx * itemSize, len * itemSize);
 }