Esempio n. 1
0
 internal void getByteArray(Page pg, int i) 
 { 
     int len = BtreePage.getKeyStrSize(pg, i);
     int offs = BtreePage.firstKeyOffs + BtreePage.getKeyStrOffs(pg, i);
     byte[] bval = new byte[len];
     Array.Copy(pg.data, offs, bval, 0, len);
     key = new Key(bval);
 }
 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;
     }
 }
Esempio n. 3
0
 internal void  getStr(Page pg, int i)
 {
     int len = BtreePage.getKeyStrSize(pg, i);
     int offs = BtreePage.firstKeyOffs + BtreePage.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);
 }
Esempio n. 4
0
 internal virtual 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++;
         }
     }
 }
Esempio n. 5
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[BtreePage.firstKeyOffs + i] = (byte) key.ival;
                    break;
				
                case ClassDescriptor.FieldType.tpShort: 
                case ClassDescriptor.FieldType.tpUShort: 
                case ClassDescriptor.FieldType.tpChar: 
                    Bytes.pack2(dst, BtreePage.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, BtreePage.firstKeyOffs + i * 4, key.ival);
                    break;
				
                case ClassDescriptor.FieldType.tpLong: 
                case ClassDescriptor.FieldType.tpULong: 
                case ClassDescriptor.FieldType.tpDate: 
                    Bytes.pack8(dst, BtreePage.firstKeyOffs + i * 8, key.lval);
                    break;
				
                case ClassDescriptor.FieldType.tpFloat: 
                    Bytes.packF4(dst, BtreePage.firstKeyOffs + i * 4, (float)key.dval);
                    break;
				
                case ClassDescriptor.FieldType.tpDouble: 
                    Bytes.packF8(dst, BtreePage.firstKeyOffs + i * 8, key.dval);
                    break;
				
                case ClassDescriptor.FieldType.tpDecimal:
                    Bytes.packDecimal(dst, BtreePage.firstKeyOffs + i * 16, key.dec);
                    break;

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


                default: 
                    Debug.Assert(false, "Invalid type");
                    break;
				
            }
            Bytes.pack4(dst, BtreePage.firstKeyOffs + (BtreePage.maxItems - i - 1) * 4, oid);
        }
        internal static BtreeResult insertByteArrayKey(StorageImpl db, Page pg, int r, BtreeKey ins, int height)
        {
            int nItems = getnItems(pg);
            int size = getSize(pg);
            int n = (height != 0)?nItems + 1:nItems;
            // insert before e[r]
            byte[] bval = (byte[])ins.key.oval;        
            int len = bval.Length;
            if (size + len + (n + 1) * strKeySize <= keySpace)
            {
                memcpy(pg, r + 1, pg, r, n - r, strKeySize);
                size += len;
                setKeyStrOffs(pg, r, keySpace - size);
                setKeyStrSize(pg, r, len);
                setKeyStrOid(pg, r, ins.oid);
                setKeyBytes(pg, keySpace - size, bval);
                nItems += 1;
            }
            else
            {
                // page is full then divide page
                int pageId = db.allocatePage();
                Page b = db.putPage(pageId);
                int moved = 0;
                int inserted = len + 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 + (bn + 1) * strKeySize) - (j * strKeySize + size - subSize + inserted);
                    if (delta >= - prevDelta)
                    {
                        if (height == 0)
                        {
                            ins.getByteArray(b, bn - 1);
                        }
                        else
                        {
                            Debug.Assert(moved + (bn + 1) * strKeySize <= keySpace, "String fits in the B-Tree page");
                            if (bn != r)
                            {
                                ins.getByteArray(pg, i);
                                setKeyStrOid(b, bn, getKeyStrOid(pg, i));
                                size -= keyLen;
                                i += 1;
                            }
                            else
                            {
                                setKeyStrOid(b, bn, ins.oid);
                            }
                        }
                        nItems = compactifyByteArrays(pg, i);
                        if (bn < r || (bn == r && height == 0))
                        {
                            memcpy(pg, r - i + 1, pg, r - i, n - r, strKeySize);
                            size += len;
                            nItems += 1;
                            Debug.Assert(size + (n - i + 1) * strKeySize <= keySpace, "String fits in the B-Tree page");
                            setKeyStrOffs(pg, r - i, keySpace - size);
                            setKeyStrSize(pg, r - i, len);
                            setKeyStrOid(pg, r - i, ins.oid);
                            setKeyBytes(pg, keySpace - size, bval);
                        }
                        setnItems(b, bn);
                        setSize(b, moved);
                        setSize(pg, size);
                        setnItems(pg, nItems);
                        ins.oid = pageId;
                        db.pool.unfix(b);
                        return BtreeResult.Overflow;
                    }
                    moved += keyLen;
                    prevDelta = delta;
                    Debug.Assert(moved + (bn + 1) * strKeySize <= keySpace, "String fits in the B-Tree page");
                    setKeyStrSize(b, bn, keyLen);
                    setKeyStrOffs(b, bn, keySpace - moved);
                    if (bn == r)
                    {
                        setKeyStrOid(b, bn, ins.oid);
                        setKeyBytes(b, keySpace - moved, bval);
                    }
                    else
                    {
                        setKeyStrOid(b, bn, getKeyStrOid(pg, i));
                        memcpy(b, keySpace - moved, pg, getKeyStrOffs(pg, i), keyLen, 1);
                        size -= keyLen;
                        i += 1;
                    }
                }
            }
            setnItems(pg, nItems);
            setSize(pg, size);
            return size + strKeySize * (nItems + 1) < keySpace / 3 ? BtreeResult.Underflow : BtreeResult.Done;
        }
 internal static void  setReference(Page pg, int index, int oid)
 {
     Bytes.pack4(pg.data, firstKeyOffs + index * 4, oid);
 }
 internal static void  setKeyStrSize(Page pg, int index, int size)
 {
     Bytes.pack2(pg.data, firstKeyOffs + index * 8 + 4, (short) size);
 }
 internal static int getnItems(Page pg)
 {
     return Bytes.unpack2(pg.data, 0);
 }
Esempio n. 10
0
 internal static BtreeResult handlePageUnderflow(StorageImpl db, Page pg, int r, ClassDescriptor.FieldType type, BtreeKey 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);
                     }
                 }
                 BtreeResult result = BtreeResult.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);
                     }
                 }
                 BtreeResult result = BtreeResult.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);
                     }
                 }
                 BtreeResult result = BtreeResult.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);
                     }
                 }
                 BtreeResult result = BtreeResult.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 BtreeResult.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 / 3 ? BtreeResult.Underflow : BtreeResult.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 BtreeResult.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 / 3 ? BtreeResult.Underflow : BtreeResult.Done;
             }
         }
     }
 }
Esempio n. 11
0
 internal static BtreeResult replaceByteArrayKey(StorageImpl db, Page pg, int r, BtreeKey ins, int height)
 {
     ins.oid = getKeyStrOid(pg, r);
     removeByteArrayKey(pg, r);
     return insertByteArrayKey(db, pg, r, ins, height);
 }
Esempio n. 12
0
 internal static BtreeResult removeByteArrayKey(Page pg, int r)
 {
     int len = getKeyStrSize(pg, r);
     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 / 3 ? BtreeResult.Underflow : BtreeResult.Done;
 }
Esempio n. 13
0
 internal override void modify(Page pg) 
 { 
     lock(this)
     {
         int pageNo = (int)(pg.offs >> Page.pageSizeLog);
         modifiedPages[pageNo >> 5] |= 1 << (pageNo & 31);
         nDirtyPages += 1;
     }
 }
Esempio n. 14
0
 internal override void unfix(Page pg) 
 { 
 }
Esempio n. 15
0
        internal virtual Page find(long addr, int state)
        {
            Debug.Assert((addr & (Page.pageSize - 1)) == 0);
            Page pg;
            int pageNo = (int)((ulong)addr >> Page.pageSizeLog);
            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)
                    {
                        if (pg.data == null) 
                        {
                            pg.data = new byte[Page.pageSize];
                        }
                        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();
                        pg.data = new byte[Page.pageSize];
                        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.pageSizeLog) % 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)
                {
                    // Console.WriteLine("Read page {0}", pg.offs);
                    if (file.Read(pg.offs, pg.data) < Page.pageSize)
                    {
                        for (int i = 0; i < Page.pageSize; i++)
                        {
                            pg.data[i] = 0;
                        }
                    }
                    pg.state &= ~ Page.psRaw;
                }
            }
            return pg;
        }
Esempio n. 16
0
 internal static void  setKeyStrOid(Page pg, int index, int oid)
 {
     Bytes.pack4(pg.data, firstKeyOffs + index * 8, oid);
 }
Esempio n. 17
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);
 }
Esempio n. 18
0
 internal static int compareStr(Key key, Page pg, int i)
 {
     char[] chars = (char[])key.oval;
     int alen = chars.Length;
     int blen = BtreePage.getKeyStrSize(pg, i);
     int minlen = alen < blen?alen:blen;
     int offs = BtreePage.getKeyStrOffs(pg, i) + BtreePage.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;
 }
Esempio n. 19
0
 internal static void  setKeyStrOffs(Page pg, int index, int offs)
 {
     Bytes.pack2(pg.data, firstKeyOffs + index * 8 + 6, (short) offs);
 }
Esempio n. 20
0
 internal static int getSize(Page pg)
 {
     return Bytes.unpack2(pg.data, 2);
 }
Esempio n. 21
0
 internal static void setKeyBytes(Page pg, int offs, byte[] bytes) 
 { 
     Array.Copy(bytes, 0, pg.data, firstKeyOffs + offs, bytes.Length);
 }
Esempio n. 22
0
 internal static int getKeyStrOffs(Page pg, int index)
 {
     return Bytes.unpack2(pg.data, firstKeyOffs + index * 8 + 6);
 }
Esempio n. 23
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[BtreePage.firstKeyOffs + i];
                
                case ClassDescriptor.FieldType.tpBoolean: 
                case ClassDescriptor.FieldType.tpByte: 
                    return (byte)key.ival - pg.data[BtreePage.firstKeyOffs + i];
				
                case ClassDescriptor.FieldType.tpShort: 
                    return (short) key.ival - Bytes.unpack2(pg.data, BtreePage.firstKeyOffs + i * 2);
                case ClassDescriptor.FieldType.tpUShort: 
                    return (ushort) key.ival - (ushort)Bytes.unpack2(pg.data, BtreePage.firstKeyOffs + i * 2);
				
                case ClassDescriptor.FieldType.tpChar: 
                    return (char) key.ival - (char) Bytes.unpack2(pg.data, BtreePage.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, BtreePage.firstKeyOffs + i * 4);
                    return (uint)key.ival < u4 ? -1 : (uint)key.ival == u4 ? 0 : 1;

                case ClassDescriptor.FieldType.tpInt: 
                    i4 = Bytes.unpack4(pg.data, BtreePage.firstKeyOffs + i * 4);
                    return key.ival < i4 ? -1 : key.ival == i4 ? 0 : 1;
				
                case ClassDescriptor.FieldType.tpLong: 
                    i8 = Bytes.unpack8(pg.data, BtreePage.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, BtreePage.firstKeyOffs + i * 8);
                    return (ulong)key.lval < u8 ? -1 : (ulong)key.lval == u8 ? 0 : 1;
				
                case ClassDescriptor.FieldType.tpFloat: 
                    r4 = Bytes.unpackF4(pg.data, BtreePage.firstKeyOffs + i * 4);
                    return key.dval < r4 ? -1 : key.dval == r4 ? 0 : 1;
				
                case ClassDescriptor.FieldType.tpDouble: 
                    r8 = Bytes.unpackF8(pg.data, BtreePage.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, BtreePage.firstKeyOffs + i*16));

                case ClassDescriptor.FieldType.tpGuid:
                    return key.guid.CompareTo(Bytes.unpackGuid(pg.data, BtreePage.firstKeyOffs + i*16));
            }
            Debug.Assert(false, "Invalid type");
            return 0;
        }
Esempio n. 24
0
 internal static int getReference(Page pg, int index)
 {
     return Bytes.unpack4(pg.data, firstKeyOffs + index * 4);
 }
Esempio n. 25
0
 internal static int compactifyStrings(Page pg, int m)
 {
     int i, j, offs, len, n = getnItems(pg);
     int[] size = new int[keySpace / 2 + 1];
     int[] index = new int[keySpace / 2 + 1];
     if (m == 0)
     {
         return n;
     }
     int nZeroLengthStrings = 0;
     if (m < 0)
     {
         m = - m;
         for (i = 0; i < n - m; i++)
         {
             len = getKeyStrSize(pg, i);
             if (len != 0)
             {
                 offs = getKeyStrOffs(pg, i) >> 1;
                 size[offs + len] = len;
                 index[offs + len] = i;
             }
             else
             {
                 nZeroLengthStrings += 1;
             }
         }
         for (; i < n; i++)
         {
             len = getKeyStrSize(pg, i);
             if (len != 0)
             {
                 offs = getKeyStrOffs(pg, i) >> 1;
                 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) >> 1;
                 size[offs + len] = len;
                 index[offs + len] = - 1;
             }
         }
         for (; i < n; i++)
         {
             len = getKeyStrSize(pg, i);
             if (len != 0)
             {
                 offs = getKeyStrOffs(pg, i) >> 1;
                 size[offs + len] = len;
                 index[offs + len] = i - m;
             }
             else
             {
                 nZeroLengthStrings += 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 -= nZeroLengthStrings;
     for (offs = keySpace / 2, i = offs; n != 0; i -= len)
     {
         len = size[i];
         j = index[i];
         if (j >= 0)
         {
             offs -= len;
             n -= 1;
             setKeyStrOffs(pg, j, offs * 2);
             if (offs != i - len)
             {
                 memcpy(pg, offs, pg, i - len, len, 2);
             }
         }
     }
     return nItems;
 }
Esempio n. 26
0
 internal static void  setnItems(Page pg, int nItems)
 {
     Bytes.pack2(pg.data, 0, (short) nItems);
 }
Esempio n. 27
0
 static int comparePrefix(string key, Page pg, int i) 
 { 
     int alen = key.Length;
     int blen = BtreePage.getKeyStrSize(pg, i);
     int minlen = alen < blen ? alen : blen;
     int offs = BtreePage.getKeyStrOffs(pg, i) + BtreePage.firstKeyOffs;
     byte[] b = pg.data;
     for (int j = 0; j < minlen; j++) 
     { 
         int diff = key[j] - (char)Bytes.unpack2(b, offs);
         if (diff != 0) 
         { 
             return diff;
         }
         offs += 2;
     }
     return minlen - blen;
 }
Esempio n. 28
0
 internal static void  setSize(Page pg, int size)
 {
     Bytes.pack2(pg.data, 2, (short) size);
 }
Esempio n. 29
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;
				
            }
        }
Esempio n. 30
0
 internal virtual void unfix(Page pg)
 {
     lock(this)
     {
         Debug.Assert(pg.accessCount > 0);
         if (--pg.accessCount == 0)
         {
             if (pg.offs <= lruLimit) 
             { 
                 lru.link(pg);
             }
             else 
             { 
                 lru.prev.link(pg);
             }
         }
     }
 }