[MOBY-guts] biomoby commit
Paul Gordon
gordonp at dev.open-bio.org
Thu Jun 7 23:55:42 UTC 2007
gordonp
Thu Jun 7 19:55:42 EDT 2007
Update of /home/repository/moby/moby-live/Java/src/main/org/biomoby/client
In directory dev.open-bio.org:/tmp/cvs-serv25439/src/main/org/biomoby/client
Modified Files:
CentralCachedCallsImpl.java
Log Message:
First stage commit of update: now concurrent requests for the sameCentral call are blocked, excepted for the first one
moby-live/Java/src/main/org/biomoby/client CentralCachedCallsImpl.java,1.1,1.2
===================================================================
RCS file: /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralCachedCallsImpl.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralCachedCallsImpl.java 2006/07/07 04:12:39 1.1
+++ /home/repository/moby/moby-live/Java/src/main/org/biomoby/client/CentralCachedCallsImpl.java 2007/06/07 23:55:42 1.2
@@ -1,13 +1,15 @@
/**
* Implements the functionality of caching by reusing identical calls to
* MOBY central (e.g. asking multiple times what services take a DNA
- * sequence in the gi namespace).
+ * sequence in the gi namespace). This is an in-memory cache in CentralImpl,
+ * but a filesystem cache backs it up here, so calls can be cached between
+ * JVM instances.
*/
package org.biomoby.client;
import org.biomoby.shared.MobyException;
-import java.util.Properties;
+import java.util.*;
public class CentralCachedCallsImpl extends CentralImpl{
@@ -15,6 +17,8 @@
protected static final long THE_EPOCH = 0; // don't care when the call is made, it shouldn't affect the onto mapping of calls to IDs
protected static final Properties PROPERTIES = null; // don't have any properties for the call
+ protected Map<String,String> inProgressCalls; //<callKey,threadName> used to synchronize concurrent, redundant calls to Central
+
/*************************************************************************
* Default constructor. It connects to a default Moby registry
* (as defined in {@link #DEFAULT_ENDPOINT}) using a default namespace
@@ -23,6 +27,7 @@
public CentralCachedCallsImpl()
throws MobyException {
super (DEFAULT_ENDPOINT, DEFAULT_NAMESPACE);
+ inProgressCalls = new HashMap();
}
/*************************************************************************
@@ -34,6 +39,7 @@
public CentralCachedCallsImpl (String endpoint)
throws MobyException {
super (endpoint, DEFAULT_NAMESPACE);
+ inProgressCalls = new HashMap();
}
/*************************************************************************
@@ -47,20 +53,59 @@
public CentralCachedCallsImpl (String endpoint, String namespace)
throws MobyException {
super (endpoint, namespace);
+ inProgressCalls = new HashMap();
}
+ /**
+ * The implementation of this method is smart enough that if the same call
+ * is made more than once, even concurrently(!), we only go to the server once,
+ * and use a cached value for all other invocations.
+ */
protected Object doCall (String method, Object[] parameters)
throws MobyException {
- String callKey = createId(method, parameters);
- if(getCacheMode() && existsInCache(callKey)){
- return getContents(callKey);
- }
+ Object result = null;
- Object result = super.doCall(method, parameters);
-
+ String callKey = createId(method, parameters);
if(getCacheMode()){
- setContents(callKey, result);
+
+ // It's in the cache?
+ if(existsInCache(callKey)){
+ return getContents(callKey);
+ }
+
+ // The same request is already in progress, in another thread?
+ Object inProgressCall = null;
+ synchronized(inProgressCalls){
+ String threadName = inProgressCalls.get(callKey);
+ if(threadName == null){
+ // No one's currently doing this request...claim it for this thread
+ threadName = Thread.currentThread().getName();
+ inProgressCalls.put(callKey, threadName);
+ }
+ inProgressCall = threadName;
+ }
+
+ // The first thread making a call will block subsequent ones with the same callKey
+ synchronized(inProgressCall){
+ // Should be true for subsequent calls
+ if(existsInCache(callKey)){
+ return getContents(callKey);
+ }
+ // Should get here only if I'm the first caller for the callKey,
+ // or subsequent call when previous doCall() for this callKey throws an exception
+ // i.e. setContents() isn't called after doCall()
+ try{
+ result = super.doCall(method, parameters);
+ setContents(callKey, result);
+ } finally{
+ // Remove the blocker, regardless of whether an Exception was thrown or not.
+ inProgressCalls.remove(callKey);
+ }
+ }
+ }
+ else{
+ result = super.doCall(method, parameters);
}
return result;
More information about the MOBY-guts
mailing list