/** * Detect possible the JVMRoute change at cluster backup node.. * * @param request * tomcat request being processed * @param response * tomcat response being processed * @exception IOException * if an input/output error has occurred * @exception ServletException * if a servlet error has occurred */ @Override public void invoke(Request request, Response response) throws IOException, ServletException { if (getEnabled() && request.getContext() != null && request.getContext().getDistributable() && !request.isAsyncDispatching()) { // valve cluster can access manager - other cluster handle turnover // at host level - hopefully! Manager manager = request.getContext().getManager(); if (manager != null && ( (manager instanceof ClusterManager && getCluster() != null && getCluster().getManager(((ClusterManager)manager).getName()) != null) || (manager instanceof PersistentManager))) handlePossibleTurnover(request); } // Pass this request on to the next valve in our pipeline getNext().invoke(request, response); }
/** * Send Cluster Replication Request * @param request current request * @param manager session manager * @param cluster replication cluster */ protected void sendSessionReplicationMessage(Request request, ClusterManager manager, CatalinaCluster cluster) { Session session = request.getSessionInternal(false); if (session != null) { String uri = request.getDecodedRequestURI(); // request without session change if (!isRequestWithoutSessionChange(uri)) { if (log.isDebugEnabled()) log.debug(sm.getString("ReplicationValve.invoke.uri", uri)); sendMessage(session,manager,cluster); } else if(doStatistics()) nrOfFilterRequests++; } }
/** * Detect possible the JVMRoute change at cluster backup node.. * * @param request * tomcat request being processed * @param response * tomcat response being processed * @exception IOException * if an input/output error has occurred * @exception ServletException * if a servlet error has occurred */ @Override public void invoke(Request request, Response response) throws IOException, ServletException { if (getEnabled() && request.getContext() != null && request.getContext().getDistributable() && !request.isAsyncDispatching()) { // valve cluster can access manager - other cluster handle turnover // at host level - hopefully! Manager manager = request.getContext().getManager(); if (manager != null && ((manager instanceof ClusterManager && getCluster() != null && getCluster().getManager(((ClusterManager) manager).getName()) != null) || (manager instanceof PersistentManager))) handlePossibleTurnover(request); } // Pass this request on to the next valve in our pipeline getNext().invoke(request, response); }
/** * Applies a diff to an existing object. * @param diff byte[] * @param offset int * @param length int * @throws IOException */ @Override public void applyDiff(byte[] diff, int offset, int length) throws IOException, ClassNotFoundException { try { lock(); ReplicationStream stream = ( (ClusterManager) getManager()).getReplicationStream(diff, offset, length); ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); try { ClassLoader[] loaders = getClassLoaders(); if (loaders != null && loaders.length > 0) Thread.currentThread().setContextClassLoader(loaders[0]); getDeltaRequest().readExternal(stream); getDeltaRequest().execute(this, ((ClusterManager)getManager()).isNotifyListenersOnReplication()); stream.close(); } finally { Thread.currentThread().setContextClassLoader(contextLoader); } }finally { unlock(); } }
/** * @param request * @param totalstart * @param isCrossContext * @param clusterManager * @param containerCluster */ protected void sendReplicationMessage(Request request, long totalstart, boolean isCrossContext, ClusterManager clusterManager, CatalinaCluster containerCluster) { //this happens after the request long start = 0; if(doStatistics()) { start = System.currentTimeMillis(); } try { // send invalid sessions // DeltaManager returns String[0] if (!(clusterManager instanceof DeltaManager)) sendInvalidSessions(clusterManager, containerCluster); // send replication sendSessionReplicationMessage(request, clusterManager, containerCluster); if(isCrossContext) sendCrossContextSession(containerCluster); } catch (Exception x) { // FIXME we have a lot of sends, but the trouble with one node stops the correct replication to other nodes! log.error(sm.getString("ReplicationValve.send.failure"), x); } finally { // FIXME this stats update are not cheap!! if(doStatistics()) { updateStats(totalstart,start); } } }
/** * Send all changed cross context sessions to backups * @param containerCluster */ protected void sendCrossContextSession(CatalinaCluster containerCluster) { List<DeltaSession> sessions = crossContextSessions.get(); if(sessions != null && sessions.size() >0) { for(Iterator<DeltaSession> iter = sessions.iterator(); iter.hasNext() ;) { Session session = iter.next(); if(log.isDebugEnabled()) log.debug(sm.getString("ReplicationValve.crossContext.sendDelta", session.getManager().getContainer().getName() )); sendMessage(session,(ClusterManager)session.getManager(),containerCluster); if(doStatistics()) { nrOfCrossContextSendRequests++; } } } }
/** * Create new Manager without add to cluster (comes with start the manager) * * @param name * Context Name of this manager * @see org.apache.catalina.Cluster#createManager(java.lang.String) * @see DeltaManager#start() */ @Override public synchronized Manager createManager(String name) { if (log.isDebugEnabled()) { log.debug("Creating ClusterManager for context " + name + " using class " + getManagerTemplate().getClass().getName()); } ClusterManager manager = null; try { manager = managerTemplate.cloneFromTemplate(); manager.setName(name); } catch (Exception x) { log.error("Unable to clone cluster manager, defaulting to org.apache.catalina.ha.session.DeltaManager", x); manager = new org.apache.catalina.ha.session.DeltaManager(); } finally { if ( manager != null) manager.setCluster(this); } return manager; }
@Override public void registerManager(Manager manager) { if (! (manager instanceof ClusterManager)) { log.warn("Manager [ " + manager + "] does not implement ClusterManager, addition to cluster has been aborted."); return; } ClusterManager cmanager = (ClusterManager) manager; // Notify our interested LifecycleListeners fireLifecycleEvent(BEFORE_MANAGERREGISTER_EVENT, manager); String clusterName = getManagerName(cmanager.getName(), manager); cmanager.setName(clusterName); cmanager.setCluster(this); managers.put(clusterName, cmanager); // Notify our interested LifecycleListeners fireLifecycleEvent(AFTER_MANAGERREGISTER_EVENT, manager); }
/** * Applies a diff to an existing object. * * @param diff * byte[] * @param offset * int * @param length * int * @throws IOException */ @Override public void applyDiff(byte[] diff, int offset, int length) throws IOException, ClassNotFoundException { try { lock(); ReplicationStream stream = ((ClusterManager) getManager()).getReplicationStream(diff, offset, length); ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); try { ClassLoader[] loaders = getClassLoaders(); if (loaders != null && loaders.length > 0) Thread.currentThread().setContextClassLoader(loaders[0]); getDeltaRequest().readExternal(stream); getDeltaRequest().execute(this, ((ClusterManager) getManager()).isNotifyListenersOnReplication()); stream.close(); } finally { Thread.currentThread().setContextClassLoader(contextLoader); } } finally { unlock(); } }
/** * Send all changed cross context sessions to backups * * @param containerCluster */ protected void sendCrossContextSession(CatalinaCluster containerCluster) { List<DeltaSession> sessions = crossContextSessions.get(); if (sessions != null && sessions.size() > 0) { for (Iterator<DeltaSession> iter = sessions.iterator(); iter.hasNext();) { Session session = iter.next(); if (log.isDebugEnabled()) log.debug(sm.getString("ReplicationValve.crossContext.sendDelta", session.getManager().getContainer().getName())); sendMessage(session, (ClusterManager) session.getManager(), containerCluster); if (doStatistics()) { nrOfCrossContextSendRequests++; } } } }
/** * Send Cluster Replication Request * * @param request * current request * @param manager * session manager * @param cluster * replication cluster */ protected void sendSessionReplicationMessage(Request request, ClusterManager manager, CatalinaCluster cluster) { Session session = request.getSessionInternal(false); if (session != null) { String uri = request.getDecodedRequestURI(); // request without session change if (!isRequestWithoutSessionChange(uri)) { if (log.isDebugEnabled()) log.debug(sm.getString("ReplicationValve.invoke.uri", uri)); sendMessage(session, manager, cluster); } else if (doStatistics()) nrOfFilterRequests++; } }
/** * Create new Manager without add to cluster (comes with start the manager) * * @param name * Context Name of this manager * @see org.apache.catalina.Cluster#createManager(java.lang.String) * @see DeltaManager#start() */ @Override public synchronized Manager createManager(String name) { if (log.isDebugEnabled()) { log.debug("Creating ClusterManager for context " + name + " using class " + getManagerTemplate().getClass().getName()); } ClusterManager manager = null; try { manager = managerTemplate.cloneFromTemplate(); manager.setName(name); } catch (Exception x) { log.error("Unable to clone cluster manager, defaulting to org.apache.catalina.ha.session.DeltaManager", x); manager = new org.apache.catalina.ha.session.DeltaManager(); } finally { if (manager != null) manager.setCluster(this); } return manager; }
@Override public void registerManager(Manager manager) { if (!(manager instanceof ClusterManager)) { log.warn("Manager [ " + manager + "] does not implement ClusterManager, addition to cluster has been aborted."); return; } ClusterManager cmanager = (ClusterManager) manager; // Notify our interested LifecycleListeners fireLifecycleEvent(BEFORE_MANAGERREGISTER_EVENT, manager); String clusterName = getManagerName(cmanager.getName(), manager); cmanager.setName(clusterName); cmanager.setCluster(this); managers.put(clusterName, cmanager); // Notify our interested LifecycleListeners fireLifecycleEvent(AFTER_MANAGERREGISTER_EVENT, manager); }
/** * Applies a diff to an existing object. * @param diff byte[] * @param offset int * @param length int * @throws IOException */ @Override public void applyDiff(byte[] diff, int offset, int length) throws IOException, ClassNotFoundException { try { lock(); ReplicationStream stream = ( (ClusterManager) getManager()).getReplicationStream(diff, offset, length); ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); try { ClassLoader[] loaders = getClassLoaders(); if (loaders != null && loaders.length > 0) Thread.currentThread().setContextClassLoader(loaders[0]); getDeltaRequest().readExternal(stream); getDeltaRequest().execute(this, ((ClusterManager)getManager()).isNotifyListenersOnReplication()); } finally { Thread.currentThread().setContextClassLoader(contextLoader); } }finally { unlock(); } }
/** * Notify the cluster of the addition of a Session to * an SSO session and associate the specified single * sign on identifier with the specified Session on the * local node. * * @param ssoId Single sign on identifier * @param session Session to be associated */ @Override protected void associate(String ssoId, Session session) { if (cluster != null && cluster.getMembers().length > 0) { messageNumber++; SingleSignOnMessage msg = new SingleSignOnMessage(cluster.getLocalMember(), ssoId, session.getId()); Manager mgr = session.getManager(); if ((mgr != null) && (mgr instanceof ClusterManager)) msg.setContextName(((ClusterManager) mgr).getName()); msg.setAction(SingleSignOnMessage.ADD_SESSION); cluster.send(msg); if (containerLog.isDebugEnabled()) containerLog.debug("SingleSignOnMessage Send with action " + msg.getAction()); } associateLocal(ssoId, session); }
/** * Notify the cluster of the removal of a Session from an * SSO session and deregister the specified session. If it is the last * session, then also get rid of the single sign on identifier on the * local node. * * @param ssoId Single sign on identifier * @param session Session to be deregistered */ @Override protected void deregister(String ssoId, Session session) { if (cluster != null && cluster.getMembers().length > 0) { messageNumber++; SingleSignOnMessage msg = new SingleSignOnMessage(cluster.getLocalMember(), ssoId, session.getId()); Manager mgr = session.getManager(); if ((mgr != null) && (mgr instanceof ClusterManager)) msg.setContextName(((ClusterManager) mgr).getName()); msg.setAction(SingleSignOnMessage.DEREGISTER_SESSION); cluster.send(msg); if (containerLog.isDebugEnabled()) containerLog.debug("SingleSignOnMessage Send with action " + msg.getAction()); } deregisterLocal(ssoId, session); }
/** * Remove a single Session from a SingleSignOn and notify the cluster * of the removal. Called when a session is timed out and no longer active. * * @param ssoId Single sign on identifier from which to remove the session. * @param session the session to be removed. */ @Override protected void removeSession(String ssoId, Session session) { if (cluster != null && cluster.getMembers().length > 0) { messageNumber++; SingleSignOnMessage msg = new SingleSignOnMessage(cluster.getLocalMember(), ssoId, session.getId()); Manager mgr = session.getManager(); if ((mgr != null) && (mgr instanceof ClusterManager)) msg.setContextName(((ClusterManager) mgr).getName()); msg.setAction(SingleSignOnMessage.REMOVE_SESSION); cluster.send(msg); if (containerLog.isDebugEnabled()) containerLog.debug("SingleSignOnMessage Send with action " + msg.getAction()); } removeSessionLocal(ssoId, session); }
@Override public void registerManager(Manager manager) { if (! (manager instanceof ClusterManager)) { log.warn("Manager [ " + manager + "] does not implement ClusterManager, addition to cluster has been aborted."); return; } ClusterManager cmanager = (ClusterManager) manager ; cmanager.setDistributable(true); // Notify our interested LifecycleListeners fireLifecycleEvent(BEFORE_MANAGERREGISTER_EVENT, manager); String clusterName = getManagerName(cmanager.getName(), manager); cmanager.setName(clusterName); cmanager.setCluster(this); managers.put(clusterName, cmanager); // Notify our interested LifecycleListeners fireLifecycleEvent(AFTER_MANAGERREGISTER_EVENT, manager); }