in evcache-core/src/main/java/com/netflix/evcache/pool/EVCacheClient.java [570:664]
private <T> Map<String, T> assembleChunks(Collection<String> keyList, Transcoder<T> tc, boolean hasZF) {
final List<String> firstKeys = new ArrayList<>();
for (String key : keyList) {
firstKeys.add(key);
firstKeys.add(key + "_00");
}
try {
final Map<String, CachedData> metadataMap = evcacheMemcachedClient.asyncGetBulk(firstKeys, chunkingTranscoder, null)
.getSome(bulkReadTimeout.get(), TimeUnit.MILLISECONDS, false, false);
if (metadataMap == null) return null;
final Map<String, T> returnMap = new HashMap<>(keyList.size() * 2);
for (String key : keyList) {
if (metadataMap.containsKey(key)) {
CachedData val = metadataMap.remove(key);
returnMap.put(key, tc.decode(val));
}
}
final List<String> allKeys = new ArrayList<>();
final Map<ChunkInfo, SimpleEntry<List<String>, byte[]>> responseMap = new HashMap<>();
for (Entry<String, CachedData> entry : metadataMap.entrySet()) {
final String firstKey = entry.getKey();
final String metadata = (String) decodingTranscoder.decode(entry.getValue());
if (metadata == null) continue;
final ChunkInfo ci = getChunkInfo(firstKey, metadata);
if (ci != null) {
final List<String> ciKeys = new ArrayList<>();
for (int i = 1; i < ci.getChunks(); i++) {
final String prefix = (i < 10) ? "0" : "";
final String _key = ci.getKey() + "_" + prefix + i;
allKeys.add(_key);
ciKeys.add(_key);
}
final byte[] data = new byte[(ci.getChunks() - 2) * ci.getChunkSize() + ci.getLastChunk()];
responseMap.put(ci, new SimpleEntry<>(ciKeys, data));
}
}
final Map<String, CachedData> dataMap = evcacheMemcachedClient.asyncGetBulk(allKeys, chunkingTranscoder, null)
.getSome(bulkReadTimeout.get(), TimeUnit.MILLISECONDS, false, false);
for (Entry<ChunkInfo, SimpleEntry<List<String>, byte[]>> entry : responseMap.entrySet()) {
final ChunkInfo ci = entry.getKey();
final SimpleEntry<List<String>, byte[]> pair = entry.getValue();
final List<String> ciKeys = pair.getKey();
byte[] data = pair.getValue();
int index = 0;
for (int i = 0; i < ciKeys.size(); i++) {
final String _key = ciKeys.get(i);
final CachedData cd = dataMap.get(_key);
if (log.isDebugEnabled()) log.debug("Chunk Key " + _key + "; Value : " + cd);
if (cd == null) continue;
final byte[] val = cd.getData();
if (val == null) {
data = null;
break;
}
final int len = (i == ciKeys.size() - 1) ? ((ci.getLastChunk() == 0 || ci.getLastChunk() > ci
.getChunkSize()) ? ci.getChunkSize() : ci.getLastChunk())
: val.length;
try {
System.arraycopy(val, 0, data, index, len);
} catch (Exception e) {
StringBuilder sb = new StringBuilder();
sb.append("ArrayCopyError - Key : " + _key + "; final data Size : " + data.length
+ "; copy array size : " + len + "; val size : " + val.length
+ "; key index : " + i + "; copy from : " + index + "; ChunkInfo : " + ci + "\n");
for (int j = 0; j < ciKeys.size(); j++) {
final String skey = ciKeys.get(j);
final byte[] sval = dataMap.get(skey).getData();
sb.append(skey + "=" + sval.length + "\n");
}
if (log.isWarnEnabled()) log.warn(sb.toString(), e);
throw e;
}
index += val.length;
}
final boolean checksumPass = checkCRCChecksum(data, ci, hasZF);
if (data != null && checksumPass) {
final CachedData cd = new CachedData(ci.getFlags(), data, Integer.MAX_VALUE);
returnMap.put(ci.getKey(), tc.decode(cd));
} else {
returnMap.put(ci.getKey(), null);
}
}
return returnMap;
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return null;
}