long sourceChecksum = computeChecksum(fs, sourcePath);
Path cachePath = computeCachePath(sourcePath);
Path cacheChecksumPath = computeCacheChecksumPath(cachePath);
IOException firstException = null;
RetryObject retry = retryStrategy.newInstance(MessageFormat.format(
"preparing cache ({0} -> {1})",
sourcePath,
cachePath));
do {
try {
// TODO reduce lock scope?
LockObject<? super Path> lock = lockProvider.tryLock(cachePath);
if (lock == null) {
continue;
}
try {
if (isCached(cachePath, cacheChecksumPath, sourceChecksum)) {
if (LOG.isDebugEnabled()) {
LOG.debug(MessageFormat.format(
"cache hit: {0} -> {1}",
sourcePath,
cachePath));
}
// just returns cached file
} else {
if (LOG.isDebugEnabled()) {
LOG.debug(MessageFormat.format(
"cache miss: {0} -> {1}",
sourcePath,
cachePath));
}
updateCache(sourcePath, sourceChecksum, cachePath, cacheChecksumPath);
}
return cachePath;
} finally {
lock.close();
}
} catch (IOException e) {
LOG.warn(MessageFormat.format(
"Failed to prepare cache: {0} -> {1}",
sourcePath,
cachePath), e);
if (firstException == null) {
firstException = e;
}
}
} while (retry.waitForNextAttempt());
if (firstException == null) {
throw new IOException(MessageFormat.format(
"Failed to acquire a lock for remote cache file: {0} ({1})",
sourcePath,
cachePath));