package org.fnppl.dbaccess; import java.util.*; /* * Copyright (C) 2010-2015 * fine people e.V. <opensdx@fnppl.org> * Henning Thieß <ht@fnppl.org> * * http://fnppl.org */ /* * Software license * * As far as this file or parts of this file is/are software, rather than documentation, this software-license applies / shall be applied. * * This file is part of openSDX * openSDX is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * openSDX is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * and GNU General Public License along with openSDX. * If not, see <http://www.gnu.org/licenses/>. * */ /* * Documentation license * * As far as this file or parts of this file is/are documentation, rather than software, this documentation-license applies / shall be applied. * * This file is part of openSDX. * Permission is granted to copy, distribute and/or modify this document * under the terms of the GNU Free Documentation License, Version 1.3 * or any later version published by the Free Software Foundation; * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. * A copy of the license is included in the section entitled "GNU * Free Documentation License" resp. in the file called "FDL.txt". * */ public class SQLOutDatingCache { //TODO optimizing :: wahl hibernation-engine //TODO optimizing :: maxfillsize //TODO optimizing :: cleanup-behaviour private Hashtable<ComposedKey, Object[]> cachico = new Hashtable<ComposedKey, Object[]>();//(Object)key -> Object[]{value,puttime,outdatetime} private long default_alive = 1000*60*30;//30 min. public static int putcount = 0; public final static int putcountTH = 1024; /** Creates a new instance of OutdatingCache */ public SQLOutDatingCache() {} public SQLOutDatingCache(long defaultAliveTime) { this(); default_alive = defaultAliveTime; } private int cleanup() { putcount=0; int ret = 0; //cleanup wird nur aus einem synchronized context aufgerufen! // synchronized(cachico) { Enumeration<ComposedKey> en = cachico.keys(); long l = System.currentTimeMillis(); while(en.hasMoreElements()) { ComposedKey key = en.nextElement(); Object[] o = (Object[])cachico.get(key.toString()); if(o==null) { continue; } DBResultSet value = (DBResultSet)o[0]; long puttime = ((Long)o[1]).longValue(); long ttl = ((Long)o[2]).longValue(); if(puttime+ttl < l) { remove(key); ret++; // System.out.println("OutdatingCache::get: "+key.toString()+" -> outdated (ttl: "+ttl+" puttime: "+puttime+")"); } } // } return ret; } private void put(ComposedKey key, DBResultSet value, long aliveTime) { // System.out.println("OutdatingCache::put: "+key.toString()+" -> "+value.toString()); synchronized(cachico) { putcount++; if(putcount >= putcountTH) { cleanup(); } cachico.put( key, new Object[]{ value, new Long(System.currentTimeMillis()), new Long(aliveTime) } ); } } public void put(SQLOutDatingCache.ComposedKey key, DBResultSet value) { // System.out.println("OutdatingCache::put "+key.toString()+" -> "+value.toString()); put(key, value, default_alive); } // public void put(String key, String value) { // put(key, value, default_alive); // } // public void put(String key, DBResultSet value) { // SQLOutDatingCache.ComposedKey keyC = new ComposedKey(); // keyC.addElement(key); // // put(keyC, value, default_alive); // } public void remove(ComposedKey key) { cachico.remove(key); } // public String getS(String key) { // return (String)get(key); // } public DBResultSet get(ComposedKey key) { // System.out.println("OutdatingCache::get: "+key.toString()); synchronized(cachico) { putcount++; if(putcount >= putcountTH) { cleanup(); } Object[] o = (Object[])cachico.get(key.toString()); if(o==null) { return null; } DBResultSet value = (DBResultSet)o[0]; long puttime = ((Long)o[1]).longValue(); long ttl = ((Long)o[2]).longValue(); if(puttime+ttl < System.currentTimeMillis()) { remove(key); return null; } return value; } } public static class ComposedKey extends Vector { private String cs = null; public ComposedKey() { super(); } public static ComposedKey createNew(String key) { ComposedKey ret = new ComposedKey(); ret.addElement(key); return ret; } public ComposedKey addKeyElement(Object o) { addElement(o); return this; } @Override public void addElement(Object o) { if(o==null) { } else { super.addElement(o); cs = null; } } @Override public String toString() { if(cs != null) { return cs; } StringBuffer s = new StringBuffer(); for(int i=0;i<size();i++) { s.append(elementAt(i).toString()); if(i+1<size()) { s.append("::"); } } cs = s.toString(); return cs; } public int hashCode() { if(cs == null) { toString(); //setzt cs implizit } return cs.hashCode(); } } }