All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.venky.core.io.FileCache Maven / Gradle / Ivy

package com.venky.core.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.logging.Logger;

import org.apache.commons.io.FileUtils;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.serializers.CompatibleFieldSerializer;
import com.venky.core.io.Locker.LockMode;
import com.venky.core.util.MultiException;

public abstract class FileCache {

		
	private final String cacheName;
	protected FileCache(String cacheName){
		this.cacheName = cacheName;
	}
	
	public static enum CacheMode {
		READ,
		WORK(){
			public String cacheSuffix(){
				return ".work";
			}
		};

		public String cacheSuffix() {
			return "";
		}
	}

	public T get() {
		T t = getFromCache(CacheMode.READ);
		if (t == null || isCacheInValidated()){
			T fresh = getValue(t);
			writeToCache(fresh);
			if (t == null || isCachingComplete()){
				t = fresh;
			}
		}
		return t;
	}
	
	protected String getCacheName(){
		return cacheName;
	}
	
	protected File getCacheDirectory(){
		File cache = new File(getCacheDirectoryName());
		if (!cache.exists()) {
			cache.mkdirs();
		}
		return cache;
	}

	public File getCacheFile(CacheMode cacheMode){
		return new File(getCacheDirectory(), cacheName + cacheMode.cacheSuffix());
	}
	
	@SuppressWarnings("unchecked")
	public T getFromCache(CacheMode cacheMode) {
		File cacheFile = getCacheFile(cacheMode);
		T cache = null;
		Logger cat = getLogger();
		if (cacheFile.exists()) {
			Kryo kryo = createCryo();
			Input in = null;
			Lock lock = Locker.instance().getLock(cacheName, LockMode.READ);
			try {
				lock.lock();
				in = new Input(new FileInputStream(cacheFile));
				cache = (T) kryo.readClassAndObject(in);
			} catch (Exception e) {
				cat.warning("Cache " + cacheName + " is corrupted!, deleting it");
				try {
					cacheFile.delete();
				}catch(SecurityException ex){
					cat.warning("Cache " + cacheName + " delete failed due to " + ex.getMessage());
				}
			} finally {
				if (lock != null) {
					lock.unlock();
				}
				if (in != null) {
					try {
						in.close();
					} catch (Exception e) {
						throw new RuntimeException(e);
					}finally {
						in = null;
					}
				}
				kryo = null;
			}
		}
		return cache;
	}
	
	public boolean isCacheInValidated(){
		File f = getCacheFile(CacheMode.READ);
		return !f.exists() || (f.lastModified() < (System.currentTimeMillis() - getCacheValidityTime()));
	}
	
	private long cacheValidityTime = Long.MAX_VALUE;
	protected long getCacheValidityTime() {
		return cacheValidityTime;
	}
	
	protected void setCacheValidityTime(long cacheValidityTime){ 
		this.cacheValidityTime = cacheValidityTime;
	}
	
	public void writeToCache(T cache) {
		Kryo kryo = createCryo();
		Lock lock = Locker.instance().getLock(cacheName,LockMode.EXCLUSIVE);
		try {
			File cacheFile = getCacheFile(CacheMode.WORK);
			lock.lock();
			FileOutputStream fos = new FileOutputStream(cacheFile);
			Output output = new Output(fos);
			kryo.writeClassAndObject(output, cache);
			output.close();
			afterCacheWrite();
		} catch (IOException e) {
			MultiException m = new MultiException();
			m.add(e);
			try {
				getCacheFile(CacheMode.WORK).delete();
			}catch (SecurityException ex){
				m.add(ex);
			}
			throw m;
		}finally {
			kryo = null; //gc 
			if (lock != null){
				lock.unlock();
				lock = null;
			}
		}
	}
	protected boolean isCachingComplete(){
		File workFile = getCacheFile(CacheMode.WORK);
		File readFile = getCacheFile(CacheMode.READ);
		if (!readFile.equals(workFile)){
			if (workFile.exists() || !readFile.exists()){
				return false;
			}
		}
		return true;
	}
	
	protected void afterCacheWrite() {
		File workFile = getCacheFile(CacheMode.WORK);
		File readFile = getCacheFile(CacheMode.READ);
		move(workFile,readFile);
	}
	
	protected void move (File source , File target) {
		if (!target.equals(source)){
			try {
				target.delete();
				FileUtils.moveFile(source, target);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}
	protected void copy (File source , File target) {
		if (!target.equals(source)){
			try {
				FileUtils.copyFile(source, target,false);
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}
	private Kryo createCryo(){
		Kryo kryo = new Kryo();
		kryo.setClassLoader(getClass().getClassLoader());
		kryo.setDefaultSerializer(CompatibleFieldSerializer.class);
		return kryo;
	}
	
	protected abstract T getValue(T oldCache);
	protected abstract Logger getLogger() ;
	protected abstract String getCacheDirectoryName();
	
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy