w_rc_t key_ranges_map::getPartitions(const Key& key1, bool key1Included,
                                     const Key& key2, bool key2Included,
                                     vector<lpid_t>& pidVec) 
{
    w_rc_t r = RCOK;
    
    if(key2 < key1) {
	// return error if the bounds are not given correctly
	return (RC(mrb_KEY_BOUNDARIES_NOT_ORDERED));
    }  
    char* key1S = (char*) malloc(key1.size());
    key1.copy_to(key1S);
    char* key2S = (char*) malloc(key2.size());
    key2.copy_to(key2S);

    _rwlock.acquire_read();
    keysIter iter1 = _keyRangesMap.lower_bound(key1S);
    keysIter iter2 = _keyRangesMap.lower_bound(key2S);
    if (iter1 == _keyRangesMap.end() || iter2 == _keyRangesMap.end()) {
	// at least one of the keys is not in the map, returns error.
	return (RC(mrb_PARTITION_NOT_FOUND));
    }
    while (iter1 != iter2) {
	pidVec.push_back(iter1->second);
	iter1++;
    }
    // check for !key2Included
    if(key2Included || umemcmp(iter1->first,key2S,key2.size())!=0) {
	pidVec.push_back(iter1->second);
    }
    _rwlock.release_read();

    return (r);
}
w_rc_t key_ranges_map::deletePartitionByKey(const Key& key,
					    lpid_t& root1, lpid_t& root2,
					    Key& startKey1, Key& startKey2)
{
    w_rc_t r = RCOK;
    char* keyS = (char*) malloc(key.size());
    key.copy_to(keyS);
    r = _deletePartitionByKey(keyS, root1, root2, startKey1, startKey2);
    free (keyS);
    return (r);
}
w_rc_t key_ranges_map::updateRoot(const Key& key, const lpid_t& root)
{
    char* keyS = (char*) malloc(key.size());
    key.copy_to(keyS);

    _rwlock.acquire_read();
    if(_keyRangesMap.find(keyS) != _keyRangesMap.end()) {
	_keyRangesMap[keyS] = root;
    } else {
	return (RC(mrb_PARTITION_NOT_FOUND));
    }
    _rwlock.release_read();
    return (RCOK);
}
w_rc_t key_ranges_map::getPartitionByKey(const Key& key, lpid_t& pid)
{
    char* keyS = (char*) malloc(key.size());
    key.copy_to(keyS);

    _rwlock.acquire_read();
    keysIter iter = _keyRangesMap.lower_bound(keyS);
    free (keyS);
    if(iter == _keyRangesMap.end()) {
	// the key is not in the map, returns error.
	return (RC(mrb_PARTITION_NOT_FOUND));
    }
    pid = iter->second;
    _rwlock.release_read();
    return (RCOK);    
}
void key_ranges_map::setMaxKey(const Key& maxKey)
{
    // pin: not sure who is going to use this function

    _rwlock.acquire_write();

    // update the maxKey
    if(_maxKey == NULL) {
	_maxKey = (char*) malloc(maxKey.size()); 
    }
    maxKey.copy_to(_maxKey);

    // delete the partitions that has higher key values than the new maxKey
    keysIter iter = _keyRangesMap.lower_bound(_maxKey);
    _keyRangesMap.erase(_keyRangesMap.begin(), iter);

    _rwlock.release_write();
}
void key_ranges_map::setMinKey(const Key& minKey)
{  
    // pin: not sure who is going to use this function
    
    _rwlock.acquire_write();

    // update the minKey
    if(_minKey == NULL) {
	_minKey = (char*) malloc(minKey.size()); 
    }
    minKey.copy_to(_minKey);
    
    // insert the new minKey
    keysIter iter = _keyRangesMap.lower_bound(_minKey);
    if(iter == _keyRangesMap.end()) {
    	iter--;
    }
    _keyRangesMap[_minKey] = iter->second;

    // delete the partitions that has lower key values than the new minKey
    _keyRangesMap.erase(iter, _keyRangesMap.end());

    _rwlock.release_write();
}
w_rc_t key_ranges_map::addPartition(const Key& key, lpid_t& newRoot)
{
    char* keyS = (char*) malloc(key.size());
    key.copy_to(keyS);
    return (_addPartition(keyS, newRoot));
}