Я работаю над встроенной платой arm в C с ядром linux 4.14.Я использую libevent версии 2 и создал обработчики для двух URL.Один для публикации файлов, а другой для получения статуса загрузки.Пользователь будет подключен через браузер и загрузит файл через многочастную форму POST и получит статус загрузки, используя запрос GET.
Вот некоторый псевдокод, чтобы вы могли получить представление о процессе.
void upload_cb(struct evhttp_request *req, void *arg){
struct bufferevent *bev = evhttp_connection_get_bufferevent(req->evcon);
if (bev) //Prio is initialized with 10 states in main
bufferevent_priority_set(bev, 9); // set to low priority
struct evbuffer* post_buffer = evhttp_request_get_input_buffer(req);
size_t body_size = evbuffer_get_length(post_buffer);
// a multipart parser takes care of writing the
// post_buffer content to a file
// this takes a few seconds and after completing this
// the status_cb is accessible again
}
void status_cb(struct evhttp_request *req, void *arg){
// send some json
}
evhttp_set_cb(_http, "/upload", upload_cb, NULL);
evhttp_set_cb(_http, "/status", status_cb, NULL);
Когда я загружаю файл размером около 10 Мб и в то же время опрашиваю URL-адрес статуса каждую 1 секунду, URL-адрес статуса не будет отвечать в течение 12 секунд, пока файл не будет правильно обработан и функция не будетвернулся.
upload_cb занимает некоторое время для обработки данных и поэтому удерживает status_cb от выполнения.Это нежелательно, потому что приложение не отвечает на данный момент.
Я пытаюсь постоянно получать статус из приложения и постоянно обновлять пользовательский интерфейс о происходящем.Из того, что я могу сказать, обратный вызов upload_cb вызывается после того, как все данные были буферизованы и готовы к обратному вызову для его обработки.Это означает, что он буферизировал бы все 10 Мбайт в памяти.
Я пытался снизить приоритет буферов в надежде, что планировщик событий прервет и даст некоторое время другим событиям, но мне кажется, чтоЛибвент работает неверно.
Я искал альтернативные решения и чувствовал, что мог бы создать отдельный поток, в котором я мог бы обрабатывать загрузку + сохранение в файл, а затем передавать управление обратно в основной поток.Но я бы предпочел спросить здесь, есть ли более элегантное решение, которое предполагает полное пребывание с libevent.
Могу ли я получить libevent для прерывания обработки загрузки и ответа на запрос статуса?Могу ли я заставить libevent получать данные порциями, чтобы он мог обрабатывать другие обратные вызовы?
ОБНОВЛЕНИЕ 1: в соответствии с этот вопрос Я должен использоватьнеблокирующие вызовы API.Хотя запись файлов неблокирующая, кажется, что буфер записи ядра заполнен, потому что я записываю 10+ Мбайт в файл.Я переместил разбор и запись в новый поток, который позволяет libevent вернуться из функции, и сейчас изучаю, как мне следует обрабатывать post_buffer (многопоточный доступ, освобождение его после использования и т. Д.)
UPDATE2: перемещение парсинга в новый поток не работает, потому что тогда возвращается обратный вызов upload_cb
и очищается evhttp_request
и его буфер, пока поток все еще хочет его проанализировать.Я склоняюсь к созданию дополнительного экземпляра event_base для бесперебойной загрузки, как указано в ссылках на этот вопрос