I am confused by the documentation when it describes the DB object:
A DB instance represents an opened database (or a single transaction session).
It sounds like each thread should have its own DB instance. I wrote this test class:
import org.mapdb.BTreeMap;
import org.mapdb.DB;
import org.mapdb.DBMaker;
import org.mapdb.Serializer;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;
public class MapDbTest
{
static final AtomicInteger count = new AtomicInteger(0);
public static void main(String[] args) throws InterruptedException
{
DB db = getDbMaker().make();
BTreeMap<String, Long> bTreeMap = getTreeMapMaker(db).create();
// db.close();
CyclicBarrier barrier = new CyclicBarrier(2);
Thread t1 = new Thread(new MyRunnable(db, barrier));
t1.start();
Thread t2 = new Thread(new MyRunnable(db, barrier));
t2.start();
t1.join();
t2.join();
// db = getDbMaker().make();
// bTreeMap = getTreeMapMaker(db).open();
System.out.println(bTreeMap.entrySet());
}
private static DB.TreeMapMaker<String, Long> getTreeMapMaker(DB db)
{
return db.treeMap("test").
keySerializer(Serializer.STRING).
valueSerializer(Serializer.LONG);
}
private static DBMaker.Maker getDbMaker()
{
return DBMaker.fileDB("db").
fileMmapEnableIfSupported().
cleanerHackEnable();
// fileLockDisable();
}
private static class MyRunnable implements Runnable
{
private final DB db;
private final CyclicBarrier barrier;
MyRunnable(DB db, CyclicBarrier barrier)
{
this.db = db;
this.barrier = barrier;
}
@Override
public void run()
{
try
{
barrier.await();
// DB db = getDbMaker().make();
BTreeMap<String, Long> bTreeMap = getTreeMapMaker(db).open();
barrier.await();
bTreeMap.put("ABC" + count.getAndIncrement(), 0L);
barrier.await();
db.commit();
}
catch (InterruptedException | BrokenBarrierException e)
{
e.printStackTrace();
}
}
}
}
The code as written appears to work correctly. I expected the commented lines to be required, but when I remove those comments, I find that the work of one thread replaces the other. That is, instead of outputting:
[MapEntry[ABC0=0], MapEntry[ABC1=0]]
it outputs:
[MapEntry[ABC0=0]]
I'm hoping someone can explain when a DB instance should be shared amongst threads and when the threads should make their own instance.
Thanks,
-Paul