![JAR search and dependency download from the Maven repository](/logo.png)
me.desair.tus.server.upload.cache.ThreadLocalCachedStorageAndLockingService Maven / Gradle / Ivy
package me.desair.tus.server.upload.cache;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.Objects;
import java.util.UUID;
import me.desair.tus.server.exception.TusException;
import me.desair.tus.server.exception.UploadNotFoundException;
import me.desair.tus.server.upload.UploadIdFactory;
import me.desair.tus.server.upload.UploadInfo;
import me.desair.tus.server.upload.UploadLock;
import me.desair.tus.server.upload.UploadLockingService;
import me.desair.tus.server.upload.UploadStorageService;
import me.desair.tus.server.upload.concatenation.UploadConcatenationService;
/**
* Combined implementation of {@link UploadStorageService} and {@link UploadLockingService}.
* Uses both of them as delegates but allowing to reduce disk operations during a request processing
* by caching UploadInfo in the memory.
* UploadLockingService service is used as a delegate to cleanup cached data on releasing a lock.
*/
public class ThreadLocalCachedStorageAndLockingService implements UploadLockingService, UploadStorageService {
private final ThreadLocal> uploadInfoCache = new ThreadLocal<>();
private final UploadLockingService lockingServiceDelegate;
private final UploadStorageService storageServiceDelegate;
private UploadIdFactory idFactory;
public ThreadLocalCachedStorageAndLockingService(UploadStorageService storageServiceDelegate,
UploadLockingService lockingServiceDelegate) {
if (storageServiceDelegate.getClass() == ThreadLocalCachedStorageAndLockingService.class) {
this.storageServiceDelegate =
((ThreadLocalCachedStorageAndLockingService) storageServiceDelegate).storageServiceDelegate;
} else {
this.storageServiceDelegate = storageServiceDelegate;
}
if (lockingServiceDelegate.getClass() == ThreadLocalCachedStorageAndLockingService.class) {
this.lockingServiceDelegate =
((ThreadLocalCachedStorageAndLockingService) lockingServiceDelegate).lockingServiceDelegate;
} else {
this.lockingServiceDelegate = lockingServiceDelegate;
}
}
@Override
public UploadInfo getUploadInfo(UUID id) throws IOException {
UploadInfo uploadInfo;
WeakReference ref = uploadInfoCache.get();
if (ref == null || (uploadInfo = ref.get()) == null || !id.equals(uploadInfo.getId())) {
uploadInfo = storageServiceDelegate.getUploadInfo(id);
uploadInfoCache.set(new WeakReference<>(uploadInfo));
}
return uploadInfo;
}
@Override
public UploadInfo getUploadInfo(String uploadUrl, String ownerKey) throws IOException {
UploadInfo uploadInfo = getUploadInfo(idFactory.readUploadId(uploadUrl));
if (uploadInfo == null || !Objects.equals(uploadInfo.getOwnerKey(), ownerKey)) {
uploadInfo = storageServiceDelegate.getUploadInfo(uploadUrl, ownerKey);
uploadInfoCache.set(new WeakReference<>(uploadInfo));
}
return uploadInfo;
}
@Override
public void update(UploadInfo uploadInfo) throws IOException, UploadNotFoundException {
storageServiceDelegate.update(uploadInfo);
uploadInfoCache.set(new WeakReference<>(uploadInfo));
}
@Override
public void setIdFactory(UploadIdFactory idFactory) {
this.idFactory = idFactory;
storageServiceDelegate.setIdFactory(idFactory);
}
@Override
public String getUploadURI() {
return storageServiceDelegate.getUploadURI();
}
@Override
public UploadInfo append(UploadInfo upload, InputStream inputStream) throws IOException, TusException {
UploadInfo info = storageServiceDelegate.append(upload, inputStream);
uploadInfoCache.set(new WeakReference<>(info));
return info;
}
@Override
public void setMaxUploadSize(Long maxUploadSize) {
storageServiceDelegate.setMaxUploadSize(maxUploadSize);
}
@Override
public long getMaxUploadSize() {
return storageServiceDelegate.getMaxUploadSize();
}
@Override
public UploadInfo create(UploadInfo info, String ownerKey) throws IOException {
UploadInfo uploadInfo = storageServiceDelegate.create(info, ownerKey);
uploadInfoCache.set(new WeakReference<>(uploadInfo));
return uploadInfo;
}
@Override
public InputStream getUploadedBytes(String uploadURI, String ownerKey) throws IOException, UploadNotFoundException {
return storageServiceDelegate.getUploadedBytes(uploadURI, ownerKey);
}
@Override
public InputStream getUploadedBytes(UUID id) throws IOException, UploadNotFoundException {
return storageServiceDelegate.getUploadedBytes(id);
}
@Override
public void copyUploadTo(UploadInfo info, OutputStream outputStream) throws UploadNotFoundException, IOException {
storageServiceDelegate.copyUploadTo(info, outputStream);
uploadInfoCache.set(new WeakReference<>(info));
}
@Override
public void cleanupExpiredUploads(UploadLockingService uploadLockingService) throws IOException {
storageServiceDelegate.cleanupExpiredUploads(uploadLockingService);
//Since any cached uploads was potentially removed by the storage service
//we clean the cache to prevent any stale state
cleanupCache();
}
@Override
public void removeLastNumberOfBytes(UploadInfo uploadInfo, long byteCount) throws UploadNotFoundException,
IOException {
storageServiceDelegate.removeLastNumberOfBytes(uploadInfo, byteCount);
uploadInfoCache.set(new WeakReference<>(uploadInfo));
}
@Override
public void terminateUpload(UploadInfo uploadInfo) throws UploadNotFoundException, IOException {
storageServiceDelegate.terminateUpload(uploadInfo);
//Since the upload is terminated and potentially removed by the storage service
//we clean the cache to prevent any stale state
cleanupCache();
}
@Override
public Long getUploadExpirationPeriod() {
return storageServiceDelegate.getUploadExpirationPeriod();
}
@Override
public void setUploadExpirationPeriod(Long uploadExpirationPeriod) {
storageServiceDelegate.setUploadExpirationPeriod(uploadExpirationPeriod);
}
@Override
public void setUploadConcatenationService(UploadConcatenationService concatenationService) {
storageServiceDelegate.setUploadConcatenationService(concatenationService);
}
@Override
public UploadConcatenationService getUploadConcatenationService() {
return storageServiceDelegate.getUploadConcatenationService();
}
@Override
public UploadLock lockUploadByUri(String requestURI) throws TusException, IOException {
UploadLock uploadLock = lockingServiceDelegate.lockUploadByUri(requestURI);
return new CachedLock(uploadLock);
}
@Override
public void cleanupStaleLocks() throws IOException {
lockingServiceDelegate.cleanupStaleLocks();
cleanupCache();
}
@Override
public boolean isLocked(UUID id) {
return lockingServiceDelegate.isLocked(id);
}
private void cleanupCache() {
WeakReference ref = uploadInfoCache.get();
if (ref != null) {
uploadInfoCache.remove();
ref.clear();
}
}
class CachedLock implements UploadLock {
private final UploadLock delegate;
CachedLock(UploadLock delegate) {
this.delegate = delegate;
}
@Override
public String getUploadUri() {
return delegate != null ? delegate.getUploadUri() : null;
}
@Override
public void release() {
if (delegate != null) {
delegate.release();
}
}
@Override
public void close() throws IOException {
if (delegate != null) {
delegate.close();
}
cleanupCache();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy