Depot
использует глобальную целочисленную переменную dpecode
для хранения кодов ошибок. Когда функции Depot
возвращают сбой, dpecode
сообщает о том, что произошло (это почти то же самое, что и в случае с переменной errno
, которая относится к системным вызовам и библиотеке С). За текстовые сообщения об ошибках отвечает функция dperrmsg()
.
#include <depot.h>
const char * dperrmsg(int ecode);
Подобно strerror()
, функция dperrmsg()
принимает код ошибки (обычно из dpecode
) и возвращает строку, в которой приводится описание возникшей ошибки.
Функции в API-интерфейсе Depot
используют указатель на структуру DEPOT
. Это непрозрачная структура (программы, использующие Depot
, не могут самостоятельно проверять значения в структуре), однако в ней содержится вся информация, используемая библиотекой для обслуживания файла, хранящегося на диске.
25.2. Основные операции
25.2.1. Открытие файла qdbm
Библиотечная функция dpopen()
используется для открытия файлов базы данных.
#include <depot.h>
DB * dpopen(const char * filename, int omode, int bnum);
Первый аргумент представляет имя файла, который будет использоваться для базы данных[176]. Аргумент omode
определяет способ доступа к файлу, и должен иметь одно из двух значений: DP_OREADER
и DP_OWRITER
, в зависимости от того, какой вид доступа к базе данных необходим программе — для чтения или для записи. По умолчанию база данных блокируется, чтобы разрешить нескольким программам доступ для чтения или одной программе доступ для записи. Если приложению не нужна блокировка, производимая qdbm
, то DP_ONOLCK
может быть объединен с omode
битовым "ИЛИ".
Когда приложения создают новые базы данных, они должны также использовать битовое "ИЛИ" с DP_CREAT
для отправки qdbm
запроса на создание нового файла, если он еще не был создан. Флаг DP_OTRUNC
сигнализирует о том, что первоначальное содержимое filename
будет удалено и заменено пустой базой данных.
Последний параметр функции dpopen()
, bnum
, сообщает qdbm
о том, сколько сегментов памяти нужно задействовать в хеш-массиве. Чем меньшим будет значение этого параметра, тем меньший размер будет иметь база данных; чем больше будет его значение, тем быстрее она будет работать благодаря сокращению количества конфликтных ситуаций в хеш-памяти. В документации к qdbm
рекомендуется, чтобы это значение составляло от половины до величины, в четыре раза большей от того количества элементов, которые, предположительно, будет иметь база данных[177]. Если вы не уверены, какое следует использовать значение, можно присвоить нулевое значение, которое является значением по умолчанию[178].
Функция dpopen()
возвращает указатель на структуру DEPOT
, который передается остальным функциям Depot
. В случае возникновения ошибки функция dpopen()
возвращает NULL
и устанавливает dpecode
.
25.2.2. Закрытие базы данных
Чтобы закрыть файлы базы данных, используйте функцию dpclose()
.
int dpclose(DEPOT * depot);
Функция dpclose()
возвращает нулевое значение после успешного закрытия файлов и ненулевое — при сбое, который может произойти из-за невозможности очистки данных из буферов базы данных. Ниже показан пример программы, которая открывает файл базы данных в текущем каталоге и сразу же закрывает его.
1: /* qdbmsimple.c */
2:
3: #include <depot.h>
4: #include <errno.h>
5: #include <fcntl.h>
6: #include <stdio.h>
7:
8: int main(void) {
9: DEPOT * dp;
10:
11: dp = dpopen("test.db", DP_OWRITER | DP_OCREAT, 0);
12: if (!dp) {
13: printf("ошибка: %s\n", dperrmsg(dpecode));
14: return 1;
15: }
16:
17: dpclose(dp);
18:
19: return 0;
20: }
25.2.3. Получение файлового дескриптора
Помимо возможности использования автоматической блокировки, которую предлагает qdbm
, в некоторых программах потребуется изменять их собственную схему блокировки. Для этой цели qdbm
обеспечивает доступ к файловому дескриптору, который ссылается на базу данных.
int dpfdesc(DEPOT * depot);
Эта функция возвращает файловый дескриптор базы данных depqt
[179].
25.2.4. Синхронизация базы данных
qdbm
кэширует данные в оперативной памяти для ускорения доступа к базе данных, а ядро Linux кэширует записи на диске, чтобы свести к минимуму задержку между вызовами функции write()
. Чтобы база данных, хранящаяся на диске, оставалась согласованной с буферизированными структурами, приложение может осуществлять ее синхронизацию. В процессе синхронизации базы данных qdbm очищает все ее внутренние буферы и вызывает функцию fsync()
для файлового дескриптора.
int dpsync(DEPOT * depot);
25.3. Чтение записей
Прочитать записи в базе данных можно двумя способами: посредством поиска записи по ее ключу и путем чтения последовательных пар "ключ-значение".
25.3.1. Чтение определенной записи
Функции dpget()
и dpgetwb()
производят поиск записей в базе данных по ключу.
int dpget(DEPOT * depot, const char * key, int keySize, int start,
int max, int * dataSize);
key
является элементом (ключом), с помощью которого производится поиск по базе данных, a keySize
определяет длину ключа (или значение -1
, при котором Depot
использует функцию strlen(key)
для определения длины ключа). С помощью следующих двух параметров, start
и max
, можно производить частичное чтение записей; параметр start
задает смещение в данных, с которого начнется операция чтения, а max
— максимальное количество байтов для чтения. Например, если область данных представляла бы собой массив из четырехбайтовых целочисленных значений int
, то в результате присвоения параметру start
значения 12
и параметру max
значения 8
производилось бы чтение четвертого и пятого элементов массива. Если для чтения доступно менее start
байтов, функция dpget()
вернет NULL
. Чтобы прочитать все байты из данных, параметру max
следует присвоить значение -1
.
176
В отличие от некоторых библиотек баз данных, использующих множество файлов с расширениями .pag
и .dir
, библиотека Depot
использует один файл.
178
Это значение можно изменить только путем оптимизации базы данных с помощью функции dpoptimize()
, описание которой можно найти на Web-сайте qdbm
.
179
Несмотря на то что qdbm
обеспечивает доступ к файловому дескриптору, использовать его следует осторожно. Дело в том, что все операции по чтению и записи в файл должны производиться через библиотеку qdbm
; операции, не связанные с изменением данных в файле, например, блокировка или установка флага для закрытия после выполнения, допускаются.