@Override
public DistributedImmutableHashMap put(int shift, int hash, Object key, Object value, Box addedLeaf) {
int bit = bitpos(hash, shift);
int index = index(bit);
DirectoryManager locator = HyFlow.getLocator();
if ((bitmap & bit) != 0) { //We check to see if the index of the hashCode in the bitmap is set
Object keyOrNull = array[2*index];
Object valOrNode = array[2*index+1];
if (keyOrNull == null) { //If null, then valOrNode is a INode
final DistributedImmutableHashMap newNode = ((DistributedImmutableHashMap) locator.open((String)valOrNode, "r")).put(shift+5, hash, key, value, addedLeaf);
final String newNodeID = (String) newNode.getId();
if(valOrNode.equals(newNodeID)) {
return this;
}
locator.delete(this);
return new BitmapIndexedNode(bitmap, cloneAndSet(array, 2*index+1, newNodeID));
}
if (keyOrNull.equals(key)) {
if (valOrNode.equals(value)) { //If we the K-V pair is already in table
return this;
}
//Else update value for key
addedLeaf.value = valOrNode; //Update value to traverse back to recursive call
locator.delete(this);
return new BitmapIndexedNode(bitmap, cloneAndSet(array, 2*index+1, value));
}
//trying to insert a key where a key is already at that index. Need to make a new node and check to see if HashCollisionNode is needed
locator.delete(this);
return new BitmapIndexedNode(bitmap, cloneAndSet(array, 2*index, null, 2*index+1, (String)(createNode(shift + 5, keyOrNull, valOrNode, hash, key, value)).getId()));
}
else {
int bitCount = Integer.bitCount(bitmap);
if (bitCount >= 16) { //16 bits set means 16 K-V pairs, need to upgrade to ArrayNode
String[] nodes = new String[32];
//Find where in the new ArrayNode the BitmapIndexedNode will go
int jdex = mask(hash, shift);
nodes[jdex] = (String) (BitmapIndexedNode.EMPTY.put(shift + 5, hash, key, value, addedLeaf)).getId();
int j = 0;
for (int i = 0; i < 32; i++) {
if (((bitmap >>> i) & 1) != 0) { //Shift to next entry, and check to see if it's set
if (array[j] == null) //Copy over INode ID
nodes[i] = (String) array[j+1];
else { //Copy over K-V in new BitmapIndexNode
nodes[i] = (String) (BitmapIndexedNode.EMPTY.put(shift + 5, array[j].hashCode(), array[j], array[j+1], addedLeaf)).getId();
}
j += 2;
}
}
locator.delete(this);
return new ArrayNode(bitCount+1, nodes);
}
else {
//Allocate more room in the array for the new K-V pair
Object[] newArray = new Object[2*(bitCount+1)];
System.arraycopy(array, 0, newArray, 0, 2*index);
newArray[2*index] = key;
newArray[2*index+1] = value;
System.arraycopy(array, 2*index, newArray, 2*(index+1), 2*(bitCount-index));
locator.delete(this);
return new BitmapIndexedNode(bitmap | bit, newArray); //Update that bitmapindexednode
}
}
}