Mercurial > hg > blitz_condensed
diff src/org/dancres/blitz/remote/view/EntryViewFactory.java @ 0:3dc0c5604566
Initial checkin of blitz 2.0 fcs - no installer yet.
author | Dan Creswell <dan.creswell@gmail.com> |
---|---|
date | Sat, 21 Mar 2009 11:00:06 +0000 |
parents | |
children | d3ec5ebc3dba |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/dancres/blitz/remote/view/EntryViewFactory.java Sat Mar 21 11:00:06 2009 +0000 @@ -0,0 +1,195 @@ +package org.dancres.blitz.remote.view; + +import java.io.IOException; + +import java.util.HashMap; + +import java.util.logging.Logger; +import java.util.logging.Level; + +import net.jini.id.Uuid; +import net.jini.id.UuidFactory; + +import net.jini.config.ConfigurationException; + +import net.jini.core.transaction.Transaction; +import net.jini.core.transaction.TransactionException; + +import org.dancres.blitz.EntryView; +import org.dancres.blitz.SpaceImpl; + +import org.dancres.blitz.mangler.MangledEntry; + +import org.dancres.blitz.lease.LeaseReaper; +import org.dancres.blitz.lease.Reapable; +import org.dancres.blitz.lease.ReapFilter; + +import org.dancres.blitz.util.Time; + +import org.dancres.blitz.Logging; + +import org.dancres.blitz.config.ConfigurationFactory; + +/** + Manages and tracks current <code>EntryView</code> instances instantiated + from a <code>SpaceImpl</code> instance. In particular it assigns those + instances a unique id and handles leasing aspects. + */ +public class EntryViewFactory implements Reapable { + private static Logger theLogger = + Logging.newLogger("org.dancres.blitz.remote.view.EntryViewFactory"); + + private static EntryViewFactory theFactory = new EntryViewFactory(); + + public static EntryViewFactory get() { + return theFactory; + } + + private HashMap theActiveViews = new HashMap(); + + private LeaseReaper theReaper; + + private boolean shouldUpdate; + + private EntryViewFactory() { + try { + long myReapInterval = + ((Long) ConfigurationFactory.getEntry("viewReapInterval", + long.class, + new Long(30 * 60 * 1000))).longValue(); + theReaper = new LeaseReaper("View", null, myReapInterval); + + theReaper.add(this); + + shouldUpdate = ((Boolean) + ConfigurationFactory.getEntry("updateContents", + boolean.class, + new Boolean(true))).booleanValue(); + + } catch (ConfigurationException aCE) { + theLogger.log(Level.SEVERE, "Failed to load config", aCE); + } + } + + public ViewRegistration newView(MangledEntry[] aTemplates, Transaction aTxn, + boolean holdLocks, long aLeaseDuration, + long aLimit, SpaceImpl aSpace) + throws IOException, TransactionException { + + // Hold locks should only stick for a non-null transaction, other + // wise we're just testing.... + + EntryView myView = aSpace.getView(aTemplates, aTxn, holdLocks, + shouldUpdate, aLimit); + + EntryViewUID myUid = new EntryViewUID(UuidFactory.generate()); + + long myExpiry = Time.getAbsoluteTime(aLeaseDuration); + + synchronized(this) { + theActiveViews.put(myUid, new ViewHolder(myView, myExpiry)); + } + + return new ViewRegistration(myUid, myExpiry); + } + + public EntryView getView(EntryViewUID aUID) { + + synchronized(this) { + ViewHolder myHolder = (ViewHolder) theActiveViews.get(aUID); + + if ((myHolder == null) || + (myHolder.hasExpired(System.currentTimeMillis()))) { + + return null; + } else { + return myHolder.getView(); + } + } + } + + public EntryView delete(EntryViewUID aUID) { + + synchronized(this) { + ViewHolder myHolder = (ViewHolder) theActiveViews.remove(aUID); + + if (myHolder != null) { + myHolder.getView().close(); + return myHolder.getView(); + } + + return null; + } + } + + public void reap(ReapFilter aFilter) { + /* + No reap filters will be configured so we can ignore those - see + initialization in constructor + */ + long myTime = System.currentTimeMillis(); + + Object[] myKeys; + + synchronized(this) { + myKeys = theActiveViews.keySet().toArray(); + } + + for (int i = 0; i < myKeys.length; i++) { + ViewHolder myHolder = + (ViewHolder) theActiveViews.get(myKeys[i]); + + if (myHolder.hasExpired(myTime)) { + delete((EntryViewUID) myKeys[i]); + } + } + } + + /* *********************************************************************** + * Lease renewal/cancel + * ***********************************************************************/ + + boolean renew(EntryViewUID aUID, long anExpiry) { + synchronized(this) { + ViewHolder myHolder = (ViewHolder) theActiveViews.get(aUID); + + if (myHolder != null) { + return myHolder.testAndSetExpiry(System.currentTimeMillis(), + anExpiry); + } + + return false; + } + } + + boolean cancel(EntryViewUID aUID) { + return (delete(aUID) != null); + } + + class ViewHolder { + private long theExpiry; + private EntryView theView; + + ViewHolder(EntryView aView, long anExpiry) { + theView = aView; + theExpiry = anExpiry; + } + + boolean hasExpired(long aTime) { + return (theExpiry < aTime); + } + + boolean testAndSetExpiry(long aTime, long anExpiry) { + if (theExpiry < aTime) + return false; + + theExpiry = anExpiry; + + return true; + } + + EntryView getView() { + return theView; + } + } +} \ No newline at end of file