|
|
|
|
@ -200,7 +200,7 @@ ETCP обеспечивает переповторы, порядок, мульт
|
|
|
|
|
- END — последняя пачка и штатное завершение содержимого источником. |
|
|
|
|
|
|
|
|
|
handle — ненулевой 64-битный ID, назначаемый получателем. |
|
|
|
|
Предлагаемый простой механизм защиты от повторов: возрастающие handles в пределах stream-сессии пира, |
|
|
|
|
Механизм защиты от повторов: возрастающие handles в пределах stream-сессии пира, |
|
|
|
|
новые SUBSCRIBE отправляются по порядку в одной управляющей FIFO. |
|
|
|
|
Номер выделяется непосредственно при постановке нового SUBSCRIBE в эту FIFO, после готовности подключения; |
|
|
|
|
параллельные ожидания NCD/INFO не резервируют номера, которые позже нарушили бы порядок отправки. |
|
|
|
|
@ -518,9 +518,28 @@ Stop/destroy выполняются по правилам ядра, вне callb
|
|
|
|
|
Общий ./check.sh: 144 passed, 0 failed, 0 skipped; proxy/full, burst и load — PASS. |
|
|
|
|
Лог общего прогона: /tmp/stream-service-check.log (107 с). |
|
|
|
|
|
|
|
|
|
[ ] Сетевая выдача: |
|
|
|
|
raw/router IDs, INFO и поколения сессий, 64-битные handles, SUBSCRIBE/RENEW/CLOSED, |
|
|
|
|
собственное владение NCD, REVERSE_REQ, курсоры кольца и общий начальный индекс от первого поставщика. |
|
|
|
|
[+] Сетевая выдача — 11.10.2026: |
|
|
|
|
stream_wire.c/h — big-endian формат, raw ETCP_ID_STREAM=0x07, routed ETCP_RT_ID_STREAM=0x39, |
|
|
|
|
INFO/ACCEPT с границами окна и путём, 64-битные эпохи/handles, отдельная подпись источника на END. |
|
|
|
|
stream_network.c/h — собственный NCD owner пира, общий для его потоков/групп; ожидание его UP, |
|
|
|
|
прямые SUBSCRIBE/ACCEPT/REJECT/DATA/GAP/RENEW/UNSUBSCRIBE/CLOSED/END, routed REVERSE_REQ/CLOSED. |
|
|
|
|
Новые handles назначаются при постановке SUBSCRIBE в общую FIFO; watermark защищает от закрытых/старых запросов. |
|
|
|
|
Первый проверенный DATA с конца устанавливает общий N; прочие latest-выдачи ждут его и запрашивают конкретный N. |
|
|
|
|
Повторный stream_receive_restart отменяет upstream старой попытки, оставляя кольцо/downstream; |
|
|
|
|
старые receive handles отсоединяются и требуют close. Уже сохранённый первый блок также устанавливает новый старт. |
|
|
|
|
DATA копируется из кольца только перед отправкой; пути сохраняются по каждому блоку и проверяются на LOOP. |
|
|
|
|
Все выбранные upstream, прошедшие недостающую пачку, позволяют потребителю выдать явный GAP и продолжить. |
|
|
|
|
END подписывает domain/ключ запуска/последний индекс; нельзя завершить выдачу до прохождения её последнего блока/пропуска. |
|
|
|
|
Период RENEW=2с, аренда=6с, первая попытка=5с; reverse не чаще 1/с в этом сроке. |
|
|
|
|
DOWN/REINIT, потеря членства и закрытие локальной подписки отменяют относящиеся выдачи; |
|
|
|
|
закрытие одной группы/выдачи сохраняет чужое владение транспортом и другие группы на том же пиру. |
|
|
|
|
test_stream_service расширен настоящей цепочкой источник -> relay -> получатель поверх ETCP, |
|
|
|
|
общим индексом, новым bootstrap, FEC 6+2 после снятия двух субпотоков, GAP, LOOP, повторами SUBSCRIBE/reverse, |
|
|
|
|
подписанным END, продлениями/таймаутом аренды и асинхронным REINIT. |
|
|
|
|
Две группы с FEC 6+2 и 1+0 используют один ETCP: истечение выдач первой сохраняет DATA второй. |
|
|
|
|
test_stream_core проверяет wire: все 64 бита, усечения, версии, пути/циклы и размеры. |
|
|
|
|
Оба теста прошли под ASAN/LeakSanitizer с detect_leaks=1 и halt_on_error=1, без ошибок и остатка живых аллокаций. |
|
|
|
|
Логи: /tmp/stream-network-asan-core.log и /tmp/stream-network-asan-service.log. |
|
|
|
|
|
|
|
|
|
[ ] Планировщик отправки и разгрузка: |
|
|
|
|
одна очередь на пира, backpressure, ограничение памяти/возраста, A/D/X/Q, |
|
|
|
|
@ -530,7 +549,36 @@ Stop/destroy выполняются по правилам ядра, вне callb
|
|
|
|
|
пути/защита от циклов, стартовые 32 пробы, дальнейший темп 1/с и полный цикл не чаще 30 с, |
|
|
|
|
постепенный перенос с перекрытием, failover, несколько источников и независимое закрытие на общем ETCP. |
|
|
|
|
|
|
|
|
|
Текущие компоненты включают основу данных, локальный API и Merkle/BGP-интеграцию в CHAT. |
|
|
|
|
Сетевая выдача DATA между stream-экземплярами ещё не подключена: test_stream_service передаёт блоки |
|
|
|
|
во внутренний dispatcher явно, а опции распространяет настоящим Merkle-обменом поверх ETCP. |
|
|
|
|
Следующий этап — raw/router bindings, отдельные NCD-владельцы и REVERSE_REQ, выдачи из кольца с handles/арендой. |
|
|
|
|
Сетевая выдача подключена: stream_receive_open выбирает явного пира/субпоток/позицию, |
|
|
|
|
stream_receive_get_info сообщает handle/прогресс/причину, stream_receive_close снимает только свою выдачу. |
|
|
|
|
Локальная подписка по-прежнему владеет кольцом; receive handle её не заменяет и закрывается отдельно. |
|
|
|
|
Прямой dispatcher в старой части теста сохранён для изолированной проверки FEC и закрытия из callback; |
|
|
|
|
новая часть проверяет реальные сетевые bindings и передачу через relay. |
|
|
|
|
Следующий этап — метрики поставщиков/общей нагрузки, OVERLOAD с подтверждением 500 мс и оптимизатор проб/переноса. |
|
|
|
|
|
|
|
|
|
17. Зафиксированный сетевой формат и пределы первого сетевого этапа |
|
|
|
|
|
|
|
|
|
Все stream-числа на wire — big-endian, без packed-структур и зависимости от host byte order. |
|
|
|
|
Заголовок raw (52 байта): cmd:1, version:1, command:1, subblock:1, |
|
|
|
|
group_id:8, source_node_id:8, source_epoch:8, sender_epoch:8, receiver_epoch:8, handle:8. |
|
|
|
|
INFO_REQ/RESP согласуют sender/receiver epochs; неизвестная receiver_epoch=0 допустима только при начальном INFO_REQ/reverse. |
|
|
|
|
Подписанный routed payload содержит тот же заголовок; его group_id сверяется с реальной группой router, |
|
|
|
|
sender берётся из end-to-end router metadata. DATA через routed service отвергается. |
|
|
|
|
|
|
|
|
|
INFO_RESP/ACCEPT: actual_seq:8, first_available:8, last_available:8, n:1, r:1, block_size:2, |
|
|
|
|
path_count:1, node_ids:8*path_count. В INFO actual_seq — последний доступный, в ACCEPT — фактический старт. |
|
|
|
|
SUBSCRIBE: requested_seq:8; REJECT: reason:1 и для отказа SUBSCRIBE first_available:8,last_available:8. |
|
|
|
|
RENEW: один header handle без payload (каждая кодограмма продлевает один элемент списка). |
|
|
|
|
UNSUBSCRIBE/CLOSED: reason:1. DATA: path_count:1,node_ids:8*path_count,неизменяемый подписанный блок. |
|
|
|
|
GAP: old_cursor:8,next_cursor:8, уведомление включает диапазон [old_cursor,next_cursor). |
|
|
|
|
END: "stream_end":10,group_id:8,source_node_id:8,source_epoch:8,last_seq:8,Ed25519:64 — всего 106 байт. |
|
|
|
|
UINT64_MAX в END означает пустой источник; запрос с конца пустого кольца явно отвергается (нет первого блока). |
|
|
|
|
|
|
|
|
|
Предел пути — 32 узла. Сохраняются только реальные узлы пути; исходный {source} не требует отдельной аллокации. |
|
|
|
|
Память пути отделена от 32-МБ бюджета данных и ограничена числом блоков кольца: |
|
|
|
|
до (8 + 8*32) байт на блок плюс поля индекса и overhead allocator; источнику эта память путей не нужна. |
|
|
|
|
64 stream-пира, 256 активных выдач всего и 64 на пира. Control FIFO — до 128 кодограмм, |
|
|
|
|
каждая не больше 338 байт wire; DATA в ней не хранится. На пира один waiter общего send_input_q, |
|
|
|
|
отправка по освобождению до пустого порога; курсоры downstream обслуживаются round-robin. |
|
|
|
|
Эти пределы задают ограниченную память базовой выдачи. A/D/X/Q, возраст нагрузки и 500-мс OVERLOAD |
|
|
|
|
подключаются следующим этапом; автоматический выбор/перекрытие поставщиков пока не запускаются. |
|
|
|
|
|