net.spy.memcached.ArrayModNodeLocator Maven / Gradle / Ivy
The newest version!
/*
* arcus-java-client : Arcus Java client
* Copyright 2010-2014 NAVER Corp.
*
* 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 net.spy.memcached;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* NodeLocator implementation for dealing with simple array lookups using a
* modulus of the hash code and node list length.
*/
public final class ArrayModNodeLocator implements NodeLocator {
private final MemcachedNode[] nodes;
private final HashAlgorithm hashAlg;
/**
* Construct an ArraymodNodeLocator over the given array of nodes and
* using the given hash algorithm.
*
* @param n the array of nodes
* @param alg the hash algorithm
*/
public ArrayModNodeLocator(List n, HashAlgorithm alg) {
super();
nodes = n.toArray(new MemcachedNode[n.size()]);
hashAlg = alg;
}
private ArrayModNodeLocator(MemcachedNode[] n, HashAlgorithm alg) {
super();
nodes = n;
hashAlg = alg;
}
public Collection getAll() {
return Arrays.asList(nodes);
}
public MemcachedNode getPrimary(String k) {
return nodes[getServerForKey(k)];
}
public Iterator getSequence(String k) {
return new NodeIterator(getServerForKey(k));
}
public NodeLocator getReadonlyCopy() {
MemcachedNode[] n = new MemcachedNode[nodes.length];
for (int i = 0; i < nodes.length; i++) {
n[i] = new MemcachedNodeROImpl(nodes[i]);
}
return new ArrayModNodeLocator(n, hashAlg);
}
public void update(Collection toAttach, Collection toDelete) {
throw new UnsupportedOperationException("update not supported");
}
private int getServerForKey(String key) {
int rv = (int) (hashAlg.hash(key) % nodes.length);
assert rv >= 0 : "Returned negative key for key " + key;
assert rv < nodes.length
: "Invalid server number " + rv + " for key " + key;
return rv;
}
class NodeIterator implements Iterator {
private final int start;
private int next = 0;
public NodeIterator(int keyStart) {
start = keyStart;
next = start;
computeNext();
assert next >= 0 || nodes.length == 1
: "Starting sequence at " + start + " of "
+ nodes.length + " next is " + next;
}
public boolean hasNext() {
return next >= 0;
}
private void computeNext() {
if (++next >= nodes.length) {
next = 0;
}
if (next == start) {
next = -1;
}
}
public MemcachedNode next() {
try {
return nodes[next];
} finally {
computeNext();
}
}
public void remove() {
throw new UnsupportedOperationException("Can't remove a node");
}
}
}