MariaDB неблокируемый с EPOLL

У меня есть однопоточный сервер, написанный на C, который принимает соединения TCP/UDP на основе EPOLL и поддерживает плагины для множества уровней протоколов, которые нам необходимо поддерживать. Это немного хорошо.

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

Мы используем MariaDB и коннектор MariaDB, который поддерживает неблокирующие функции в своем API.

https://mariadb.com/kb/en/mariadb/using-the-non-blocking-library/

Но то, что я нахожу, не то, что я ожидал, а то, что я ожидал, описано ниже.

Сначала я уволить mysql_real_connect_start() и если он возвращает ноль, мы немедленно отправляем запрос, поскольку это указывает на то, что блокировка не требуется, хотя это никогда не происходит.

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

s = mysql_get_socket(mysql);

if(s > 0)
{
    brt_socket_set_fds(endpoint, s);
    struct epoll_event event;
    event.data.fd = s;
    event.events = EPOLLRDHUP | EPOLLIN | EPOLLET | EPOLLOUT;
    s = epoll_ctl(efd, EPOLL_CTL_ADD, s, &event);
    if (s == -1) {
        syslog(LOG_ERR, "brd_db : epoll error.");
        // handle error.
    }
...

Итак, через некоторое время я получаю EPOLLOUT, указывающий, что сокет был открыт.

И я покорно вызываю mysql_real_connect_cont(), но на этом этапе он все еще возвращает ненулевое значение, указывая, что я должен ждать дольше?

Но тогда это последнее событие EPOLL, которое я получаю, за исключением EPOLLRDHUP, когда я предполагаю, что MariaDB зависает через 10 секунд.

Может кто-нибудь помочь мне понять, если эта идея даже работоспособна?

Спасибо... Спасибо... большое Спасибо.

1 ответ

Хорошо для всех, кто приземлится здесь, я исправил это или, вернее, не сломал его.

Обратите внимание, что - из примеров - возвращенное состояние от вызовов _start / _cont передается в качестве параметра следующему _cont. Оказывается, это очень важно.

Статус содержит флаги MYSQL_WAIT_READ, MYSQL_WAIT_WRITE, MYSQL_WAIT_EXCEPT, MYSQL_WAIT_TIMEOUT, и если он не передан следующему _конту, я думаю, вы связываетесь с конечным автоматом _cont.

Я не сохранял состояние статуса между разными местами, где вызывались _start и _cont.

struct MC
{
    MYSQL *mysql;
    int status;
} MC;
...
// Initial call
mc->status = mysql_real_connect_start(&ret, mc->mysql, host, user, password, NULL, 0, NULL, 0);

// EPOLL raised calls.
mc->status = mysql_real_connect_cont(&ret, mc->mysql, mc->status);
if(mc->status) return... // keep waiting check for errors.
Другие вопросы по тегам