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

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");
    }

  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy