public ServiceResponse getEntry(ServiceRequest request, ServiceResponse response, K key,
OperationDiagnostics diag)
throws StoreException
{
String rangeStr = request.getHeader(ClusterMateConstants.HTTP_HEADER_RANGE_FOR_REQUEST);
ByteRange range;
try {
range = request.findByteRange();
} catch (IllegalArgumentException e) {
return invalidRange(response, key, rangeStr, e.getMessage());
}
final StorableStore entryStore = _stores.getEntryStore();
String acceptableEnc = request.getHeader(ClusterMateConstants.HTTP_HEADER_ACCEPT_COMPRESSION);
Storable rawEntry;
try {
rawEntry = findRawEntryForReads(entryStore, key, diag);
} catch (IOException e) {
return _storeError(response, key, e);
}
if (rawEntry == null) {
return handleGetForMissing(request, response, key);
}
// second: did we get a tombstone?
if (rawEntry.isDeleted()) {
ServiceResponse resp = handleGetForDeleted(request, response, key, rawEntry);
if (resp != null) {
return resp;
}
}
// [issue #7]: Conditional GET with Etag
if (_notChanged(request, rawEntry)) {
return response.notChanged();
}
final long accessTime = _timeMaster.currentTimeMillis();
final E entry = _entryConverter.entryFromStorable(rawEntry);
updateLastAccessedForGet(request, response, entry, accessTime);
Compression comp = entry.getCompression();
boolean skipCompression;
// Range to resolve, now that we know full length?
if (range != null) {
range = range.resolveWithTotalLength(entry.getActualUncompressedLength());
final long length = range.calculateLength();
// any bytes matching? If not, it's a failure
if (length <= 0L) {
return response.badRange(new GetErrorResponse<K>(key, "Invalid 'Range' HTTP Header (\""+range+"\")"));
}
// note: can not skip decompress if we have to give range...
skipCompression = false;
} else {
skipCompression = (comp != Compression.NONE) && comp.isAcceptable(acceptableEnc);
}
StreamingResponseContent output;
if (entry.hasExternalData()) { // need to stream from File
File f = entry.getRaw().getExternalFile(_fileManager);
// this is where we can expect to get "file not found exception".
// NOTE: not optimal, since this is one I/O operation that is outside throttling;
// but that can't be helped for now -- we MUST catch the problem here, before
// adding other response information
try {
output = new FileBackedResponseContentImpl(diag, _timeMaster, entryStore,
accessTime, f, skipCompression ? null : comp, range, entry);
} catch (StoreException e) {
LOG.error("Problem trying to GET entry '"+key+"': "+e.getMessage());
return response.internalFileNotFound(new GetErrorResponse<K>(key, e.getMessage()));
}
} else { // inline
ByteContainer inlined = entry.getRaw().getInlinedData();
if (!skipCompression) {
try {
inlined = Compressors.uncompress(inlined, comp, (int) entry.getRaw().getOriginalLength());
} catch (IOException e) {
return internalGetError(response, e, key, "Failed to decompress inline data");
}
}
output = new SimpleStreamingResponseContent(diag, _timeMaster, inlined, range, inlined.byteLength());
}
// #21: provide content length header
long cl = output.getLength();
if (cl >= 0L) {
response = response.setContentLength(cl);
}
// one more thing; add header for range if necessary; also, response code differs
if (range == null) {
response = response.ok(output);
} else {
response = response.partialContent(output, range.asResponseHeader());
}
// Issue #6: Need to provide Etag, if content hash available
int contentHash = rawEntry.getContentHash();
if (contentHash != HashConstants.NO_CHECKSUM) {
StringBuilder sb = new StringBuilder();