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; }
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); } } }
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; }
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); } } }
internal override void Insert(BtreeKey key, int i) { items.Set(i, key.node); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. data[i] = (float) key.key.dval; }
public void OpenCloseInsertSeekDeleteGuidKeyStringValue() { Utility.WrapNativeSyncInvokeInMTA(() => { Uri owner = new Uri("fabric://test/btree"); LogHelper.Log("Begin construct btree"); Btree <Guid, string, GuidKeyBitConverter, UnicodeStringValueBitConverter> tree = new Btree <Guid, string, GuidKeyBitConverter, UnicodeStringValueBitConverter>(); Btree <Guid, string, GuidKeyBitConverter, UnicodeStringValueBitConverter> treeApply = new Btree <Guid, string, GuidKeyBitConverter, UnicodeStringValueBitConverter>(); LogHelper.Log("End construct btree"); // // Key configuration // LogHelper.Log("Start create key description"); GuidKeyComparison guidKeyComparison = new GuidKeyComparison(); LogHelper.Log("End create key description"); // // Storage configuration // LogHelper.Log("Start create storage description"); BtreeStorageConfigurationDescription storageDescription = new BtreeStorageConfigurationDescription(); storageDescription.IsVolatile = true; storageDescription.MaximumMemoryInMB = 1024; storageDescription.MaximumPageSizeInKB = 4; storageDescription.MaximumStorageInMB = 0; storageDescription.RetriesBeforeTimeout = 100; storageDescription.StoreDataInline = true; LogHelper.Log("End create key description"); // // Btree configuration // LogHelper.Log("Start create btree description"); BtreeConfigurationDescription btreeConfig = new BtreeConfigurationDescription(); btreeConfig.KeyComparison = guidKeyComparison.KeyComparison; btreeConfig.StorageConfiguration = storageDescription; btreeConfig.PartitionId = Guid.NewGuid(); btreeConfig.ReplicaId = 130083631515748206; LogHelper.Log("End create btree description"); // // Open the btree // LogHelper.Log("Begin open btree"); tree.OpenAsync(btreeConfig, false, CancellationToken.None).Wait(); btreeConfig.PartitionId = Guid.NewGuid(); treeApply.OpenAsync(btreeConfig, false, CancellationToken.None).Wait(); LogHelper.Log("End open btree"); long sequenceNumber = 1; BtreeKey <Guid, GuidKeyBitConverter> key1 = new BtreeKey <Guid, GuidKeyBitConverter>(Guid.NewGuid()); BtreeKey <Guid, GuidKeyBitConverter> key2 = new BtreeKey <Guid, GuidKeyBitConverter>(Guid.NewGuid()); BtreeValue <string, UnicodeStringValueBitConverter> value1 = new BtreeValue <string, UnicodeStringValueBitConverter>("value"); BtreeValue <string, UnicodeStringValueBitConverter> value2 = new BtreeValue <string, UnicodeStringValueBitConverter>(null as string); // // Insert into the btree // IRedoUndoInformation infoRedoUndoInsert1 = tree.InsertAsync(key1, value1, sequenceNumber++, CancellationToken.None).Result; IBtreeOperation insertOperation11 = treeApply.ApplyWithOutputAsync(sequenceNumber, infoRedoUndoInsert1.Redo, true, CancellationToken.None).Result; IBtreeOperation insertOperation12 = treeApply.ApplyWithOutputAsync(sequenceNumber, infoRedoUndoInsert1.Redo, false, CancellationToken.None).Result; IRedoUndoInformation infoRedoUndoInsert2 = tree.InsertAsync(key2, value2, sequenceNumber++, CancellationToken.None).Result; // // Insert again the same key from the btree // try { tree.InsertAsync(key2, value2, sequenceNumber++, CancellationToken.None).Wait(); Debug.Assert(false); } catch (AggregateException e) { if (!(e.InnerException is ArgumentException)) { Debug.Assert(false); } } // // Read from the btree // IBtreeValue seekValue1 = tree.SeekAsync(key1, CancellationToken.None).Result; IBtreeValue seekValue2 = tree.SeekAsync(key2, CancellationToken.None).Result; byte[] seekValue2InBytes = seekValue2.Bytes; if (null != seekValue2InBytes) { LogHelper.Log("Seek value {0}", seekValue2InBytes.Length); throw new InvalidOperationException(); } // // Delete from the btree // Tuple <bool, IRedoUndoInformation> infoRedoUndoDelete1 = tree.DeleteAsync(key1, sequenceNumber++, CancellationToken.None).Result; if (3 != infoRedoUndoDelete1.Item2.Redo.Count()) { LogHelper.Log("Delete redo buffers {0}", infoRedoUndoDelete1.Item2.Redo.Count()); throw new InvalidOperationException(); } if (3 != infoRedoUndoDelete1.Item2.Undo.Count()) { LogHelper.Log("Delete undo buffers {0}", infoRedoUndoDelete1.Item2.Undo.Count()); throw new InvalidOperationException(); } Tuple <bool, IRedoUndoInformation> infoRedoUndoDelete2 = tree.DeleteAsync(key2, sequenceNumber++, CancellationToken.None).Result; if (3 != infoRedoUndoDelete2.Item2.Redo.Count()) { LogHelper.Log("Delete redo buffers {0}", infoRedoUndoDelete2.Item2.Redo.Count()); throw new InvalidOperationException(); } if (3 != infoRedoUndoDelete2.Item2.Undo.Count()) { LogHelper.Log("Delete undo buffers {0}", infoRedoUndoDelete2.Item2.Undo.Count()); throw new InvalidOperationException(); } IBtreeOperation deleteOperation11 = treeApply.ApplyWithOutputAsync(sequenceNumber, infoRedoUndoDelete1.Item2.Redo, true, CancellationToken.None).Result; IBtreeOperation deleteOperation12 = treeApply.ApplyWithOutputAsync(sequenceNumber, infoRedoUndoDelete1.Item2.Redo, false, CancellationToken.None).Result; // // Delete from the btree // try { tree.DeleteAsync(key1, sequenceNumber++, CancellationToken.None).Wait(); Debug.Assert(false); } catch (AggregateException e) { if (!(e.InnerException is KeyNotFoundException)) { Debug.Assert(false); } } // // Read from the btree // try { tree.SeekAsync(key1, CancellationToken.None).Wait(); Debug.Assert(false); } catch (AggregateException e) { if (!(e.InnerException is KeyNotFoundException)) { Debug.Assert(false); } } // // Close the btree // LogHelper.Log("Begin close btree"); tree.CloseAsync(true, CancellationToken.None).Wait(); treeApply.CloseAsync(true, CancellationToken.None).Wait(); LogHelper.Log("End close btree"); }, "OpenCloseInsertSeekDeleteGuidKeyStringValue"); }
public void OpenCloseInsertStringKeyGuidValue() { Utility.WrapNativeSyncInvokeInMTA(() => { Uri owner = new Uri("fabric://test/btree"); LogHelper.Log("Begin construct btree"); Btree <string, Guid, UnicodeStringKeyBitConverter, GuidValueBitConverter> tree = new Btree <string, Guid, UnicodeStringKeyBitConverter, GuidValueBitConverter>(); LogHelper.Log("End construct btree"); // // Key configuration // LogHelper.Log("Start create key description"); StringKeyComparisonEnglishUs stringKeyComparison = new StringKeyComparisonEnglishUs(); LogHelper.Log("End create key description"); // // Storage configuration // LogHelper.Log("Start create storage description"); BtreeStorageConfigurationDescription storageDescription = new BtreeStorageConfigurationDescription(); storageDescription.IsVolatile = true; storageDescription.MaximumMemoryInMB = 1 << 16; storageDescription.MaximumPageSizeInKB = 64; storageDescription.MaximumStorageInMB = 0; storageDescription.RetriesBeforeTimeout = 100; storageDescription.StoreDataInline = true; LogHelper.Log("End create key description"); // // Btree configuration // LogHelper.Log("Start create btree description"); BtreeConfigurationDescription btreeConfig = new BtreeConfigurationDescription(); btreeConfig.KeyComparison = stringKeyComparison.KeyComparison; btreeConfig.StorageConfiguration = storageDescription; btreeConfig.PartitionId = Guid.NewGuid(); btreeConfig.ReplicaId = 130083631515748206; LogHelper.Log("End create btree description"); // // Open the btree // LogHelper.Log("Begin open btree"); tree.OpenAsync(btreeConfig, true, CancellationToken.None).Wait(); LogHelper.Log("End open btree"); // // Insert into the btree // for (int sequenceNumber = 0; sequenceNumber < 16; sequenceNumber++) { BtreeKey <string, UnicodeStringKeyBitConverter> key = new BtreeKey <string, UnicodeStringKeyBitConverter>(sequenceNumber.ToString()); BtreeValue <Guid, GuidValueBitConverter> value = new BtreeValue <Guid, GuidValueBitConverter>(Guid.NewGuid()); IRedoUndoInformation infoRedoUndo = tree.InsertAsync(key, value, sequenceNumber, CancellationToken.None).Result; } // // Close the btree // LogHelper.Log("Begin close btree"); tree.CloseAsync(true, CancellationToken.None).Wait(); LogHelper.Log("End close btree"); }, "OpenCloseInsertStringKeyGuidValue"); }
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; } } } }
internal virtual void Remove(BtreeKey rem) { if (root == null) { throw new StorageError(StorageError.KEY_NOT_FOUND); } int result = root.Remove(rem, height); if (result == op_not_found) { throw new StorageError(StorageError.KEY_NOT_FOUND); } nElems -= 1; if (result == op_underflow) { if (root.nItems == 0) { BtreePage newRoot = null; if (height != 1) { newRoot = (BtreePage) root.items.Get(0); } root.Deallocate(); root = newRoot; height -= 1; } } updateCounter += 1; Modify(); }
internal IPersistent Insert(Key key, IPersistent obj, bool overwrite) { BtreeKey ins = new BtreeKey(CheckKey(key), obj); if (root == null) { AllocateRootPage(ins); height = 1; } else { int result = root.Insert(ins, height, unique, overwrite); if (result == op_overflow) { AllocateRootPage(ins); height += 1; } else if (result == op_duplicate || result == op_overwrite) { return ins.oldNode; } } updateCounter += 1; nElems += 1; Modify(); return null; }
internal void AllocateRootPage(BtreeKey ins) { Storage s = Storage; BtreePage newRoot = null; switch (type) { case ClassDescriptor.tpByte: newRoot = new BtreePageOfByte(s); break; case ClassDescriptor.tpShort: newRoot = new BtreePageOfShort(s); break; case ClassDescriptor.tpBoolean: newRoot = new BtreePageOfBoolean(s); break; case ClassDescriptor.tpInt: newRoot = new BtreePageOfInt(s); break; case ClassDescriptor.tpLong: newRoot = new BtreePageOfLong(s); break; case ClassDescriptor.tpFloat: newRoot = new BtreePageOfFloat(s); break; case ClassDescriptor.tpDouble: newRoot = new BtreePageOfDouble(s); break; case ClassDescriptor.tpObject: newRoot = new BtreePageOfObject(s); break; case ClassDescriptor.tpString: newRoot = new BtreePageOfString(s); break; case ClassDescriptor.tpRaw: newRoot = new BtreePageOfRaw(s); break; default: Assert.Failed("Invalid type"); break; } newRoot.Insert(ins, 0); newRoot.items.Set(1, root); newRoot.nItems = 1; root = newRoot; }
public virtual IPersistent Remove(Key key) { if (!unique) { throw new StorageError(StorageError.KEY_NOT_UNIQUE); } BtreeKey rk = new BtreeKey(CheckKey(key), null); Remove(rk); return rk.oldNode; }
internal override void Insert(BtreeKey key, int i) { items.Set(i, key.node); data[i] = (string) key.key.oval; }
internal override void Insert(BtreeKey key, int i) { items.Set(i, key.node); ((object[]) data)[i] = key.key.oval; }
internal override void Insert(BtreeKey key, int i) { items.Set(i, key.node); data.Set(i, (IPersistent) key.key.oval); }
internal virtual int HandlePageUnderflow(int r, BtreeKey rem, int height) { BtreePage a = (BtreePage) items.Get(r); a.Modify(); Modify(); int an = a.nItems; if (r < nItems) { // exists greater page BtreePage b = (BtreePage) items.Get(r + 1); int bn = b.nItems; Assert.That(bn >= an); if (height != 1) { MemCopyData(a, an, this, r, 1); an += 1; bn += 1; } if (an + bn > items.Size) { // reallocation of nodes between pages a and b int i = bn - ((an + bn) >> 1); b.Modify(); MemCopy(a, an, b, 0, i); MemCopy(b, 0, b, i, bn - i); MemCopyData(this, r, a, an + i - 1, 1); if (height != 1) { a.ClearKeyValue(an + i - 1); } b.MemSet(bn - i, i); b.nItems -= i; a.nItems += i; return TenderBaseImpl.AltBtree.op_done; } else { // merge page b to a MemCopy(a, an, b, 0, bn); b.Deallocate(); MemCopyData(this, r, this, r + 1, nItems - r - 1); MemCopyItems(this, r + 1, this, r + 2, nItems - r - 1); items.Set(nItems, null); a.nItems += bn; nItems -= 1; return nItems < (items.Size >> 1) ? TenderBaseImpl.AltBtree.op_underflow : TenderBaseImpl.AltBtree.op_done; } } else { // page b is before a BtreePage b = (BtreePage) items.Get(r - 1); int bn = b.nItems; Assert.That(bn >= an); if (height != 1) { an += 1; bn += 1; } if (an + bn > items.Size) { // reallocation of nodes between pages a and b int i = bn - ((an + bn) >> 1); b.Modify(); MemCopy(a, i, a, 0, an); MemCopy(a, 0, b, bn - i, i); if (height != 1) { MemCopyData(a, i - 1, this, r - 1, 1); } MemCopyData(this, r - 1, b, bn - i - 1, 1); if (height != 1) { b.ClearKeyValue(bn - i - 1); } b.MemSet(bn - i, i); b.nItems -= i; a.nItems += i; return TenderBaseImpl.AltBtree.op_done; } else { // merge page b to a MemCopy(a, bn, a, 0, an); MemCopy(a, 0, b, 0, bn); if (height != 1) { MemCopyData(a, bn - 1, this, r - 1, 1); } b.Deallocate(); items.Set(r - 1, a); items.Set(nItems, null); a.nItems += bn; nItems -= 1; return nItems < (items.Size >> 1) ? TenderBaseImpl.AltBtree.op_underflow : TenderBaseImpl.AltBtree.op_done; } } }
internal static int ReplaceStrKey(StorageImpl db, Page pg, int r, BtreeKey ins, int height) { ins.oid = GetKeyStrOid(pg, r); RemoveStrKey(pg, r); return InsertStrKey(db, pg, r, ins, height); }
internal abstract void Insert(BtreeKey key, int i);
public void OpenCloseInsert() { Utility.WrapNativeSyncInvokeInMTA(() => { Uri owner = new Uri("fabric://test/btree"); LogHelper.Log("Begin construct btree"); Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter> tree = new Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter>(); LogHelper.Log("End construct btree"); // // Key configuration // LogHelper.Log("Start create key description"); KeyComparisonDescription keyDescription = new KeyComparisonDescription(); keyDescription.CultureInfo = Globalization.CultureInfo.InvariantCulture; keyDescription.IsFixedLengthKey = true; keyDescription.KeyDataType = (int)DataType.Int32; keyDescription.MaximumKeySizeInBytes = sizeof(int); LogHelper.Log("End create key description"); // // Storage configuration // LogHelper.Log("Start create storage description"); BtreeStorageConfigurationDescription storageDescription = new BtreeStorageConfigurationDescription(); storageDescription.IsVolatile = true; storageDescription.MaximumMemoryInMB = 1024; storageDescription.MaximumPageSizeInKB = 4; storageDescription.MaximumStorageInMB = 0; storageDescription.RetriesBeforeTimeout = 100; storageDescription.StoreDataInline = true; LogHelper.Log("End create key description"); // // Btree configuration // LogHelper.Log("Start create btree description"); BtreeConfigurationDescription btreeConfig = new BtreeConfigurationDescription(); btreeConfig.KeyComparison = keyDescription; btreeConfig.StorageConfiguration = storageDescription; btreeConfig.PartitionId = Guid.NewGuid(); btreeConfig.ReplicaId = 130083631515748206; LogHelper.Log("End create btree description"); // // Open the btree // LogHelper.Log("Begin open btree"); tree.OpenAsync(btreeConfig, false, CancellationToken.None).Wait(); LogHelper.Log("End open btree"); // // Insert into the btree // for (int sequenceNumber = 0; sequenceNumber < 100; sequenceNumber++) { BtreeKey <int, Int32KeyBitConverter> key = new BtreeKey <int, Int32KeyBitConverter>(sequenceNumber); BtreeValue <int, Int32ValueBitConverter> value = new BtreeValue <int, Int32ValueBitConverter>(sequenceNumber); IRedoUndoInformation infoRedoUndo = tree.InsertAsync(key, value, sequenceNumber, CancellationToken.None).Result; LogHelper.Log("Insert redo buffers {0}", infoRedoUndo.Redo.Count()); LogHelper.Log("Insert undo buffers {0}", infoRedoUndo.Undo.Count()); } // // Close the btree // LogHelper.Log("Begin close btree"); tree.CloseAsync(true, CancellationToken.None).Wait(); LogHelper.Log("End close btree"); }, "OpenCloseInsert"); }
internal virtual int Insert(BtreeKey ins, int height, bool unique, bool overwrite) { int result; int l = 0, n = nItems, r = n; while (l < r) { int i = (l + r) >> 1; if (Compare(ins.key, i) > 0) { l = i + 1; } else { r = i; } } Assert.That(l == r); /* insert before e[r] */ if (--height != 0) { result = ((BtreePage) items.Get(r)).Insert(ins, height, unique, overwrite); Assert.That(result != TenderBaseImpl.AltBtree.op_not_found); if (result != TenderBaseImpl.AltBtree.op_overflow) { return result; } n += 1; } else if (r < n && Compare(ins.key, r) == 0) { if (overwrite) { ins.oldNode = items.Get(r); Modify(); items.Set(r, ins.node); return TenderBaseImpl.AltBtree.op_overwrite; } else if (unique) { ins.oldNode = items.Get(r); return TenderBaseImpl.AltBtree.op_duplicate; } } int max = items.Size; Modify(); if (n < max) { MemCopy(this, r + 1, this, r, n - r); Insert(ins, r); nItems += 1; return TenderBaseImpl.AltBtree.op_done; } else { /* page is full then divide page */ BtreePage b = ClonePage(); Assert.That(n == max); int m = max / 2; if (r < m) { MemCopy(b, 0, this, 0, r); MemCopy(b, r + 1, this, r, m - r - 1); MemCopy(this, 0, this, m - 1, max - m + 1); b.Insert(ins, r); } else { MemCopy(b, 0, this, 0, m); MemCopy(this, 0, this, m, r - m); MemCopy(this, r - m + 1, this, r, max - r); Insert(ins, r - m); } MemSet(max - m + 1, m - 1); ins.node = b; ins.key = b.GetKey(m - 1); if (height == 0) { nItems = max - m + 1; b.nItems = m; } else { b.ClearKeyValue(m - 1); nItems = max - m; b.nItems = m - 1; } return TenderBaseImpl.AltBtree.op_overflow; } }
public void OpenCloseInsertApply() { Utility.WrapNativeSyncInvokeInMTA(() => { Uri owner = new Uri("fabric://test/btree"); LogHelper.Log("Begin construct btrees"); Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter> tree = new Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter>(); Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter> treeApply = new Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter>(); LogHelper.Log("End construct btrees"); // // Key configuration // LogHelper.Log("Start create key description"); KeyComparisonDescription keyDescription = new KeyComparisonDescription(); keyDescription.CultureInfo = Globalization.CultureInfo.InvariantCulture; keyDescription.IsFixedLengthKey = true; keyDescription.KeyDataType = (int)DataType.Int32; keyDescription.MaximumKeySizeInBytes = sizeof(int); LogHelper.Log("End create key description"); // // Storage configuration // LogHelper.Log("Start create storage description"); BtreeStorageConfigurationDescription storageDescription = new BtreeStorageConfigurationDescription(); storageDescription.IsVolatile = true; storageDescription.MaximumMemoryInMB = 1024; storageDescription.MaximumPageSizeInKB = 4; storageDescription.MaximumStorageInMB = 0; storageDescription.RetriesBeforeTimeout = 100; storageDescription.StoreDataInline = true; LogHelper.Log("End create key description"); Guid treeGuid = Guid.NewGuid(); Guid treeApplyGuid = Guid.NewGuid(); // // Btree configuration // LogHelper.Log("Start create btree description"); BtreeConfigurationDescription btreeConfig = new BtreeConfigurationDescription(); btreeConfig.KeyComparison = keyDescription; btreeConfig.StorageConfiguration = storageDescription; btreeConfig.PartitionId = treeGuid; btreeConfig.ReplicaId = 130083631515748206; LogHelper.Log("End create btree description"); // // Open the btrees // LogHelper.Log("Begin open btree {0}", treeGuid); tree.OpenAsync(btreeConfig, false, CancellationToken.None).Wait(); LogHelper.Log("End open btree {0}", treeGuid); LogHelper.Log("Begin open btree {0}", treeApplyGuid); btreeConfig.PartitionId = treeApplyGuid; treeApply.OpenAsync(btreeConfig, false, CancellationToken.None).Wait(); LogHelper.Log("End open btree {0}", treeApplyGuid); // // Insert/Apply into the btrees // DateTime dtStart = DateTime.UtcNow; for (int sequenceNumber = 0; sequenceNumber < 1024; sequenceNumber++) { BtreeKey <int, Int32KeyBitConverter> key = new BtreeKey <int, Int32KeyBitConverter>(sequenceNumber); BtreeValue <int, Int32ValueBitConverter> value = new BtreeValue <int, Int32ValueBitConverter>(sequenceNumber); IRedoUndoInformation infoRedoUndo = tree.InsertAsync(key, value, sequenceNumber, CancellationToken.None).Result; if (3 != infoRedoUndo.Redo.Count()) { LogHelper.Log("Insert redo buffers {0}", infoRedoUndo.Redo.Count()); throw new InvalidOperationException(); } if (3 != infoRedoUndo.Undo.Count()) { LogHelper.Log("Insert undo buffers {0}", infoRedoUndo.Undo.Count()); throw new InvalidOperationException(); } IBtreeOperation btreeOperation = treeApply.ApplyWithOutputAsync(sequenceNumber, infoRedoUndo.Redo, true, CancellationToken.None).Result; IBtreeOperation btreeOperation2 = treeApply.ApplyWithOutputAsync(sequenceNumber, infoRedoUndo.Redo, false, CancellationToken.None).Result; BtreeKey <int, Int32KeyBitConverter> keyDecodeOnly = new BtreeKey <int, Int32KeyBitConverter>(btreeOperation.Key.Bytes); BtreeKey <int, Int32KeyBitConverter> keyDecode = new BtreeKey <int, Int32KeyBitConverter>(btreeOperation2.Key.Bytes); BtreeValue <int, Int32ValueBitConverter> valueDecodeOnly = new BtreeValue <int, Int32ValueBitConverter>(btreeOperation.Value.Bytes); BtreeValue <int, Int32ValueBitConverter> valueDecode = new BtreeValue <int, Int32ValueBitConverter>(btreeOperation2.Value.Bytes); if (keyDecodeOnly.Key != keyDecode.Key || key.Key != keyDecode.Key) { throw new InvalidOperationException(); } if (valueDecodeOnly.Value != valueDecode.Value || valueDecode.Value != value.Value) { throw new InvalidOperationException(); } } DateTime dtEnd = DateTime.UtcNow; BtreeStatistics stats = tree.Statistics; LogHelper.Log("Items {0}", stats.RecordCount); LogHelper.Log((dtEnd - dtStart).TotalMilliseconds.ToString()); // // Close the btrees // LogHelper.Log("Begin close btree {0}", treeGuid); tree.CloseAsync(true, CancellationToken.None).Wait(); LogHelper.Log("End close btree {0}", treeGuid); LogHelper.Log("Begin close btree {0}", treeApplyGuid); treeApply.CloseAsync(true, CancellationToken.None).Wait(); LogHelper.Log("End close btree {0}", treeApplyGuid); }, "OpenCloseInsertApply"); }
internal virtual int Remove(BtreeKey rem, int height) { int i, n = nItems, l = 0, r = n; while (l < r) { i = (l + r) >> 1; if (Compare(rem.key, i) > 0) { l = i + 1; } else { r = i; } } if (--height == 0) { IPersistent node = rem.node; while (r < n) { if (Compare(rem.key, r) == 0) { if (node == null || items.ContainsElement(r, node)) { rem.oldNode = items.Get(r); Modify(); MemCopy(this, r, this, r + 1, n - r - 1); nItems = --n; MemSet(n, 1); return n < (items.Size >> 1) ? TenderBaseImpl.AltBtree.op_underflow : TenderBaseImpl.AltBtree.op_done; } } else { break; } r += 1; } return TenderBaseImpl.AltBtree.op_not_found; } do { switch (((BtreePage) items.Get(r)).Remove(rem, height)) { case TenderBaseImpl.AltBtree.op_underflow: return HandlePageUnderflow(r, rem, height); case TenderBaseImpl.AltBtree.op_done: return TenderBaseImpl.AltBtree.op_done; } } while (++r <= n); return TenderBaseImpl.AltBtree.op_not_found; }
public void OpenCloseInsertPerf() { Utility.WrapNativeSyncInvokeInMTA(() => { Uri owner = new Uri("fabric://test/btree"); LogHelper.Log("Begin construct btrees"); Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter> tree = new Btree <int, int, Int32KeyBitConverter, Int32ValueBitConverter>(); LogHelper.Log("End construct btrees"); // // Key configuration // LogHelper.Log("Start create key description"); KeyComparisonDescription keyDescription = new KeyComparisonDescription(); keyDescription.CultureInfo = Globalization.CultureInfo.InvariantCulture; keyDescription.IsFixedLengthKey = true; keyDescription.KeyDataType = (int)DataType.Int32; keyDescription.MaximumKeySizeInBytes = sizeof(int); LogHelper.Log("End create key description"); // // Storage configuration // LogHelper.Log("Start create storage description"); BtreeStorageConfigurationDescription storageDescription = new BtreeStorageConfigurationDescription(); storageDescription.IsVolatile = true; storageDescription.MaximumMemoryInMB = 1024; storageDescription.MaximumPageSizeInKB = 4; storageDescription.MaximumStorageInMB = 0; storageDescription.RetriesBeforeTimeout = 100; storageDescription.StoreDataInline = true; LogHelper.Log("End create key description"); Guid treeGuid = Guid.NewGuid(); Guid treeApplyGuid = Guid.NewGuid(); // // Btree configuration // LogHelper.Log("Start create btree description"); BtreeConfigurationDescription btreeConfig = new BtreeConfigurationDescription(); btreeConfig.KeyComparison = keyDescription; btreeConfig.StorageConfiguration = storageDescription; btreeConfig.PartitionId = treeGuid; btreeConfig.ReplicaId = 130083631515748206; LogHelper.Log("End create btree description"); // // Open the btrees // LogHelper.Log("Begin open btree {0}", treeGuid); tree.OpenAsync(btreeConfig, false, CancellationToken.None).Wait(); LogHelper.Log("End open btree {0}", treeGuid); // // Insert/Apply into the btrees // List <Task> tasks = new List <Task>(); DateTime dtStart = DateTime.UtcNow; for (int sequenceNumber = 0; sequenceNumber < 1024; sequenceNumber++) { BtreeKey <int, Int32KeyBitConverter> key = new BtreeKey <int, Int32KeyBitConverter>(sequenceNumber); BtreeValue <int, Int32ValueBitConverter> value = new BtreeValue <int, Int32ValueBitConverter>(sequenceNumber); tasks.Add(tree.InsertAsync(key, value, sequenceNumber, CancellationToken.None)); } Task.WaitAll(tasks.ToArray()); DateTime dtEnd = DateTime.UtcNow; LogHelper.Log((dtEnd - dtStart).TotalMilliseconds.ToString()); BtreeStatistics stats = tree.Statistics; LogHelper.Log("Items {0}", stats.RecordCount); // // Close the btrees // LogHelper.Log("Begin close btree {0}", treeGuid); tree.CloseAsync(true, CancellationToken.None).Wait(); LogHelper.Log("End close btree {0}", treeGuid); }, "OpenCloseInsertPerf"); }
internal override void Insert(BtreeKey key, int i) { items.Set(i, key.node); data[i] = (byte) key.key.ival; }