Причина повреждения файла

У меня есть повторяющаяся проблема с приложением в дикой природе.

У него довольно простой XML файл, который он выгружается время от времени, примерно каждые 30 минут.

Файлы данных часто довольно малы - например, < 5KB.

Он не содержит блокировки файла - он просто воссоздает его с нуля каждый раз.

Мне посчастливилось увидеть проблему на тестовой машине, и я заметил, что файл был поврежден и установлен на "nulls" (т.е. 00 в Hex). Что действительно странно, так это то, что это точно правильная длина по сравнению с тем, что должно было быть.

Я пытаюсь быть очень осторожным в своем процессе сохранения:

  • Я пишу xml в файл temp в том же каталоге, что и в действительности, чтобы сохранить его
  • Я выполняю Win32 MoveFile() с набором MOVEFILE_WRITE_THROUGH (поэтому он должен блокироваться до тех пор, пока перемещение действительно и действительно не завершено), чтобы переместить файл, чтобы заменить существующий файл данных

Я даже блокирую Mutex, чтобы убедиться, что это не проблема с потоками.

Не так часто бывает, например, 1 из 1000 пользователей.

Теперь я в прошлом наблюдал, что файлы данных были повреждены сбоем питания или BSOD во время записи, и я видел такие вещи, как 32kb файла, все NULL.

Но похоже, что это происходит больше, чем я ожидал, учитывая шансы сбоя питания во время записи, и особенно, поскольку я использую MOVEFILE_WRITE_THROUGH.

Любые идеи?

Джон

Ответы на некоторые вопросы:

  • В: Почему бы не написать файл напрямую Ответ: Я избегал этого, чтобы сделать программное обеспечение менее уязвимым для проблем с электропитанием. Например. вы на полпути через запись файла и аварийный /powerfail/BSOD, тогда у вас определенно есть поврежденный файл. Выполнение записи временного файла, а затем переход - это обычно используемый и простой способ обеспечения максимально возможной работы с атомарным файлом (ну, насколько это разумно, без использования специфичных для NTFS API). Я должен сказать, что программное обеспечение представляет собой систему архивирования/резервного копирования, поэтому я должен заботиться о согласованности данных, чем другие приложения.

  • Q: Это происходит во время нормальной работы?

  • A: Поскольку эта проблема возникает в дикой природе, я работаю только с несколькими подсказками, поэтому я не знаю точно. Могу сказать, что программное обеспечение работает в 99,9% случаев. Я предполагаю, что суть моего вопроса: это просто случайная неудача, вызванная сбоем BSOD/power или это ошибка?

  • В: Какая среда/ОС:

  • A: XP, Vista, 7, Server 200X. Скорее всего, NTFS, но может быть FAT32

  • Q: Я закрываю файл перед перемещением

  • A: Да. Я использую потоки С++ и вызываю close(), прежде чем я сделаю MoveFile

  • В: Какие другие процессы обращаются к файлу?

  • A: Никто не управляется мной. Очевидно, что я не контролирую Virus Checker, Folder Syncers и т.д. Файл находится в папке AppData\Local на компьютере пользователя.
2 ответа

Как мой опыт, возможно, это связано с кэшем файлов в окнах. Вам следует попытаться сохранить файл с помощью CreateFile() с FILE_FLAG_WRITE_THROUGH. В этом случае сохранение файла может привести к тому, что файл войдет на жесткий диск.

У меня была небольшая программа, чтобы проверить это. Если программа создает файл с std::ofstream и использует MoveFileEx() с MOVEFILE_WRITE_THROUGH для перемещения этого файла, файл повреждается почти каждый раз, если вы отключите питание (не выключите), сразу после завершения перемещения файла; В противном случае, если программа использует CreateFile() с FILE_FLAG_WRITE_THROUGH для создания файла и повторяет то же самое, файл не поврежден (я тестировал примерно 10 раз, но этого не произошло).

После этих простых тестов, я думаю, вы должны попытаться использовать CreateFile() с FILE_FLAG_WRITE_THROUGH, чтобы решить вашу проблему.

Дополнительная информация: Кэширование файлов (Windows) Windows Internals, 6-е издание, Глава 11 Cache Manager


Вот несколько идей:

  • Сбросить поток после критического информации или в течение длительного времени нет записи.
  • Убедитесь, что никакие другие объекты не являются запись в файл.
  • Убедитесь, что буферизованные данные не являются перезаписан другим кодом.
  • Закройте файл между длительными сроками без письменного разрешения.

licensed under cc by-sa 3.0 with attribution.