public async Task AddItemAsync(T new_key, int[] new_value, AddedItem <T> addedItem) { // Find the key after the spot where this item goes. int spot = 0; while (spot < NumKeysUsed) { if (this.Compare(Keys[spot], new_key) >= 0) { break; } spot++; } // See if we found it. if ((spot < NumKeysUsed) && (this.Compare(Keys[spot], new_key) == 0)) { Array.Resize <int>(ref Values[spot], Values[spot].Length + 1); Values[spot][Values[spot].Length - 1] = new_value[0]; addedItem.up_key = default(T); addedItem.up_value = null; addedItem.up_node = null; await this.PersistAsync().ConfigureAwait(false); return; } await CheckChildrenAsync().ConfigureAwait(false); // See if we are in a leaf node. if (Children[0] == null) { // This is a leaf. await AddItemToNodeAsync(spot, new_key, new_value, null, addedItem).ConfigureAwait(false); } else { // This is not a leaf. Move into the proper subtree. await Children[spot].AddItemAsync(new_key, new_value, addedItem).ConfigureAwait(false); // See if we had a bucket split. if (addedItem.up_node != null) { // We had a bucket split. Add the new bucket here. await AddItemToNodeAsync(spot, addedItem.up_key, addedItem.up_value, addedItem.up_node, addedItem).ConfigureAwait(false); } } }
public async Task AddItemAsync(T new_key, int[] new_value) { if (this.Root.OID == 0) { await this.Root.PersistAsync().ConfigureAwait(false); } AddedItem <T> addedItem = new AddedItem <T>(); await Root.AddItemAsync(new_key, new_value, addedItem).ConfigureAwait(false); // See if there was a root bucket split. if (addedItem.up_node != null) { BTreeNode <T> new_root = new BTreeNode <T>(siaqodb, this); new_root.Keys[0] = addedItem.up_key; new_root.Values[0] = addedItem.up_value; new_root.Children[0] = Root; new_root.Children[1] = addedItem.up_node; new_root.NumKeysUsed = 1; Root = new_root; await new_root.PersistAsync().ConfigureAwait(false); } }
private async Task SplitNodeAsync(int spot, T new_key, int[] new_value, BTreeNode <T> new_child, AddedItem <T> addedItem) { // Make arrays holding all of the keys, values, and children. T[] new_keys = new T[KEYS_PER_NODE + 1]; Array.Copy(this.Keys, 0, new_keys, 0, spot); new_keys[spot] = new_key; Array.Copy(this.Keys, spot, new_keys, spot + 1, KEYS_PER_NODE - spot); int[][] new_values = new int[KEYS_PER_NODE + 1][]; Array.Copy(this.Values, 0, new_values, 0, spot); new_values[spot] = new_value; Array.Copy(this.Values, spot, new_values, spot + 1, KEYS_PER_NODE - spot); BTreeNode <T>[] new_children = new BTreeNode <T> [CHILDREN_PER_NODE + 1]; Array.Copy(this.Children, 0, new_children, 0, spot + 1); new_children[spot + 1] = new_child; Array.Copy(this.Children, spot + 1, new_children, spot + 2, KEYS_PER_NODE - spot); // Copy the first half of the items into this node. Array.Copy(new_keys, 0, this.Keys, 0, HALF_NUM_KEYS); Array.Copy(new_values, 0, this.Values, 0, HALF_NUM_KEYS); Array.Copy(new_children, 0, this.Children, 0, HALF_NUM_KEYS + 1); Array.Clear(this.Keys, HALF_NUM_KEYS, HALF_NUM_KEYS); Array.Clear(this.Values, HALF_NUM_KEYS, HALF_NUM_KEYS); Array.Clear(this.Children, HALF_NUM_KEYS + 1, HALF_NUM_KEYS); this.NumKeysUsed = HALF_NUM_KEYS; // Set the up key and value. addedItem.up_key = new_keys[HALF_NUM_KEYS]; addedItem.up_value = new_values[HALF_NUM_KEYS]; // Make the new node to pass up. addedItem.up_node = new BTreeNode <T>(this.siaqodb, this.btree); Array.Copy(new_keys, HALF_NUM_KEYS + 1, addedItem.up_node.Keys, 0, HALF_NUM_KEYS); Array.Copy(new_values, HALF_NUM_KEYS + 1, addedItem.up_node.Values, 0, HALF_NUM_KEYS); Array.Copy(new_children, HALF_NUM_KEYS + 1, addedItem.up_node.Children, 0, HALF_NUM_KEYS + 1); addedItem.up_node.NumKeysUsed = HALF_NUM_KEYS; await this.PersistAsync().ConfigureAwait(false); await addedItem.up_node.PersistAsync().ConfigureAwait(false); }
// Add the new item to this node, if it fits. private async Task AddItemToNodeAsync(int spot, T new_key, int[] new_value, BTreeNode <T> new_child, AddedItem <T> addedItem) { // See if we have room. if (NumKeysUsed < KEYS_PER_NODE) { // There is room here. await AddItemInNodeWithRoomAsync(spot, new_key, new_value, new_child).ConfigureAwait(false); addedItem.up_key = default(T); addedItem.up_value = null; addedItem.up_node = null; } else { // There is no room here. await SplitNodeAsync(spot, new_key, new_value, new_child, addedItem).ConfigureAwait(false); } }