You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
358 lines
35 KiB
358 lines
35 KiB
Файлы участников CHAT-группы |
|
=========================== |
|
|
|
Модуль: src/member_files/. Desktop-браузер: tools/chatgui/src/member_files/. |
|
Отдельный сервис router ETCP_RT_ID_MEMBER_FILES (0x39), отдельно от вложений |
|
сообщений media_delivery и E2E-файлов DM. Серверы выбираются явно; между |
|
серверными деревьями автоматической репликации нет. |
|
|
|
Хранение и конфигурация |
|
---------------------- |
|
|
|
Корень по умолчанию: <db_path>/member_files/ (без db_path — ./member_files/). |
|
Публичное дерево: <корень>/<group_id>/<node_id>/<относительный путь>. |
|
Временные файлы: <корень>/.uploads/<upload UUID в hex>. |
|
При старте сервис создаёт/открывает корень в дисковом worker, удаляет старые |
|
незавершённые temp и сканирует опубликованные файлы. До готовности отвечает BUSY. |
|
Ошибка сканирования оставляет локальное хранилище недоступным до restart; |
|
частичные счётчики клиенту не выдаются. Клиентские передачи к другим серверам продолжают работать. |
|
Очистка кэша вложений media/ это дерево не обходит. |
|
|
|
Настройки [chatserver] / [chat]: |
|
member_files_enabled=1 |
|
member_files_user_quota_mb=1024 |
|
member_files_upload_ttl_sec=3600 |
|
member_files_path=/путь/к/хранилищу (опционально, до 255 байт UTF-8) |
|
|
|
Путь, квота и TTL читаются при старте чат-сервиса; изменение требует его restart. |
|
enabled проверяется на каждом запросе. Лимит одинаков для каждого UID отдельно, |
|
размер UID суммируется по всем группам на этом сервере. Значение в МиБ (1024*1024 байт). |
|
Счётчики used/reserved/files/directories хранятся в памяти дискового worker и восстанавливаются с диска только при старте. |
|
Каталоги не занимают байтовую квоту. files/directories считают опубликованные файлы и каталоги внутри деревьев UID |
|
по всем группам; корни групп, корни UID и .uploads исключены. Пустой опубликованный файл считается файлом. |
|
Сохранённые файлы удалённых участников также занимают квоту. |
|
При начале загрузки резервируется размер нового файла или положительный прирост при замене. |
|
WRITE не изменяет used; COMMIT обновляет used на разницу размеров и освобождает резерв. |
|
ABORT/Cancel/TTL освобождают резерв после удаления temp; REMOVE вычитает размер файла. |
|
Переименование внутри UID не меняет размер и числа объектов. Новый COMMIT увеличивает files на 1; |
|
замена существующего файла, включая нулевой размер, сохраняет files. MKDIR увеличивает directories на 1, |
|
REMOVE уменьшает соответствующий счётчик. Для mkdir учитывается факт создания даже при последующей ошибке sync. |
|
BEGIN/WRITE/ABORT/Cancel/TTL не увеличивают files: temp не опубликован. |
|
Все изменения корректируют счётчики инкрементально, без обхода каталога пользователя; |
|
QUOTA только читает их из памяти. LIST выполняет свой обычный обход для отображения записей, не пересчитывая статистику. |
|
Повторы BEGIN/COMMIT/MKDIR/REMOVE не меняют учёт повторно. |
|
Уже превышенная квота не удаляет данные: чтение, удаление и уменьшение файла доступны, |
|
новый положительный прирост запрещён. Физический temp может занимать больше места, |
|
чем резерв прироста; нехватка места файловой системы остаётся отдельной I/O-ошибкой. |
|
Нехватка квоты/места возвращает NO_SPACE; опубликованные файлы не вытесняются. |
|
Общая member_files_quota_mb удалена. Корень обслуживается только файловым сервисом; |
|
ручные изменения требуют повторного сканирования через restart. |
|
|
|
Сервер — действующий полный мембер группы с подписанным adm_tags.storage="yes". |
|
Колонка peers.storage — производный сетевой приоритет, для полномочий не используется. |
|
Каждый запрос и ответ подписаны Ed25519 и зашифрованы end-to-end средствами |
|
route_crypto. group/src берутся только из проверенного заголовка router; |
|
ETCP peer промежуточного хопа не считается автором запроса. |
|
Читать могут действующие участники той же группы. Изменять дерево может только |
|
src == owner. Удалённые записи и source=1 (плейсхолдеры) доступа не дают. |
|
Открытый fd/UUID загрузки не отменяют повторную проверку членства. |
|
Файлы удалённого участника сохраняются на диске, но через сервис не доступны. |
|
|
|
Wire, версия 4 |
|
-------------- |
|
|
|
Все числа LE, без сырых структур и padding. Фиксированный заголовок 125 байт: |
|
0 protocol_version:u8 = 4 |
|
1 kind:u8 (1=request, 2=response) |
|
2 command:u8 |
|
3 status:u16 (request=0) |
|
5 request_id:u64, ненулевой случайный ID |
|
13 owner:u64 (UID каталога; 0 только для LIST виртуального корня группы) |
|
21 offset:u64 |
|
29 size:u64 |
|
37 cursor:u64 |
|
45 version:16 |
|
61 upload:16 |
|
77 hash:32 |
|
109 mtime:u64, Unix seconds |
|
117 type:u8 (1=file, 2=directory) |
|
118 more:u8 (0/1) |
|
119 path_len:u16 |
|
121 target_len:u16 |
|
123 data_len:u16 |
|
После заголовка: path[path_len], target[target_len], data[data_len], без NUL. |
|
Длина пакета обязана точно совпадать с указанными размерами. |
|
Путь максимум 1024 байта, компонент максимум 255 байт, максимум 60 компонентов. |
|
Данные максимум 8192 байт; вместе с полным router-путём и crypto укладываются |
|
в лимит normalizer 16384 байта. Размер файла/смещение ограничены INT64_MAX. |
|
Пути — строгий UTF-8, относительные, разделитель '/'. Запрещены пустые компоненты, |
|
компоненты с ведущей '.', завершающей точкой/пробелом, управляющие символы, |
|
Windows device names и символы \ : * ? " < > |. Корень внутри UID — пустой путь. |
|
POSIX разрешает путь через *at/O_NOFOLLOW; regular-файлы с hardlink отвергаются. |
|
Windows удерживает родительские каталоги без SHARE_DELETE и не принимает reparse points. |
|
|
|
Команды |
|
--------------- |
|
|
|
1 LIST: owner/path/cursor/version. Первая страница cursor=0, version=0. |
|
Ответ data — записи: name_len:u16,type:u8,size:u64,mtime:u64,version:16,name. |
|
cursor — сколько записей уже выдано. more=1 требует следующую страницу с |
|
возвращёнными cursor/version. При изменении снимка — STALE, начать сначала. |
|
Размер каталога не ограничивает память страницы. Виртуальный корень группы |
|
выдаёт UID действующих полных участников, даже если каталог ещё не создан. |
|
Изменение namespace сервера консервативно инвалидирует дисковые LIST-курсоры. |
|
|
|
2 STAT: owner/path. Ответ type/size/mtime/version. Не хеширует весь файл. |
|
version — непрозрачный снимок identity/size/mtime/ctime и эпохи сервера. |
|
Закрытие fd по таймауту токен не меняет; restart меняет дисковые токены. |
|
|
|
3 READ: owner/path/version/offset/size (1..8192). |
|
Ответ size — полный размер файла, data_len — фактически прочитано, |
|
more — есть ли байты после ответа. offset==EOF возвращает 0 байт/more=0; |
|
offset>EOF — INVALID_RANGE. Изменение файла между блоками — STALE. |
|
Клиент не смешивает версии и публикует локальный файл только по завершении. |
|
|
|
4 BEGIN_WRITE: owner/path/upload/size/hash/version. |
|
upload — 16 случайных байт, size — конечный размер, hash — SHA256 содержимого. |
|
version=0 означает создать новый файл, существующий возвращает EXISTS. |
|
Для замены требуется версия из STAT/LIST. В один путь одна активная загрузка. |
|
UUID привязан к group/src/owner/path; повтор BEGIN с теми же параметрами безопасен. |
|
|
|
5 WRITE: owner/path/upload/offset/size/data. size==data_len, диапазон внутри |
|
конечного размера. Можно писать в произвольном порядке и повторять блок. |
|
ACK подтверждает запись в temp, а не durable публикацию всего файла. |
|
|
|
6 COMMIT: owner/path/upload. Проверяет SHA256, fsync/_commit и ожидаемую |
|
версию назначения, затем атомарно заменяет файл и синхронизирует namespace. |
|
Прежний файл виден до публикации. Ответ содержит размер/версию/SHA256. |
|
Незаписанные sparse-области читаются как нули; неправильное содержимое не |
|
проходит SHA256. Пустые файлы поддерживаются. При I/O-ошибке во время |
|
публикации результат может быть неопределённым; нужно повторно проверить STAT. |
|
|
|
7 ABORT: owner/path/upload. Удаляет temp, освобождает резервацию. |
|
Неизвестный UUID — OK; опубликованные файлы никогда не удаляет. |
|
|
|
8 MKDIR: owner/path. Создаёт один каталог; родители должны существовать. |
|
9 RENAME: owner/path/target/version. Только внутри UID/группы, без замены |
|
существующего назначения. Активная загрузка в затрагиваемом пути — BUSY. |
|
10 REMOVE: owner/path/version. Файл или пустой каталог, без рекурсивного удаления. |
|
|
|
11 STREAM_WRITE: открытие потоковой загрузки; поля как BEGIN_WRITE, |
|
cursor — ненулевой ID потока. Ответ подтверждает готовность temp и конечный размер. |
|
12 STREAM_READ: открытие потокового скачивания; owner/path/version/size/cursor, |
|
upload — случайный токен клиента. Сервер сверяет снимок и размер перед началом. |
|
13 STREAM_DATA: request_id — ID потока, owner/path/upload, offset/size/data. |
|
kind=request для upload, response для download. Ответа на блок нет. |
|
offset обязан равняться следующему принятому смещению; size==data_len, не более 8192. |
|
14 STREAM_END: ID потока, owner/path/upload, offset==size==размер файла, SHA256. |
|
Upload: клиент отправляет END после всех DATA, сервер отвечает END после COMMIT. |
|
Download: сервер отправляет END после DATA и повторной проверки версии; клиент |
|
проверяет SHA256 записанных данных, синхронизирует и публикует локальный файл. |
|
Ошибка сервера приходит END.status!=OK; ошибка открытия — ответом на STREAM_READ/WRITE. |
|
15 STREAM_CANCEL: клиент отменяет конкретный поток. Поздние DATA не публикуются. |
|
|
|
16 QUOTA: owner=UID, path/target пустые, cursor=0, data_len=0. |
|
Права чтения те же, что у STAT/LIST выбранного участника. Ответ data_len=40: |
|
used:u64, limit:u64, reserved:u64, files:u64, directories:u64, LE. |
|
Первые три значения в байтах, последние два — числа объектов. Снимок общий для UID во всех группах. |
|
Не резервирует место и не занимает квитанцию мутации. used может превышать limit |
|
после уменьшения лимита; сервер не выдаёт фиктивный нулевой размер при ошибке учёта. |
|
|
|
Открытие потока — обычный повторяемый запрос с отдельным request_id. cursor связывает |
|
его с DATA/END/CANCEL. Поток определяется group/peer/kind/ID; один ID не может |
|
одновременно обозначать разные открытия. Каждый пакет по-прежнему подписан и зашифрован. |
|
При закрытии/перезапуске router-канала его handles завершаются с IO_ERROR; |
|
байты разных эпох не смешиваются. Возобновление через новую эпоху пока не реализовано. |
|
|
|
Статусы (0..13): OK, ACCESS_DENIED, NOT_FOUND, INVALID_PATH, INVALID_RANGE, |
|
EXISTS, BUSY, STALE, NO_SPACE, IO_ERROR, BAD_PACKET, HASH_MISMATCH, CANCELLED, TIMEOUT. |
|
Мутации COMMIT/MKDIR/RENAME/REMOVE сохраняют успешный ответ на 120 секунд |
|
(64 квитанции); тот же request_id с другим содержимым — BAD_PACKET. |
|
COMMIT дополнительно узнаётся по upload UUID. При заполнении квитанций новая |
|
мутация возвращает BUSY до истечения старых. Клиент повторяет запрос с прежним |
|
request_id раз в 5 секунд, общий срок 120 секунд. Повторы после этого срока |
|
не дают гарантии того же результата; перед новой мутацией требуется STAT. |
|
|
|
Потоки, таймауты и остановка |
|
--------------------------- |
|
|
|
На экземпляр один дисковый pthread с очередью до 64 обычных задач. Сеть, |
|
ACL, таймеры и state machines выполняются в uasync; open/stat/readdir/read/write, |
|
resize/hash/sync/rename/remove/close — в дисковом потоке. GUI только передаёт |
|
команды через bridge и получает события. Нет вызова дискового I/O из callback |
|
таймера. Completion резервируется до постановки задачи; без polling workers. |
|
Локальные файлы transfer и серверное дерево используют тот же дисковый поток. |
|
Для обязательной очистки резервируется отдельная задача до открытия файла. |
|
Обращение к своему серверу доставляется через отдельную ограниченную очередь |
|
call_soon в тот же обработчик, без сетевого канала. ACL и дисковый поток общие; |
|
сетевой recv не принимает unsigned даже при src == self. |
|
|
|
Сервер держит до 64 открытых файлов. Каждый READ/WRITE/BEGIN продлевает idle. |
|
После 10 секунд простоя fd закрывается на очередном дисковом sweep (таймер 1 с); |
|
занятый дисковый поток откладывает sweep до освобождения. Закрытие не публикует |
|
и не удаляет файл. Temp можно открыть заново до истечения upload TTL. |
|
После restart незавершённые temp удаляются; опубликованные файлы остаются. |
|
|
|
Лимиты: 16 клиентских запросов, 32 серверных задания/ответа, 16 временных |
|
загрузок, 16 клиентских и 16 серверных потоков на экземпляр. Каждый поток имеет |
|
кольцо 32 x 8192 байт (256 КиБ); worker обрабатывает до 16 блоков за задачу. |
|
Чтение следующей порции перекрывается с отправкой уже подготовленной. |
|
Все серверные и локальные I/O используют один FIFO worker, без блокировки uasync. |
|
|
|
Отправитель добавляет пакеты, пока send_q router находится под нижним порогом |
|
(сейчас count<=0), затем ждёт etcp_router_on_send_ready. Файловый слой не устанавливает |
|
своё окно inflight и не повторяет DATA; транспортные ACK, retransmit и порядок — router. |
|
Callback отправляет не более 8 блоков за запуск, уступая очередь другим потокам. |
|
Параллельные файлы одного пира разделяют канал и FIFO/round-robin waiters. |
|
|
|
Готовность приёмника проверяется router до доставки следующего seq. Заполненное |
|
кольцо или очередь заданий оставляют пакет в recv_q: rx_seq/ACK не продвигаются. |
|
Освобождение места вызывает отложенный resume; pump отменяется при reset/close. |
|
ACK RECEIVE_BUSY (flags bit0) раз в 100 мс отличает ожидание диска от потери транспорта. |
|
Отправитель приостанавливает новые DATA, а живые busy ACK продлевают таймаут router. |
|
Буфер router ограничен его receive window. Локальная доставка использует такую же |
|
проверку готовности и ограниченный FIFO, а не сеть или отдельные подтверждения. |
|
|
|
При остановке сначала отменяются producers/requests и дожидаются все stream cleanup |
|
continuations; только затем worker освобождает storage. Отмена после уже выполненной |
|
публикации не удаляет опубликованный файл. |
|
|
|
Transfer владеет CM handle до окончания/отмены; DOWN/TIMEOUT handle не освобождает. |
|
quiesce запрещает новые команды, отменяет таймеры, waiter и запросы; destroy |
|
вне callbacks дожидается только своих работ/completions и закрывает дисковый |
|
поток до уничтожения CHAT-групп. Контексты не освобождаются под работающим I/O. |
|
Отмена не прерывает текущий системный I/O или хеширование, а ждёт его completion. |
|
|
|
Desktop |
|
------- |
|
|
|
Контекстное меню канала: Group files. Меню участника: Member files. |
|
Окно: выбор сервера/UID, путь, Up/Refresh, таблица каталогов/файлов, |
|
Upload/Download/New folder/Rename/Delete, прогресс и Cancel transfer. |
|
Чужой UID доступен только для чтения. Автор может быть offline. |
|
Open скачивает в выбранный пользователем локальный файл и открывает его |
|
приложением ОС после завершения. Смена контекста отбрасывает поздние ответы. |
|
Для выбранного UID строка хранилища показывает занято/всего, число файлов/каталогов и резерв текущих загрузок. |
|
Точные байты доступны в tooltip. QUOTA запрашивается отдельно от LIST при выборе |
|
сервера/UID, обновлении каталога, завершении передачи и каждые две секунды видимого окна. |
|
Поздние ответы старого UID/сервера игнорируются. BUSY при стартовом сканировании |
|
сохраняет Loading directory и повторяет LIST через секунду; новый переход отменяет повтор. |
|
|
|
API параллельных передач |
|
----------------------- |
|
|
|
member_files_transfer_start(request, callback, arg) копирует request и возвращает |
|
отдельный mf_transfer* на каждый файл. upload задаёт направление, group/server/owner |
|
выбираются для каждой операции. id=0 выбирает случайный ID; id в callback — фактический. |
|
NULL означает отказ запуска без callback; причина пишется в лог. |
|
max_bytes=0 оставляет прежний лимит; ненулевое значение ограничивает размер файла. |
|
Upload проверяет размер источника до хеширования, download — ответ STAT до открытия |
|
локального temp. STREAM привязан к проверенным размеру/version; превышение — INVALID_RANGE. |
|
|
|
callback(arg, mf_transfer_progress*) получает id/done/total/status/finished. |
|
Прогресс заимствован до возврата callback. done для отправителя означает байты, |
|
принятые router в очередь; успешный finished подтверждает завершение операции, |
|
для upload — публикацию на сервере, для download — публикацию локального файла. |
|
finished приходит ровно один раз, handle к этому моменту уже освобождён; |
|
вызывающий обнуляет свой указатель в callback. member_files_transfer_cancel(handle) |
|
отменяет только этот файл, ждёт его I/O и ставит CANCEL в очередь с backpressure. |
|
Stop сервиса/группы завершает все принадлежащие ему handles. |
|
|
|
Все API/callbacks выполняются в uasync-потоке экземпляра. GUI trampolines используют |
|
тот же API и превращают callback в существующие события прогресса; Qt не делает I/O. |
|
Один локальный файл назначения не может одновременно принадлежать двум download. |
|
|
|
Аватарки пользователей |
|
--------------------- |
|
|
|
Относительный путь avatars/<sha256>.png находится внутри обычного дерева UID: |
|
<корень>/<group>/<UID>/avatars/<sha256>.png. Дополнительного UID в API/пути нет. |
|
Аватарка по умолчанию копируется в каждую группу, где выбранный сервер имеет |
|
подписанную storage-роль. Ссылка каждого канала публикуется только после COMMIT |
|
соответствующей копии; отсутствующий сервер в другом канале не создаёт битую ссылку. |
|
Новое членство обнаруживается через снимки участников и повторяет публикацию. |
|
Между серверами автоматического копирования нет. |
|
|
|
userinfo содержит строковые avatar_server (16 hex цифр) и avatar_file (64 hex SHA256 + .png). |
|
Оба поля отсутствуют при удалённой аватарке. Профиль подписан ключом участника; |
|
смена имени/адресов сохраняет остальные плоские JSON-атрибуты. userinfo ограничен |
|
1024 байтами UTF-8. Merkle, JOIN_INFO_RESP, CHANNEL_INVITE и JOIN_REQUEST используют |
|
длину userinfo:u16 BE вместо прежнего u8. Bootstrap передаёт существующий подписанный |
|
профиль инвайтера, не создавая более свежую запись только с именем. Обе стороны |
|
нужно обновить: обратной совместимости нет. |
|
|
|
Снимок участника CHAT_MEMBER_DISPLAY_SIZE теперь 157 байт: прежние 79 байт, |
|
avatar_server:8LE, avatar_file:69 (с NUL), storage_role:1. storage_role обозначает |
|
подписанную роль сервера, независимо от существующей колонки storage — сетевого |
|
приоритета, который может быть 0 у сервера за NAT. Потребители используют общий |
|
chat_member.h; локальное изменение профиля также вызывает MEMBER_UPDATED. |
|
|
|
В Settings → Profile доступны Upload avatar, выбор storage-сервера, предпросмотр |
|
и Remove avatar. Изменения применяются сразу, независимо от Save других настроек. |
|
Worker проверяет размер входного изображения (до 16 мегапикселей), обрезает центральный |
|
квадрат и сохраняет статический PNG 256×256. Файл ограничен 1 МиБ. Сервер проверяет |
|
каноническое имя/SHA256, размер и запрещает замену под прежним именем и rename |
|
в/из avatars. Файлы и каталог входят в обычные инкрементальные квоты/счётчики. |
|
Прежние версии сохраняются на сервере; владелец может удалить их через файловый браузер. |
|
|
|
AvatarManager общий для списка участников и сообщений, максимум две операции |
|
одновременно, одинаковые хеши не скачиваются параллельно. Изменение своего профиля |
|
имеет приоритет перед фоновыми загрузками. Для DM используются ссылки из общих |
|
каналов; при отсутствии доступной ссылки остаются инициалы. Онлайн-статус списка |
|
отображается отдельной точкой поверх фотографии. Поздний результат старой ссылки |
|
пополняет кеш, но не заменяет картинку новой ссылки. |
|
|
|
Кеш аккаунта: <db_path>/avatar_cache/<local_UID_hex>/<sha256>.png; без db_path |
|
используется Qt AppLocalDataLocation. Проверяются SHA256 и квадратный PNG до 512×512; |
|
превышение/битая картинка не публикуются. Публикация кеша атомарна через QSaveFile, |
|
незавершённые download/part очищаются при старте. Готовые файлы не требуют TTL/STAT: |
|
смена содержимого меняет имя. Дисковый LRU — 100 МиБ, кеш QImage — 32 МиБ; |
|
собственная аватарка и источники незавершённых upload сохраняются при вытеснении. |
|
Дисковое I/O и декодирование выполняются вне GUI/uasync. Повторы неудачных загрузок: |
|
5/10/20/40/80/160 секунд; новая ссылка сбрасывает задержку. RTT/online не меняют ссылку |
|
и не вызывают повторной загрузки. Желаемая собственная ссылка/удаление сохраняются |
|
атомарно одной строкой ui_state.avatar_default, незавершённая публикация повторяется |
|
после запуска при наличии локального источника. |
|
|
|
test_avatars проверяет нормализацию, хеш/размеры, очистку temp, настоящее storage |
|
в двух каналах, публикацию, сохранение при смене имени, DM-кеш, restart без сети, |
|
автоматический download после потери кеша и удаление ссылок. Также проверяются |
|
max_bytes до открытия local temp и смена аватарки при задержанном download старой |
|
версии: поздний результат не заменяет новый рисунок. test_member_adapter проверяет |
|
подписанные профили 191/255/256/512/1023/1024 байт вместе с adm_tags до 8192. |
|
Категория media=debug показывает discovery, cache hit/eviction, направление, |
|
group/owner/server/hash, ошибки проверки и retry; media=info — передачи/публикации. |
|
|
|
Проверки и диагностика |
|
--------------------- |
|
|
|
tests/test_member_files: wire/UTF-8, произвольные блоки, повторы, EOF, версии, |
|
короткая замена, SHA256, пустой файл, независимые квоты UID, общий учёт по группам, |
|
резервирование/повторы/TTL, инкрементальные files/directories, замены пустых файлов, |
|
создание/удаление/rename каталогов, отсутствие runtime-rescan, стартовый scan и его ошибки, ссылки, expiry/restart, 10-секундный |
|
fd idle и принадлежность work/done потокам. |
|
tests/test_member_files_network: настоящие A/B/M, подписанная storage-роль, |
|
параллельные upload/download одного пира, local loopback, пустые файлы, побайтная |
|
проверка, отмена одного handle, restart router и destroy с активным server I/O. |
|
Шестисекундная задержка worker проверяет receive backpressure и busy ACK. |
|
Также проверяются чужая запись, виртуальный корень и подписанное удаление читателя. |
|
QUOTA проверяется на настоящем подписанном/зашифрованном канале; удалённый читатель не получает счётчики. |
|
test_services — stop/start общего чат-сервиса. |
|
Текущая диагностика выделена в категорию debug. Настройка для полного трасса: |
|
[debug] |
|
debug=trace |
|
debug=debug показывает запрос/ответ, ACL, очереди, маршрут, ACK, crypto-решения, |
|
I/O, fd idle и состояние браузера. trace дополнительно показывает каждый |
|
read/write и передачу задач/завершений между дисковым потоком и uasync. |
|
stream progress раз в секунду показывает ID/направление, done/total, число блоков |
|
в кольце, активность I/O, причину ожидания и скорость B/s. Router логирует переходы |
|
receive paused/resumed и peer receive busy без повторного сообщения на каждый блок. |
|
quota scan started/ready показывают путь, число пользователей и время обхода; |
|
quota updated показывает UID/операцию/used/reserved/files/directories; quota exceeded — used/reserved/growth/limit. |
|
По request_id видны GUI post → core request → router seq → server rx → ACL → |
|
disk queued/start/done → response tx → GUI result/bridge → directory ready. |
|
PID создания worker, PID отправки задачи и startup PID позволяют однозначно |
|
обнаружить fork после создания потока; несовпадение PID логируется как ошибка. |
|
Ключи шифрования, plaintext файлов и сырые медиа в debug не выводятся. |
|
Старые VAD/рация/GUI/вложения сообщения перенесены в vad/radio/chat/media/config; |
|
ошибки и пользовательские info остаются в тематических категориях.
|
|
|