Author: kayyagari
Date: Sun Mar 31 15:41:47 2013
New Revision: 1462992
URL: http://svn.apache.org/r1462992
Log:
o modified delete operation to handle multiple values
o renamed removeElement() to copyAfterRemovingElement()
o fixed the LeafTest as per the new signature of delete()
o added tests
Modified:
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Node.java
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Page.java
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/BTreeDuplicateKeyTest.java
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java
Modified:
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java?rev=1462992&r1=1462991&r2=1462992&view=diff
==============================================================================
---
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java
(original)
+++
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java
Sun Mar 31 15:41:47 2013
@@ -811,11 +811,13 @@ public class BTree<K, V>
/**
- * Delete the value from an entry which key is given as a parameter. If
the value
- * is present, we will return it. If the remaining entry is empty, we will
remove it
- * from the tree.
+ * Delete the value from an entry associated with the given key. If the
value
+ * If the value is present, it will be deleted first, later if there are
no other
+ * values associated with this key(which can happen when duplicates are
enabled),
+ * we will remove the key from the tree.
*
* @param key The key for the entry we try to remove
+ * @param value The value to delete (can be null)
* @return A Tuple<K, V> containing the removed entry, or null if it's not
found.
*/
public Tuple<K, V> delete( K key, V value ) throws IOException
@@ -832,7 +834,7 @@ public class BTree<K, V>
long revision = generateRevision();
- Tuple<K, V> deleted = delete( key, revision );
+ Tuple<K, V> deleted = delete( key, value, revision );
// Decrease the number of element in the current tree if the delete is
successful
if ( deleted != null )
@@ -853,6 +855,23 @@ public class BTree<K, V>
*/
private Tuple<K, V> delete( K key, long revision ) throws IOException
{
+ return delete( key, null, revision );
+ }
+
+ /**
+ *
+ * Deletes the given <key,value> pair if both key and value match. If the
given value is null
+ * and there is no null value associated with the given key then the entry
with the given key
+ * will be removed.
+ *
+ * @param key The key to be removed
+ * @param value The value to be removed (can be null, and when no null
value exists the key will be removed irrespective of the value)
+ * @param revision The revision to be associated with this operation
+ * @return
+ * @throws IOException
+ */
+ private Tuple<K, V> delete( K key, V value, long revision ) throws
IOException
+ {
writeLock.lock();
try
@@ -863,7 +882,7 @@ public class BTree<K, V>
// Try to delete the entry starting from the root page. Here, the
root
// page may be either a Node or a Leaf
- DeleteResult<K, V> result = rootPage.delete( revision, key, null,
-1 );
+ DeleteResult<K, V> result = rootPage.delete( revision, key, value,
null, -1 );
if ( result instanceof NotPresentResult )
{
Modified:
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java?rev=1462992&r1=1462991&r2=1462992&view=diff
==============================================================================
---
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java
(original)
+++
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java
Sun Mar 31 15:41:47 2013
@@ -123,7 +123,7 @@ public class Leaf<K, V> extends Abstract
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
- public DeleteResult<K, V> delete( long revision, K key, Page<K, V> parent,
int parentPos )
+ public DeleteResult<K, V> delete( long revision, K key, V value, Page<K,
V> parent, int parentPos )
throws IOException
{
// Check that the leaf is not empty
@@ -142,17 +142,83 @@ public class Leaf<K, V> extends Abstract
return NotPresentResult.NOT_PRESENT;
}
+ // Get the removed element
+ Tuple<K, V> removedElement = null;
+
+ // flag to detect if a key was completely removed
+ boolean keyRemoved = false;
+
int index = -( pos + 1 );
+
+ if( btree.isAllowDuplicates() )
+ {
+ if( value == null );
+ BTree<V,V> dups = ( BTree<V,V> ) values[index].getValue( btree );
+
+ if( dups.hasKey( value ) )
+ {
+ dups.delete( value );
+
+ if( dups.getNbElems() == 0 )
+ {
+ keyRemoved = true;
+ }
+
+ removedElement = new Tuple<K, V>( keys[index], value ); // we
deleted only one value (even if it is from a tree of size 1)
+ }
+ else if( value == null ) // this is a case to delete entire
<K,dupsTree>
+ {
+ removedElement = new Tuple<K, V>( keys[index], ( V ) dups );
// the entire tree was removed so pass it as the value
+ keyRemoved = true;
+ }
+ else // value is not found
+ {
+ return NotPresentResult.NOT_PRESENT;
+ }
+ }
+ else
+ {
+ V existing = values[index].getValue( btree );
+
+ if( ( ( existing == null ) && ( value == null ) ) || ( value ==
null ) )
+ {
+ removedElement = new Tuple<K, V>( keys[index], existing );
+ keyRemoved = true;
+ }
+ else if( btree.getValueSerializer().compare( value, existing ) ==
0 )
+ {
+ removedElement = new Tuple<K, V>( keys[index], value );
+ keyRemoved = true;
+ }
+ else
+ {
+ return NotPresentResult.NOT_PRESENT;
+ }
+ }
+
+ Leaf<K, V> newLeaf = null;
+
+ if( keyRemoved )
+ {
+ newLeaf = new Leaf<K, V>( btree, revision, nbElems - 1 );
+ }
+ else
+ {
+ newLeaf = new Leaf<K, V>( btree, revision, nbElems );
+ }
+
+ // Create the result
+ DeleteResult<K, V> defaultResult = new RemoveResult<K, V>( newLeaf,
removedElement );
// If the parent is null, then this page is the root page.
if ( parent == null )
{
// Just remove the entry if it's present
- DeleteResult<K, V> result = removeElement( revision, index );
+ copyAfterRemovingElement( keyRemoved, newLeaf, index );
- return result;
+ return defaultResult;
}
- else
+ else if( keyRemoved )
{
// The current page is not the root. Check if the leaf has more
than N/2
// elements
@@ -170,7 +236,7 @@ public class Leaf<K, V> extends Abstract
if ( sibling.getNbElems() == halfSize )
{
// We will merge the current page with its sibling
- DeleteResult<K, V> result = mergeWithSibling( revision,
sibling, ( siblingPos < parentPos ), index );
+ DeleteResult<K, V> result = mergeWithSibling(
removedElement, revision, sibling, ( siblingPos < parentPos ), index );
return result;
}
@@ -179,14 +245,14 @@ public class Leaf<K, V> extends Abstract
// We can borrow the element from the left sibling
if ( siblingPos < parentPos )
{
- DeleteResult<K, V> result = borrowFromLeft( revision,
sibling, index );
+ DeleteResult<K, V> result = borrowFromLeft(
removedElement, revision, sibling, index );
return result;
}
else
{
// Borrow from the right sibling
- DeleteResult<K, V> result = borrowFromRight( revision,
sibling, index );
+ DeleteResult<K, V> result = borrowFromRight(
removedElement, revision, sibling, index );
return result;
}
@@ -198,11 +264,13 @@ public class Leaf<K, V> extends Abstract
// We simply remove the element from the page, and if it was
the leftmost,
// we return the new pivot (it will replace any instance of
the removed
// key in its parents)
- DeleteResult<K, V> result = removeElement( revision, index );
+ copyAfterRemovingElement( keyRemoved, newLeaf, index );
- return result;
+ return defaultResult;
}
}
+
+ return defaultResult;
}
@@ -216,13 +284,12 @@ public class Leaf<K, V> extends Abstract
* @return The new created leaf containing the sibling and the old page.
* @throws IOException If we have an error while trying to access the page
*/
- private DeleteResult<K, V> mergeWithSibling( long revision, Leaf<K, V>
sibling, boolean isLeft, int pos )
+ private DeleteResult<K, V> mergeWithSibling( Tuple<K, V> removedElement,
long revision, Leaf<K, V> sibling, boolean isLeft, int pos )
throws EndOfFileExceededException, IOException
{
// Create the new page. It will contain N - 1 elements (the maximum
number)
// as we merge two pages that contain N/2 elements minus the one we
remove
Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision,
btree.getPageSize() - 1 );
- Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos],
values[pos].getValue( btree ) );
if ( isLeft )
{
@@ -274,7 +341,7 @@ public class Leaf<K, V> extends Abstract
* @return The resulting pages
* @throws IOException If we have an error while trying to access the page
*/
- private DeleteResult<K, V> borrowFromLeft( long revision, Leaf<K, V>
sibling, int pos )
+ private DeleteResult<K, V> borrowFromLeft( Tuple<K, V> removedElement,
long revision, Leaf<K, V> sibling, int pos )
throws IOException
{
// The sibling is on the left, borrow the rightmost element
@@ -300,9 +367,6 @@ public class Leaf<K, V> extends Abstract
System.arraycopy( keys, pos + 1, newLeaf.keys, pos + 1, keys.length -
pos - 1 );
System.arraycopy( values, pos + 1, newLeaf.values, pos + 1,
values.length - pos - 1 );
- // Create the result
- Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos],
values[pos].getValue( btree ) );
-
DeleteResult<K, V> result = new BorrowedFromLeftResult<K, V>( newLeaf,
newSibling, removedElement );
return result;
@@ -320,7 +384,7 @@ public class Leaf<K, V> extends Abstract
* @return The resulting pages
* @throws IOException If we have an error while trying to access the page
*/
- private DeleteResult<K, V> borrowFromRight( long revision, Leaf<K, V>
sibling, int pos )
+ private DeleteResult<K, V> borrowFromRight( Tuple<K, V> removedElement,
long revision, Leaf<K, V> sibling, int pos )
throws IOException
{
// The sibling is on the left, borrow the rightmost element
@@ -350,9 +414,6 @@ public class Leaf<K, V> extends Abstract
System.arraycopy( keys, pos + 1, newLeaf.keys, pos, keys.length - pos
- 1 );
System.arraycopy( values, pos + 1, newLeaf.values, pos, values.length
- pos - 1 );
- // Create the result
- Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos],
values[pos].getValue( btree ) );
-
DeleteResult<K, V> result = new BorrowedFromRightResult<K, V>(
newLeaf, newSibling, removedElement );
return result;
@@ -360,38 +421,37 @@ public class Leaf<K, V> extends Abstract
/**
- * Removes the element at a given position.
- *
- * @param revision The revision of the modified page
+ * Copies the elements of the current page to a new page
+ *
+ * @param keyRemoved a flag stating if the key was removed
+ * @param newLeaf The new page into which the remaining keys and values
will be copied
* @param pos The position into the page of the element to remove
- * @return The modified page with the <K,V> element added
* @throws IOException If we have an error while trying to access the page
*/
- private DeleteResult<K, V> removeElement( long revision, int pos ) throws
IOException
+ private void copyAfterRemovingElement( boolean keyRemoved, Leaf<K, V>
newLeaf, int pos ) throws IOException
{
- // First copy the current page, but remove one element in the copied
page
- Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems - 1 );
-
- // Get the removed element
- Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos],
values[pos].getValue( btree ) );
-
- // Deal with the special case of an page with only one element by
skipping
- // the copy, as we won't have any remaining element in the page
- if ( nbElems > 1 )
+ if( keyRemoved )
{
+ // Deal with the special case of a page with only one element by
skipping
+ // the copy, as we won't have any remaining element in the page
+ if( nbElems == 1 )
+ {
+ return;
+ }
+
// Copy the keys and the values up to the insertion position
System.arraycopy( keys, 0, newLeaf.keys, 0, pos );
System.arraycopy( values, 0, newLeaf.values, 0, pos );
-
+
// And copy the elements after the position
System.arraycopy( keys, pos + 1, newLeaf.keys, pos, keys.length -
pos - 1 );
System.arraycopy( values, pos + 1, newLeaf.values, pos,
values.length - pos - 1 );
}
-
- // Create the result
- DeleteResult<K, V> result = new RemoveResult<K, V>( newLeaf,
removedElement );
-
- return result;
+ else // one of the many values of the same key was removed, no change
in the number of keys
+ {
+ System.arraycopy( keys, 0, newLeaf.keys, 0, nbElems );
+ System.arraycopy( values, 0, newLeaf.values, 0, nbElems );
+ }
}
Modified:
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Node.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Node.java?rev=1462992&r1=1462991&r2=1462992&view=diff
==============================================================================
---
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Node.java
(original)
+++
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Node.java
Sun Mar 31 15:41:47 2013
@@ -560,7 +560,7 @@ public class Node<K, V> extends Abstract
/**
* {@inheritDoc}
*/
- public DeleteResult<K, V> delete( long revision, K key, Page<K, V> parent,
int parentPos ) throws IOException
+ public DeleteResult<K, V> delete( long revision, K key, V value, Page<K,
V> parent, int parentPos ) throws IOException
{
// We first try to delete the element from the child it belongs to
// Find the key in the page
@@ -574,12 +574,12 @@ public class Node<K, V> extends Abstract
{
index = -( pos + 1 );
child = children[-pos].getValue( btree );
- deleteResult = child.delete( revision, key, this, -pos );
+ deleteResult = child.delete( revision, key, value, this, -pos );
}
else
{
child = children[pos].getValue( btree );
- deleteResult = child.delete( revision, key, this, pos );
+ deleteResult = child.delete( revision, key, value, this, pos );
}
// If the key is not present in the tree, we simply return
Modified:
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Page.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Page.java?rev=1462992&r1=1462991&r2=1462992&view=diff
==============================================================================
---
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Page.java
(original)
+++
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/main/java/org/apache/mavibot/btree/Page.java
Sun Mar 31 15:41:47 2013
@@ -66,18 +66,20 @@ public interface Page<K, V>
/**
- * Deletes an entry with the given key from this page. We first find the
place were to
- * remove the <K,V> into the tree, by recursively browsing the pages :<br/>
- * <p>
+ * Deletes the value from an entry associated with the given key in this
page. We first find
+ * the place were to remove the <K,V> into the tree, by recursively
browsing the pages.
+ * If the value is present, it will be deleted first, later if there are
no other values associated with
+ * this key(which can happen when duplicates are enabled), we will remove
the key from the tree.
*
* @param revision The new revision for the modified pages
* @param key The key to delete
+ * @param value The value to delete (can be null)
* @param parent The parent page
* @param parentPos The position of the current page in it's parent
* @return Either a modified Page if the key has been removed from the
page, or a NotPresentResult.
* @throws IOException If we have an error while trying to access the page
*/
- DeleteResult<K, V> delete( long revision, K key, Page<K, V> parent, int
parentPos ) throws IOException;
+ DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V>
parent, int parentPos ) throws IOException;
/**
Modified:
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/BTreeDuplicateKeyTest.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/BTreeDuplicateKeyTest.java?rev=1462992&r1=1462991&r2=1462992&view=diff
==============================================================================
---
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/BTreeDuplicateKeyTest.java
(original)
+++
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/BTreeDuplicateKeyTest.java
Sun Mar 31 15:41:47 2013
@@ -197,4 +197,36 @@ public class BTreeDuplicateKeyTest
assertFalse( btree.contains( 0, null ) );
assertFalse( btree.contains( null, null ) );
}
+
+ @Test
+ public void testRemoveDuplicateKey() throws Exception
+ {
+ IntSerializer serializer = new IntSerializer();
+
+ BTreeConfiguration<Integer, Integer> config = new
BTreeConfiguration<Integer, Integer>();
+ config.setAllowDuplicates( true );
+ config.setName( "master" );
+ config.setSerializers( serializer, serializer );
+ BTree<Integer, Integer> btree = new BTree<Integer, Integer>( config );
+
+ btree.insert( 1, 1 );
+ btree.insert( 1, 2 );
+
+ assertEquals( 2l, btree.getNbElems() );
+
+ Tuple<Integer,Integer> t = btree.delete( 1, 1 );
+ assertEquals( Integer.valueOf( 1 ), t.getKey() );
+ assertEquals( Integer.valueOf( 1 ), t.getValue() );
+
+ assertEquals( 1l, btree.getNbElems() );
+
+ t = btree.delete( 1, 2 );
+ assertEquals( Integer.valueOf( 1 ), t.getKey() );
+ assertEquals( Integer.valueOf( 2 ), t.getValue() );
+
+ assertEquals( 0l, btree.getNbElems() );
+
+ t = btree.delete( 1, 2 );
+ assertNull( t );
+ }
}
Modified:
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java?rev=1462992&r1=1462991&r2=1462992&view=diff
==============================================================================
---
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java
(original)
+++
labs/mavibot/branches/mavibot-multivalue-support/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java
Sun Mar 31 15:41:47 2013
@@ -83,7 +83,7 @@ public class LeafTest
{
Leaf<Long, String> leaf = new Leaf<Long, String>( btree );
- DeleteResult<Long, String> result = leaf.delete( 1L, 1L, null, -1 );
+ DeleteResult<Long, String> result = leaf.delete( 1L, 1L, null, null,
-1 );
assertEquals( NotPresentResult.NOT_PRESENT, result );
}
@@ -102,7 +102,7 @@ public class LeafTest
leaf = insert( leaf, 3L, "v3" );
leaf = insert( leaf, 4L, "v4" );
- DeleteResult<Long, String> result = leaf.delete( 2L, 5L, null, -1 );
+ DeleteResult<Long, String> result = leaf.delete( 2L, 5L, null, null,
-1 );
assertEquals( NotPresentResult.NOT_PRESENT, result );
}
@@ -121,7 +121,7 @@ public class LeafTest
leaf = insert( leaf, 3L, "v3" );
leaf = insert( leaf, 4L, "v4" );
- DeleteResult<Long, String> result = leaf.delete( 4L, 3L, null, -1 );
+ DeleteResult<Long, String> result = leaf.delete( 4L, 3L, null, null,
-1 );
assertTrue( result instanceof RemoveResult );
@@ -168,7 +168,7 @@ public class LeafTest
leaf = insert( leaf, 3L, "v3" );
leaf = insert( leaf, 4L, "v4" );
- DeleteResult<Long, String> result = leaf.delete( 4L, 1L, null, -1 );
+ DeleteResult<Long, String> result = leaf.delete( 4L, 1L, null, null,
-1 );
assertTrue( result instanceof RemoveResult );
@@ -248,7 +248,7 @@ public class LeafTest
parent.keys[1] = 10L;
// Now, delete the element from the target page
- DeleteResult<Long, String> result = target.delete( 2L, 7L, parent, 1 );
+ DeleteResult<Long, String> result = target.delete( 2L, 7L, null,
parent, 1 );
assertTrue( result instanceof BorrowedFromLeftResult );
@@ -321,7 +321,7 @@ public class LeafTest
parent.keys[1] = 10L;
// Now, delete the element from the target page
- DeleteResult<Long, String> result = target.delete( 2L, 7L, parent, 1 );
+ DeleteResult<Long, String> result = target.delete( 2L, 7L, null,
parent, 1 );
assertTrue( result instanceof BorrowedFromRightResult );
@@ -394,7 +394,7 @@ public class LeafTest
parent.keys[1] = 9L;
// Now, delete the element from the target page
- DeleteResult<Long, String> result = target.delete( 2L, 7L, parent, 1 );
+ DeleteResult<Long, String> result = target.delete( 2L, 7L, null,
parent, 1 );
assertTrue( result instanceof MergedWithSiblingResult );
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]