/* * Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License, * Version 1.0, and under the Eclipse Public License, Version 1.0 * (http://h2database.com/html/license.html). * Initial Developer: H2 Group */ package org.h2.util; import java.lang.ref.PhantomReference; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.HashMap; import org.h2.constant.SysProperties; import org.h2.message.DbException; import org.h2.store.fs.FileUtils; /** * This class deletes temporary files when they are not used any longer. */ public class TempFileDeleter { private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); private final HashMap<PhantomReference<?>, String> refMap = New.hashMap(); private TempFileDeleter() { // utility class } public static TempFileDeleter getInstance() { return new TempFileDeleter(); } /** * Add a file to the list of temp files to delete. The file is deleted once * the file object is garbage collected. * * @param fileName the file name * @param file the object to monitor * @return the reference that can be used to stop deleting the file */ public synchronized Reference<?> addFile(String fileName, Object file) { IOUtils.trace("TempFileDeleter.addFile", fileName, file); PhantomReference<?> ref = new PhantomReference<Object>(file, queue); refMap.put(ref, fileName); deleteUnused(); return ref; } /** * Delete the given file now. This will remove the reference from the list. * * @param ref the reference as returned by addFile * @param fileName the file name */ public synchronized void deleteFile(Reference<?> ref, String fileName) { if (ref != null) { String f2 = refMap.remove(ref); if (f2 != null) { if (SysProperties.CHECK) { if (fileName != null && !f2.equals(fileName)) { DbException.throwInternalError("f2:" + f2 + " f:" + fileName); } } fileName = f2; } } if (fileName != null && FileUtils.exists(fileName)) { try { IOUtils.trace("TempFileDeleter.deleteFile", fileName, null); FileUtils.tryDelete(fileName); } catch (Exception e) { // TODO log such errors? } } } /** * Delete all registered temp files. */ public void deleteAll() { for (String tempFile : New.arrayList(refMap.values())) { deleteFile(null, tempFile); } deleteUnused(); } /** * Delete all unused files now. */ public void deleteUnused() { while (queue != null) { Reference<? extends Object> ref = queue.poll(); if (ref == null) { break; } deleteFile(ref, null); } } /** * This method is called if a file should no longer be deleted if the object * is garbage collected. * * @param ref the reference as returned by addFile * @param fileName the file name */ public void stopAutoDelete(Reference<?> ref, String fileName) { IOUtils.trace("TempFileDeleter.stopAutoDelete", fileName, ref); if (ref != null) { String f2 = refMap.remove(ref); if (SysProperties.CHECK) { if (f2 == null || !f2.equals(fileName)) { DbException.throwInternalError("f2:" + f2 + " " + (f2 == null ? "" : f2) + " f:" + fileName); } } } deleteUnused(); } }