Просматривал лог и обнаружил битые данные, вроде такого Enumerating network events f\xD3\xAE\x09.
Это произошло из-за того, что под временный буфер выделяется исключительно need_capacity байтов, без заверщающего нулевого символа, а в TryAppend при форматировании строки шаблон %s требует данные с нулём в конце. Можно исправить, выделяя под буфер на один байт больше, либо указав шаблон %.*s с размером.
Как я понял, Вы сделали ограничение на вставку в буфер, чтобы данные точно смогли вместиться в него, т.к. в предыдущей версии оставалась возможность, что если количество данных для записи превышает размер буфера, то всё встанет.
Я же предлагаю не обрезать данные. Сейчас основная проблема в том, что если данные превышают доступный размер буфера, мы не можем заполнить остаток буфера частью данных из-за того, что TryAppend форматирует данные внутри себя, а не оперирует над каким-то фиксированным куском данных.
отделил форматирование сообщений от операций над буферами: FormattedWrite форматирует данные и отсылает фиксированный кусок данных в InternalWrite
TryAppend упрощается до функции заполнения доступного в буфере места
InternalWrite теперь последовательно пишет сначала в первый буфер, потом во второй (полностью используя всё пространство буферов) при необходимости ожидая освобождения буфера
привёл микс знаковых/беззнаковых типов (int64_t, uint64_t) к стандартному size_t
пофиксил функцию Buffer::Flush
По поводу Buffer::Flush - было 3 проблемы:
функция fwrite не возвращает в качестве флага ошибки значения меньшие нуля (после приведения к знаковому типу). Возвращаемое значение - исключтельно количество записанных элементов
в цикле количество записываемых элементов произвольно: size_ - n_write, где n_write осталось с предыдущей итерации, а size_ при этом не меняется
на каждой итерации fwrite записывает тот же самый буфер, т.к. указатель data_ не продвигается
Ситуацию спасает то, что используется проверка n_write == size_ и то, что если нет никаких проблем при записи, fwrite записывает весь буфер за один раз.
Протестировал работу при разных размерах буферов, в том числе крошечных вроде 128 байт, а также при указании INFINITE в pthread_cond_timedwait.
Попытка №2.
Просматривал лог и обнаружил битые данные, вроде такого
Enumerating network events f\xD3\xAE\x09
.Это произошло из-за того, что под временный буфер выделяется исключительно
need_capacity
байтов, без заверщающего нулевого символа, а вTryAppend
при форматировании строки шаблон%s
требует данные с нулём в конце. Можно исправить, выделяя под буфер на один байт больше, либо указав шаблон%.*s
с размером.Как я понял, Вы сделали ограничение на вставку в буфер, чтобы данные точно смогли вместиться в него, т.к. в предыдущей версии оставалась возможность, что если количество данных для записи превышает размер буфера, то всё встанет.
Я же предлагаю не обрезать данные. Сейчас основная проблема в том, что если данные превышают доступный размер буфера, мы не можем заполнить остаток буфера частью данных из-за того, что
TryAppend
форматирует данные внутри себя, а не оперирует над каким-то фиксированным куском данных.В пулл реквесте:
pthread_cond_signal
FormattedWrite
форматирует данные и отсылает фиксированный кусок данных вInternalWrite
TryAppend
упрощается до функции заполнения доступного в буфере местаInternalWrite
теперь последовательно пишет сначала в первый буфер, потом во второй (полностью используя всё пространство буферов) при необходимости ожидая освобождения буфераint64_t
,uint64_t
) к стандартномуsize_t
Buffer::Flush
По поводу
Buffer::Flush
- было 3 проблемы:fwrite
не возвращает в качестве флага ошибки значения меньшие нуля (после приведения к знаковому типу). Возвращаемое значение - исключтельно количество записанных элементовsize_ - n_write
, гдеn_write
осталось с предыдущей итерации, аsize_
при этом не меняетсяfwrite
записывает тот же самый буфер, т.к. указательdata_
не продвигаетсяСитуацию спасает то, что используется проверка
n_write == size_
и то, что если нет никаких проблем при записи,fwrite
записывает весь буфер за один раз.Протестировал работу при разных размерах буферов, в том числе крошечных вроде
128
байт, а также при указанииINFINITE
вpthread_cond_timedwait
.