package org.solbase.cache; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.concurrent.atomic.AtomicInteger; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; import org.apache.log4j.Logger; public abstract class VersionedCache<K, V, Z> { private static final Logger log = Logger.getLogger(VersionedCache.class); private AtomicInteger hitCount = new AtomicInteger(0); private AtomicInteger count = new AtomicInteger(0); protected Long timeout; protected abstract CachedObjectWrapper<V, Z> getInternal(K key) throws IOException; public abstract void put(K key, CachedObjectWrapper<V, Z> aValue) throws IOException; public abstract void clear() throws IOException; public boolean isCacheFull() { return false; } public CachedObjectWrapper<V, Z> get(K key) throws IOException { count.incrementAndGet(); CachedObjectWrapper<V, Z> tmp = getInternal(key); if (tmp != null) { hitCount.incrementAndGet(); if (count.intValue() % 100 == 0) { log.debug("Cache hit rate: " + (hitCount.intValue() * 100)/count.intValue() + "% "+ this.getClass().getSimpleName() + "/" + tmp.getValue().getClass().getSimpleName()); } } return tmp; } public void setTimeout(Long timeout) { this.timeout = timeout; } public void resetCacheTime(K key, Long time) throws IOException { CachedObjectWrapper<V, Z> cow = getInternal(key); if (cow != null) { cow.setCacheTime(time); } } protected byte[] serialize(V o) { if (o == null) { throw new NullPointerException("Can't serialize null"); } byte[] rv = null; try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream os = new ObjectOutputStream(bos); os.writeObject(o); os.close(); bos.close(); rv = bos.toByteArray(); } catch (IOException e) { throw new IllegalArgumentException("Non-serializable object", e); } return rv; } @SuppressWarnings("unchecked") protected V deserialize(byte[] in) { Object rv = null; ByteArrayInputStream bis = null; ObjectInputStream is = null; try { if (in != null) { bis = new ByteArrayInputStream(in); is = new ObjectInputStream(bis); rv = is.readObject(); } } catch (IOException e) { log.error("Caught IOException decoding " + in.length + " bytes of data", e); } catch (ClassNotFoundException e) { log.error("Caught CNFE decoding " + in.length + " bytes of data", e); } finally { if (is != null) { try { is.close(); } catch (IOException e) { // ignore } } if (bis != null) { try { bis.close(); } catch (IOException e) { // ignore } } } return (V) rv; } protected static final byte[] compress(byte[] in) { if (in == null) { throw new NullPointerException("Can't compress null"); } ByteArrayOutputStream bos = new ByteArrayOutputStream(); GZIPOutputStream gz = null; try { gz = new GZIPOutputStream(bos); gz.write(in); } catch (IOException e) { throw new RuntimeException("IO exception compressing data", e); } finally { if (gz != null) { try { gz.close(); } catch (IOException e) { log.error("Close GZIPOutputStream error", e); } } if (bos != null) { try { bos.close(); } catch (IOException e) { log.error("Close ByteArrayOutputStream error", e); } } } byte[] rv = bos.toByteArray(); // log.debug("Compressed %d bytes to %d", in.length, rv.length); return rv; } /** * Decompress the given array of bytes. * * @return null if the bytes cannot be decompressed */ protected static byte[] decompress(byte[] in) { ByteArrayOutputStream bos = null; if (in != null) { ByteArrayInputStream bis = new ByteArrayInputStream(in); bos = new ByteArrayOutputStream(); GZIPInputStream gis = null; try { gis = new GZIPInputStream(bis); byte[] buf = new byte[16 * 1024]; int r = -1; while ((r = gis.read(buf)) > 0) { bos.write(buf, 0, r); } } catch (IOException e) { log.error("Failed to decompress data", e); bos = null; } finally { if (gis != null) { try { gis.close(); } catch (IOException e) { log.error("Close GZIPInputStream error", e); } } if (bis != null) { try { bis.close(); } catch (IOException e) { log.error("Close ByteArrayInputStream error", e); } } } } return bos == null ? null : bos.toByteArray(); } }