All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.javakaffee.web.msm.SuffixBasedNodeLocator Maven / Gradle / Ivy

There is a newer version: 2.3.2
Show newest version
/*
 * Copyright 2009 Martin Grotzke
 *
 * 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.
 *
 */
package de.javakaffee.web.msm;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import net.spy.memcached.MemcachedConnection;

import net.spy.memcached.MemcachedNode;
import net.spy.memcached.NodeLocator;
import net.spy.memcached.ops.Operation;

/**
 * Locates nodes based on their id which is a part of the sessionId (key).
 *
 * @author Martin Grotzke
 * @version $Id$
 */
class SuffixBasedNodeLocator implements NodeLocator {

    private final List _nodes;
	private final MemcachedNodesManager _memcachedNodesManager;
    private final Map _nodesMap;
	private final SessionIdFormat _sessionIdFormat;

    /**
     * Create a new {@link SuffixBasedNodeLocator}.
     *
     * @param nodes
     *            the nodes to select from.
     * @param memcachedNodesManager
     *            the memcached nodes manager that holds list of nodeIds and can resolve nodeId by {@link InetSocketAddress}.
     * @param sessionIdFormat
     *            used to extract the node id from the session id.
     */
    public SuffixBasedNodeLocator( final List nodes, final MemcachedNodesManager memcachedNodesManager,
    		final SessionIdFormat sessionIdFormat) {
        _nodes = nodes;
        _memcachedNodesManager = memcachedNodesManager;

        final Map map = new HashMap( nodes.size(), 1 );
        for ( int i = 0; i < nodes.size(); i++ ) {
            final MemcachedNode memcachedNode = nodes.get( i );
            final String nodeId = memcachedNodesManager.getNodeId( (InetSocketAddress) memcachedNode.getSocketAddress() );
            map.put( nodeId, memcachedNode );
        }
        _nodesMap = map;

        _sessionIdFormat = sessionIdFormat;
    }

	@Override
	public void updateLocator(final List nodes) {
		// TODO: how to handle this? When does this happen?
		// The nodes could be updated like in the constructor, but
		// then the memcachedNodesManager would have to be able to provide a nodeId to a new
		// address. Should nodeIds be autogenerated then, e.g. following some pattern?
		throw new UnsupportedOperationException("Not yet supported.");
	}

    /**
     * {@inheritDoc}
     */
    @Override
	public Collection getAll() {
        return _nodesMap.values();
    }

    /**
     * {@inheritDoc}
     */
    @Override
	public MemcachedNode getPrimary( final String key ) {
        final String nodeId = getNodeId( key );
        final MemcachedNode result = _nodesMap.get( nodeId );
        if ( result == null ) {
            throw new IllegalArgumentException( "No node found for key " + key + " (nodeId: " + nodeId + ", known nodeIds: " + _nodesMap.keySet() + ")" );
        }
        return result;
    }

    private String getNodeId( final String key ) {
        final String nodeId = _sessionIdFormat.extractMemcachedId( key );
        if ( !_sessionIdFormat.isBackupKey( key ) ) {
            return nodeId;
        }
        return _memcachedNodesManager.getNextAvailableNodeId( nodeId );
    }

    /**
     * {@inheritDoc}
     */
    @Override
	public Iterator getSequence( final String key ) {
        throw new UnsupportedOperationException( "This should not be called as we specified FailureMode.Cancel." );
    }

    /**
     * {@inheritDoc}
     */
    @Override
	public NodeLocator getReadonlyCopy() {
        final List nodes = new ArrayList();
        for ( final MemcachedNode node : _nodes ) {
            nodes.add( new MyMemcachedNodeROImpl( node ) );
        }
        return new SuffixBasedNodeLocator( nodes, _memcachedNodesManager, _sessionIdFormat );
    }

    /**
     * The class that is used for readonly copies.
     * Basically a copy of net.spy.memcached.MemcachedNodeROImpl (which is not visible).
     */
    static class MyMemcachedNodeROImpl implements MemcachedNode {

        private final MemcachedNode root;

        public MyMemcachedNodeROImpl( final MemcachedNode node ) {
            this.root = node;
        }

        /**
         * {@inheritDoc}
         */
        @Override
		public String toString() {
            return root.toString();
        }

        @Override
        public void addOp(final Operation op) {
          throw new UnsupportedOperationException();
        }

        @Override
        public void insertOp(final Operation op) {
          throw new UnsupportedOperationException();
        }

        @Override
        public void connected() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void copyInputQueue() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void fillWriteBuffer(final boolean optimizeGets) {
          throw new UnsupportedOperationException();
        }

        @Override
        public void fixupOps() {
          throw new UnsupportedOperationException();
        }

        @Override
        public int getBytesRemainingToWrite() {
          return root.getBytesRemainingToWrite();
        }

        @Override
        public SocketChannel getChannel() {
          throw new UnsupportedOperationException();
        }

        @Override
        public Operation getCurrentReadOp() {
          throw new UnsupportedOperationException();
        }

        @Override
        public Operation getCurrentWriteOp() {
          throw new UnsupportedOperationException();
        }

        @Override
        public ByteBuffer getRbuf() {
          throw new UnsupportedOperationException();
        }

        @Override
        public int getReconnectCount() {
          return root.getReconnectCount();
        }

        @Override
        public int getSelectionOps() {
          return root.getSelectionOps();
        }

        @Override
        public SelectionKey getSk() {
          throw new UnsupportedOperationException();
        }

        @Override
        public SocketAddress getSocketAddress() {
          return root.getSocketAddress();
        }

        @Override
        public ByteBuffer getWbuf() {
          throw new UnsupportedOperationException();
        }

        @Override
        public boolean hasReadOp() {
          return root.hasReadOp();
        }

        @Override
        public boolean hasWriteOp() {
          return root.hasReadOp();
        }

        @Override
        public boolean isActive() {
          return root.isActive();
        }

        @Override
        public void reconnecting() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void registerChannel(final SocketChannel ch, final SelectionKey selectionKey) {
          throw new UnsupportedOperationException();
        }

        @Override
        public Operation removeCurrentReadOp() {
          throw new UnsupportedOperationException();
        }

        @Override
        public Operation removeCurrentWriteOp() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void setChannel(final SocketChannel to) {
          throw new UnsupportedOperationException();
        }

        @Override
        public void setSk(final SelectionKey to) {
          throw new UnsupportedOperationException();
        }

        @Override
        public void setupResend() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void transitionWriteItem() {
          throw new UnsupportedOperationException();
        }

        @Override
        public int writeSome() throws IOException {
          throw new UnsupportedOperationException();
        }

        @Override
        public Collection destroyInputQueue() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void authComplete() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void setupForAuth() {
          throw new UnsupportedOperationException();
        }

        @Override
        public int getContinuousTimeout() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void setContinuousTimeout(final boolean isIncrease) {
          throw new UnsupportedOperationException();
        }

        @Override
        public boolean isAuthenticated() {
          throw new UnsupportedOperationException();
        }

        @Override
        public long lastReadDelta() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void completedRead() {
          throw new UnsupportedOperationException();
        }

        @Override
        public MemcachedConnection getConnection() {
          throw new UnsupportedOperationException();
        }

        @Override
        public void setConnection(MemcachedConnection mc) {
          throw new UnsupportedOperationException();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy