gt:             int count = closeSessionsForManager(uuid);
context: /*
   *   $Id$
   *
   *   Copyright 2008 Glencoe Software, Inc. All rights reserved.
   *   Use is subject to license terms supplied in LICENSE.txt
   */
  
  package ome.services.blitz.fire;
  
  import java.sql.Timestamp;
  import java.util.Arrays;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  import ome.model.meta.Node;
  import ome.services.blitz.redirect.NullRedirector;
  import ome.services.blitz.redirect.Redirector;
  import ome.services.blitz.util.BlitzConfiguration;
  import ome.services.sessions.SessionManager;
  import ome.services.util.Executor;
  import ome.system.Principal;
  import ome.system.ServiceFactory;
  import ome.util.SqlAction;
  import omero.grid.ClusterNodePrx;
  import omero.grid.ClusterNodePrxHelper;
  import omero.grid._ClusterNodeDisp;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.hibernate.Query;
  import org.hibernate.Session;
  import org.springframework.transaction.annotation.Transactional;
  
  import Glacier2.CannotCreateSessionException;
  import Glacier2.SessionPrx;
  import Ice.Current;
  
  /**
   * Distributed ring of {@link BlitzConfiguration} objects which manages lookups
   * of sessions and other resources from all the blitzes which take part in the
   * cluster. Membership in the {@link Ring} is based on a single token --
   * "omero.instance" -- retrieved from the current context, or if missing, a
   * calculated value which will prevent this instance from taking part in
   * clustering.
   * 
   * The {@link Ring} also listens for
   * 
   *@since Beta4
   */
  public class Ring extends _ClusterNodeDisp implements Redirector.Context {
  
      private final static Log log = LogFactory.getLog(Ring.class);
  
      /**
       * UUID for this cluster node. Used to uniquely identify the session manager
       * in this blitz instance. Most likely used in common with internal server
       * components. <em>Must</em> specify a valid session id.
       */
      public final String uuid;
  
      public final Principal principal;
  
      private final Executor executor;
  
      private final Redirector redirector;
  
      private/* final */Ice.Communicator communicator;
  
      private/* final */Registry registry;
  
      /**
       * Standard blitz adapter which is used for the callback.
       */
      private/* final */Ice.ObjectAdapter adapter;
  
      /**
       * Direct proxy value to the {@link SessionManager} in this blitz instance.
       */
      private/* final */String directProxy;
  
      public Ring(String uuid, Executor executor) {
          this(uuid, executor, new NullRedirector());
      }
  
      public Ring(String uuid, Executor executor, Redirector redirector) {
          this.uuid = uuid;
          this.executor = executor;
          this.redirector = redirector;
          this.principal = new Principal(uuid, "system", "Internal");
      }
  
      /**
       * Sets the {@link Registry} for this instance. This is currently done in
       * {@link BlitzConfiguration}
       */
      public void setRegistry(Registry registry) {
          this.registry = registry;
      }
  
      // Redirector.Context API
      // =========================================================================
  
      public String uuid() {
          return this.uuid;
      }
  
      public Principal principal() {
          return this.principal;
      }
  
      /**
       * Returns the proxy information for the local {@link SessionManager}.
       * 
       * @return
       */
      public String getDirectProxy() {
          return this.directProxy;
      }
  
      public Ice.Communicator getCommunicator() {
          return this.communicator;
      }
  
      // Configuration and cluster usage
      // =========================================================================
  
      /**
       * Typically called from within {@link BlitzConfiguration} after the
       * communicator and adapter have been properly setup.
       */
      public void init(Ice.ObjectAdapter adapter, String directProxy) {
          this.adapter = adapter;
          this.communicator = adapter.getCommunicator();
          this.directProxy = directProxy;
  
          // Before we add our self we check the validity of the cluster.
          Set<String> nodeUuids = checkCluster();
          if (nodeUuids == null) {
              log.warn("No clusters found. Aborting ring initialization");
              return; // EARLY EXIT!
          }
          
          try {
              // Now our checking is done, add ourselves.
              Ice.Identity clusterNode = this.communicator
                      .stringToIdentity("ClusterNode/" + uuid);
              this.adapter.add(this, clusterNode); // OK ADAPTER USAGE
              addManager(uuid, directProxy);
              registry.addObject(this.adapter.createDirectProxy(clusterNode));
              nodeUuids.add(uuid);
              redirector.chooseNextRedirect(this, nodeUuids);
          } catch (Exception e) {
              throw new RuntimeException("Cannot register self as node: ", e);
          }
      }
  
      /**
       * Method called during initialization to get all the active uuids within
       * the cluster, and remove any dead nodes. May return null if lookup fails.
       */
      public Set<String> checkCluster() {
          
          log.info("Checking cluster");
          ClusterNodePrx[] nodes = registry.lookupClusterNodes();
          if (nodes == null) {
              log.error("Could not lookup nodes. Skipping initialization...");
              return null; // EARLY EXIT
          }
  
          // Contact each of the cluster. During init this, instance has not been
          // added, so this will not cause a callback. On clusterCheckTrigger,
          // however, it might.
          Set<String> nodeUuids = new HashSet<String>();
          for (int i = 0; i < nodes.length; i++) {
              ClusterNodePrx prx = nodes[i];
              if (prx == null) {
                  log.warn("Null proxy found");
                  continue;
              } else {
                  try {
                      nodeUuids.add(nodes[i].getNodeUuid());
                  } catch (Exception e) {
                      log.warn("Error getting uuid from node " + nodes[i]
                              + " -- removing.");
                      registry.removeObjectSafely(prx.ice_getIdentity());
                  }
              }
          }
          log.info("Got " + nodeUuids.size() + " cluster uuids : " + nodeUuids);
  
          // Now any stale nodes (ones not found in the registry) are forcibly
          // removed, since it is assumed they didn't shut down cleanly.
          assertNodes(nodeUuids);
  
          return nodeUuids;
      }
  
      public void destroy() {
          try {
              Ice.Identity id = this.communicator.stringToIdentity("ClusterNode/"
                      + uuid);
              registry.removeObjectSafely(id);
              redirector.handleRingShutdown(this, this.uuid);
  