Today's anonymous submitter works on a project which uses Apache Derby to provide database services. Derby is a tiny database you can embed into your Java application, like SQLite. Even though it's part of the application, that doesn't mean it doesn't need to be backed up from time to time.
Our submitter was handed the code because the backup feature was "peculiar", and failed for reasons no one had figured out yet. It didn't take too long to figure out that the failures were triggered by not having enough space on the device for a backup. But they definitely had a enoughFreeSpaceForBackup
check, so what was going wrong?
private boolean enoughFreeSpaceForBackup() throws IOException {
final Path databaseDir = workingDirectory.resolve("database"); // resolve folder where database is written to
final FileStore store = Files.getFileStore(workingDirectory.getRoot()); // get the filestore
final long backupFreeSpace = store.getTotalSpace(); // get the ... yes ... total size of the file store
final long databaseSpace = sizeInBytes(databaseDir); // determine the complete size of the database
return backupFreeSpace > databaseSpace / 2; // if our databasesize, divided by 2, is smaller than the total size of the file store ... we have enough space for a backup.
}
As our submitter's comments highlight, it's the call to store.getTotalSpace()
, which helpfully tells us the total size of the file store. Not, however, how much of that space is unallocated, which is what getUnallocatedSpace
tell us. Or getUsableSpace
, which tells us how much of the device is actually accessible by the JVM.
That is to say, there are three methods pertaining to size, and the developer managed to pick the one which was totally wrong.
But that's not the WTF. It's an easy mistake to make, after all, especially if you're not super familiar with the API. I mean, getTotalSpace
sounds, well, like it's getting the total amount of space, not the amount I can use, but this is a simple enough mistake that it could happen to anyone.
But that's why you test. That's why you have code reviews. This software had been shipped, it was installed on people's devices, it was doing work. And in production environments, it was absolutely certain that it always had enough room to take a backup of itself, because the only time this wolud return false
was if the database were two times larger than the drive it was on.