prevent and keep track of which objects handling element/jv obj synchronizations.
authorjprocter <Jim Procter>
Fri, 12 Jun 2009 15:54:53 +0000 (15:54 +0000)
committerjprocter <Jim Procter>
Fri, 12 Jun 2009 15:54:53 +0000 (15:54 +0000)
src/jalview/io/vamsas/DatastoreRegistry.java [new file with mode: 0644]

diff --git a/src/jalview/io/vamsas/DatastoreRegistry.java b/src/jalview/io/vamsas/DatastoreRegistry.java
new file mode 100644 (file)
index 0000000..21083dd
--- /dev/null
@@ -0,0 +1,160 @@
+package jalview.io.vamsas;
+
+import java.util.Enumeration;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import uk.ac.vamsas.client.Vobject;
+
+public class DatastoreRegistry
+{
+  protected static org.apache.log4j.Logger log = org.apache.log4j.Logger
+          .getLogger(DatastoreRegistry.class);
+
+  /**
+   * map between Datastore objects and the objects they are handling- used to
+   * prevent cycles in the synchronization pattern. Keys are both vamsas objects
+   * and jalview objects, values are datastore objects.
+   */
+  IdentityHashMap dsObjReg;
+
+  /**
+   * all datastore items - value is [jvObject,vObject]
+   */
+  IdentityHashMap dsItemReg;
+
+  public DatastoreRegistry()
+  {
+    dsObjReg = new IdentityHashMap();
+    dsItemReg = new IdentityHashMap();
+  }
+
+  /**
+   * 
+   * @param obj
+   * @return true if obj is in the registry
+   */
+  public boolean isInvolvedInDsitem(Object obj)
+  {
+    return (obj instanceof DatastoreItem) ? dsItemReg.containsKey(obj)
+            : dsObjReg.containsKey(obj);
+  }
+
+  /**
+   * 
+   * @param obj
+   * @return DatastoreItem associated with obj - or null
+   */
+  public DatastoreItem getDatastoreItemFor(Object obj)
+  {
+    if (obj instanceof DatastoreItem)
+    {
+      log.debug("Returning DatastoreItem self reference.");// TODO: we could
+                                                           // store the update
+                                                           // hierarchy - so
+                                                           // retrieve parent
+                                                           // for obj.
+      return (DatastoreItem) obj;
+    }
+    return (DatastoreItem) dsObjReg.get(obj);
+  }
+
+  public void registerDsObj(DatastoreItem dsitem)
+  {
+    synchronized (dsItemReg)
+    {
+      Object[] dsregitem = (Object[]) dsItemReg.get(dsitem);
+      if (dsregitem == null)
+      {
+        // create a new item entry
+        dsregitem = new Object[]
+        { dsitem.jvobj, dsitem.vobj };
+        dsItemReg.put(dsitem, dsregitem);
+      }
+      // atomic update of the jv and vobject references in the dsObjReg
+      synchronized (dsObjReg)
+      {
+        // for the jvobject
+        if (dsitem.jvobj != dsregitem[0])
+        {
+          // overwrite existing involved entries.
+          if (dsregitem[0] != null)
+          {
+            dsObjReg.remove(dsregitem[0]);
+          }
+          if ((dsregitem[0] = dsitem.jvobj) != null)
+          {
+            dsObjReg.put(dsregitem[0], dsitem);
+          }
+        }
+        // and for the vobject
+        if (dsitem.vobj != dsregitem[1])
+        {
+          // overwrite existing involved entries.
+          if (dsregitem[1] != null)
+          {
+            dsObjReg.remove(dsregitem[1]);
+          }
+          if ((dsregitem[1] = dsitem.vobj) != null)
+          {
+            dsObjReg.put(dsregitem[1], dsitem);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Remove dsitem from the registry
+   * 
+   * @param dsitem
+   * @return null or last known Object[] { jvobject, vobject } references for
+   *         this dsitem
+   */
+  public Object[] removeDsObj(DatastoreItem dsitem)
+  {
+    Object[] dsregitem = null;
+    synchronized (dsItemReg)
+    {
+      synchronized (dsObjReg)
+      {
+        dsregitem = (Object[]) dsItemReg.remove(dsitem);
+        if (dsregitem != null)
+        {
+          // eliminate object refs too
+          if (dsregitem[0] != null)
+          {
+            dsObjReg.remove(dsregitem[0]);
+          }
+          if (dsregitem[1] != null)
+          {
+            dsObjReg.remove(dsregitem[1]);
+          }
+        }
+      }
+    }
+    return dsregitem;
+  }
+
+  protected void finalize()
+  {
+    if (dsObjReg != null)
+    {
+      Iterator items = dsObjReg.entrySet().iterator();
+      // avoid the nested reference memory leak.
+      while (items.hasNext())
+      {
+        Object[] vals = (Object[]) ((Map.Entry) items.next()).getValue();
+        vals[0] = null;
+        vals[1] = null;
+      }
+      items = null;
+      dsObjReg.clear();
+    }
+    if (dsItemReg!=null)
+    {
+      dsItemReg.clear();
+    }
+  }
+}