Файлы с отображением в память и атомарные записи отдельных блоков - PullRequest
12 голосов
/ 21 сентября 2010

Если я читаю и записываю один файл, используя обычные API ввода-вывода, запись гарантируется на атомарной основе для каждого блока.То есть, если моя запись изменяет только один блок, операционная система гарантирует, что либо записан весь блок, либо ничего вообще.

Как добиться того же эффекта для файла с отображенной памятью?

Файлы, отображаемые в память, представляют собой просто байтовые массивы, поэтому, если я изменю байтовый массив, операционная система не сможет узнать, когда я считаю запись «выполненной», поэтому она может (даже если это маловероятно) заменитьпамять только в середине моей операции записи блока, и в действительности я пишу половину блока.

Мне понадобится какой-то «вход / выход из критической секции» или какой-то метод «закрепления»страница файла в память, пока я пишу в него.Существует ли что-то подобное?Если да, то переносимо ли это в распространенных системах POSIX и Windows?

1 Ответ

5 голосов
/ 25 октября 2010

Техника ведения журнала кажется единственной. Я не знаю, как это работает с несколькими приложениями, записывающими в один файл. У проекта Cassandra есть хорошая статья о том, как добиться успеха с журналом. Главное, чтобы убедиться в том, что журнал записывает только положительных действий (мой первый подход состоял в том, чтобы записать предварительное изображение каждой записи в журнал, позволяющее вам выполнить откат, но это оказалось слишком сложным ).

Таким образом, в основном ваш отображенный в память файл имеет transactionId в заголовке, если ваш заголовок помещается в один блок, вы знаете, что он не будет поврежден, хотя многие люди пишут его дважды с контрольной суммой: [header[cksum]] [header[cksum]] , Если первая контрольная сумма не пройдена, используйте вторую.

Журнал выглядит примерно так:

[beginTxn[txnid]] [offset, length, data...] [commitTxn[txnid]]

Вы просто продолжаете добавлять записи журнала, пока они не станут слишком большими, а затем перевернуть их в какой-то момент. При запуске вашей программы вы проверяете, находится ли идентификатор транзакции для файла с последним идентификатором транзакции журнала - если нет, вы воспроизводите все транзакции в журнале для синхронизации.

...