Пример генерации транспортных методов и типов

21 мая 2024

ID transport_code_overview

При сборке решения компилятор NK на основе EDL-, CDL- и IDL-описаний генерирует набор специальных методов и типов, упрощающих формирование, отправку, прием и обработку IPC-сообщений.

В качестве примера рассмотрим класс процессов Server, предоставляющий службу FS, которая содержит единственный метод Open():

Server.edl

entity Server

/* OpsComp - именованный экземпляр компонента Operations */

components {

OpsComp: Operations

}

Operations.cdl

component Operations

/* FS - локальное имя службы, реализующей интерфейс Filesystem */

endpoints {

FS: Filesystem

}

Filesystem.idl

package Filesystem

interface {

Open(in string<256> name, out UInt32 h);

}

На основе этих описаний будут сгенерированы файлы Server.edl.h, Operations.cdl.h, и Filesystem.idl.h содержащие следующие методы и типы:

Методы и типы, общие для клиента и сервера

  • Абстрактные интерфейсы, содержащие указатели на реализации входящих в них методов.

    В нашем примере будет сгенерирован один абстрактный интерфейс – Filesystem:

    typedef struct Filesystem {

    const struct Filesystem_ops *ops;

    } Filesystem;

    typedef nk_err_t

    Filesystem_Open_fn(struct Filesystem *, const

    struct Filesystem_Open_req *,

    const struct nk_arena *,

    struct Filesystem_Open_res *,

    struct nk_arena *);

    typedef struct Filesystem_ops {

    Filesystem_Open_fn *Open;

    } Filesystem_ops;

  • Набор интерфейсных методов.

    При вызове интерфейсного метода в запросе автоматически проставляются соответствующие значения RIID и MID.

    В нашем примере будет сгенерирован единственный интерфейсный метод Filesystem_Open:

    nk_err_t Filesystem_Open(struct Filesystem *self,

    struct Filesystem_Open_req *req,

    const

    struct nk_arena *req_arena,

    struct Filesystem_Open_res *res,

    struct nk_arena *res_arena)

Методы и типы, используемые только на клиенте

  • Типы прокси-объектов.

    Прокси-объект используется как аргумент интерфейсного метода. В нашем примере будет сгенерирован единственный тип прокси-объекта Filesystem_proxy:

    typedef struct Filesystem_proxy {

    struct Filesystem base;

    struct nk_transport *transport;

    nk_iid_t iid;

    } Filesystem_proxy;

  • Функции для инициализации прокси-объектов.

    В нашем примере будет сгенерирована единственная инициализирующая функция Filesystem_proxy_init:

    void Filesystem_proxy_init(struct Filesystem_proxy *self,

    struct nk_transport *transport,

    nk_iid_t iid)

  • Типы, определяющие структуру фиксированной части сообщения для каждого конкретного метода.

    В нашем примере будет сгенерировано два таких типа: Filesystem_Open_req (для запроса) и Filesystem_Open_res (для ответа).

    typedef struct __nk_packed Filesystem_Open_req {

    __nk_alignas(8)

    struct nk_message base_;

    __nk_alignas(4) nk_ptr_t name;

    } Filesystem_Open_req;

    typedef struct Filesystem_Open_res {

    union {

    struct {

    __nk_alignas(8)

    struct nk_message base_;

    __nk_alignas(4) nk_uint32_t h;

    };

    struct {

    __nk_alignas(8)

    struct nk_message base_;

    __nk_alignas(4) nk_uint32_t h;

    } res_;

    struct Filesystem_Open_err err_;

    };

    } Filesystem_Open_res;

Методы и типы, используемые только на сервере

  • Тип, содержащий все службы компонента, а также инициализирующая функция. (Для каждого компонента сервера.)

    При наличии вложенных компонентов этот тип также содержит их экземпляры, а инициализирующая функция принимает соответствующие им инициализированные структуры. Таким образом, при наличии вложенных компонентов, их инициализацию необходимо начинать с самого вложенного.

    В нашем примере будет сгенерирована структура Operations_component и функция Operations_component_init:

    typedef struct Operations_component {

    struct Filesystem *FS;

    };

    void Operations_component_init(struct Operations_component *self,

    struct Filesystem *FS)

  • Тип, содержащий все службы, предоставляемые сервером непосредственно; все экземпляры компонентов, входящие в сервер; а также инициализирующая функция.

    В нашем примере будет сгенерирована структура Server_entity и функция Server_entity_init:

    #define Server_entity Server_component

    typedef struct Server_component {

    struct : Operations_component *OpsComp;

    } Server_component;

    void Server_entity_init(struct Server_entity *self,

    struct Operations_component *OpsComp)

  • Типы, определяющие структуру фиксированной части сообщения для любого метода конкретного интерфейса.

    В нашем примере будет сгенерировано два таких типа: Filesystem_req (для запроса) и Filesystem_res (для ответа).

    typedef union Filesystem_req {

    struct nk_message base_;

    struct Filesystem_Open_req Open;

    };

    typedef union Filesystem_res {

    struct nk_message base_;

    struct Filesystem_Open_res Open;

    };

  • Типы, определяющие структуру фиксированной части сообщения для любого метода любой службы конкретного компонента.

    При наличии вложенных компонентов эти типы также содержат структуры фиксированной части сообщения для любых методов любых служб, включенных во все вложенные компоненты.

    В нашем примере будет сгенерировано два таких типа: Operations_component_req (для запроса) и Operations_component_res (для ответа).

    typedef union Operations_component_req {

    struct nk_message base_;

    Filesystem_req FS;

    } Operations_component_req;

    typedef union Operations_component_res {

    struct nk_message base_;

    Filesystem_res FS;

    } Operations_component_res;

  • Типы, определяющие структуру фиксированной части сообщения для любого метода любой службы конкретного компонента, экземпляр которого входит в сервер.

    При наличии вложенных компонентов эти типы также содержат структуры фиксированной части сообщения для любых методов любых служб, включенных во все вложенные компоненты.

    В нашем примере будет сгенерировано два таких типа: Server_entity_req (для запроса) и Server_entity_res (для ответа).

    #define Server_entity_req Server_component_req

    typedef union Server_component_req {

    struct nk_message base_;

    Filesystem_req OpsComp_FS;

    } Server_component_req;

    #define Server_entity_res Server_component_res

    typedef union Server_component_res {

    struct nk_message base_;

    Filesystem_res OpsComp_FS;

    } Server_component_res;

  • Dispatch-методы (диспетчеры) для отдельного интерфейса, компонента или класса процессов.

    Диспетчеры анализируют полученный запрос (значения RIID и MID), вызывают реализацию соответствующего метода, после чего сохраняют ответ в буфер. В нашем примере будут сгенерированы диспетчеры Filesystem_interface_dispatch, Operations_component_dispatch и Server_entity_dispatch.

    Диспетчер класса процессов обрабатывает запрос и вызывает методы, реализуемые этим классом. Если запрос содержит некорректный RIID (например, относящийся к другой службе, которой нет у этого класса процессов) или некорректный MID, диспетчер возвращает NK_EOK или NK_ENOENT.

    nk_err_t Server_entity_dispatch(struct Server_entity *self,

    const

    struct nk_message *req,

    const

    struct nk_arena *req_arena,

    struct nk_message *res,

    struct nk_arena *res_arena)

    В специальных случаях можно использовать диспетчеры интерфейса и компонента. Они принимают дополнительный аргумент – ID реализации интерфейса (nk_iid_t). Запрос будет обработан только если переданный аргумент и RIID из запроса совпадают, а MID корректен. В противном случае диспетчеры возвращают NK_EOK или NK_ENOENT.

    nk_err_t Operations_component_dispatch(struct Operations_component *self,

    nk_iid_t iidOffset,

    const

    struct nk_message *req,

    const

    struct nk_arena *req_arena,

    struct nk_message *res,

    struct nk_arena *res_arena)

    nk_err_t Filesystem_interface_dispatch(struct Filesystem *impl,

    nk_iid_t iid,

    const

    struct nk_message *req,

    const

    struct nk_arena *req_arena,

    struct nk_message *res,

    struct nk_arena *res_arena)

Вам помогла эта статья?
Что нам нужно улучшить?
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!
Спасибо за ваш отзыв, вы помогаете нам становиться лучше!