Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make switch of files more robust #33

Open
jwkohnen opened this issue Mar 18, 2017 · 0 comments
Open

Make switch of files more robust #33

jwkohnen opened this issue Mar 18, 2017 · 0 comments

Comments

@jwkohnen
Copy link

jwkohnen commented Mar 18, 2017

The current mechanism is not robust in two ways. It can be fixed completely on POSIX and be fixed somewhat on Windows.

  1. This is also documented in your code: The old file is moved to a backup path, then the new file is moved from a temp path to the target path. If the world stops between these steps, there is no file at the target path. At least POSIX guarantees that a file rename(2) is atomic, i.e. if you do not move the old file from the target path, but "over"-os.(*File).Rename() the new file to the target path, then whenever the world stops, there will always be either the old file or the new file. Never no file. This atomic rename guarantee is valid on POSIX, only valid-ish on Windows.

  2. You should fsync(2) the files. When the world stops you do not have any guarantee of what your files look like, except for the backup file. If Go's file methods resemble the POSIX semantics (I assume they do), then os.(*File).Close() is not enough. You need to do os.(*File).Sync() before os.(*File).Close(). Crashing a process and crashing the machine are two different error modes. Writing files, then not syncing the files, then renaming files, then pulling the power cord leads to unpredictable results even with journaling filesystems.

I'd suggest to do the following:

  1. copy from target path to backup path
  2. sync then close backup file
  3. write new file
  4. sync then close new file
  5. rename new file to target path
  6. on rollback rename backup path to target path.
  7. on success hide or delete backup path

If possible do a hard link instead of a copy in step 1 (would need admin privileges on Windows, IIRC).

There were quite extensive and enlightening discussions about filesystem consistency myths back in the day. For some background information refer to Ted Ts'os blog post Don't fear the fsync.

/e fixed web link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant