dbTalk Databases Forums  

Comparator Bug in Java Edition 3.1

comp.databases.berkeley-db comp.databases.berkeley-db


Discuss Comparator Bug in Java Edition 3.1 in the comp.databases.berkeley-db forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
luzius.meisser@gmail.com
 
Posts: n/a

Default Comparator Bug in Java Edition 3.1 - 10-12-2006 , 09:20 AM






Hi,

I'm not sure whether this is the right place for reporting bugs. There
seems to be no official "bug report" page or bug report email adresses.

My problem is the following: When inserting two identical keys with
identical values into a newly created database with a custom
BTreeComparator and DuplicateComparator, the BTreeComparator gets
called to compare the *values* of the two inserted entries. But
according to the documentation, the BTreeComparator should only be
called to compare *keys*.

I've attached a simple Testcase that reproduces this behaviour. The
problem does not appear if there are already other entries in the
database. As a workaround, I currently require the first two items of a
database to have different values. To me, this bug is not critical, but
I thought you might like to know about it.

I'm using Berkeley DB Java Edition 3.1, but the bug also showed up in
the previous version (3.0.?). You should enable assertions to run it.

Regards,
Luzius


The resulting stack trace:

Exception in thread "main" java.lang.AssertionError
at IntComparator.compare(BugDemonstrator.java:87)
at IntComparator.compare(BugDemonstrator.java:1)
at com.sleepycat.je.tree.Key.compareKeys(Key.java:105 )
at com.sleepycat.je.dbi.CursorImpl.putCurrent(CursorI mpl.java:1163)
at com.sleepycat.je.dbi.CursorImpl.put(CursorImpl.jav a:1003)
at com.sleepycat.je.Cursor.putAllowPhantoms(Cursor.ja va:856)
at com.sleepycat.je.Cursor.putNoNotify(Cursor.java:79 3)
at com.sleepycat.je.Cursor.putInternal(Cursor.java:75 0)
at com.sleepycat.je.Cursor.put(Cursor.java:321)
at com.sleepycat.util.keyrange.RangeCursor.put(RangeC ursor.java:839)
at com.sleepycat.collections.DataCursor.put(DataCurso r.java:760)
at
com.sleepycat.collections.StoredContainer.put(Stor edContainer.java:301)
at com.sleepycat.collections.StoredMap.put(StoredMap. java:249)
at
com.kangoo.searchserver.BugDemonstrator.run(BugDem onstrator.java:40)
at
com.kangoo.searchserver.BugDemonstrator.main(BugDe monstrator.java:74)

The testclass:

import java.io.File;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Comparator;

import com.sleepycat.bind.EntryBinding;
import com.sleepycat.collections.StoredSortedMap;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;

public class BugDemonstrator {

private StoredSortedMap index;

public BugDemonstrator() throws DatabaseException {
Environment env = initEnvironment();
Database db = openDatabase(env);
index = new StoredSortedMap(db, new IntBinding(), new
LongBinding(), true);
}

public void run(boolean provokeAssertionError) {
index.put(new Integer(1), new Long(7));
if (!provokeAssertionError) {
index.put(new Integer(1), new Long(5));
}
index.put(new Integer(1), new Long(7));
}

private Database openDatabase(Environment env) throws
DatabaseException {
DatabaseConfig config = new DatabaseConfig();
config.setAllowCreate(true);
config.setTransactional(true);
config.setSortedDuplicates(true);
config.setBtreeComparator(new IntComparator());
config.setDuplicateComparator(new LongComparator());
Database db = env.openDatabase(null, "testdb", config);
return db;
}

private Environment initEnvironment() throws DatabaseException {
File file = new File("testdatabase");
if (file.exists()) {
throw new RuntimeException("Please delete the old
'testdatabase' dir before running again");
}
file.mkdirs();
EnvironmentConfig config = new EnvironmentConfig();
config.setAllowCreate(true);
config.setTransactional(true);
config.setReadOnly(false);
return new Environment(file, config);
}

public static void main(String[] args) throws DatabaseException {
boolean assertionsOn = false;
assert assertionsOn = true;
if (assertionsOn) {
new BugDemonstrator().run(true);
} else {
throw new RuntimeException("Please run this class with
assertions enabled");
}
}

}

class IntBinding implements EntryBinding {

public Object entryToObject(DatabaseEntry entry) {
return new Integer(ByteBuffer.wrap(entry.getData()).getInt()) ;
}

public void objectToEntry(Object object, DatabaseEntry entry) {
Integer key = (Integer) object;
ByteBuffer buffer = ByteBuffer.allocate(4);
buffer.putInt(key);
entry.setData(buffer.array());
}

}

class IntComparator implements Comparator<byte[]>, Serializable {

public int compare(byte[] o1, byte[] o2) {
assert o1.length == 4;
int i1 = ByteBuffer.wrap(o1).getInt();
int i2 = ByteBuffer.wrap(o2).getInt();
return i1 - i2;
}
}

class LongBinding implements EntryBinding {

public Object entryToObject(DatabaseEntry entry) {
return new Long(ByteBuffer.wrap(entry.getData()).getLong());
}

public void objectToEntry(Object object, DatabaseEntry entry) {
Long key = (Long) object;
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.putLong(key);
entry.setData(buffer.array());
}

}

class LongComparator implements Comparator<byte[]>, Serializable {

public int compare(byte[] o1, byte[] o2) {
assert o1.length == 8;
long i1 = ByteBuffer.wrap(o1).getLong();
long i2 = ByteBuffer.wrap(o2).getLong();
return i1 > i2 ? 1 : (i1 == i2 ? 0 : -1);
}
}


Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.