Pregunta

I am using db4o 8.0. The db4odatabase file size is 21MB. The database has following Objects in it.

User : There is 1 user in db.
PostedMessage : There are 10000 postedMessages in db.

I delete all 10000 PostedMessages. Then I try to defragment the db4o database. Following code is used for Defragmentation.

private void processDefrag() {
    try {
        String dbpath = "D:\\db4oDatabase";

        IdMapping mapping = new InMemoryIdMapping();
        //new DatabaseIdMapping(dbpath); //use this if heap overflows

        DefragmentConfig config = new DefragmentConfig(dbpath, dbpath+".bak", mapping);
        config.storedClassFilter(new AvailableClassFilter());
        config.forceBackupDelete(false);
        config.objectCommitFrequency(1000);
        Defragment.defrag(config);
        System.out.println("Defrag completed");

    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

My expectation is that the db4oDatabase file size will go back to 21 Kb. And the db4oDatabase will still contain the 1 User object in it. However, after running the above code, the db4odatabase becomes completely empty. Why is it happening like that?

How can I avoid losing the other objects which were not deleted (in this case the 1 User object)? What is the right way of doing defragmentation on db4o database?

¿Fue útil?

Solución

If it's not accepting the class because it can't find it, you might try writing a StoredClassFilter of your own that just accepts all StoredClass objects.

public class AcceptAllClassFilter implements StoredClassFilter {

    @Override
    public boolean accept(StoredClass storedClass) {
        return true;
    }
}

Then:

config.storedClassFilter(new AcceptAllClassFilter());

This will work unless the defrag process just deletes everything without a StoredClass automatically. If this is the case, we may need to figure out why the User class doesn't have a corresponding StoredClass instance for the container.

Otros consejos

public static void printStoredClasses(ObjectContainer db) {
    StoredClass[] storedClasses = db.ext().storedClasses();
    for (StoredClass sc : storedClasses) {
        try {        
            Class<?> c = Class.forName(sc.getName());
            DebugMessagePrinter.print(c.getName());
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }
}

I used the above method to print the stored classes. And as Brian guessed it, for some reason, it did not print the User and PostedMessage class names. That implies that it is not able to see those classes in the db4o database file.

Finally, with the help of Brian's AcceptAllFilter class, I could successfully defrag the db4oDatabase file. The size reduced to 12MB from 21 MB. The working method is shown below.

private void process() {
    try {
        String dbpath = "D:\\db4oDatabase";
        printStoredClassNames(dbpath);

        IdMapping mapping = new InMemoryIdMapping();
        //new DatabaseIdMapping(dbpath); //use this if heap overflows

        DefragmentConfig config = new DefragmentConfig(dbpath, dbpath+".bak2", mapping);
        config.storedClassFilter(new AcceptAllClassFilter());
        config.forceBackupDelete(false);
        config.objectCommitFrequency(1000);
        config.db4oConfig().add(new UuidSupport());
        Defragment.defrag(config);
        System.out.println("Defrag completed" + t.s());

    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

Btw, the defragmentation does not seem to be doing its job at its best. After deleting 10000 PostedMessage objects, the database contained only the 1 User Object. I would expect the database file size to be in KBs.

But, as they say, something is better than nothing. With this some amount of success, I will keep the search for better defragmeentation on. if I happen to get better results, I will post em here.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top