23 API · прямой вызов внутри процесса (разрешение по адресу через tcc_add_symbol)

Справочник API слоя XServer

Реализованы в едином процессе хоста; скрипты вызывают их напрямую по адресу. Все прочие возможности — символы xrt или расширений; за пределами этой страницы см. групповой индекс xrt.

Запросы топологии (7)

Дисциплина retained lease: xsServerFind возвращает аренду со ссылкой, которую обязан парный xsServerRelease; параметры колбэка перечисления заимствуются только на время колбэка — перед сохранением обязателен xsServerRetain. host дополнительно защищён арендой своего server.

xsServerFind запрос

Найти server по глобально уникальному имени; возвращает retained lease.

XS_ServerInfo* xsServerFind(const char* sName);
Возврат: NULL = не найденВладение: retained, обязателен Release
Пример
XS_ServerInfo* pSrv = xsServerFind("demo");
if ( pSrv != NULL ) {
    /* используем данные топологии ... */
    xsServerRelease(pSrv);
}

xsServerRetain / xsServerRelease запрос

Продлить аренду server / вернуть ссылку. Retain нужен на время жизни соединения и перед сохранением за пределами колбэка перечисления.

XS_ServerInfo* xsServerRetain(XS_ServerInfo* pServer); void xsServerRelease(XS_ServerInfo* pServer);
Парность: на каждый Retain — один ReleaseСмысл: не дать топологии уйти на переработку во время смены поколения

xsHostFind запрос

Найти host по имени внутри server; результат дополнительно защищён переданной арендой server (отдельный release не нужен).

XS_HostInfo* xsHostFind(XS_ServerInfo* pServer, const char* sName);
Предусловие: pServer — аренда, которая у вас естьВозврат: NULL = не найден

xsEnumServers / xsEnumHosts запрос

Перечислить все server / все host одного server. Параметры заимствуются только на время колбэка.

void xsEnumServers(XS_ServerEnumProc procEach, void* pUserData); void xsEnumHosts(XS_ServerInfo* pServer, XS_HostEnumProc procEach, void* pUserData);
Колбэк возвращает: false = прекратить перечислениеЗаимствование: для сохранения вне колбэка нужен Retain
Пример
static bool PrintServer(XS_ServerInfo* pServer, void* pUserData)
{
    printf("server: %s (%s)\n", pServer->Name, pServer->Class);
    return true;   /* продолжаем перечисление */
}
xsEnumServers(PrintServer, NULL);

xsConfigRoot запрос

Возвращает верхнеуровневый Custom из xs.json (всё сверх предустановленных полей) — чтобы приложение читало свои ручки.

xvalue* xsConfigRoot(void);
Владение: retained, нужен xrtValueReleaseСодержимое: непредустановленные поля корневого уровня

Горячая перезагрузка (7)

reload — это задача согласования желаемого состояния, а не синхронная команда. Автомат конечных состояний: ACCEPTED → PREPARING → SUCCEEDED / FAILED / SUPERSEDED / CANCELLED; новое намерение на том же server перекрывает неисполненные старые; предел очереди pending — 64.

xsReloadHostSubmit перезагрузка

Подать намерение перезагрузки одного host (единица публикации — его server).

XS_ReloadId xsReloadHostSubmit(XS_HostInfo* pHost);
Возврат: 0 = не принято; ненулевое = стабильный IDСемантика: асинхронно, опрос через xsReloadQuery

xsReloadServerSubmit перезагрузка

Подать намерение перезагрузки целого server по имени.

XS_ReloadId xsReloadServerSubmit(const char* sName);
Возврат: 0 = не принято

xsReloadAllSubmit перезагрузка

Пакетная транзакция: кандидаты всех server прекомпилируются; любая неудача откатывает всё.

XS_ReloadId xsReloadAllSubmit(void);
Транзакционность: всё или ничего

xsReloadQuery перезагрузка

Опросить конечное состояние намерения; результат несёт отпечаток содержимого Revision и описание цели.

bool xsReloadQuery(XS_ReloadId iId, XS_ReloadResult* pResult);
Поле XS_ReloadResultПояснение
Id / StateID намерения и одно из семи состояний
Revisionотпечаток содержимого неизменяемого входного снимка (при отсутствии конфигурационного входа включает отпечаток скриптов)
Target[160] / Message[256]описание цели и сообщение результата (причина неудачи)
Пример · паттерн управляющего маршрута
XS_ReloadId iId = xsReloadHostSubmit(pHost);
XS_ReloadResult tRes;
if ( iId != 0 && xsReloadQuery(iId, &tRes) )
    printf("reload #%llu: %d\n",
        (unsigned long long)tRes.Id, (int)tRes.State);

xsReloadHost / xsReloadServer / xsReloadAll перезагрузка

bool-совместимые обёртки — сообщают лишь, вернул ли Submit ненулевое значение; конечного состояния не ждут.

bool xsReloadHost(XS_HostInfo* pHost); bool xsReloadServer(const char* sName); bool xsReloadAll(void);
Применение: простые сценарии без отслеживания результата

Таймеры (2)

xsTimerAfter таймер

Одноразовый таймер, привязанный к поколению владельца — смена поколения автоматически гасит таймеры старого; в новый они не выстрелят.

uint64 xsTimerAfter(XS_HostInfo* pOwner, uint32 iMillisecond, XS_TimerProc proc, void* pUserData);
Поток колбэка: поток движкаВозврат: 0 = неудача; ненулевое = ID таймера
Пример
static void OnTick(void* pUserData)
{
    printf("tick: %s\n", (const char*)pUserData);
}
/* в ServiceInit: сработать один раз через 5 с */
(void)xsTimerAfter(pHost, 5000, OnTick, "hello");

xsTimerCancel таймер

Отменить таймер. ID, который уже сработал или погашен сменой поколения, вернёт false.

bool xsTimerCancel(uint64 iTimerId);
Возврат: false = уже не существует

Развёртывание и вложенность (3)

xsAppPath развёртывание

Каталог приложения (исполняемого файла), UTF-8 — совпадает с каталогом конфигурации; якорь разбора относительных путей.

const char* xsAppPath(void);
Владение: статическое заимствование, освобождать не нужно

xsExtensionEnabled развёртывание

Рантайм-проверка: вкомпилировано ли расширение в этот вариант, по имени реестра (= аргументу сборки, как в стартовом баннере и --version). Без учёта регистра; зависимости, подтянутые через requires, тоже видны; неизвестное имя, пустая строка и NULL возвращают ложь без установки ошибки. Компиляционный эквивалент — #ifdef XS_USE_<имя>.

bool xsExtensionEnabled(const char* sName);
Пример
if ( xsExtensionEnabled("sqlite") ) {
    /* в этом хосте есть sqlite — пользуемся напрямую */
    db_open(&db);
} /* не вкомпилировано: идём запасным путём */

xsExtensionCount / xsExtensionName развёртывание

Перечисление расширений, вкомпилированных в этот вариант: count возвращает количество, name — имя по индексу (= аргументу сборки, тот же источник данных, что стартовый баннер и --version). Возвращаемый указатель заимствует статическую константу — действителен всё время жизни процесса, освобождать не нужно; выход за границы возвращает NULL без установки ошибки. В варианте default count равен 0; каждое имя из перечисления, переданное xsExtensionEnabled, даёт истину.

uint32 xsExtensionCount(void); const char* xsExtensionName(uint32 iIndex);
Пример
for ( uint32 i = 0; i < xsExtensionCount(); i++ ) {
    printf("%u: %s
", i, xsExtensionName(i));
}

xsCreateTCC / xsDestroyTCC вложенность

Создать вложенный компилятор с предустановленными путями include/lib и импортом символов — фундамент системы плагинов на уровне приложения.

TCCState* xsCreateTCC(void); void xsDestroyTCC(TCCState* pTcc);
Предустановки: заголовки SDK из VFS + таблица символов хостаВарианты: символы расширений тоже доступны

Передача состояния (1)

xsSwapTake передача

Действует только в ServiceInit нового поколения: забрать снимок, экспортированный ServiceSwap старого. Нет данных передачи — NULL.

xvalue* xsSwapTake(XS_HostInfo* pHost);
Окно: только ServiceInit нового поколенияВладение: забрали — ваше; освобождение через xrtValueRelease
Пример · контрактный паттерн
static void ServiceInit(XS_HostInfo* pHost)
{
    xvalue* pState = xsSwapTake(pHost);
    if ( pState != NULL ) {
        G_iCounter = xrtValueInt64(
            xrtValueObjectGet(pState, "counter"));
        xrtValueRelease(pState);   /* забрали — освобождаем сами */
    }
}