2015-07-29 1 views
0

Я хочу переписать содержимое файла атомарно. Мне нужно это для поддержания целостности при перезаписывании конфигурационного файла, поэтому обновление должно либо пройти, либо сбой, и никогда не оставлять файл наполовину написанным или поврежденным.Как надежно перезаписать файл в Windows

Я прошел через множество итераций, чтобы решить эту проблему, вот мое текущее решение.

Шаги перезаписать файл "foo.config":

  • Введите глобальный семафор (уникальный для каждого имени файла)
  • Написать новое содержание в "foo.config.tmp"
  • вызовов FlushFileBuffers на дескриптор файла перед закрытием файла, чтобы очистить файл ОС буферы
  • вызова ReplaceFile который будет внутренне
    • переименования "foo.config" в "foo.config.bak"
    • переименования "foo.config.tmp" в "foo.config"
  • Удалить "foo.config.bak"
  • релиз глобальный мьютекс

Я думал, что это решение является надежным, но страшная проблема возникла снова в производстве после сбоя питания. Файл конфигурации был поврежден, заполнен символом «NULL», файл .tmp или .bak не существовал.

Моя теория заключается в том, что исходное содержимое файла было обнулено при удалении «foo.config.bak», но обновление метаданных файловой системы, вызванное вызовом ReplaceFile, не было сброшено на диск. Поэтому после перезагрузки «foo.config» указывает на исходное содержимое файла, которое было обнулено, возможно ли это, так как ReplaceFile вызывается перед DeleteFile?

Файл хранился на SSD (SanDisk X110).

Вы видите недостаток в моей процедуре перезаписи файлов? Может ли это быть аппаратным сбоем в SSD? У вас есть идея гарантировать, что атомарность файла будет перезаписана даже в случае сбоя питания? В идеале я хотел бы удалить файл tmp и bak после перезаписывания.

Спасибо,

+0

Удаление файла не равно нулю. Я думаю, что более вероятно, что данные, записанные в файл foo.config.tmp, никогда не достигали диска, возможно, из-за кэширования внутри SSD, или сама файловая система могла стать поврежденной, и данные были потеряны во время самовосстановления. На самом деле нет надежного способа предотвратить выключение питания из-за такого рода проблем, хотя может помочь отключение кэширования записи (через диспетчер устройств). Другими предложениями являются диск с батареей и/или ИБП для сервера. –

+0

Ваш подход ReplaceFile кажется звуковым, но между вами и диском (или SSD) есть все виды кода, которые могут не делать то, что вы ожидаете перед отключением питания. (Я знаю, по крайней мере, один жесткий диск, который с радостью сообщит ОС, что все его кэши были сброшены, когда на самом деле они этого не сделали.) Я настоятельно рекомендую источник бесперебойного питания. –

ответ

0

Использование MoveFileEx с MOVEFILE_WRITE_THROUGH флагом при переименовании файла. Это должно указывать Windows, чтобы сразу написать файл, а не кэшировать его.

+0

Но это не просто Windows.Когда вы будете проинструктировать о записи, некоторые диски будут обманывать и возвращать код успеха, прежде чем данные будут переданы на постоянное хранение. –

Смежные вопросы