Beispiel #1
0
        internal static int HandlePageUnderflow(StorageImpl db, Page pg, int r, int type, BtreeKey rem, int height)
        {
            int nItems = GetItemsCount(pg);
            if (type == ClassDescriptor.tpString)
            {
                Page a = db.PutPage(GetKeyStrOid(pg, r));
                int an = GetItemsCount(a);
                if (r < nItems)
                {
                    // exists greater page
                    Page b = db.GetPage(GetKeyStrOid(pg, r + 1));
                    int bn = GetItemsCount(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);
                            }
                        }
                        int result = Btree.op_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);
                                MemCopy(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));
                                MemCopy(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);
                            SetItemsCount(a, an);
                            SetItemsCount(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));
                            MemCopy(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));
                        SetItemsCount(a, an);
                        MemCopy(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 = GetItemsCount(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);
                            }
                        }
                        int result = Btree.op_done;
                        if (i > 0)
                        {
                            k = i;
                            Assert.That(i < bn);
                            if (height != 1)
                            {
                                SetSize(b, GetSize(b) - GetKeyStrSize(b, bn - k) * 2);
                                MemCopy(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));
                                MemCopy(a, GetKeyStrOffs(a, k), pg, GetKeyStrOffs(pg, r - 1), len * 2, 1);
                            }
                            else
                            {
                                MemCopy(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));
                                MemCopy(a, GetKeyStrOffs(a, j), b, GetKeyStrOffs(b, bn - k + j), len * 2, 1);
                            }
                            an += i;
                            SetItemsCount(a, an);
                            rem.GetStr(b, bn - k - 1);
                            result = ReplaceStrKey(db, pg, r - 1, rem, height);
                            SetItemsCount(b, CompactifyStrings(b, -i));
                        }
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return result;
                    }
                    else
                    {
                        // merge page b to a
                        if (height != 1)
                        {
                            MemCopy(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));
                            MemCopy(a, GetKeyStrOffs(a, bn), pg, GetKeyStrOffs(pg, r - 1), len * 2, 1);
                            an += 1;
                        }
                        else
                        {
                            MemCopy(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;
                        SetItemsCount(a, an);
                        SetSize(a, GetSize(a) + GetSize(b));
                        MemCopy(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.tpArrayOfByte)
            {
                Page a = db.PutPage(GetKeyStrOid(pg, r));
                int an = GetItemsCount(a);
                if (r < nItems)
                {
                    // exists greater page
                    Page b = db.GetPage(GetKeyStrOid(pg, r + 1));
                    int bn = GetItemsCount(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);
                            }
                        }
                        int result = Btree.op_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);
                                MemCopy(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));
                                MemCopy(a, GetKeyStrOffs(a, an), b, GetKeyStrOffs(b, j), len, 1);
                                an += 1;
                            }
                            rem.GetByteArray(b, i - 1);
                            result = ReplaceByteArrayKey(db, pg, r, rem, height);
                            SetItemsCount(a, an);
                            SetItemsCount(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));
                            MemCopy(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));
                        SetItemsCount(a, an);
                        MemCopy(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 = GetItemsCount(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);
                            }
                        }
                        int result = Btree.op_done;
                        if (i > 0)
                        {
                            k = i;
                            Assert.That(i < bn);
                            if (height != 1)
                            {
                                SetSize(b, GetSize(b) - GetKeyStrSize(b, bn - k));
                                MemCopy(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));
                                MemCopy(a, GetKeyStrOffs(a, k), pg, GetKeyStrOffs(pg, r - 1), len, 1);
                            }
                            else
                            {
                                MemCopy(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));
                                MemCopy(a, GetKeyStrOffs(a, j), b, GetKeyStrOffs(b, bn - k + j), len, 1);
                            }
                            an += i;
                            SetItemsCount(a, an);
                            rem.GetByteArray(b, bn - k - 1);
                            result = ReplaceByteArrayKey(db, pg, r - 1, rem, height);
                            SetItemsCount(b, CompactifyByteArrays(b, -i));
                        }
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return result;
                    }
                    else
                    {
                        // merge page b to a
                        if (height != 1)
                        {
                            MemCopy(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));
                            MemCopy(a, GetKeyStrOffs(a, bn), pg, GetKeyStrOffs(pg, r - 1), len, 1);
                            an += 1;
                        }
                        else
                        {
                            MemCopy(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;
                        SetItemsCount(a, an);
                        SetSize(a, GetSize(a) + GetSize(b));
                        MemCopy(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
            {
                // scalar types
                Page a = db.PutPage(GetReference(pg, maxItems - r - 1));
                int an = GetItemsCount(a);
                int itemSize = ClassDescriptor.Sizeof[type];
                if (r < nItems)
                {
                    // exists greater page
                    Page b = db.GetPage(GetReference(pg, maxItems - r - 2));
                    int bn = GetItemsCount(b);
                    Assert.That(bn >= an);
                    if (height != 1)
                    {
                        MemCopy(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));
                        MemCopy(a, an, b, 0, i, itemSize);
                        MemCopy(b, 0, b, i, bn - i, itemSize);
                        MemCopy(a, maxItems - an - i, b, maxItems - i, i, 4);
                        MemCopy(b, maxItems - bn + i, b, maxItems - bn, bn - i, 4);
                        MemCopy(pg, r, a, an + i - 1, 1, itemSize);
                        SetItemsCount(b, GetItemsCount(b) - i);
                        SetItemsCount(a, GetItemsCount(a) + i);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return Btree.op_done;
                    }
                    else
                    {
                        // merge page b to a
                        MemCopy(a, an, b, 0, bn, itemSize);
                        MemCopy(a, maxItems - an - bn, b, maxItems - bn, bn, 4);
                        db.FreePage(GetReference(pg, maxItems - r - 2));
                        MemCopy(pg, maxItems - nItems, pg, maxItems - nItems - 1, nItems - r - 1, 4);
                        MemCopy(pg, r, pg, r + 1, nItems - r - 1, itemSize);
                        SetItemsCount(a, GetItemsCount(a) + bn);
                        SetItemsCount(pg, nItems - 1);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return nItems * (itemSize + 4) < keySpace / 2 ? Btree.op_underflow : Btree.op_done;
                    }
                }
                else
                {
                    // page b is before a
                    Page b = db.GetPage(GetReference(pg, maxItems - r));
                    int bn = GetItemsCount(b);
                    Assert.That(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));
                        MemCopy(a, i, a, 0, an, itemSize);
                        MemCopy(a, 0, b, bn - i, i, itemSize);
                        MemCopy(a, maxItems - an - i, a, maxItems - an, an, 4);
                        MemCopy(a, maxItems - i, b, maxItems - bn, i, 4);
                        if (height != 1)
                        {
                            MemCopy(a, i - 1, pg, r - 1, 1, itemSize);
                        }
                        MemCopy(pg, r - 1, b, bn - i - 1, 1, itemSize);
                        SetItemsCount(b, GetItemsCount(b) - i);
                        SetItemsCount(a, GetItemsCount(a) + i);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return Btree.op_done;
                    }
                    else
                    {
                        // merge page b to a
                        MemCopy(a, bn, a, 0, an, itemSize);
                        MemCopy(a, 0, b, 0, bn, itemSize);
                        MemCopy(a, maxItems - an - bn, a, maxItems - an, an, 4);
                        MemCopy(a, maxItems - bn, b, maxItems - bn, bn, 4);
                        if (height != 1)
                        {
                            MemCopy(a, bn - 1, pg, r - 1, 1, itemSize);
                        }
                        db.FreePage(GetReference(pg, maxItems - r));
                        SetReference(pg, maxItems - r, GetReference(pg, maxItems - r - 1));
                        SetItemsCount(a, GetItemsCount(a) + bn);
                        SetItemsCount(pg, nItems - 1);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return nItems * (itemSize + 4) < keySpace / 2 ? Btree.op_underflow : Btree.op_done;
                    }
                }
            }
        }
Beispiel #2
0
 internal static void ExportPage(StorageImpl db, XMLExporter exporter, int pageId, int type, int height)
 {
     Page pg = db.GetPage(pageId);
     try
     {
         int i, n = GetItemsCount(pg);
         if (--height != 0)
         {
             if (type == ClassDescriptor.tpString || type == ClassDescriptor.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.tpString || type == ClassDescriptor.tpArrayOfByte)
             {
                 // page of strings
                 for (i = 0; i < n; i++)
                 {
                     exporter.ExportAssoc(GetKeyStrOid(pg, i), pg.data, BtreePage.firstKeyOffs + BtreePage.GetKeyStrOffs(pg, i), BtreePage.GetKeyStrSize(pg, i), type);
                 }
             }
             else
             {
                 for (i = 0; i < n; i++)
                 {
                     exporter.ExportAssoc(GetReference(pg, maxItems - 1 - i), pg.data, BtreePage.firstKeyOffs + i * ClassDescriptor.Sizeof[type], ClassDescriptor.Sizeof[type], type);
                 }
             }
         }
     }
     finally
     {
         db.pool.Unfix(pg);
     }
 }
Beispiel #3
0
 internal static bool Find(StorageImpl db, int pageId, Key firstKey, Key lastKey, Btree tree, int height, ArrayList result)
 {
     Page pg = db.GetPage(pageId);
     int l = 0, n = GetItemsCount(pg), r = n;
     int oid;
     height -= 1;
     try
     {
         if (tree.type == ClassDescriptor.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;
                     }
                 }
                 Assert.That(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.type == ClassDescriptor.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;
                     }
                 }
                 Assert.That(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;
                     }
                 }
                 Assert.That(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;
 }
Beispiel #4
0
        internal static int Remove(StorageImpl db, int pageId, Btree tree, BtreeKey rem, int height)
        {
            Page pg = db.GetPage(pageId);
            try
            {
                int i, n = GetItemsCount(pg), l = 0, r = n;

                if (tree.type == ClassDescriptor.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 Btree.op_underflow:
                                    db.pool.Unfix(pg);
                                    pg = null;
                                    pg = db.PutPage(pageId);
                                    return HandlePageUnderflow(db, pg, r, tree.type, rem, height);

                                case Btree.op_done:
                                    return Btree.op_done;

                                case Btree.op_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.type == ClassDescriptor.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 Btree.op_underflow:
                                    db.pool.Unfix(pg);
                                    pg = null;
                                    pg = db.PutPage(pageId);
                                    return HandlePageUnderflow(db, pg, r, tree.type, rem, height);

                                case Btree.op_done:
                                    return Btree.op_done;

                                case Btree.op_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
                {
                    // scalar types
                    int itemSize = ClassDescriptor.Sizeof[tree.type];
                    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);
                                    MemCopy(pg, r, pg, r + 1, n - r - 1, itemSize);
                                    MemCopy(pg, maxItems - n + 1, pg, maxItems - n, n - r - 1, 4);
                                    SetItemsCount(pg, --n);
                                    return n * (itemSize + 4) < keySpace / 2 ? Btree.op_underflow : Btree.op_done;
                                }
                            }
                            else
                            {
                                break;
                            }
                            r += 1;
                        }
                        return Btree.op_not_found;
                    }
                    do
                    {
                        switch (Remove(db, GetReference(pg, maxItems - r - 1), tree, rem, height))
                        {
                            case Btree.op_underflow:
                                db.pool.Unfix(pg);
                                pg = null;
                                pg = db.PutPage(pageId);
                                return HandlePageUnderflow(db, pg, r, tree.type, rem, height);

                            case Btree.op_done:
                                return Btree.op_done;
                            }
                    }
                    while (++r <= n);
                }
                return Btree.op_not_found;
            }
            finally
            {
                if (pg != null)
                {
                    db.pool.Unfix(pg);
                }
            }
        }
Beispiel #5
0
 internal static int TraverseForward(StorageImpl db, int pageId, int type, int height, IPersistent[] result, int pos)
 {
     Page pg = db.GetPage(pageId);
     int oid;
     try
     {
         int i, n = GetItemsCount(pg);
         if (--height != 0)
         {
             if (type == ClassDescriptor.tpString || type == ClassDescriptor.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.tpString || type == ClassDescriptor.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);
     }
 }
Beispiel #6
0
 internal static bool PrefixSearch(StorageImpl db, int pageId, char[] key, int height, ArrayList result)
 {
     Page pg = db.GetPage(pageId);
     int l = 0, n = GetItemsCount(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;
             }
         }
         Assert.That(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;
 }
Beispiel #7
0
 internal static void Purge(StorageImpl db, int pageId, int type, int height)
 {
     if (--height != 0)
     {
         Page pg = db.GetPage(pageId);
         int n = GetItemsCount(pg) + 1;
         if (type == ClassDescriptor.tpString || type == ClassDescriptor.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);
 }
Beispiel #8
0
 internal static int Insert(StorageImpl db, int pageId, Btree tree, BtreeKey ins, int height, bool unique, bool overwrite)
 {
     Page pg = db.GetPage(pageId);
     int result;
     int l = 0, n = GetItemsCount(pg), r = n;
     try
     {
         if (tree.type == ClassDescriptor.tpString)
         {
             while (l < r)
             {
                 int i = (l + r) >> 1;
                 if (CompareStr(ins.key, pg, i) > 0)
                 {
                     l = i + 1;
                 }
                 else
                 {
                     r = i;
                 }
             }
             Assert.That(l == r);
             if (--height != 0)
             {
                 result = Insert(db, GetKeyStrOid(pg, r), tree, ins, height, unique, overwrite);
                 Assert.That(result != Btree.op_not_found);
                 if (result != Btree.op_overflow)
                 {
                     return result;
                 }
             }
             else if (r < n && CompareStr(ins.key, pg, r) == 0)
             {
                 if (overwrite)
                 {
                     db.pool.Unfix(pg);
                     pg = null;
                     pg = db.PutPage(pageId);
                     ins.oldOid = GetKeyStrOid(pg, r);
                     SetKeyStrOid(pg, r, ins.oid);
                     return Btree.op_overwrite;
                 }
                 else if (unique)
                 {
                     return Btree.op_duplicate;
                 }
             }
             db.pool.Unfix(pg);
             pg = null;
             pg = db.PutPage(pageId);
             return InsertStrKey(db, pg, r, ins, height);
         }
         else if (tree.type == ClassDescriptor.tpArrayOfByte)
         {
             while (l < r)
             {
                 int i = (l + r) >> 1;
                 if (tree.CompareByteArrays(ins.key, pg, i) > 0)
                 {
                     l = i + 1;
                 }
                 else
                 {
                     r = i;
                 }
             }
             Assert.That(l == r);
             if (--height != 0)
             {
                 result = Insert(db, GetKeyStrOid(pg, r), tree, ins, height, unique, overwrite);
                 Assert.That(result != Btree.op_not_found);
                 if (result != Btree.op_overflow)
                 {
                     return result;
                 }
             }
             else if (r < n && tree.CompareByteArrays(ins.key, pg, r) == 0)
             {
                 if (overwrite)
                 {
                     db.pool.Unfix(pg);
                     pg = null;
                     pg = db.PutPage(pageId);
                     ins.oldOid = GetKeyStrOid(pg, r);
                     SetKeyStrOid(pg, r, ins.oid);
                     return Btree.op_overwrite;
                 }
                 else if (unique)
                 {
                     return Btree.op_duplicate;
                 }
             }
             db.pool.Unfix(pg);
             pg = null;
             pg = db.PutPage(pageId);
             return InsertByteArrayKey(db, pg, r, ins, height);
         }
         else
         {
             while (l < r)
             {
                 int i = (l + r) >> 1;
                 if (Compare(ins.key, pg, i) > 0)
                     l = i + 1;
                 else
                     r = i;
             }
             Assert.That(l == r);
             /* insert before e[r] */
             if (--height != 0)
             {
                 result = Insert(db, GetReference(pg, maxItems - r - 1), tree, ins, height, unique, overwrite);
                 Assert.That(result != Btree.op_not_found);
                 if (result != Btree.op_overflow)
                 {
                     return result;
                 }
                 n += 1;
             }
             else if (r < n && Compare(ins.key, pg, r) == 0)
             {
                 if (overwrite)
                 {
                     db.pool.Unfix(pg);
                     pg = null;
                     pg = db.PutPage(pageId);
                     ins.oldOid = GetReference(pg, maxItems - r - 1);
                     SetReference(pg, maxItems - r - 1, ins.oid);
                     return Btree.op_overwrite;
                 }
                 else if (unique)
                 {
                     return Btree.op_duplicate;
                 }
             }
             db.pool.Unfix(pg);
             pg = null;
             pg = db.PutPage(pageId);
             int itemSize = ClassDescriptor.Sizeof[tree.type];
             int max = keySpace / (4 + itemSize);
             if (n < max)
             {
                 MemCopy(pg, r + 1, pg, r, n - r, itemSize);
                 MemCopy(pg, maxItems - n - 1, pg, maxItems - n, n - r, 4);
                 ins.Pack(pg, r);
                 SetItemsCount(pg, GetItemsCount(pg) + 1);
                 return Btree.op_done;
             }
             else
             {
                 /* page is full then divide page */
                 pageId = db.AllocatePage();
                 Page b = db.PutPage(pageId);
                 Assert.That(n == max);
                 int m = max / 2;
                 if (r < m)
                 {
                     MemCopy(b, 0, pg, 0, r, itemSize);
                     MemCopy(b, r + 1, pg, r, m - r - 1, itemSize);
                     MemCopy(pg, 0, pg, m - 1, max - m + 1, itemSize);
                     MemCopy(b, maxItems - r, pg, maxItems - r, r, 4);
                     ins.Pack(b, r);
                     MemCopy(b, maxItems - m, pg, maxItems - m + 1, m - r - 1, 4);
                     MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - m + 1, 4);
                 }
                 else
                 {
                     MemCopy(b, 0, pg, 0, m, itemSize);
                     MemCopy(pg, 0, pg, m, r - m, itemSize);
                     MemCopy(pg, r - m + 1, pg, r, max - r, itemSize);
                     MemCopy(b, maxItems - m, pg, maxItems - m, m, 4);
                     MemCopy(pg, maxItems - r + m, pg, maxItems - r, r - m, 4);
                     ins.Pack(pg, r - m);
                     MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - r, 4);
                 }
                 ins.oid = pageId;
                 ins.Extract(b, firstKeyOffs + (m - 1) * itemSize, tree.type);
                 if (height == 0)
                 {
                     SetItemsCount(pg, max - m + 1);
                     SetItemsCount(b, m);
                 }
                 else
                 {
                     SetItemsCount(pg, max - m);
                     SetItemsCount(b, m - 1);
                 }
                 db.pool.Unfix(b);
                 return Btree.op_overflow;
             }
         }
     }
     finally
     {
         if (pg != null)
         {
             db.pool.Unfix(pg);
         }
     }
 }
Beispiel #9
0
            internal static int Remove(StorageImpl db, int pageId, int oid, int height)
            {
                Page pg = db.GetPage(pageId);
                try
                {
                    int i, n = GetItemsCount(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);
                            MemCopy(pg, r, pg, r + 1, n - r - 1);
                            MemCopy(pg, maxItems - n + 1, pg, maxItems - n, n - r - 1);
                            SetItemsCount(pg, --n);
                            return n < max / 2 ? TenderBaseImpl.Btree.op_underflow : TenderBaseImpl.Btree.op_done;
                        }

                        return TenderBaseImpl.Btree.op_not_found;
                    }
                    else
                    {
                        while (l < r)
                        {
                            i = (l + r) >> 1;
                            if (oid > GetItem(pg, i))
                            {
                                l = i + 1;
                            }
                            else
                            {
                                r = i;
                            }
                        }

                        int result = Remove(db, GetItem(pg, maxItems - r - 1), oid, height);
                        if (result == TenderBaseImpl.Btree.op_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);
                    }
                }
            }
Beispiel #10
0
            internal static int Insert(StorageImpl db, int pageId, Key ins, int height)
            {
                Page pg = db.GetPage(pageId);
                int l = 0, n = GetItemsCount(pg), r = n;
                int oid = ins.oid;
                try
                {
                    if (--height != 0)
                    {
                        while (l < r)
                        {
                            int i = (l + r) >> 1;
                            if (oid > GetItem(pg, i))
                            {
                                l = i + 1;
                            }
                            else
                            {
                                r = i;
                            }
                        }
                        Assert.That(l == r);
                        /* insert before e[r] */
                        int result = Insert(db, GetItem(pg, maxItems - r - 1), ins, height);
                        Assert.That(result != TenderBaseImpl.Btree.op_not_found);
                        if (result != TenderBaseImpl.Btree.op_overflow)
                        {
                            return result;
                        }
                        n += 1;
                    }
                    else
                    {
                        while (l < r)
                        {
                            int i = (l + r) >> 1;
                            if (oid > GetItem(pg, maxItems - 1 - i))
                            {
                                l = i + 1;
                            }
                            else
                            {
                                r = i;
                            }
                        }

                        if (r < n && oid == GetItem(pg, maxItems - 1 - r))
                        {
                            db.pool.Unfix(pg);
                            pg = null;
                            pg = db.PutPage(pageId);
                            SetItem(pg, r, ins.key);
                            return TenderBaseImpl.Btree.op_overwrite;
                        }
                    }
                    db.pool.Unfix(pg);
                    pg = null;
                    pg = db.PutPage(pageId);
                    if (n < max)
                    {
                        MemCopy(pg, r + 1, pg, r, n - r);
                        MemCopy(pg, maxItems - n - 1, pg, maxItems - n, n - r);
                        SetItem(pg, r, ins.key);
                        SetItem(pg, maxItems - 1 - r, ins.oid);
                        SetItemsCount(pg, GetItemsCount(pg) + 1);
                        return TenderBaseImpl.Btree.op_done;
                    }
                    else
                    {
                        /* page is full then divide page */
                        pageId = db.AllocatePage();
                        Page b = db.PutPage(pageId);
                        Assert.That(n == max);
                        int m = max / 2;
                        if (r < m)
                        {
                            MemCopy(b, 0, pg, 0, r);
                            MemCopy(b, r + 1, pg, r, m - r - 1);
                            MemCopy(pg, 0, pg, m - 1, max - m + 1);
                            MemCopy(b, maxItems - r, pg, maxItems - r, r);
                            SetItem(b, r, ins.key);
                            SetItem(b, maxItems - 1 - r, ins.oid);
                            MemCopy(b, maxItems - m, pg, maxItems - m + 1, m - r - 1);
                            MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - m + 1);
                        }
                        else
                        {
                            MemCopy(b, 0, pg, 0, m);
                            MemCopy(pg, 0, pg, m, r - m);
                            MemCopy(pg, r - m + 1, pg, r, max - r);
                            MemCopy(b, maxItems - m, pg, maxItems - m, m);
                            MemCopy(pg, maxItems - r + m, pg, maxItems - r, r - m);
                            SetItem(pg, r - m, ins.key);
                            SetItem(pg, maxItems - 1 - r + m, ins.oid);
                            MemCopy(pg, maxItems - max + m - 1, pg, maxItems - max, max - r);
                        }

                        ins.oid = pageId;
                        if (height == 0)
                        {
                            ins.key = GetItem(b, maxItems - m);
                            SetItemsCount(pg, max - m + 1);
                            SetItemsCount(b, m);
                        }
                        else
                        {
                            ins.key = GetItem(b, m - 1);
                            SetItemsCount(pg, max - m);
                            SetItemsCount(b, m - 1);
                        }

                        db.pool.Unfix(b);
                        return TenderBaseImpl.Btree.op_overflow;
                    }
                }
                finally
                {
                    if (pg != null)
                    {
                        db.pool.Unfix(pg);
                    }
                }
            }
Beispiel #11
0
            internal static int HandlePageUnderflow(StorageImpl db, Page pg, int r, int height)
            {
                int nItems = GetItemsCount(pg);
                Page a = db.PutPage(GetItem(pg, maxItems - r - 1));
                int an = GetItemsCount(a);
                if (r < nItems)
                {
                    // exists greater page
                    Page b = db.GetPage(GetItem(pg, maxItems - r - 2));
                    int bn = GetItemsCount(b);
                    Assert.That(bn >= an);
                    if (height != 1)
                    {
                        MemCopy(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));
                        MemCopy(a, an, b, 0, i);
                        MemCopy(b, 0, b, i, bn - i);
                        MemCopy(a, maxItems - an - i, b, maxItems - i, i);
                        MemCopy(b, maxItems - bn + i, b, maxItems - bn, bn - i);
                        if (height != 1)
                        {
                            MemCopy(pg, r, a, an + i - 1, 1);
                        }
                        else
                        {
                            MemCopy(pg, r, a, maxItems - an - i, 1);
                        }

                        SetItemsCount(b, GetItemsCount(b) - i);
                        SetItemsCount(a, GetItemsCount(a) + i);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return TenderBaseImpl.Btree.op_done;
                    }
                    else
                    {
                        // merge page b to a
                        MemCopy(a, an, b, 0, bn);
                        MemCopy(a, maxItems - an - bn, b, maxItems - bn, bn);
                        db.FreePage(GetItem(pg, maxItems - r - 2));
                        MemCopy(pg, maxItems - nItems, pg, maxItems - nItems - 1, nItems - r - 1);
                        MemCopy(pg, r, pg, r + 1, nItems - r - 1);
                        SetItemsCount(a, GetItemsCount(a) + bn);
                        SetItemsCount(pg, nItems - 1);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        if (nItems < max / 2)
                            return TenderBaseImpl.Btree.op_underflow;
                        else
                            return TenderBaseImpl.Btree.op_done;
                    }
                }
                else
                {
                    // page b is before a
                    Page b = db.GetPage(GetItem(pg, maxItems - r));
                    int bn = GetItemsCount(b);
                    Assert.That(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));
                        MemCopy(a, i, a, 0, an);
                        MemCopy(a, 0, b, bn - i, i);
                        MemCopy(a, maxItems - an - i, a, maxItems - an, an);
                        MemCopy(a, maxItems - i, b, maxItems - bn, i);
                        if (height != 1)
                        {
                            MemCopy(a, i - 1, pg, r - 1, 1);
                            MemCopy(pg, r - 1, b, bn - i - 1, 1);
                        }
                        else
                        {
                            MemCopy(pg, r - 1, b, maxItems - bn + i, 1);
                        }

                        SetItemsCount(b, GetItemsCount(b) - i);
                        SetItemsCount(a, GetItemsCount(a) + i);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return TenderBaseImpl.Btree.op_done;
                    }
                    else
                    {
                        // merge page b to a
                        MemCopy(a, bn, a, 0, an);
                        MemCopy(a, 0, b, 0, bn);
                        MemCopy(a, maxItems - an - bn, a, maxItems - an, an);
                        MemCopy(a, maxItems - bn, b, maxItems - bn, bn);
                        if (height != 1)
                        {
                            MemCopy(a, bn - 1, pg, r - 1, 1);
                        }
                        db.FreePage(GetItem(pg, maxItems - r));
                        SetItem(pg, maxItems - r, GetItem(pg, maxItems - r - 1));
                        SetItemsCount(a, GetItemsCount(a) + bn);
                        SetItemsCount(pg, nItems - 1);
                        db.pool.Unfix(a);
                        db.pool.Unfix(b);
                        return nItems < max / 2 ? TenderBaseImpl.Btree.op_underflow : TenderBaseImpl.Btree.op_done;
                    }
                }
            }
Beispiel #12
0
 internal static int Find(StorageImpl db, int pageId, int oid, int height)
 {
     Page pg = db.GetPage(pageId);
     try
     {
         int i, n = GetItemsCount(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 StorageError(StorageError.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);
         }
     }
 }