use of net.spy.memcached.MemcachedClient in project zm-mailbox by Zimbra.
the class ZimbraMemcachedClient method connect.
/**
* Connects/reconnects the memcached client with server list, protocol and hashing algorithm.
* @param servers memcached server list
* @param useBinaryProtocol if true, use the binary protocol; if false, use the ascii protocol
* @param hashAlgorithm net.spy.memcached.HashAlgorithm enum
* @param defaultExpiry in seconds
* @param defaultTimeout in milliseconds
* @throws ServiceException
*/
public void connect(String[] servers, boolean useBinaryProtocol, String hashAlgorithm, int defaultExpiry, long defaultTimeout) throws ServiceException {
// Force spymemcached to use log4j rather than raw stdout/stderr.
Properties props = System.getProperties();
props.put("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.Log4JLogger");
HashAlgorithm hashAlgo = DefaultHashAlgorithm.KETAMA_HASH;
if (hashAlgorithm != null && hashAlgorithm.length() > 0) {
HashAlgorithm ha = DefaultHashAlgorithm.valueOf(hashAlgorithm);
if (ha != null)
hashAlgo = ha;
}
int qLen = DefaultConnectionFactory.DEFAULT_OP_QUEUE_LEN;
int bufSize = DefaultConnectionFactory.DEFAULT_READ_BUFFER_SIZE;
MemcachedClient client = null;
StringBuilder serverList = new StringBuilder();
if (servers != null && servers.length > 0) {
// Eliminate duplicates and sort case-insensitively. This negates operator error
// configuring server list with inconsistent order on different memcached clients.
// TreeSet provides deduping and sorting.
TreeSet<String> tset = new TreeSet<String>();
for (int i = 0; i < servers.length; ++i) {
tset.add(servers[i].toLowerCase());
}
for (String s : tset) {
if (serverList.length() > 0)
serverList.append(", ");
serverList.append(s);
}
List<InetSocketAddress> serverAddrs = parseServerList(tset.toArray(new String[0]));
ConnectionFactory cf;
if (useBinaryProtocol)
cf = new BinaryConnectionFactory(qLen, bufSize, hashAlgo);
else
cf = new DefaultConnectionFactory(qLen, bufSize, hashAlgo);
try {
client = new MemcachedClient(cf, serverAddrs);
boolean added = client.addObserver(new ConnObserver());
if (!added)
ZimbraLog.misc.error("Unable to add connection observer to memcached client");
} catch (IOException e) {
throw ServiceException.FAILURE("Unable to initialize memcached client", e);
}
}
MemcachedClient oldClient = null;
synchronized (this) {
oldClient = mMCDClient;
mMCDClient = client;
mDefaultExpiry = defaultExpiry;
mDefaultTimeout = defaultTimeout;
mServerList = serverList.length() > 0 ? serverList.toString() : null;
mHashAlgorithm = hashAlgo.toString();
mBinaryProtocolEnabled = useBinaryProtocol;
}
// New client is ready for use by other threads at this point.
if (oldClient != null)
disconnect(oldClient, 30000);
}
use of net.spy.memcached.MemcachedClient in project zm-mailbox by Zimbra.
the class ZimbraMemcachedClient method putBigByteArray.
/**
* Puts the key/value pair for a big byte array.
*
* A big byte array value is a byte array whose length can be greater than memcached limit of 1MB.
* If the data is smaller than MAX_CHUNK_SIZE (1MB - 1KB) it is set in a single key/value pair in
* memcached, with the value suffixed with a "V". (V for value) If the data is bigger, the data is
* split into MAX_CHUNK_SIZE chunks and set as individual cache entries. The cache keys for the
* chunks are the combination of the original key, the data "fingerprint" (for some uniqueness),
* and chunk number. The cache value for the original key is set to a table of contents containing
* the number of chunks, the fingerprint, and length and checksum of each chunk, followed by a "T".
* (T for table of contents)
*
* During retrieval, the value for the main key is examined to see if the last byte is a V or T. If
* it's a V, the preceding bytes constitute the entire cache value. If it's a T, the preceding bytes
* are interpreted as the table of contents. The information in the table of contents can be used
* to then fetch the chunks and reassemble them. All chunks must exist and must match the length and
* checksum in the table of contents. Otherwise the whole get operation is considered a cache miss.
*
* When the main key is updated or removed, the chunk values become orphaned because the table of contents
* will no longer contain the same fingerprint. (Some collision risk exists.) These entries will age
* out of the cache eventually.
*
* Example of a short value:
*
* key = "foo", value = ['b', 'a', 'r']
* Memcached will have "foo" = ['b', 'a', 'r', 'V'].
*
* Example of a big value:
*
* key = "foo", value = <1.5MB byte array>
* Assume the fingerprint computed is 1234567890.
* Memcached will have:
* "foo" = <table of contents> 'T'
* "foo:1234567890.0" = <1st chunk of ~1MB>
* "foo:1234567890.1" = <2nd chunk of ~0.5MB>
*
* @param key
* @param value
* @param expirySec expiry in seconds
* @param timeout in millis
* @param waitForAck if true, block until ack'd or timeout; if false, return immediately
* @return
*/
public boolean putBigByteArray(String key, byte[] value, int expirySec, long timeout, boolean waitForAck) {
MemcachedClient client;
synchronized (this) {
client = mMCDClient;
if (expirySec == DEFAULT_EXPIRY)
expirySec = mDefaultExpiry;
if (timeout == DEFAULT_TIMEOUT)
timeout = mDefaultTimeout;
}
if (client == null)
return false;
ByteArrayTranscoder bat = new ByteArrayTranscoder();
ByteArray mainValue;
if (value.length < MAX_CHUNK_SIZE) {
// Value is short enough. Set it directly, with a prefix. Requires 1 memcached set operation.
byte[] prefixed = new byte[value.length + 1];
System.arraycopy(value, 0, prefixed, 0, value.length);
prefixed[value.length] = BBA_PREFIX_VALUE;
mainValue = new ByteArray(prefixed);
} else {
// Value can't fit in a single memcached entry. Split into chunks and use table of contents.
// Requires N+1 memcached set operations.
ByteArrayChunks chunks;
try {
chunks = new ByteArrayChunks(value);
} catch (ServiceException e) {
ZimbraLog.misc.warn("Unable to split byte array into chunks", e);
return false;
}
ByteArrayChunksTOC toc = chunks.makeTOC();
// Add chunks to the cache.
String chunkKeyPrefix = key + ":" + toc.getFingerprint() + ".";
int numChunks = chunks.getNumChunks();
for (int i = 0; i < numChunks; ++i) {
String chunkKey = chunkKeyPrefix + i;
ByteArray byteArray = chunks.getChunk(i);
Future<Boolean> future = client.set(chunkKey, expirySec, byteArray, bat);
if (waitForAck) {
Boolean success = null;
try {
success = future.get(timeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
ZimbraLog.misc.warn("memcached set timed out after " + timeout + "ms", e);
future.cancel(false);
} catch (InterruptedException e) {
ZimbraLog.misc.warn("InterruptedException during memcached set operation", e);
} catch (ExecutionException e) {
ZimbraLog.misc.warn("ExecutionException during memcached set operation", e);
}
if (success == null || !success.booleanValue())
return false;
}
}
// Put the table of contents as the main value. Do this after all chunks have been
// added successfully.
byte[] tocBytes;
try {
tocBytes = toc.encode().getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
ZimbraLog.misc.warn("Unable to get bytes for BBA table of contents", e);
return false;
}
byte[] prefixed = new byte[tocBytes.length + 1];
System.arraycopy(tocBytes, 0, prefixed, 0, tocBytes.length);
prefixed[tocBytes.length] = BBA_PREFIX_TOC;
mainValue = new ByteArray(prefixed);
}
// Put the main value.
Future<Boolean> future = client.set(key, expirySec, mainValue, bat);
if (waitForAck) {
Boolean success = null;
try {
success = future.get(timeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
ZimbraLog.misc.warn("memcached set timed out after " + timeout + "ms", e);
future.cancel(false);
} catch (InterruptedException e) {
ZimbraLog.misc.warn("InterruptedException during memcached set operation", e);
} catch (ExecutionException e) {
ZimbraLog.misc.warn("ExecutionException during memcached set operation", e);
}
return success != null && success.booleanValue();
} else {
return true;
}
}
use of net.spy.memcached.MemcachedClient in project zm-mailbox by Zimbra.
the class ZimbraMemcachedClient method get.
/**
* Retrieves the value corresponding to the given key.
* @param key
* @param timeout in millis
* @return null if no value is found for the key
*/
public Object get(String key, long timeout) {
Object value = null;
MemcachedClient client;
synchronized (this) {
client = mMCDClient;
if (timeout == DEFAULT_TIMEOUT)
timeout = mDefaultTimeout;
}
if (client == null)
return null;
Future<Object> future = client.asyncGet(key);
try {
value = future.get(timeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
ZimbraLog.misc.warn("memcached asyncGet timed out after " + timeout + "ms", e);
future.cancel(false);
} catch (InterruptedException e) {
ZimbraLog.misc.warn("InterruptedException during memcached asyncGet operation", e);
} catch (ExecutionException e) {
ZimbraLog.misc.warn("ExecutionException during memcached asyncGet operation", e);
}
return value;
}
use of net.spy.memcached.MemcachedClient in project DataX by alibaba.
the class ConfigurationChecker method hostReachableCheck.
/**
* 检查ocs服务器网络是否可达
*/
private static void hostReachableCheck(Configuration config) {
String proxy = config.getString(Key.PROXY);
String port = config.getString(Key.PORT);
String username = config.getString(Key.USER);
String password = config.getString(Key.PASSWORD);
AuthDescriptor ad = new AuthDescriptor(new String[] { "PLAIN" }, new PlainCallbackHandler(username, password));
try {
MemcachedClient client = new MemcachedClient(new ConnectionFactoryBuilder().setProtocol(ConnectionFactoryBuilder.Protocol.BINARY).setAuthDescriptor(ad).build(), AddrUtil.getAddresses(proxy + ":" + port));
client.get("for_check_connectivity");
client.getVersions();
if (client.getAvailableServers().isEmpty()) {
throw new RuntimeException("没有可用的Servers: getAvailableServers() -> is empty");
}
client.shutdown();
} catch (Exception e) {
throw DataXException.asDataXException(OcsWriterErrorCode.HOST_UNREACHABLE, String.format("OCS[%s]服务不可用", proxy), e);
}
}
use of net.spy.memcached.MemcachedClient in project hazelcast by hazelcast.
the class InvalidEndpointTest method attemptMemcacheOnHttpEndpoint.
@Test
public void attemptMemcacheOnHttpEndpoint() throws IOException, InterruptedException {
Config config = createRestEndpointConfig();
HazelcastInstance instance = factory.newHazelcastInstance(config);
// Invalid endpoint - points to REST
InetSocketAddress address = instance.getCluster().getLocalMember().getSocketAddress(REST);
ConnectionFactory factory = new ConnectionFactoryBuilder().setOpTimeout(60 * 60 * 60).setDaemon(true).setFailureMode(FailureMode.Retry).build();
MemcachedClient client = new MemcachedClient(factory, Collections.singletonList(address));
try {
client.set("one", 0, "two").get();
fail("Should not be able to connect");
} catch (InterruptedException e) {
ignore(e);
} catch (ExecutionException e) {
ignore(e);
}
shutdownQuietly(client);
}
Aggregations