Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

Функция

SLtt_get_terminfo
пытается предположить, будет ли цвет доступен на текущем терминале. К сожалению, многие базы данных termcap и terminfo в этом отношении несовершенны. Если будет задана переменная среды
COLORTERM
, то S-Lang установит переменную
SLtt_Use_Ansi_Colors
независимо от того, что отражено в базе данных терминала.

Большинство приложений, обеспечивающих поддержку цветов, также предлагают опцию командной строки, позволяя избирательно разрешать поддержку цветов. Указание этой опции приводит к явной установке переменной

SLtt_Use_Ansi_Colors
в приложении.

Глава 25

Библиотека хешированных баз данных

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

В системах семейства Unix одной из первых использовалась библиотека
dbm
(впоследствии она была повторно реализована как
ndbm
), что привело затем к появлению библиотек Berkley db и
gdbm
проекта GNU. Все эти библиотеки обеспечивали простой доступ к файлам, организованным в виде хеш-таблиц, с двоичным ключом, который обеспечивал доступ к области бинарных данных [173] .

173

Библиотека Berkley db была существенно расширена, и сейчас включает реализацию B-деревьев и весь спектр работы с транзакциями.

Несмотря на то что

gdbm
и Berkley db широко доступны в системах Linux, лицензии, сопровождаемые их, снижают удобство их коммерческого использования [174] . Библиотека
gdbm
во многом похожа на другие библиотеки, но подпадает под действие лицензии LGPL, что делает ее более привлекательной для большинства разработчиков. Базовый API-интерфейс каждой из этих библиотек похож на остальные, поэтому переносить код между библиотеками несложно.

174

В настоящее время Berkley db разрабатывается некоммерческой организацией, которая продает альтернативные лицензии для своей библиотеки, поэтому на них вполне можно ориентироваться при разработке определенного рода приложений.

Полный исходный код и документацию по библиотеке

gdbm
можно найти на Web-сайте по адресуВ этой главе будут описаны все функции, которые большинство приложений должны использовать для
qdbm
(каждая из них имеет близкие аналоги в Berkley db,
adbm
и
ndbm
). Доступны также и другие функции API, описание которых можно найти на Web-сайте
qdbm
.

25.1. Обзор

qdbm
предлагает несколько различных API-интерфейсов. Самый основной из них, Depot, является низкоуровневым API, который мы и рассмотрим в этой главе. Интерфейс
Curia
позволяет разбивать базу данных на несколько файлов (для повышения масштабируемости или с целью работы в файловой системе с ограничениями), а функции
Villa
предлагают две модели: модель B-деревьев и модель транзакций. API-интерфейс
Odeon
позволяет работать с инвертированными индексами [175] . Два последних API,
Relic
и
Hovel
, предлагают реализацию таких интерфейсов, как
ndbm
и
qdbm
.

175

Инвертированные индексы представляют собой структуры данных, предназначенные для полнотекстового поиска.

Функции

Depot
обеспечивают выполнение основных операций по схеме "ключ-значение", при этом ключ используется для извлечения значения. Ключ и значение представляют собой произвольные бинарные потоки, размер которых передается отдельно от данных; библиотеке ничего не нужно знать об их структуре. Однако у интерфейса
Depot
имеется пара функциональных средств, благодаря которым применение строк в качестве ключей и элементов данных становится более удобным. Во-первых, всякий раз при передаче размера ключа или элемента данных в библиотеку вместо них может быть передано значение
– 1
, на основании которого
Depot
будет использовать функцию
strlen
для вычисления используемого размера. Во-вторых, большинство функций чтения ключей и элементов данных автоматически добавляют к возвращаемому значению байт
0
. Этот дополнительный символ не включается в возвращаемый размер, поэтому его можно проигнорировать, если значение не является строкой. Если же это строка, то возвращаемое значение может быть обработано как строка, и приложению не нужно будет завершать ее с помощью
NULL
.

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
битовым "ИЛИ".

176

В отличие от некоторых библиотек баз данных, использующих множество файлов с расширениями

.pag
и
.dir
, библиотека
Depot
использует один файл.

Когда приложения создают новые базы данных, они должны также использовать битовое "ИЛИ" с

DP_CREAT
для отправки
qdbm
запроса на создание нового файла, если он еще не был создан. Флаг
DP_OTRUNC
сигнализирует о том, что первоначальное содержимое
filename
будет удалено и заменено пустой базой данных.

Последний параметр функции

dpopen
,
bnum
, сообщает
qdbm
о том, сколько сегментов памяти нужно задействовать в хеш-массиве. Чем меньшим будет значение этого параметра, тем меньший размер будет иметь база данных; чем больше будет его значение, тем быстрее она будет работать благодаря сокращению количества конфликтных ситуаций в хеш-памяти. В документации к
qdbm
рекомендуется, чтобы это значение составляло от половины до величины, в четыре раза большей от того количества элементов, которые, предположительно, будет иметь база данных [177] . Если вы не уверены, какое следует использовать значение, можно присвоить нулевое значение, которое является значением по умолчанию [178] .

177

Хорошее описание хеш-таблиц можно найти в [11].

178

Это значение можно изменить только путем оптимизации базы данных с помощью функции

dpoptimize
, описание которой можно найти на Web-сайте
qdbm
.

Функция

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) {

Поделиться с друзьями: