make locks expire

git-svn-id: http://google-refine.googlecode.com/svn/trunk@1014 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
Stefano Mazzocchi 2010-06-21 07:45:57 +00:00
parent 2237ec2335
commit f690c55fab
6 changed files with 102 additions and 9 deletions

5
.gitignore vendored
View File

@ -9,4 +9,7 @@ appengine/classes/
tools/ tools/
extensions/sample-extension/module/MOD-INF/classes/ extensions/sample-extension/module/MOD-INF/classes/
extensions/jython/module/MOD-INF/classes/ extensions/jython/module/MOD-INF/classes/
extensions/jython/module/MOD-INF/lib/cachedir/ extensions/jython/module/MOD-INF/lib/cachedir/
broker/appengine/module/MOD-INF/classes/
broker/core/module/MOD-INF/classes/
broker/local/module/MOD-INF/classes/

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/expire_locks</url>
<schedule>every 5 seconds synchronized</schedule>
</cron>
</cronentries>

View File

@ -1,10 +1,6 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<!DOCTYPE web-app <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
<web-app>
<servlet> <servlet>
<servlet-name>Butterfly</servlet-name> <servlet-name>Butterfly</servlet-name>
@ -16,5 +12,14 @@
<servlet-name>Butterfly</servlet-name> <servlet-name>Butterfly</servlet-name>
<url-pattern>/*</url-pattern> <url-pattern>/*</url-pattern>
</servlet-mapping> </servlet-mapping>
<security-constraint>
<web-resource-collection>
<url-pattern>/expire_locks</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
</web-app> </web-app>

View File

@ -4,6 +4,7 @@ import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.jdo.Extent;
import javax.jdo.JDOHelper; import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager; import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory; import javax.jdo.PersistenceManagerFactory;
@ -53,6 +54,39 @@ public class AppEngineGridworksBroker extends GridworksBroker {
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
protected void expireLocks(HttpServletResponse response) throws Exception {
PersistenceManager pm = pmfInstance.getPersistenceManager();
try {
Extent<Lock> extent = pm.getExtent(Lock.class, false);
try {
for (Lock lock : extent) {
if (lock.timestamp + LOCK_DURATION < System.currentTimeMillis()) {
Transaction tx = pm.currentTransaction();
try {
tx.begin();
pm.deletePersistent(lock);
tx.commit();
} finally {
if (tx.isActive()) {
tx.rollback();
}
}
}
}
} finally {
extent.closeAll();
}
respond(response, OK);
} finally {
pm.close();
}
}
protected void getLock(HttpServletResponse response, String pid) throws Exception { protected void getLock(HttpServletResponse response, String pid) throws Exception {
PersistenceManager pm = pmfInstance.getPersistenceManager(); PersistenceManager pm = pmfInstance.getPersistenceManager();
@ -295,6 +329,7 @@ public class AppEngineGridworksBroker extends GridworksBroker {
o.put("lock_id", lock.id); o.put("lock_id", lock.id);
o.put("project_id", lock.pid); o.put("project_id", lock.pid);
o.put("user_id", lock.uid); o.put("user_id", lock.uid);
o.put("timestamp", lock.timestamp);
} }
return o; return o;
} }
@ -312,10 +347,14 @@ public class AppEngineGridworksBroker extends GridworksBroker {
@Persistent @Persistent
String uid; String uid;
@Persistent
long timestamp;
Lock(String id, String pid, String uid) { Lock(String id, String pid, String uid) {
this.id = id; this.id = id;
this.pid = pid; this.pid = pid;
this.uid = uid; this.uid = uid;
this.timestamp = System.currentTimeMillis();
} }
} }

View File

@ -62,6 +62,9 @@ public abstract class GridworksBroker extends ButterflyModuleImpl {
} }
} }
static public final long LOCK_DURATION = 60 * 1000; // 1 minute
static public final long LOCK_EXPIRATION_CHECK_DELAY = 5 * 1000; // 5 seconds
protected HttpClient httpclient; protected HttpClient httpclient;
@Override @Override
@ -98,6 +101,8 @@ public abstract class GridworksBroker extends ButterflyModuleImpl {
if ("get_lock".equals(path)) { if ("get_lock".equals(path)) {
getLock(response, pid); getLock(response, pid);
} else if ("expire_locks".equals(path)) {
expireLocks(response);
} else if ("obtain_lock".equals(path)) { } else if ("obtain_lock".equals(path)) {
obtainLock(response, pid, uid); obtainLock(response, pid, uid);
} else if ("release_lock".equals(path)) { } else if ("release_lock".equals(path)) {
@ -128,6 +133,8 @@ public abstract class GridworksBroker extends ButterflyModuleImpl {
// ---------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------
protected abstract HttpClient getHttpClient(); protected abstract HttpClient getHttpClient();
protected abstract void expireLocks(HttpServletResponse response) throws Exception;
protected abstract void getLock(HttpServletResponse response, String pid) throws Exception; protected abstract void getLock(HttpServletResponse response, String pid) throws Exception;

View File

@ -4,6 +4,8 @@ import java.io.File;
import java.io.Writer; import java.io.Writer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.servlet.ServletConfig; import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -36,12 +38,17 @@ public class LocalGridworksBroker extends GridworksBroker {
PrimaryIndex<String,Project> projectById; PrimaryIndex<String,Project> projectById;
PrimaryIndex<String,Lock> lockByProject; PrimaryIndex<String,Lock> lockByProject;
protected HttpClient httpclient; Timer timer;
LockExpirer expirer;
@Override @Override
public void init(ServletConfig config) throws Exception { public void init(ServletConfig config) throws Exception {
super.init(config); super.init(config);
timer = new Timer();
expirer = new LockExpirer();
timer.schedule(expirer, LOCK_EXPIRATION_CHECK_DELAY, LOCK_EXPIRATION_CHECK_DELAY);
File dataPath = new File("data"); // FIXME: data should be configurable; File dataPath = new File("data"); // FIXME: data should be configurable;
EnvironmentConfig envConfig = new EnvironmentConfig(); EnvironmentConfig envConfig = new EnvironmentConfig();
@ -77,6 +84,20 @@ public class LocalGridworksBroker extends GridworksBroker {
} }
} }
class LockExpirer extends TimerTask {
public void run() {
for (Lock lock : lockByProject.entities()) {
if (lock.timestamp + LOCK_DURATION < System.currentTimeMillis()) {
try {
releaseLock(null, lock.pid, lock.uid, lock.id);
} catch (Exception e) {
logger.error("Exception while expiring lock for project '" + lock.pid + "'", e);
}
}
}
}
}
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
protected HttpClient getHttpClient() { protected HttpClient getHttpClient() {
@ -85,6 +106,11 @@ public class LocalGridworksBroker extends GridworksBroker {
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
protected void expireLocks(HttpServletResponse response) throws Exception {
expirer.run();
respond(response, OK);
}
protected void getLock(HttpServletResponse response, String pid) throws Exception { protected void getLock(HttpServletResponse response, String pid) throws Exception {
respond(response, lockToJSON(getLock(pid))); respond(response, lockToJSON(getLock(pid)));
} }
@ -135,7 +161,9 @@ public class LocalGridworksBroker extends GridworksBroker {
} }
} }
respond(response, OK); if (response != null) { // this because the expiration thread can call this method without a real response
respond(response, OK);
}
} }
// ---------------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------------
@ -283,6 +311,7 @@ public class LocalGridworksBroker extends GridworksBroker {
o.put("lock_id", lock.id); o.put("lock_id", lock.id);
o.put("project_id", lock.pid); o.put("project_id", lock.pid);
o.put("user_id", lock.uid); o.put("user_id", lock.uid);
o.put("timestamp", lock.timestamp);
} }
return o; return o;
} }
@ -297,10 +326,13 @@ public class LocalGridworksBroker extends GridworksBroker {
String uid; String uid;
long timestamp;
Lock(String id, String pid, String uid) { Lock(String id, String pid, String uid) {
this.id = id; this.id = id;
this.pid = pid; this.pid = pid;
this.uid = uid; this.uid = uid;
this.timestamp = System.currentTimeMillis();
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")