Below you find the constructor of a server in order to setup it. In a few words, it restore its state from the last time that it was up reading a List
of objects (called log
) and two int
(called currentTerm
and votedFor
). Any time that any of these "volatile" fields will be updated, the relative file will have to be updated too (and so make upadate the consistent state), so I need the two ObjectOutPutStream
called metadataWriter
and logWriter
. Since the server could go down in any moment, I cannot write any close()
method. Do you think that the only possible solution in order to avoid an EOFException
the next time that I setup the server (during the reading operation) is to flush()
the output stream everytime (like I've done on the last lines of the code)?
public ServerRMI(...)
{
...
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
{
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);
metadataWriter.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
...
}
IMPORTANT NOTE:
I don't think that the try-with-resources in every method which use them (and so each method that update server's state) as someone have suggested is a feasible solution, since it would be ok for the metadata
file (the two int
written on it are always replaced at every update/write to file) but for the log
file it would mean to write the whole list every time that it is changed (the operation made on it are not only appen, but replacement too!), which I think that it's not so good for performance!