Reference Cache In Client-Server Mode

Db4o uses object reference cache for easy access to persistent objects during one transaction. In client/server mode each client has its own reference cache, which helps to achieve good performance. However it gets complicated, when different clients work on the same object, as this object's cached value is used on each side. It means, that even when the operations go serially, the object's value won't be updated serially unless it is refreshed before each update.

The following example demonstrates this behaviour.

InconsistentGraphExample.java: main
1public static void main(String[] args) throws IOException { 2 new InconsistentGraphExample().run(); 3 }
InconsistentGraphExample.java: run
01public void run() throws IOException, DatabaseFileLockedException { 02 new File(DB4O_FILE_NAME).delete(); 03 ObjectServer server = Db4o.openServer(DB4O_FILE_NAME, PORT); 04 try { 05 server.grantAccess(USER, PASSWORD); 06 07 ObjectContainer client1 = server.openClient(); 08 ObjectContainer client2 = server.openClient(); 09 10 if (client1 != null && client2 != null) { 11 try { 12 // wait for the operations to finish 13 waitForCompletion(); 14 15 // save pilot with client1 16 Car client1Car = new Car("Ferrari", 2006, new Pilot( 17 "Schumacher")); 18 client1.set(client1Car); 19 client1.commit(); 20 System.out.println("Client1 version initially: " + client1Car); 21 waitForCompletion(); 22 23 // retrieve the same pilot with client2 24 Car client2Car = (Car) client2.query(Car.class).next(); 25 System.out.println("Client2 version initially: " + client2Car); 26 27 // delete the pilot with client1 28 Pilot client1Pilot = (Pilot)client1.query(Pilot.class).next(); 29 client1.delete(client1Pilot); 30 // modify the car, add and link a new pilot with client1 31 client1Car.setModel(2007); 32 client1Car.setPilot(new Pilot("Hakkinnen")); 33 client1.set(client1Car); 34 client1.commit(); 35 36 waitForCompletion(); 37 client1Car = (Car) client1.query(Car.class).next(); 38 System.out.println("Client1 version after update: " + client1Car); 39 40 41 System.out.println(); 42 System.out.println("client2Car still holds the old object graph in its reference cache"); 43 client2Car = (Car) client2.query(Car.class).next(); 44 System.out.println("Client2 version after update: " + client2Car); 45 ObjectSet result = client2.query(Pilot.class); 46 System.out.println("Though the new Pilot is retrieved by a new query: "); 47 listResult(result); 48 49 waitForCompletion(); 50 } catch (Exception ex) { 51 ex.printStackTrace(); 52 } finally { 53 closeClient(client1); 54 closeClient(client2); 55 } 56 } 57 } catch (Exception ex) { 58 ex.printStackTrace(); 59 } finally { 60 server.close(); 61 } 62 }

In order to make the objects consistent on each client you must refresh them from the server when they get updated. This can be done by using Committed Callbacks.