Exemple #1
0
 internal static int Allocate(StorageImpl db, int root, int type, BtreeKey ins)
 {
     int pageId = db.AllocatePage();
     Page pg = db.PutPage(pageId);
     SetItemsCount(pg, 1);
     if (type == ClassDescriptor.tpString)
     {
         char[] sval = (char[]) ins.key.oval;
         int len = sval.Length;
         SetSize(pg, len * 2);
         SetKeyStrOffs(pg, 0, keySpace - len * 2);
         SetKeyStrSize(pg, 0, len);
         SetKeyStrOid(pg, 0, ins.oid);
         SetKeyStrOid(pg, 1, root);
         SetKeyStrChars(pg, keySpace - len * 2, sval);
     }
     else if (type == ClassDescriptor.tpArrayOfByte)
     {
         byte[] bval = (byte[]) ins.key.oval;
         int len = bval.Length;
         SetSize(pg, len);
         SetKeyStrOffs(pg, 0, keySpace - len);
         SetKeyStrSize(pg, 0, len);
         SetKeyStrOid(pg, 0, ins.oid);
         SetKeyStrOid(pg, 1, root);
         SetKeyBytes(pg, keySpace - len, bval);
     }
     else
     {
         ins.Pack(pg, 0);
         SetReference(pg, maxItems - 2, root);
     }
     db.pool.Unfix(pg);
     return pageId;
 }
Exemple #2
0
        internal static int InsertStrKey(StorageImpl db, Page pg, int r, BtreeKey ins, int height)
        {
            int nItems = GetItemsCount(pg);
            int size = GetSize(pg);
            int n = (height != 0) ? nItems + 1 : nItems;
            // insert before e[r]
            char[] sval = (char[]) ins.key.oval;
            int len = sval.Length;
            if (size + len * 2 + (n + 1) * strKeySize <= keySpace)
            {
                MemCopy(pg, r + 1, pg, r, n - r, strKeySize);
                size += len * 2;
                SetKeyStrOffs(pg, r, keySpace - size);
                SetKeyStrSize(pg, r, len);
                SetKeyStrOid(pg, r, ins.oid);
                SetKeyStrChars(pg, keySpace - size, sval);
                nItems += 1;
            }
            else
            {
                // page is full then divide page
                int pageId = db.AllocatePage();
                Page b = db.PutPage(pageId);
                int moved = 0;
                int inserted = len * 2 + strKeySize;
                int prevDelta = (1 << 31) + 1;

                for (int bn = 0, i = 0; ; bn += 1)
                {
                    int addSize, subSize;
                    int j = nItems - i - 1;
                    int keyLen = GetKeyStrSize(pg, i);
                    if (bn == r)
                    {
                        keyLen = len;
                        inserted = 0;
                        addSize = len;
                        if (height == 0)
                        {
                            subSize = 0;
                            j += 1;
                        }
                        else
                        {
                            subSize = GetKeyStrSize(pg, i);
                        }
                    }
                    else
                    {
                        addSize = subSize = keyLen;
                        if (height != 0)
                        {
                            if (i + 1 != r)
                            {
                                subSize += GetKeyStrSize(pg, i + 1);
                                j -= 1;
                            }
                            else
                            {
                                inserted = 0;
                            }
                        }
                    }
                    int delta = (moved + addSize * 2 + (bn + 1) * strKeySize) - (j * strKeySize + size - subSize * 2 + inserted);
                    if (delta >= -prevDelta)
                    {
                        if (height == 0)
                        {
                            ins.GetStr(b, bn - 1);
                        }
                        else
                        {
                            Assert.That("String fits in the B-Tree page", moved + (bn + 1) * strKeySize <= keySpace);
                            if (bn != r)
                            {
                                ins.GetStr(pg, i);
                                SetKeyStrOid(b, bn, GetKeyStrOid(pg, i));
                                size -= keyLen * 2;
                                i += 1;
                            }
                            else
                            {
                                SetKeyStrOid(b, bn, ins.oid);
                            }
                        }
                        nItems = CompactifyStrings(pg, i);
                        if (bn < r || (bn == r && height == 0))
                        {
                            MemCopy(pg, r - i + 1, pg, r - i, n - r, strKeySize);
                            size += len * 2;
                            nItems += 1;
                            Assert.That("String fits in the B-Tree page", size + (n - i + 1) * strKeySize <= keySpace);
                            SetKeyStrOffs(pg, r - i, keySpace - size);
                            SetKeyStrSize(pg, r - i, len);
                            SetKeyStrOid(pg, r - i, ins.oid);
                            SetKeyStrChars(pg, keySpace - size, sval);
                        }
                        SetItemsCount(b, bn);
                        SetSize(b, moved);
                        SetSize(pg, size);
                        SetItemsCount(pg, nItems);
                        ins.oid = pageId;
                        db.pool.Unfix(b);
                        return Btree.op_overflow;
                    }
                    moved += keyLen * 2;
                    prevDelta = delta;
                    Assert.That("String fits in the B-Tree page", moved + (bn + 1) * strKeySize <= keySpace);
                    SetKeyStrSize(b, bn, keyLen);
                    SetKeyStrOffs(b, bn, keySpace - moved);
                    if (bn == r)
                    {
                        SetKeyStrOid(b, bn, ins.oid);
                        SetKeyStrChars(b, keySpace - moved, sval);
                    }
                    else
                    {
                        SetKeyStrOid(b, bn, GetKeyStrOid(pg, i));
                        MemCopy(b, keySpace - moved, pg, GetKeyStrOffs(pg, i), keyLen * 2, 1);
                        size -= keyLen * 2;
                        i += 1;
                    }
                }
            }
            SetItemsCount(pg, nItems);
            SetSize(pg, size);
            return size + strKeySize * (nItems + 1) < keySpace / 2 ? Btree.op_underflow : Btree.op_done;
        }
Exemple #3
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);
                    }
                }
            }
Exemple #4
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);
         }
     }
 }
Exemple #5
0
 internal static int Allocate(StorageImpl db, int root, Key ins)
 {
     int pageId = db.AllocatePage();
     Page pg = db.PutPage(pageId);
     SetItemsCount(pg, 1);
     SetItem(pg, 0, ins.key);
     SetItem(pg, maxItems - 1, ins.oid);
     SetItem(pg, maxItems - 2, root);
     db.pool.Unfix(pg);
     return pageId;
 }