package freenet.node;
import static java.util.concurrent.TimeUnit.MINUTES;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import freenet.support.Logger;
import freenet.support.SimpleFieldSet;
import freenet.support.Ticker;
import freenet.support.io.Closer;
import freenet.support.io.FileUtil;
class Persister implements Runnable {
private static volatile boolean logMINOR;
static {
Logger.registerClass(Persister.class);
}
static final long PERIOD = MINUTES.toMillis(15);
Persister(Persistable t, File persistTemp, File persistTarget, Ticker ps) {
this.persistable = t;
this.persistTemp = persistTemp;
this.persistTarget = persistTarget;
this.ps = ps;
}
// Subclass must set the others later
protected Persister(Persistable t, Ticker ps) {
this.persistable = t;
this.ps = ps;
}
final Persistable persistable;
private final Ticker ps;
File persistTemp;
File persistTarget;
private boolean started;
void interrupt() {
synchronized(this) {
notifyAll();
}
}
@Override
public void run() {
freenet.support.Logger.OSThread.logPID(this);
try {
persistThrottle();
} catch (Throwable t) {
Logger.error(this, "Caught in ThrottlePersister: "+t, t);
System.err.println("Caught in ThrottlePersister: "+t);
t.printStackTrace();
System.err.println("Will restart ThrottlePersister...");
}
ps.queueTimedJob(this, PERIOD);
}
private void persistThrottle() {
if (logMINOR) {
Logger.minor(this, "Trying to persist throttles...");
}
SimpleFieldSet fs = persistable.persistThrottlesToFieldSet();
FileOutputStream fos = null;
try {
fos = new FileOutputStream(persistTemp);
fs.writeToBigBuffer(fos);
fos.close();
FileUtil.renameTo(persistTemp, persistTarget);
} catch (FileNotFoundException e) {
Logger.error(this, "Could not store throttle data to disk: " + e, e);
} catch (IOException e) {
persistTemp.delete();
} finally {
Closer.close(fos);
}
}
public SimpleFieldSet read() {
SimpleFieldSet throttleFS = null;
try {
throttleFS = SimpleFieldSet.readFrom(persistTarget, false, true);
} catch (IOException e) {
try {
throttleFS = SimpleFieldSet.readFrom(persistTemp, false, true);
} catch (FileNotFoundException e1) {
// Ignore
} catch (IOException e1) {
if(persistTarget.length() > 0 || persistTemp.length() > 0)
Logger.error(this, "Could not read "+persistTarget+" ("+e+") and could not read "+persistTemp+" either ("+e1+ ')');
}
}
return throttleFS;
}
public void start() {
synchronized(this) {
if(started) {
Logger.error(this, "Already started: "+this, new Exception("debug"));
return;
}
started = true;
}
SemiOrderedShutdownHook.get().addEarlyJob(new Thread() {
public void run() {
System.out.println("Writing "+persistTarget+" on shutdown");
persistThrottle();
}
});
run();
}
}