Блокирование физических записей
Если вы разрабатываете СУБД с коллективным доступом к файлам базы данных, расположенным на сервере, метод блокирования файлов может оказаться не слишком удобным. Так как разные пользователи в разные моменты времени работают с различными участками (записями) базы данных, едва ли стоит блокировать весь файл, если один из пользователей решил изменить содержимое только одной записи в базе данных. Было бы лучше заблокировать только эту запись.
Средства сетевой оболочки позволяют вам блокировать отдельные записи в разных файлах, образуя группу блокируемых записей (по аналогии с группой файлов, рассмотренной нами в предыдущем разделе). В группу могут входить записи из одного или нескольких файлов. Каждая запись идентифицируется индексом файла (файл необходимо открыть функцией open() или аналогичными средствами), смещением начала записи в байтах от начала файла и размером записи в байтах.
Для создания группы физических записей используется функция LogPhysicalRecord(), аналогичная по назначению функции LogFile(), но работающая с записями. Удалить запись из группы можно функцией ClearPhysicalRecord(). Вся группа записей удаляется функцией ClearPhysicalRecordSet().
Записи можно блокировать сразу при их добавлении в группу либо позже. Вы можете заблокировать сразу все записи, относящиеся к группе, вызвав функцию LockPhysicalRecordSet().
Для разблокирования записи используется функция ReleasePhysicalRecord(). Если надо разблокировать сразу все записи, вызывайте функцию ReleasePhysicalRecordSet().
Функция LogPhysicalRecord() имеет следующий прототип: int LogPhysicalRecord(int FileHandle, long RecordStartOffset, long RecordLength, BYTE LockDirective,WORD Timeout);
Параметр FileHandle задает индекс файла, которому принадлежит блокируемая запись.
Параметры RecordStartOffset и RecordLength задают смещение от начала файла и размер блокируемой записи в байтах.
Параметр LockDirective определяет, надо ли блокировать запись сразу после его добавления в группу:
0x00 | Запись добавляется в группу, но не блокируется |
0x01 | Добавляемая запись блокируется для использования заблокировавшей его программой в монопольном режиме |
0x03 | Добавляемая запись блокируется для совместного использования |
Параметр Timeout определяет период времени (в 18-х долях секунды), в течение которого файл-сервер будет ожидать, если запись нельзя заблокировать немедленно. Если для этого параметра задать нулевое значение, ожидание выполняться не будет.
Функция возвращает 0 при успешном завершении или код ошибки:
Код ошибки | Значение |
0x96 | Мало памяти на файл-сервере |
0xFE | Истек период ожидания, заданный параметром Timeout, но запись так и не удалось заблокировать |
0xFF | Сбой при блокировании записи |
Для удаления записи из группы можно использовать функцию ClearPhysicalRecord(): int ClearPhysicalRecord(int FileHandle, long RecordStartOffset, long RecordLength);
Параметры этой функции аналогичны параметрам функции LogPhysicalRecord. Функция возвращает нулевое значение или значение 0xFF, если в списке нет указанной записи.
Функция ClearPhysicalRecordSet() позволяет разблокировать все записи группы и удалить группу void ClearPhysicalRecordSet(void);
Прототип функции LockPhysicalRecordSet(), используемой для блокирования группы записей: int LockPhysicalRecordSet(BYTE LockDirective, WORD Timeout);
Параметр LockDirective задает режим блокирования. Если он равен 0, записи блокируются для монопольного использования программой, заблокировавшей записи. Если параметр имеет значение 1, записи блокируются для совместного использования в режиме чтения.
Параметр Timeout используется так же, как и при вызове функции LogPhysicalRecord().
Функция возвращает 0 при успешном завершении или код ошибки:
Код ошибки | Значение |
0xFE | Истек период ожидания, заданный параметром Timeout, но запись так и не удалось заблокировать |
0xFF | Сбой при блокировании записи |
После того как группа записей заблокирована, вы можете разблокировать отдельные записи или всю группу сразу.
Для разблокирования отдельных записей используйте функцию ReleasePhysicalRecord(): int ReleasePhysicalRecord(int FileHandle, long RecordStartOffset, long RecordLength);
Параметры задают индекс файла, смещение записи и ее длину. Функция возвращает нулевое значение или значение 0xFF, если указанной записи нет в списке.
Если надо разблокировать сразу все записи, добавленные в группу, используйте функцию ReleasePhysicalRecordSet(): void ReleasePhysicalRecordSet(void);
Для добавления записей в группу вместо функции LogPhysicalRecord() можно использовать функцию BCh прерывания INT21h:
На входе: | AH | = | BCh; |
AL | = | Параметр LockDirective; | |
BP | = | Параметр Timeout; | |
BX | = | Индекс файла; | |
CX | = | Старшее слово смещения записи относительно начала файла; | |
DX | = | Младшее слово смещения; | |
SI | = | Длина записи. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
Для удаления записи из списка вместо функции ClearPhysicalRecord() можно использовать функцию BEh прерывания INT 21h:
На входе: | AH | = | BEh; |
BX | = | Индекс файла; | |
CX | = | Старшее слово смещения записи относительно начала файла; | |
DX | = | Младшее слово смещения. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
Для удаления группы записей и разблокирования всех записей вместо функции ClearPhysicalRecordSet() можно использовать функцию C4h прерывания INT 21h:
На входе: | AH | = | C4h. |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
Для блокирования группы записей вместо функции LockPhysicalRecordSet() можно использовать функцию C2h прерывания INT 21h:
На входе: | AH | = | C2h; |
AL | = | Параметр LockDirective; | |
BP | = | Параметр Timeout. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
Для разблокирования записи вместо функции ReleasePhysicalRecord() можно использовать функцию BDh прерывания INT 21h:
На входе: | AH | = | BDh; |
BX | = | Индекс файла; | |
CX | = | Старшее слово смещения записи относительно начала файла; | |
DX | = | Младшее слово смещения. | |
На выходе: | AL | = | Код ошибки или 0, если операция завершилась без ошибок. |
Для разблокирования группы записей вместо функции ReleasePhysicalRecordSet() можно использовать функцию C3h прерывания INT 21h:
На входе: | AH | = | C3h. |
На выходе: | = | Регистры не используются. |