I have a server which has a permanent state which has to be saved on stable storage. It is composed by three fields:
List<LogEntry> log
int currentTerm
int votedFor
They have to be set during the server setup (in other words, when the server object is created). Every time that I update their "volatile" value, the relative file must be updated. Until the first time that any of these fields is updated, the value of the relative file must not be changed (in this way if the server goes down before the first udpate, then the state files remain untouched). As last thing, usually the only operation made on the log
field is the append operation, but it is possible to replace elements too.
I'd like to have your opinion about the server setup operation (in other words, the constructor). Below you will find my code and solution, but I don't like the fact that when you create a ObjectOutPutStream
the original file is overwritten with a new one, but I didn't think anything better than this.
public ServerRMI(...)
{
...
ObjectInputStream reader;
log = new ArrayList<>();
try {
//if Log file exists then should exists Metadata too
if(Files.exists(Paths.get("Server" + id + "Log"), LinkOption.NOFOLLOW_LINKS))
{
reader = new ObjectInputStream(new FileInputStream("Server"+id+"Log"));
try
{
//until there are LogEntry objects in the file, read them and add them to log
while(true)
log.add((LogEntry) reader.readObject());
}
catch (EOFException e){}
catch (ClassNotFoundException e) {
e.printStackTrace();
}
reader = new ObjectInputStream(new FileInputStream("Server"+id+"Metadata"));
currentTerm = reader.readInt();
votedFor = reader.readInt();
}
else//if it is the first time that the server is set up initialize all persistent fields
{
currentTerm = 1;
votedFor = -1;
log = new ArrayList<LogEntry>();
}
logWriter = new ObjectOutputStream(new FileOutputStream("Server"+id+"Log"));
metadataWriter = new ObjectOutputStream(new FileOutputStream("Server" + id + "Metadata"));
//since creating a new ObjectOutputStream overwrite the old file with the an empty one, as first thing we rewrite the old content
for(LogEntry entry : log)
logWriter.writeObject(entry);
metadataWriter.writeInt(currentTerm);
metadataWriter.writeInt(votedFor);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}