Saturday, September 12, 2009

Method for dealing with temporary files in a java server program

Method for dealing with temporary files in a server program

Problem

To handle temporary files Java provides two mechanisms

- File class provides a set of createTempFile methods which ensure that each file gets a unique name

- File class has a method deleteOnExit method which ensures that the file gets deleted when the JVM terminates.

But these methods prove insufficient while dealing with temporary files in a (java) server process. The server process (jvm) runs for a long time before crashing/restart, hence files cannot be cleaned only on process (jvm) start or process (jvm) exit, it has to be done regularly so that the files do not accumulate on the hard-disk.

Scenarios when manual deletion of files is not possible

  • An image file is referenced by html sent back to the web-browser. There is no way of knowing when the image file has been requested and downloaded by the web-browser.
  • A file cannot be deleted manually because an input-stream is opened on the file and passed to an asynchronous API.

Possible Solutions

  • File system itself to provide a file expiry attribute
  • Java to provide a file expiry attribute

The above 2 are not available

Proposed Solution

Provide a file expiry time while creating a temp file. All such files are marked to be deleted when the expiry time is over and can be deleted in an independent thread running on the server.


Sample Implementation

public class TempFile extends File {

private Date d = null;

/*

* The default expiry time is 1 day

*/

private Date getDefaultExpiry() {

Calendar c = Calendar.getInstance();

c.setTime(new Date());

c.add(Calendar.DATE, 1);

return c.getTime();

}

/*

* Constructor from super class

*/

public TempFile(String pathname) {

super(pathname);

setExpiry(getDefaultExpiry());

}

/*

* Constructors with expiry parameter

*/

public TempFile(String pathname, Date expiry) {

super(pathname);

setExpiry(expiry);

}

/*

* Let the user set the expiry attribute after construction of object

*/

public void setExpiry(Date d) {

this.d = d;

FileGarbageCollector collector = FileGarbageCollector.getInstance();

collector.addFile(this);

}

}

public class FileGarbageCollector implements Runnable {

private static FileGarbageCollector ref = null;

Thread t = null;

public static FileGarbageCollector getInstance() {

if (ref == null) {

ref = new FileGarbageCollector();

}

return ref;

}

/*

* The files for which an expiry time is set.

*/

private static List files = null;

private FileGarbageCollector() {

files = new ArrayList();

}

public void addFile(TempFile f) {

files.add(f);

if (t == null || !t.isAlive()) {

t = new Thread(ref);

t.start();

}

}

public void run() {

while (files.size() > 0) {

Date d = new Date();

for (int i = 0; i < files.size(); i++)

if ( d.getTime() > files.get(i).getExpiry().getTime() ) {

TempFile t = files.remove(i);

i--;

t.delete();

System.out.println(t.getPath() + " deleted at "

+ new Date());

}

}

try {

Thread.sleep(8000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

No comments:

Post a Comment