de.javakaffee.web.msm.SuffixBasedNodeLocator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of memcached-session-manager Show documentation
Show all versions of memcached-session-manager Show documentation
The msm core, provides java serialization strategy.
/*
* 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();
}
}
}