Digital Q.DataBase предлагает механизм асинхронного уведомления
с помощью команд LISTEN и NOTIFY
командами. Клиентский сеанс регистрирует свою заинтересованность в определенном канале уведомлений с помощью LISTEN команды (и
может прекратить прослушивание с помощью UNLISTEN команды). Всем
сеансам, прослушивающим определенный канал, будут направлены асинхронные уведомления,
когда любым сеансом будет выполнена NOTIFY команда с этим
именем канала. Для передачи слушателям дополнительных данных может быть использована «строка полезной нагрузки» string can
be passed to communicate additional data to the listeners.
libpq приложения отправляют
LISTEN, UNLISTEN,
и NOTIFY команды как
обычные SQL-команды. Поступление NOTIFY
сообщений впоследствии может быть обнаружено путем вызова функции
PQnotifies.
Функция PQnotifies возвращает следующее уведомление
из списка необработанных уведомлений, полученных от сервера.
Функция возвращает значение NULL, если ожидающих уведомлений нет. Как только уведомление возвращается функцией PQnotifies, оно считается обработанным и удаляется из списка уведомлений.
PGnotify *PQnotifies(PGconn *conn);
typedef struct pgNotify
{
char *relname; /* имя канала уведомлений */
int be_pid; /* идентификатор уведомляющего серверного процесса */
char *extra; /* строка полезной нагрузки уведомления */
} PGnotify;
После завершения обработки PGnotify объекта, возвращенного
функцией PQnotifies, его необходимо освободить с помощью функции
PQfreemem. Достаточно освободить
PGnotify указатель; поля
relname и extra
не являются отдельными участками выделенной памяти. (Имена этих полей
сохранились по историческим причинам; в частности, имена каналов могут не иметь
никакого отношения к именам отношений.)
Пример 4.1.2 содержит пример программы, иллюстрирующий применение асинхронных уведомлений.
PQnotifies фактически не считывает данные с сервера; она лишь возвращает сообщения, ранее принятые другой
libpq функцией. В ранних версиях
libpq, это единственный способ обеспечить своевременное получение NOTIFY сообщений была постоянная отправка команд, даже пустых, с последующей проверкой PQnotifies после каждой команды
PQexec. Хотя этот метод все еще работает, он признан устаревшим, так как приводит к нерациональному расходу вычислительных ресурсов.
Более эффективным способом проверки наличия NOTIFY сообщений при отсутствии
необходимых для выполнения команд является вызов функции
PQconsumeInput
, с последующей проверкой функции
PQnotifies. Можно использовать функцию
select() для ожидания поступления данных от сервера, что позволяет не расходовать ресурсы ЦП без необходимости.
(См. функцию PQsocket для получения номера дескриптора файла, используемого с функцией select().) Обратите внимание, что это будет работать корректно независимо от того, отправляются ли команды с
PQsendQuery/PQgetResult или
просто используете функцию PQexec. Тем не менее, следует не забывать
проверять результат функции PQnotifies после каждой команды
PQgetResult или PQexec, чтобы выяснить, поступили ли какие-либо уведомления во время обработки команды.