Package net.rubyeye.xmemcached.impl

Source Code of net.rubyeye.xmemcached.impl.ArrayMemcachedSessionLocator

/**
*Copyright [2009-2010] [dennis zhuang(killme2008@gmail.com)]
*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.rubyeye.xmemcached.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import net.rubyeye.xmemcached.HashAlgorithm;
import net.rubyeye.xmemcached.networking.MemcachedSession;

import com.google.code.yanf4j.core.Session;

/**
* Session locator base on hash(key) mod sessions.size().Standard hash strategy
*
* @author dennis
*
*/
public class ArrayMemcachedSessionLocator extends
    AbstractMemcachedSessionLocator {

  private HashAlgorithm hashAlgorighm;
  private transient volatile List<List<Session>> sessions;

  public ArrayMemcachedSessionLocator() {
    this.hashAlgorighm = HashAlgorithm.NATIVE_HASH;
  }

  public ArrayMemcachedSessionLocator(HashAlgorithm hashAlgorighm) {
    this.hashAlgorighm = hashAlgorighm;
  }

  public final void setHashAlgorighm(HashAlgorithm hashAlgorighm) {
    this.hashAlgorighm = hashAlgorighm;
  }

  public final long getHash(int size, String key) {
    long hash = this.hashAlgorighm.hash(key);
    return hash % size;
  }

  final Random rand = new Random();

  public final Session getSessionByKey(final String key) {
    if (this.sessions == null || this.sessions.size() == 0) {
      return null;
    }
    // Copy on read
    List<List<Session>> sessionList = this.sessions;
    int size = sessionList.size();
    if (size == 0) {
      return null;
    }
    long start = this.getHash(size, key);
    List<Session> sessions = sessionList.get((int) start);
    Session session = getRandomSession(sessions);

    // If it is not failure mode,get next available session
    if (!this.failureMode && (session == null || session.isClosed())) {
      long next = this.getNext(size, start);
      while ((session == null || session.isClosed()) && next != start) {
        sessions = sessionList.get((int) next);
        next = this.getNext(size, next);
        session = getRandomSession(sessions);
      }
    }
    return session;
  }

  private Session getRandomSession(List<Session> sessions) {
    if (sessions == null || sessions.isEmpty())
      return null;
    return sessions.get(rand.nextInt(sessions.size()));
  }

  public final long getNext(int size, long start) {
    if (start == size - 1) {
      return 0;
    } else {
      return start + 1;
    }
  }

  public final void updateSessions(final Collection<Session> list) {
    if (list == null || list.isEmpty()) {
      this.sessions = Collections.emptyList();
      return;
    }
    Collection<Session> copySessions = list;
    List<List<Session>> tmpList = new ArrayList<List<Session>>();
    Session target = null;
    List<Session> subList = null;
    for (Session session : copySessions) {
      if (target == null) {
        target = session;
        subList = new ArrayList<Session>();
        subList.add(target);
      } else {
        if (session.getRemoteSocketAddress().equals(
            target.getRemoteSocketAddress())) {
          subList.add(session);
        } else {         
          tmpList.add(subList);
          target = session;
          subList = new ArrayList<Session>();
          subList.add(target);
        }
      }
    }

    // The last one
    if (subList != null) {
      tmpList.add(subList);
    }

    List<List<Session>> newSessions = new ArrayList<List<Session>>(
        tmpList.size() * 2);
    for (List<Session> sessions : tmpList) {
      if (sessions != null && !sessions.isEmpty()) {
        Session session = sessions.get(0);
        if (session instanceof MemcachedTCPSession) {
          int weight = ((MemcachedSession) session).getWeight();
          for (int i = 0; i < weight; i++) {
            newSessions.add(sessions);
          }
        } else {
          newSessions.add(sessions);
        }
      }

    }
    this.sessions = newSessions;
  }
}
TOP

Related Classes of net.rubyeye.xmemcached.impl.ArrayMemcachedSessionLocator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.