dain / leveldb

Port of LevelDB to Java
Apache License 2.0
1.53k stars 429 forks source link

Using Snapshots in other classes #134

Open platacc opened 2 years ago

platacc commented 2 years ago

Hello,

I have followed the documentation and there is limited information on how to use Snapshots in other methods and classes. When I open a database instance, take a snapshot, then export it to a new method, the entire JVM crashes which I have never seen before:

A fatal error has been detected by the Java Runtime Environment:

Here is how I am grabbing the Snapshot:

    public synchronized DBIterator getSnapShot() throws IOException {

        ReadOptions options = new ReadOptions();

        DBIterator iterator = null;

        try {
            setLinkPacDatabase(factory.open(new File(Finals.LINKPACDB_FILEPATH), setupLevelDbOptions(true, false)));
            options.snapshot(getLinkPacDatabase().getSnapshot());
            iterator = getLinkPacDatabase().iterator(options);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            getLinkPacDatabase().close();
        }
        return iterator;
    }

But when I try to iterate the Snapshot like below in other classes, the JVM crashes:

    for (iterator.seekToFirst(); iterator.hasNext(); iterator.next()) {

What is the correct way to take a Snapshot of the database and use it elsewhere?

platacc commented 2 years ago

Just to provide an update, I have edited some code, but when I close the database, the JVM crashes with the fatal error exception. However if I leave the database connection open, then it works fine:

public synchronized DBIterator getSnapshot() throws IOException {

    ReadOptions ro = new ReadOptions();
    DB db = factory.open(new File(Finals.LINKPACDB_FILEPATH), setupLevelDbOptions(true, false));
    ro.snapshot(db.getSnapshot());
    try {

        return db.iterator(ro);

    } finally {
        // Make sure you close the snapshot to avoid resource leaks.
        ro.snapshot().close();
        db.close();
    }
}
pcmind commented 2 years ago

This code sample close the database and snapshot (in finally clause) before returning the DBIterator. Both should only be closed after DBIterator is used/iterated and not before usage.

But it is true that DB/Iterator/Snapshot should fail with a proper message when resources are closed when used.

platacc commented 2 years ago

I've tried it with 4 different JDKs and the error is the same. Sometimes the program works fine, but 90% of the time the JVM crashes upon db.close();

This only happens when the DB/Iterator/Snapshot is used in a different class.

It works absolutely fine 100% of the time if the DB/Iterator/Snapshot is used within the same class.

So to summarise; JVM crashes if DB/Iterator/Snapshot is used in a different class.