net.rubyeye.xmemcached.impl.LibmemcachedMemcachedSessionLocator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xmemcached Show documentation
Show all versions of xmemcached Show documentation
Extreme performance modern memcached client for java
/**
* Copyright [2009-2010] [dennis zhuang([email protected])] 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.List;
import java.util.Random;
import java.util.SortedMap;
import java.util.TreeMap;
import net.rubyeye.xmemcached.HashAlgorithm;
import net.rubyeye.xmemcached.impl.AbstractMemcachedSessionLocator;
import com.google.code.yanf4j.core.Session;
/**
* Consistent Hash Algorithm implementation is compatible with libmemcached method.
*
* @author dennis
*
*/
public class LibmemcachedMemcachedSessionLocator extends AbstractMemcachedSessionLocator {
static final int DEFAULT_NUM_REPS = 100;
private transient volatile TreeMap> ketamaSessions =
new TreeMap>();
private int maxTries;
private int numReps = DEFAULT_NUM_REPS;
private final Random random = new Random();
private HashAlgorithm hashAlgorithm = HashAlgorithm.ONE_AT_A_TIME;
public LibmemcachedMemcachedSessionLocator() {}
public LibmemcachedMemcachedSessionLocator(int numReps, HashAlgorithm hashAlgorithm) {
super();
this.numReps = numReps;
this.hashAlgorithm = hashAlgorithm;
}
private final void buildMap(Collection list, HashAlgorithm alg) {
TreeMap> sessionMap = new TreeMap>();
for (Session session : list) {
String sockStr = null;
if (session.getRemoteSocketAddress().getPort() != 11211) {
sockStr = session.getRemoteSocketAddress().getHostName() + ":"
+ session.getRemoteSocketAddress().getPort();
} else {
sockStr = session.getRemoteSocketAddress().getHostName();
}
for (int i = 0; i < this.numReps; i++) {
long key = hashAlgorithm.hash(sockStr + "-" + i);
this.getSessionList(sessionMap, key).add(session);
}
}
this.ketamaSessions = sessionMap;
this.maxTries = list.size();
}
private List getSessionList(TreeMap> sessionMap, long k) {
List sessionList = sessionMap.get(k);
if (sessionList == null) {
sessionList = new ArrayList();
sessionMap.put(k, sessionList);
}
return sessionList;
}
public final Session getSessionByKey(final String key) {
if (this.ketamaSessions == null || this.ketamaSessions.size() == 0) {
return null;
}
long hash = hashAlgorithm.hash(key);
Session rv = this.getSessionByHash(hash);
int tries = 0;
while (!this.failureMode && (rv == null || rv.isClosed()) && tries++ < this.maxTries) {
hash = this.nextHash(hash, key, tries);
rv = this.getSessionByHash(hash);
}
return rv;
}
public final Session getSessionByHash(final long hash) {
TreeMap> sessionMap = this.ketamaSessions;
if (sessionMap.size() == 0) {
return null;
}
Long resultHash = hash;
if (!sessionMap.containsKey(hash)) {
// Java 1.6 adds a ceilingKey method, but xmemcached is compatible
// with jdk5,So use tailMap method to do this.
SortedMap> tailMap = sessionMap.tailMap(hash);
if (tailMap.isEmpty()) {
resultHash = sessionMap.firstKey();
} else {
resultHash = tailMap.firstKey();
}
}
//
// if (!sessionMap.containsKey(resultHash)) {
// resultHash = sessionMap.ceilingKey(resultHash);
// if (resultHash == null && sessionMap.size() > 0) {
// resultHash = sessionMap.firstKey();
// }
// }
List sessionList = sessionMap.get(resultHash);
if (sessionList == null || sessionList.size() == 0) {
return null;
}
int size = sessionList.size();
return sessionList.get(this.random.nextInt(size));
}
public final long nextHash(long hashVal, String key, int tries) {
long tmpKey = hashAlgorithm.hash(tries + key);
hashVal += (int) (tmpKey ^ tmpKey >>> 32);
hashVal &= 0xffffffffL; /* truncate to 32-bits */
return hashVal;
}
public final void updateSessions(final Collection list) {
this.buildMap(list, null);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy