package hu.sztaki.ilab.longneck.dns.db; import com.sleepycat.je.DatabaseException; import com.sleepycat.je.Environment; import com.sleepycat.je.Transaction; import com.sleepycat.persist.EntityCursor; import com.sleepycat.persist.StoreConfig; import hu.sztaki.ilab.longneck.util.database.BDBConfiguration; import hu.sztaki.ilab.longneck.util.database.Configuration; import hu.sztaki.ilab.longneck.util.database.DatabaseConfigurationException; import hu.sztaki.ilab.longneck.util.database.DatabaseConnectionManager; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import org.apache.log4j.Logger; import org.springframework.beans.factory.DisposableBean; /** * Cache for reverse DNS query results. * * This class is thread-safe. * * @author Bendig Loránd <lbendig@ilab.sztaki.hu> * @author Molnár Péter <molnar.peter@sztaki.mta.hu> */ public class DnsCache implements DisposableBean { private final Logger LOG = Logger.getLogger(DnsCache.class); /** The database environment. */ private Environment environment; /** The cache accessor. */ private DnsCacheAccessor dnsCacheAccessor; public DnsCache(DatabaseConnectionManager databaseConnectionManager, String connectionName) { // Get configuration and check correct type Configuration dbConf = databaseConnectionManager.getConfiguration(connectionName); if (! (dbConf instanceof BDBConfiguration)) { throw new DatabaseConfigurationException( String.format("Connection %1$s should be instance of %2$s.", connectionName, BDBConfiguration.class.getName())); } BDBConfiguration bdbConf = (BDBConfiguration) dbConf; // Get database environment environment = bdbConf.getEnvironment(); // Configure store StoreConfig storeConfig = new StoreConfig(); storeConfig.setAllowCreate(true); dnsCacheAccessor = new DnsCacheAccessor(environment, storeConfig); } @Override public void destroy() throws Exception { dnsCacheAccessor.close(); dnsCacheAccessor = null; } public ReverseData add(ReverseData reverseData) { return dnsCacheAccessor.reversePrimaryIndex.put(reverseData); } public ReverseData getReverse(String ipAddress) { try { return dnsCacheAccessor.reversePrimaryIndex.get(ipAddress); } catch (IllegalArgumentException e) { throw new RuntimeException(e); } } public synchronized List<ReverseData> getReverseList() { List<ReverseData> result = new ArrayList<ReverseData>(); EntityCursor<ReverseData> cursor = null; try { cursor = dnsCacheAccessor.reversePrimaryIndex.entities(); for (ReverseData ent : cursor) { result.add(ent); } return result; } finally { cursor.close(); } } public void removeReverse(String ipAddress) { dnsCacheAccessor.reversePrimaryIndex.delete(ipAddress); } /** * Removes expired entries from the database. */ public void removeExpiredReverse() { EntityCursor<ReverseData> cursor = null; Transaction txn = null; int removedEntries = 0; try { long currentDate = Calendar.getInstance().getTimeInMillis(); txn = environment.beginTransaction(null, null); cursor = dnsCacheAccessor.reversePrimaryIndex.entities(txn, null); for (ReverseData entity = cursor.first(); entity != null; entity = cursor.next()) { if (currentDate > entity.getExpirationDate()) { cursor.delete(); removedEntries++; } } txn.commit(); } catch (DatabaseException ex) { LOG.error("Expired reverse dns data cleanup has failed.", ex); if (txn != null) txn.abort(); } finally { if (cursor != null) cursor.close(); } } }