LocalRoutingTable.java 7.14 KB
Newer Older
Gaston Dombiak's avatar
Gaston Dombiak committed
1 2 3 4 5
/**
 * $RCSfile: $
 * $Revision: $
 * $Date: $
 *
6
 * Copyright (C) 2005-2008 Jive Software. All rights reserved.
Gaston Dombiak's avatar
Gaston Dombiak committed
7
 *
8 9 10 11 12 13 14 15 16 17 18
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
Gaston Dombiak's avatar
Gaston Dombiak committed
19 20 21 22
 */

package org.jivesoftware.openfire.spi;

23 24 25 26 27 28 29
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;

Gaston Dombiak's avatar
Gaston Dombiak committed
30
import org.jivesoftware.openfire.RoutableChannelHandler;
31
import org.jivesoftware.openfire.SessionManager;
32 33 34 35 36
import org.jivesoftware.openfire.session.LocalClientSession;
import org.jivesoftware.openfire.session.LocalOutgoingServerSession;
import org.jivesoftware.openfire.session.LocalSession;
import org.jivesoftware.openfire.session.OutgoingServerSession;
import org.jivesoftware.openfire.session.Session;
37 38
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.util.TaskEngine;
39 40
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
41
import org.xmpp.packet.JID;
Gaston Dombiak's avatar
Gaston Dombiak committed
42 43 44 45 46 47 48 49 50 51

/**
 * Internal component used by the RoutingTable to keep references to routes hosted by this JVM. When
 * running in a cluster each cluster member will have its own RoutingTable containing an instance of
 * this class. Each LocalRoutingTable is responsible for storing routes to components, client sessions
 * and outgoing server sessions hosted by local cluster node.
 *
 * @author Gaston Dombiak
 */
class LocalRoutingTable {
52 53 54
	
	private static final Logger Log = LoggerFactory.getLogger(LocalRoutingTable.class);

Gaston Dombiak's avatar
Gaston Dombiak committed
55 56 57 58 59 60 61
    Map<String, RoutableChannelHandler> routes = new ConcurrentHashMap<String, RoutableChannelHandler>();

    /**
     * Adds a route of a local {@link RoutableChannelHandler}
     *
     * @param address the string representation of the JID associated to the route.
     * @param route the route hosted by this node.
62
     * @return true if the element was added or false if was already present.
Gaston Dombiak's avatar
Gaston Dombiak committed
63
     */
64 65
    boolean addRoute(String address, RoutableChannelHandler route) {
        return routes.put(address, route) != route;
Gaston Dombiak's avatar
Gaston Dombiak committed
66 67 68 69 70 71 72 73 74 75 76 77
    }

    /**
     * Returns the route hosted by this node that is associated to the specified address.
     *
     * @param address the string representation of the JID associated to the route.
     * @return the route hosted by this node that is associated to the specified address.
     */
    RoutableChannelHandler getRoute(String address) {
        return routes.get(address);
    }

78 79 80 81 82
    /**
     * Returns the client sessions that are connected to this JVM.
     *
     * @return the client sessions that are connected to this JVM.
     */
83 84
    Collection<LocalClientSession> getClientRoutes() {
        List<LocalClientSession> sessions = new ArrayList<LocalClientSession>();
85
        for (RoutableChannelHandler route : routes.values()) {
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
            if (route instanceof LocalClientSession) {
                sessions.add((LocalClientSession) route);
            }
        }
        return sessions;
    }

    /**
     * Returns the outgoing server sessions that are connected to this JVM.
     *
     * @return the outgoing server sessions that are connected to this JVM.
     */
    Collection<LocalOutgoingServerSession> getServerRoutes() {
        List<LocalOutgoingServerSession> sessions = new ArrayList<LocalOutgoingServerSession>();
        for (RoutableChannelHandler route : routes.values()) {
            if (route instanceof LocalOutgoingServerSession) {
                sessions.add((LocalOutgoingServerSession) route);
            }
        }
        return sessions;
    }

    /**
     * Returns the external component sessions that are connected to this JVM.
     *
     * @return the external component sessions that are connected to this JVM.
     */
    Collection<RoutableChannelHandler> getComponentRoute() {
        List<RoutableChannelHandler> sessions = new ArrayList<RoutableChannelHandler>();
        for (RoutableChannelHandler route : routes.values()) {
            if (!(route instanceof LocalOutgoingServerSession || route instanceof LocalClientSession)) {
                sessions.add(route);
118 119 120 121 122
            }
        }
        return sessions;
    }

Gaston Dombiak's avatar
Gaston Dombiak committed
123 124 125 126 127 128 129 130 131
    /**
     * Removes a route of a local {@link RoutableChannelHandler}
     *
     * @param address the string representation of the JID associated to the route.
     */
    void removeRoute(String address) {
        routes.remove(address);
    }

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
    public void start() {
        // Run through the server sessions every 3 minutes after a 3 minutes server startup delay (default values)
        int period = 3 * 60 * 1000;
        TaskEngine.getInstance().scheduleAtFixedRate(new ServerCleanupTask(), period, period);
    }

    public void stop() {
        try {
            // Send the close stream header to all connected connections
            for (RoutableChannelHandler route : routes.values()) {
                if (route instanceof LocalSession) {
                    LocalSession session = (LocalSession) route;
                    try {
                        // Notify connected client that the server is being shut down
                        session.getConnection().systemShutdown();
                    }
                    catch (Throwable t) {
                        // Ignore.
                    }
                }
            }
        }
        catch (Exception e) {
            // Ignore.
        }
    }

159 160 161 162
    public boolean isLocalRoute(JID jid) {
        return routes.containsKey(jid.toString());
    }

163 164 165 166 167 168 169
    /**
     * Task that closes idle server sessions.
     */
    private class ServerCleanupTask extends TimerTask {
        /**
         * Close outgoing server sessions that have been idle for a long time.
         */
170 171
        @Override
		public void run() {
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
            // Do nothing if this feature is disabled
            int idleTime = SessionManager.getInstance().getServerSessionIdleTime();
            if (idleTime == -1) {
                return;
            }
            final long deadline = System.currentTimeMillis() - idleTime;
            for (RoutableChannelHandler route : routes.values()) {
                // Check outgoing server sessions
                if (route instanceof OutgoingServerSession) {
                    Session session = (Session) route;
                    try {
                        if (session.getLastActiveDate().getTime() < deadline) {
                            session.close();
                        }
                    }
                    catch (Throwable e) {
                        Log.error(LocaleUtils.getLocalizedString("admin.error"), e);
                    }
                }
            }
        }
    }
Gaston Dombiak's avatar
Gaston Dombiak committed
194
}