docs(member-files): specify wire codec and worker ownership
This commit is contained in:
1 parent
41f0aa2439
commit
f7b064a11a
2 files changed
+38
-10
No files matched your search
@@ -1,4 +1,5 @@
|
||||
/* Файловый протокол участников CHAT-группы. Все числа на проводе little-endian.
|
||||
/* Файловый протокол участников CHAT-группы. Codec не проверяет членство/подпись/шифрование: это делает сервис.
|
||||
* Все числа на проводе little-endian.
|
||||
* Группа и подписанный отправитель приходят от router; owner — UID каталога.
|
||||
* version — непрозрачный снимок объекта, upload — случайный ID временного файла.
|
||||
* Нулевая version в BEGIN означает создание; замена требует version из STAT.
|
||||
@@ -27,6 +28,8 @@ extern "C" {
|
||||
#define MF_AVATAR_MAX_BYTES (1024 * 1024)
|
||||
#define MF_AVATAR_ORIGINAL_MAX_BYTES (32 * 1024 * 1024)
|
||||
#define MF_AVATAR_MANIFEST_MAX_BYTES 4096
|
||||
/* Имя объекта аватарки:64 lowercase hex и .png/.jpg/.webp/.json; вход — NUL-строка, NULL даёт0.
|
||||
* valid/manifest_valid возвращают1/0; file_limit — лимит32MiB для изображения,4096 для JSON,0 при неверном имени. */
|
||||
int mf_avatar_file_valid(const char* file);
|
||||
int mf_avatar_manifest_valid(const char* file);
|
||||
uint64_t mf_avatar_file_limit(const char* file);
|
||||
@@ -48,22 +51,37 @@ enum mf_status {
|
||||
};
|
||||
|
||||
struct mf_message {
|
||||
uint8_t kind, command, type, more;
|
||||
uint16_t status;
|
||||
uint64_t request_id, owner, offset, size, cursor, mtime;
|
||||
uint8_t version[16], upload[16], hash[32];
|
||||
char path[MF_PATH_MAX + 1], target[MF_PATH_MAX + 1];
|
||||
uint32_t data_len;
|
||||
uint8_t data[MF_BLOCK_SIZE];
|
||||
uint8_t kind, command; // MF_REQUEST/RESPONSE и mf_command; group/src берутся отдельно из router.
|
||||
uint8_t type, more; // MF_FILE/DIRECTORY и признак продолжения LIST/READ (0/1).
|
||||
uint16_t status; // mf_status; у запроса всегда MF_OK.
|
||||
uint64_t request_id; // Ненулевой ID одной неизменной команды; у DATA/END/CANCEL — ID потока.
|
||||
uint64_t owner; // UID дерева;0 только для виртуального LIST корня группы.
|
||||
uint64_t offset, size; // Диапазон READ/WRITE/DATA либо полный размер BEGIN/END/STAT.
|
||||
uint64_t cursor; // LIST: число выданных записей; открытие STREAM:ID потока; mutation BUSY:retry_after_tb.
|
||||
uint64_t mtime; // Unix seconds в ответах/записях каталога.
|
||||
uint8_t version[16]; // Непрозрачный снимок объекта; нули BEGIN означают создание.
|
||||
uint8_t upload[16]; // Случайный токен temp/потока; проверяется вместе с group/peer/owner/path.
|
||||
uint8_t hash[32]; // SHA256 полного файла для BEGIN/COMMIT/END.
|
||||
char path[MF_PATH_MAX + 1], target[MF_PATH_MAX + 1]; // NUL-строки; target используется RENAME.
|
||||
uint32_t data_len; // Длина data; фактический предел MF_BLOCK_SIZE, wire использует u16.
|
||||
uint8_t data[MF_BLOCK_SIZE]; // Байты файла, LIST entries или QUOTA, по команде.
|
||||
};
|
||||
|
||||
/* Прочитать/записать ровно8 байт LE; буферы обязательны и имеют достаточный размер. */
|
||||
uint64_t mf_get64(const uint8_t* p);
|
||||
void mf_put64(uint8_t* p, uint64_t value);
|
||||
/* 1 — все n байт нулевые, иначе0. */
|
||||
int mf_zero(const uint8_t* p, size_t n);
|
||||
/* Проверка UTF-8 и переносимых компонентов. Пустой путь допустим только для корня. */
|
||||
/* 1/0: строгий UTF-8, путь<=1024 байт, до60 компонентов по1..255 байт; root_allowed разрешает пустую строку.
|
||||
* Отвергает leading '.', trailing '.'/' ', ASCII C0/DEL, Windows device names и \\: *?"<>| (без разрешения пробела после двоеточия). */
|
||||
int mf_path_valid(const char* path, int root_allowed);
|
||||
/* Записать wire: длина>0 либо-1 при переполнении; выход не меняется при отказе длины.
|
||||
* Проверяет размеры, но не семантику command/ID/path. message/wire обязательны и не перекрываются. */
|
||||
int mf_encode(const struct mf_message* message, uint8_t* wire, size_t capacity);
|
||||
/* 0/-1: проверить формат/точную длину/общие поля и декодировать. При ошибке message может быть изменён.
|
||||
* Невалидный UTF-8/путь и смысл полей отдельных команд проверяет вызывающий сервис/storage. */
|
||||
int mf_decode(const uint8_t* wire, size_t length, struct mf_message* message);
|
||||
/* Заимствованные статические строки; неизвестное значение возвращает Unknown error/UNKNOWN. */
|
||||
const char* mf_status_text(int status);
|
||||
const char* mf_command_text(int command);
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
/* Единственный дисковый поток модуля. submit/done выполняются в uasync, work —
|
||||
* в pthread. Очередь ограничена; completion резервируется до передачи работы.
|
||||
* Для обязательной очистки reserve выполняется до открытия файлов. destroy вне
|
||||
* callbacks ждёт работ и доставляет done, включая поставленные ими cleanup jobs. */
|
||||
* callbacks ждёт работ и доставляет done, включая поставленные ими cleanup jobs.
|
||||
* data/arg заимствованы до done; worker освобождает только собственную оболочку работы.
|
||||
* ua/work/done и worker обязательны; ua живёт до конца destroy. Останавливать worker из done нельзя. */
|
||||
#ifndef MEMBER_FILES_WORKER_H
|
||||
#define MEMBER_FILES_WORKER_H
|
||||
struct UASYNC;
|
||||
struct mf_worker;
|
||||
struct mf_work;
|
||||
typedef void (*mf_work_fn)(void* arg);
|
||||
/* error=0 — work завершён, результат операции находится в data; -1 — обычная задача не принята (синхронно). */
|
||||
typedef void (*mf_done_fn)(void* arg, int error);
|
||||
/* Создать pthread/mutex/condition; возвращает owner либо NULL, без дискового I/O. */
|
||||
struct mf_worker* mf_worker_create(struct UASYNC* ua);
|
||||
/* Резерв оболочки и completion, NULL при OOM. Сам по себе не занимает очередь/не задаёт worker. */
|
||||
struct mf_work* mf_worker_reserve(void);
|
||||
/* Освободить только ещё не переданный в submit_reserved резерв; NULL допустим. */
|
||||
void mf_worker_unreserve(struct mf_work* work);
|
||||
/* До64 обычных задач, включая ожидающие done. При отказе done(-1) синхронно, work не вызывается. */
|
||||
void mf_worker_submit(struct mf_worker* worker, mf_work_fn work, void* data, mf_done_fn done, void* arg);
|
||||
/* Передать резерв worker без проверки лимита64: только обязательные cleanup continuations.
|
||||
* После вызова резерв нельзя освобождать/использовать повторно. FIFO, done ровно один раз. */
|
||||
void mf_worker_submit_reserved(struct mf_worker* worker, struct mf_work* reserved,
|
||||
mf_work_fn work, void* data, mf_done_fn done, void* arg);
|
||||
// После quiesce владельца, вне callbacks: дождаться работ и их cleanup continuations, не останавливая pthread.
|
||||
void mf_worker_drain(struct mf_worker* worker);
|
||||
/* Drain, затем join и освобождение. Работы не прерываются и получают обычный done(0); NULL допустим. */
|
||||
void mf_worker_destroy(struct mf_worker* worker);
|
||||
#endif
|
||||
Reference in new issue
Block a user