AW: [OJB-developers] Re: Named Root Objects
Brought to you by:
thma
From: Mahler T. <tho...@it...> - 2002-01-15 09:29:38
|
Hi Michael, There will be a lot of people using OJB who do not use named roots. Just imagine their faces when the GC starts and deletes all their objects because they where unreferenced >:-() !!! Thus Having the GC as a separate tool is a good idea, not to say a MUST! Implementing a GC that will reclaim everything that can not be reached from a named root will not be difficult. The algorithm you describe is a simple "mark and sweep" algorithm. Would be fun to implement such a thing! cheers, Thomas > > Hi Thomas! > > I've been thinking about the GC process over the last few days. > > > Currently there is no GC implemented. > > IMHO it will be VERY difficult to have a real GC as it > would be possible > > with an OODBMS. > > It will be very difficult to decide if objects can safely > be deleted. > > > > BUT: we have been thinking of changing the semantics of > DList.remove() > > an similar methods as name roots unbind so that removed objects are > > deleted from the DB. > > A first step towards true persistence by reachability could > be to offer > offline GC. This way you don't have the to deal with objects which not > reachable from any named root object any more but are still > referenced under > another transaction that has not yet committed. The algorithm > could look > like this: > > 1. Make a list of all objects stored in the database > 2. from every named root object traverse the object graph and mark any > object you come across as being persistent > 3. delete all the objects from the database which are > currently not marked > as persistent. > > The algorithm can be implemented using recursion. In order to avoid > indefinite loops caused by cyclic references, the algorithm > has to check > whether an object under investigation is already marked. > > Another advantage is that people who do not want seamless > persistence the > "Java Way" but instead want to have a more basic level > control over their > data still have the option not to execute the garbage collector. > > What do you think about it? > > Greetings Michael > ----- Original Message ----- > From: "Thomas Mahler" <tho...@ho...> > To: "Michael Nowotny" <mic...@gm...>; "ojb" > <obj...@li...> > Sent: Wednesday, January 09, 2002 6:51 PM > Subject: Re: Named Root Objects > > > > Hi again, > > > > > > Michael Nowotny wrote: > > > > > Hi Thomas! > > > > > > Thanks for the illustration. Binding collections works > fine for me now! > > > The reason why my earlier attempt failed was that I was > still using > > > InstantDB.It seems that some transactions got only > halfway commited due > to > > > program termination following db.close(). Now I'm using > Hypersonic and > > > everything works. > > > > > > > Fine ! > > > > > > > During the course of setting up a test procedure I came > across some > strange > > > behaviour. The following code snipped throws an > ObjectNameNotBoundException. > > > > > > // fails: > > > tx = odmg.newTransaction(); > > > tx.begin(); > > > db.bind(odmg.newDList(), "MyList"); > > > db.unbind("MyList"); > > > db.bind(odmg.newDList(), "MyList"); > > > // DList list = (DList)db.lookup("MyList"); > > > tx.commit(); > > > > > > tx = odmg.newTransaction(); > > > tx.begin(); > > > DList newList = (DList)db.lookup("MyList"); > > > tx.commit(); > > > > > > Binding the same name twice within the same transaction > seems to cause > an > > > error. > > > > > > Oops, This is a bug. I'll add it to my todo list! > > > > > > This is not very important though because usually one wouldn't want > > > to bind an object to a some name and thereafter unbinding > that name > withing > > > the same transaction. > > > > > > Another question arose when I had a look at the contents > of my database. > If > > > I add content to my list which is a named root object > this content gets > > > persistent as well. That's part of persistence by > reachability. But when > I > > > unbind the root object and the content is therefore no > longer reachable, > it > > > doesn't get removed from the database but is still > present. Is there any > way > > > of performing some kind of garbage collection? > > > > > > > > > > > Currently there is no GC implemented. > > IMHO it will be VERY difficult to have a real GC as it > would be possible > > with an OODBMS. > > It will be very difficult to decide if objects can safely > be deleted. > > > > BUT: we have been thinking of changing the semantics of > DList.remove() > > an similar methods as name roots unbind so that removed objects are > > deleted from the DB. > > > > Any ideas? > > > > -- Thomas > > > > > > > > > > > Keep up the good work! > > > > > > Thanks, Michael > > > > > > ----- Original Message ----- > > > From: "Thomas Mahler" <tho...@ho...> > > > To: "Michael Nowotny" <mic...@gm...>; "ojb" > > > <obj...@li...> > > > Sent: Tuesday, January 08, 2002 8:20 PM > > > Subject: Re: Named Root Objects > > > > > > > > > > > >>Hi Michael, > > >> > > >>please see the attached Java class. > > >> > > >>You can replace the original version of > test.ojb.odmg.OdmgExamples with > > >>this new version to have it executed with the OJB JUnit tests. > > >> > > >>There is a new testMethod testNrmAndDlists that tests > your scenario. > > >>Works great! > > >> > > >>HTH, > > >> > > >>Thomas > > >> > > >>Michael Nowotny wrote: > > >> > > >> > > >>>Hi Thomas! > > >>> > > >>>Just found your OJB project on sourceforge. I think it's > great to have > > >>> > > > an > > > > > >>>open source ODMG implementation around. > > >>>Now I've got a question concerning the ODMG implemetation. > > >>>Is it possible to use a DList for example as a named root object. > > >>> > > > Binding > > > > > >>>that object to a name works but looking it up again causes an > > >>>IllegalArgumentException. > > >>> > > >>>Have you ever tried to bind a Collection. If so, I would > be grateful if > > >>> > > > you > > > > > >>>could drop me some lines of source code. > > >>> > > >>>Thanks Michael > > >>> > > >>> > > >>> > > >>> > > >>> > > >>> > > >> > > >> > > > > > > > > > > > -------------------------------------------------------------- > ------------ > -- > > > ---- > > > > > > > > > > > >>package test.ojb.odmg; > > >> > > >> > > >>import junit.framework.TestCase; > > >>import ojb.broker.Identity; > > >>import ojb.broker.PersistenceBroker; > > >>import ojb.broker.PersistenceBrokerFactory; > > >>import ojb.broker.cache.ObjectCacheFactory; > > >>import ojb.odmg.OJB; > > >>import ojb.odmg.states.ModificationState; > > >>import ojb.odmg.states.StateNewClean; > > >>import ojb.odmg.states.StateNewDirty; > > >>import org.odmg.*; > > >> > > >>import java.util.List; > > >> > > >>/** Demo Application that shows basic concepts for > Applications using > the > > >> > > > OJB ODMG > > > > > >> * implementation as an transactional object server. > > >> */ > > >>public class OdmgExamples extends TestCase > > >>{ > > >> public static void main(String[] args) > > >> { > > >> String[] arr = {CLASS.getName()}; > > >> junit.textui.TestRunner.main(arr); > > >> } > > >> > > >> private static Class CLASS = OdmgExamples.class; > > >> private String databaseName; > > >> > > >> /** > > >> * Insert the method's description here. > > >> * Creation date: (24.12.2000 00:33:40) > > >> */ > > >> public OdmgExamples(String name) > > >> { > > >> super(name); > > >> } > > >> > > >> /** > > >> * Insert the method's description here. > > >> * Creation date: (06.12.2000 21:58:53) > > >> */ > > >> public void setUp() > > >> { > > >> databaseName = > > >> > > > > PersistenceBrokerFactory.getConfiguration().getRepositoryFilename(); > > > > > >> > > >> } > > >> > > >> /** > > >> * Insert the method's description here. > > >> * Creation date: (06.12.2000 21:59:14) > > >> */ > > >> public void tearDown() > > >> { > > >> databaseName = null; > > >> } > > >> > > >> /**TestThreadsNLocks state transition of modification states*/ > > >> public void testModificationStates() > > >> { > > >> // get facade instance > > >> Implementation odmg = OJB.getInstance(); > > >> Database db = odmg.newDatabase(); > > >> //open database > > >> try > > >> { > > >> db.open(databaseName, Database.OPEN_READ_WRITE); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> ModificationState oldState = StateNewClean.getInstance(); > > >> ModificationState newState = oldState.markDirty(); > > >> assertEquals(StateNewDirty.getInstance(), newState); > > >> > > >> oldState = newState; > > >> newState = oldState.markDirty(); > > >> assertEquals(oldState, newState); > > >> > > >> > > >> // close database > > >> try > > >> { > > >> db.close(); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> > > >> } > > >> > > >> public void testOdmgSession() > > >> { > > >> // get facade instance > > >> Implementation odmg = OJB.getInstance(); > > >> Database db = odmg.newDatabase(); > > >> //open database > > >> try > > >> { > > >> db.open(databaseName, Database.OPEN_READ_WRITE); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> Transaction tx = odmg.newTransaction(); > > >> > > >> //perform transaction > > >> try > > >> { > > >> tx.begin(); > > >> > > >> Article example = new Article(); > > >> example.setArticleId(777); > > >> db.makePersistent(example); > > >> > > >> > > >> > > >> // modify Object > > >> example.setStock(333); > > >> example.addToStock(47); > > >> example.addToStock(7); > > >> example.addToStock(4); > > >> > > >> > > >> //System.out.println("now commit all changes..."); > > >> tx.commit(); > > >> } > > >> catch (Exception ex) > > >> { > > >> tx.abort(); > > >> } > > >> > > >> // close database > > >> try > > >> { > > >> db.close(); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> } > > >> > > >> public void testOQLQuery() > > >> { > > >> // get facade instance > > >> Implementation odmg = OJB.getInstance(); > > >> Database db = odmg.newDatabase(); > > >> //open database > > >> try > > >> { > > >> db.open(databaseName, Database.OPEN_READ_WRITE); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> Transaction tx = odmg.newTransaction(); > > >> > > >> //perform transaction > > >> try > > >> { > > >> tx.begin(); > > >> > > >> > > >> OQLQuery query = odmg.newOQLQuery(); > > >> query.create("select anArticle from " + > > >> > > > Article.class.getName() + " where articleId = 7"); > > > > > >> List results = (List) query.execute(); > > >> > > >> Article a = (Article) results.get(0); > > >> > > >> > > >> // cross check with PersistenceBroker lookup > > >> // 1. get OID > > >> Article example = new Article(); > > >> example.setArticleId(7); > > >> Identity oid = new Identity(example); > > >> // 2. lookup object by OID > > >> PersistenceBroker broker = > OJB.getInstance().getBroker(); > > >> broker.clearCache(); > > >> Article b = (Article) broker.getObjectByIdentity(oid); > > >> > > >> assertEquals("should be same object", a, b); > > >> > > >> //System.out.println("now commit all changes..."); > > >> tx.commit(); > > >> } > > >> catch (Exception ex) > > >> { > > >> tx.abort(); > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> > > >> // close database > > >> try > > >> { > > >> db.close(); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> } > > >> > > >> public void testNrmAndDlists() > > >> { > > >> // get facade instance > > >> Implementation odmg = OJB.getInstance(); > > >> Database db = odmg.newDatabase(); > > >> //open database > > >> try > > >> { > > >> db.open(databaseName, Database.OPEN_READ_WRITE); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> Transaction tx = odmg.newTransaction(); > > >> > > >> //perform transaction > > >> try > > >> { > > >> tx.begin(); > > >> > > >> > > >> OQLQuery query = odmg.newOQLQuery(); > > >> query.create("select x from " + > Article.class.getName() + " > > >> > > > where productGroupId = 7"); > > > > > >> DList results = (DList) query.execute(); > > >> > > >> > > >> int originalSize = results.size(); > > >> > > >> OJB.getLogger().info(results); > > >> > > >> String name = "gimme fruits !"; > > >> > > >> db.bind(results, name); > > >> tx.commit(); > > >> > > >> // clear the cache to make sure things are > loaded from RDBMS > ! > > >> OJB.getInstance().getBroker().clearCache(); > > >> > > >> tx = odmg.newTransaction(); > > >> tx.begin(); > > >> > > >> // look it up again > > >> DList newResults = (DList) db.lookup(name); > > >> > > >> assertEquals(originalSize,newResults.size()); > > >> OJB.getLogger().info(results); > > >> > > >> tx.commit(); > > >> > > >> > > >> } > > >> catch (Throwable t) > > >> { > > >> tx.abort(); > > >> fail("ODMGException: " + t.getMessage()); > > >> } > > >> > > >> // close database > > >> try > > >> { > > >> db.close(); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> } > > >> > > >> > > >> > > >> public void testOQLQueryBind() > > >> { > > >> // get facade instance > > >> Implementation odmg = OJB.getInstance(); > > >> Database db = odmg.newDatabase(); > > >> //open database > > >> try > > >> { > > >> db.open(databaseName, Database.OPEN_READ_WRITE); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> Transaction tx = odmg.newTransaction(); > > >> > > >> //perform transaction > > >> try > > >> { > > >> tx.begin(); > > >> > > >> > > >> OQLQuery query = odmg.newOQLQuery(); > > >> query.create("select anArticle from " + > > >> > > > Article.class.getName() + " where articleId = $678"); > > > > > >> query.bind(new Integer(7)); > > >> > > >> List results = (List) query.execute(); > > >> > > >> Article a = (Article) results.get(0); > > >> > > >> //crosscheck with PersistenceBroker lookup > > >> // 1. get OID > > >> Article example = new Article(); > > >> example.setArticleId(7); > > >> Identity oid = new Identity(example); > > >> > > >> ObjectCacheFactory.getObjectCache().clear(); > > >> // 2. lookup object by OID > > >> PersistenceBroker broker = > OJB.getInstance().getBroker(); > > >> broker.clearCache(); > > >> Article b = (Article) broker.getObjectByIdentity(oid); > > >> > > >> assertEquals("should be same object", a, b); > > >> > > >> //System.out.println("now commit all changes..."); > > >> tx.commit(); > > >> } > > >> catch (Exception ex) > > >> { > > >> tx.abort(); > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> > > >> // close database > > >> try > > >> { > > >> db.close(); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> } > > >> > > >> public void tesOQLQueryOnCollections() > > >> { > > >> // get facade instance > > >> Implementation odmg = OJB.getInstance(); > > >> Database db = odmg.newDatabase(); > > >> //open database > > >> try > > >> { > > >> db.open(databaseName, Database.OPEN_READ_WRITE); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> Transaction tx = odmg.newTransaction(); > > >> > > >> //perform transaction > > >> try > > >> { > > >> tx.begin(); > > >> OQLQuery query = odmg.newOQLQuery(); > > >> query.create("select aLotOfArticles from " + > > >> > > > Article.class.getName() + " where productGroupId = 4"); > > > > > >> DCollection results = (DCollection) query.execute(); > > >> results = results.query("price > 35"); > > >> > > >> // now perform control query > > >> query = odmg.newOQLQuery(); > > >> query.create("select aLotOfArticles from " + > > >> > > > Article.class.getName() + " where productGroupId = 4 and > price > 35"); > > > > > >> DCollection check = (DCollection) query.execute(); > > >> > > >> assertEquals(results, check); > > >> > > >> > > >> tx.commit(); > > >> } > > >> catch (Exception ex) > > >> { > > >> tx.abort(); > > >> ex.printStackTrace(); > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> > > >> // close database > > >> try > > >> { > > >> db.close(); > > >> } > > >> catch (ODMGException ex) > > >> { > > >> fail("ODMGException: " + ex.getMessage()); > > >> } > > >> } > > >> > > >> > > >> /**try to open non-existing db*/ > > >> public void tesWrongDbName() > > >> { > > >> // get facade instance > > >> OJB objectserver = OJB.getInstance(); > > >> Database db = objectserver.newDatabase(); > > >> > > >> //try open database with non existing repository file: > > >> String wrongDatabaseName = "ThereIsNoSuchFile"; > > >> try > > >> { > > >> db.open(wrongDatabaseName, Database.OPEN_READ_WRITE); > > >> fail("should not be able to open database " + > > >> > > > wrongDatabaseName); > > > > > >> } > > >> catch (ODMGException ex) > > >> { > > >> return; > > >> } > > >> } > > >>} > > >> > > >> > > > > > > > > > > > > > > > > > > > > > _______________________________________________ > Objectbridge-developers mailing list > Obj...@li... > https://lists.sourceforge.net/lists/listinfo/objectbridge-developers > |