Tuesday, 22 January 2013

Db4o Concurrent Access

Db4o has access limitations, which means you cannot use the ObjectContainer to query/store objects in different process than the one it was opened in. For example if you open db

ObjectContainer db= Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(),
DB_PATH);

You cannot use this ObjectContainer, db for database operations in other processes. If you try to open db again in some other process you might get
DatabaseFileLockedException. So db4o don't allow concurrent access this way. However, in real world applications, we need to perform database operations in many different threads, AsyncTask and services. To perform such concurrent operations in isolation, db4o provides many mechanisms, one of which is, opening different db sessions in different processes. Once you have opened the database, You can use it to open session in different process like:

ObjectContainer db_session= db.ext.openSession();

now we can execute all db operations with this ObjectContainer e.g

  db_session.store(someObj);
  db_session.commit();

However, keep in mind, that you need to explicitly close the session by

  db_session.Close();
 
Below is a helper class, can be used to open/close db.

//////////////////////////////////////////////////////////////////////////////////////
public class dbHelper {

private static ObjectContainer database;
private static final String DATABASE_NAME = "My_database.db4o";
private static final int DATABASE_MODE = 0;
 private static Context ctx;

public dbHelper(Context context) {

   ctx=context;
   database=null;

}

private OpenDatabse(){

try {
if (database == null) {
database = Db4oEmbedded.openFile(Db4oEmbedded.newConfiguration(),
db4oDBFullPath());
}
} catch (Exception ie) {
Log.e(DbHelper.class.getName(), ie.toString());
}


}

private String db4oDBFullPath() {
return ctx.getDir("data", DATABASE_MODE) + "/" + DATABASE_NAME;
}

public void close() {
if (this.database != null) {
this.database.close();
}
}

public ObjectContainer getDatabaseSession() {

         return database.ext().openSession();
}

}


/////////////////////////////////////////////////////////////////////////////////

Using this helper class we can pen the db somewhere at application start,


dbHelper helper= new dbHelper(context);
helper.OpenDatabse();

and close the db some where at application finish, by

helper.CloseDb();

Now in any process where you want to access db, use getSession method

ObjectContainer db= helper.getDatabaseSession();

db.store(someObj);
db.commit();
db.Close();

 That's it about concurrent access, hope it will be helpful.

2 comments:

  1. Really a great piece of useful information. Finally i got a conceptualize explanation here after searching for hours. Keep the good work up. And it will be cool if you provide a sample or a simple example so that it will be easier to depict the solution. Thanks a lot.

    ReplyDelete