/*
* Copyright 2009 Glencoe Software, Inc. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.services.blitz.redirect;
import ome.api.IConfig;
import ome.model.meta.Node;
import ome.parameters.Parameters;
import ome.services.blitz.fire.Ring;
import ome.services.util.Executor;
import ome.system.ServiceFactory;
import omero.constants.cluster.REDIRECT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.Session;
import org.springframework.transaction.annotation.Transactional;
import Glacier2.CannotCreateSessionException;
import Glacier2.SessionControlPrx;
import Glacier2.SessionManagerPrx;
import Glacier2.SessionManagerPrxHelper;
import Glacier2.SessionPrx;
import Ice.Current;
/**
* Base {@link Redirector}
*
*@since Beta-4.0-RC2
*/
public abstract class AbstractRedirector implements Redirector {
protected final static String ROUTED_FROM = "omero.routed_from";
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final Executor executor;
public AbstractRedirector(Executor ex) {
this.executor = ex;
}
/**
* Returns null early if the {@link Ice.Current} has already once been
* routed by a {@link Redirector} implementation, returns an existing
* session if it can be found, or returns a null.
*
* @see #ROUTED_FROM
*/
public SessionPrx getProxyOrNull(Context ctx, String userId,
SessionControlPrx control, Current current)
throws CannotCreateSessionException {
if (alreadyRouted(current)) {
log.info("Session creation already routed once for " + userId);
return null;
} else {
// Check if the session is in ring
String proxyString = proxyForSession(ctx, userId);
if (proxyString != null
&& !proxyString.equals(ctx.getDirectProxy())) {
log.info(String.format("Returning remote session on %s",
proxyString));
return obtainProxy(proxyString, ctx, userId, control, current);
} else {
return null;
}
}
}
protected boolean alreadyRouted(Ice.Current current) {
if (current != null) {
if (current.ctx != null) {
return current.ctx.containsKey(ROUTED_FROM);
}
}
return false;
}
protected SessionPrx obtainProxy(String proxyString, Context ctx,
String userId, SessionControlPrx control, Ice.Current current)
throws CannotCreateSessionException {
if (proxyString != null) {
current.ctx.put("omero.routed_from", ctx.getDirectProxy());
Ice.ObjectPrx remote = ctx.getCommunicator().stringToProxy(
proxyString);
SessionManagerPrx sessionManagerPrx = SessionManagerPrxHelper
.checkedCast(remote);
try {
return sessionManagerPrx.create(userId, control, current.ctx);
} catch (Exception e) {
if (e instanceof CannotCreateSessionException) {
throw (CannotCreateSessionException) e;
} else {
log.error("Error while routing to " + remote, e);
throw new CannotCreateSessionException(
"Error while routing to remote blitz");
}
}
}
return null;
}
/**
* Returns the current redirect, to which all calls to
* {@link #getProxyOrNull(Context, String, Glacier2.SessionControlPrx, Ice.Current)}
* will be pointed. May be null, but is typically set to a non-null value
* when the first {@link Ring} joins the cluster.
*/
protected String getRedirect(Context ctx) {
return (String) executor.execute(ctx.principal(),
new Executor.SimpleWork(this, "getRedirect") {
@Transactional(readOnly = true)
public Object doWork(Session session, ServiceFactory sf) {
return sf.getConfigService().getConfigValue(
REDIRECT.value);
}
});
}
/**
* Set the new redirect value if null, or if the uuid is null or empty, then
* the existing redirect will be removed. Otherwise the value is set if it
* is currently missing.
*/
protected boolean initializeRedirect(Context ctx, final String managerUuid) {
return (Boolean) executor.execute(ctx.principal(),
new Executor.SimpleWork(this, "setRedirect") {
@Transactional(readOnly = false)
public Object doWork(Session session, ServiceFactory sf) {
IConfig config = sf.getConfigService();
if (managerUuid == null || managerUuid.length() == 0) {
config.setConfigValue(REDIRECT.value, null);
return true;
} else {
return config.setConfigValueIfEquals(
REDIRECT.value, managerUuid, null);
}
}
});
}
protected String findProxy(Context ctx, final String redirect) {
final String query = "select node from Node node where node.uuid = :uuid";
return nodeProxyQuery(ctx, redirect, query);
}
protected String proxyForSession(Context ctx, final String sessionUuid) {
final String query = "select node from Node node "
+ "join node.sessions as s where s.uuid = :uuid";
return nodeProxyQuery(ctx, sessionUuid, query);
}
protected String nodeProxyQuery(Context ctx, final String uuid,
final String query) {
return (String) executor.execute(ctx.principal(),
new Executor.SimpleWork(this, "nodeProxyQuery") {
@Transactional(readOnly = true)
public Object doWork(Session session, ServiceFactory sf) {
Parameters p = new Parameters().addString("uuid", uuid);
Node node = sf.getQueryService().findByQuery(query, p);
if (node == null) {
return null;
} else {
return node.getConn();
}
}
});
}
}