-
Notifications
You must be signed in to change notification settings - Fork 0
License
kalloc/libqtp
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Платформа Q.
QTP 1.3.0 (UNSTABLE)
(Q-Lang dialect version 2.1 preview)
1. Введение.
(ВНИМАНИЕ!!! ДАННЫЙ РЕЛИЗ СЧИТАЕТСЯ НЕСТАБИЛЬНЫМ И ВЫПУСКАЕТСЯ ТОЛЬКО
ДЛЯ ТЕСТИРОВАНИЯ НОВЫХ ФИЧ ДИАЛЕКТА 2.1. СКОРЕЕ ВСЕГО НЕ ВСЕ ОПИСАННОЕ
ТУТ БУДЕТ РАБОТАТЬ ДО ВЫХОДА РЕЛИЗА 1.4.0, А ЧТО-ТО И ВОВСЕ ИЗМЕНИТСЯ)
(ВНИМАНИЕ!!! Начиная с версии 1.3.0 необходимо инклудить только:
#include <qtp.h>, а линковать к проекту нужно только -lfcgi -lqtp,
библиотека cgix теперь входит в libqtp)
Платформа Q это совокупность программных средств для разработки
CGI-приложений, рассчитанных на высокую нагрузку. В состав платформы входят:
- FastCGI система организации работы CGI-приложений, как отдельных
программ (демонов/сервисов), которые после запуска постоянно
находятся в памяти и обрабатывают приходящие к ним от web-сервера
запросы.
- QTP (или Q-Lang) препроцессор шаблонов, рассчитанных на высокую
нагрузку и оптимизированных для встраивания непосредственно в код
программы.
- CGIX модифицированная версия CGIC, оптимизированная для работы с
FastCGI и QTP (или Q-Lang).
- QCM система динамического кэширования
- QQM система написания плагинов для построения запросов напрямую из
шаблонов. (!!!не реализовано!!!)
- QSM система сессионного движка
Преимущества использования платформы Q:
- Высокая скорость работы приложений.
- Наличие всего необходимого инструментария для быстрого построения
cgi-приложений.
- Возможность post-кэширования обработанных запросов с помощью сохранения
сгенерированного контента в обычные .html файлы.
- Возможность автоматического динамического кэширования (libqcm).
- Возможность получения "Content-Length" для результата работы,
а стало быть возможность использования http-акселераторов на
полную мощность.
- Возможность посылать SQL и подобные запросы напрямую из шаблонов.
(!!!не реализовано!!!)
- Возможность написания плагинов для любых реляционных баз данных.
(!!!не реализовано!!!)
- Система QSM (session manager) позволяет с помощью сессий решать
проблемы с секурной авторизацией.
(!!!реализовано, но не оттестировано!!!)
Некоторые особенности использования платформы Q:
- Необходимо учитывать цикличность работы приложений при работе с памятью.
- Необходимо тщательно продумывать шаблоны и их обработчики в связи со
строгостью синтаксиса.
- Желательно оперативные данные хранить в памяти приложения.
(то есть, не использовать для динамических данных RDBMS)
- Устанавливать соединение с СУБД один раз при старте приложения.
- Необходимо знание языка C на достаточно высоком уровне.
- Необходимо детальное понимание философии QPLATFORM.
2. Синтаксис шаблонов препроцессора QTP.
Сам .qtp скрипт фактически является прокомментированным .html, в
комментариях которого содержится служебная информация для построения
шаблонов (.c и .h)
Синтаксис .qtp довольно прост.Все служебные команды располагаются после
выделенной части .html, чтобы определить ее назначение и обработку. В шаблоне
.qtp должно содержаться фиксированное кол-во proc'едур для совместимости с
шаблонным обработчиком, который пишется на C.
Существует четыре блок-делимитера: proc, loop, execute, extern, intern и query
Синтаксис:
<!-- proc <имя процедуры> [тип параметр 1],[тип параметр 2],...; -->
Делимитер процедуры (обработчик <имя модуля>_<имя_процедуры>_do)
<!-- loop <имя процедуры> [тип параметр 1],[тип параметр 2],...; -->
Делимитер цикла (обработчик <имя модуля>_<имя_цикла>_do)
<!-- extern <имя модуля>_<имя процедуры>; -->
Делимитер внешнего вызова (обработчик <имя модуля>_<имя процедуры>_do
<!-- intern <имя процедуры>; -->
Делимитер внутренней функции (обработчик отсутствует)
<!-- query <имя модуля> <запрос>; -->
Делимитер запроса к базе (!!!НЕ РЕАЛИЗОВАН!!!)
<!-- source <имя файла>; -->
Вставляет #include в генериуемый файл .c
<!-- use <имя модуля>.q; exec <имя процедуры>; -->
Делимитер исполнителя, который может вызывать внешние блоки из <имя модуля>.q
<!-- lib <имя процедуры> [тип параметр 1],[тип параметр 2],...; -->
Делимитер библиотечной функции (используется use/exec)
Описатели блоков-делимитеров ставятся после блока и означают его завершение.
Начало блока находится либо в начале исходного текста, либо после очередного
делимитора.
Внутри блока proc (exec, loop) допустимы следующие операторы:
{var "<format>",<variable>,<variable>...} - вставить переменную (как printf)
{if <expression>}...[{else}]...{/if} - условие (только внутри блока)
{include <file>} - вставить внешний файл (как то header и footer)
Внутри блока query допустимы следующие операторы:
{res <num>} - вставляет порядковый номер результата из запроса
Пример #1:
<!-- proc header char *title; -->
Пример #2:
<!-- loop body char *name,int age,char *sex; -->
Пример #3:
<!-- extern news_head; -->
Пример #4:
<!-- intern head; -->
Пример #5 (не утверждено):
This is Users:
{if isform}
<!-- intern users_begin; -->
Name: {res 1} Age: {res 2}
<!-- query mysql select name,age from users where adminid=12; -->
{else}
No users in this class...
{/if}
<!-- proc userlist int isform; -->
3. Пример проекта.
Назначение QTP - обеспечение максимального удобства программирования
и построения шаблонов. То есть, шаблоны, созданные для QTP легко
просматриваются в браузере как обычный html.
Рассмотрим шаблон:
<HTML>
<HEAD>
<TITLE>Example</TITLE>
</HEAD>
<BODY>
<TABLE>
<!-- intern header; -->
<!-- extern news_body; -->
<TR><TD>Имя: {if name}{var "%s",name}{/if}</TD>
<TD>Возраст: {var "%s",age}</TD></TR>
<!-- proc body char *name,char *age; -->
</TABLE>
</BODY>
</HTML>
<!-- intern footer; -->
Теперь подадим комманду:
qtp -sanketa.qtp -oanketa
Получаем два файла anketa.c и anketa.h:
В файле anketa.c функции, объявленные как extern, соответствуют определенным
в шаблоне proc'едурам с постфиксом _do и префиксом anketa_ (anketa_header_do,
ankeata_body_do, anketa_footer_do) и применяются для описания call-back
обработчиков. Также в шаблоне вызывается внешний шаблонный элемент body из
модуля news: void news_body_do();
При выводе параметра name проверяется его неравенство 0 ({if..)
В файле anketa.h определен порядок парсинга элементов шаблона, а также
объявлены функции, которые нужно вызывать в соответствующих call-back
обработчиках (например, обработчик anketa_header_do() должен оперировать
только функцией заполнения anketa_header, использование кросс-вызова например
функции anketa_footer() будет считаться плохим стилем, хотя работать конечно
будет).
anketa.h:
/* Generated from [anketa.qtp] by QTP (version 1.0rc1) [release candidate] */
void anketa_header ();
void anketa_body (char *name, char *age);
void anketa_footer ();
void anketa();
Пример обработчика:
main.c:
#include <qtp.h>
#include "anketa.h"
// У нас header описан как intern, он не требует обработчика
// void anketa_header_do () {// Обработчик anketa_head
// anketa_header();
// }
void anketa_body_do () { // Обработчик anketa_body
int i; // Рассматривать как пример!
char st1[200],st2[200];
for (i=0;i<20;i++) {
snprintf (st1,200,"user-%d",i);
snprintf (st2,200,"%d",i);
anketa_body (st1,st2); // Заполняем anketa_body(name,age);
}
}
// У нас footer описан как intern, он не требует обработчика
// void anketa_footer_do () { // Обработчик anketa_bottom
// anketa_footer();
// }
int cgiInit () {
// Инициализация FastCGI демона.
return 0;
}
int cgiMain () {
printf ("Content-Type: text/html\n\n");
anketa();
return 0;
}
а также
void news_body() {
...
Тут находится call-back функция шаблона news элемента body
...
}
В результате получаем FastCGI демон, который выводит следующую информацию:
<HTML>
<HEAD>
<TITLE>Example</TITLE>
</HEAD>
<BODY>
<TABLE>
<TR><TD>Имя: user-0</TD><TD>Возраст: 0</TD></TR>
<TR><TD>Имя: user-1</TD><TD>Возраст: 1</TD></TR>
<TR><TD>Имя: user-2</TD><TD>Возраст: 2</TD></TR>
[пропущено несколько строк...]
<TR><TD>Имя: user-18</TD><TD>Возраст: 18</TD></TR>
<TR><TD>Имя: user-19</TD><TD>Возраст: 19</TD></TR>
</TABLE>
</BODY>
</HTML>
4. Параметры запуска препроцессора qtp.
qtp 1.3.0
-h --help Вывод справки по опциям qtp
-V --version Версия протокола и номер релиза.
-sSTR --source=STR Исходный текст шаблона .qtp
-oSTR --out=STR Имя проекта. (по умолч source до первой точки)
-cSTR --out-c=STR Имя результирующего файла .c
(если не указано, то <имя проекта>.c)
-rSTR --out-h=STR Имя результирующего файла .h
(если не указано, то <имя проекта>.h)
-fSTR --file=STR Данная опция применяется для того, чтобы при
отработке шаблона в рабочих условиях вывод
происходил не только на stdout, но и в указанный
файл-дескриптор (FILE *). Опция может быть
указана несколько раз. Применяется для
кэширования результата работы CGI-приложения.
-n --nostd Данная опция отключает вывод на stdout
сгенерированной пары (.c .h). Применяется
для оффлайновой генерации шаблонов, когда вывод
на экран не требуется.
-l --contentlength Выводить Content-Length для каждой итерации
демона.
-i --include=STR Делает #include "%s" в сгенерированный файл .c
-p --prefix=STR Добавляет ко всем функциям префикс
--nocgix Отключает систему cgix.
-u --userarg Добавляет void *userarg к вызову всех процедур
-m --module Определяет модуль в котором искать описания
query плагинов. (идентично --include, но
с добавлением в конец ".h")
5. Использование системы динамического кэширования QCM.
Для того, чтобы начать использовать QCM Вам необходимо собрать
Ваши шаблоны с ключом -f<имя переменной "FILE *">
Далее описываем поведение кэшера, например:
FILE *cachef=NULL; // Обязательно прировнять файл к NULL!
qcm_contentlength_set (size_t разм. внутр. кэша, size_t разм. внеш. кэша);
Определяет размер буферов для работы QTP с Content-Length.
Если буфера не будет хватать, выведется только та часть, которая
поместилась в буфер.
qcm_init(); // Вызывается в самомо начале ТОЛЬКО 1 РАЗ
// Также вызывается, если используется система просчета Content-Length
qcm_dir(char *); // Определяем каталог в котором будет лежать кэш
qcm_contentlength_on(); // Определяет то, что у нас будет выводиться
content-length для закэшированных данных
qcm_contentlength_off(); // Определяет то, что у нас не будет выводиться
content-length для закэшированных данных
Далее:
qcm_checker(параметры в формате printf) выставляется timestamp тестер для
определения устаревания кэша.
qcm_set(char *); // Определяем по какому полю (GET/POST) производить
кэширование (может повторять несколько раз, для определения нескольких
полей.
qcm_set(NULL); // Сбрасывает список кэширования.
qcm_open(параметры в формате printf); // Определяет основное название
файла кэша.
(если вернуло NULL значит сработало кэширование, больше ничего
делать не нужно делаем выход)
возвращенное значение присваивается переменной FILE *, которая определеня
при вызове qtp.
qcm_close (FILE *); // Завершить работы qcm с файлом кэша.
qcm_clear (); // Сбрасывает кэш для группы выбранной qcm_checker()
Задача: Нам нужно кэшировать ленту новостей:
Решение:
FILE *cachef; // Файл кэша (qtp -fcachef - чтобы механизм начал работать)
int cgiInit ()
{
qcm_contentlength_set (500000,65535);
// Устанавливаем размеры внутренних буферов
// Внутренний - 500000, временный - 65535
qcm_contentlength_on (); // Включаем поддержку content-length
qcm_dir("/tmp/cache"); // Выставляем директорию для кэша
qcm_init();
}
int cgiMain ()
{
... // Проверки определили, что мы должны вывести новости
qcm_checker ("lenta%d",lenta_id);
qcm_set (NULL);
qcm_set ("offset"); // для определения имени кэша используем смещение
cachef = qcm_open("lenta%d",lenta_id);
if (!cachef) return 0; // Сработал кэш, ничего делать больше не надо
lenta(); // Вызываем QTP элемент "lenta"
qcm_close (&fl);
... // Проверки определили, что добавилась новая новость
qcm_checker ("lenta%d",lenta_id);
qcm_clear ();
...
}
6. Использование сессий внутри проекта на QTP.
Внутри cgiInit() нужно вызвать qsm_init() если Вы собираетесь использовать
сессии внутри вашего проекта.
qsm_init("<путь к каталогу с сессиями>","<имя группы сессий>",<время жизни>);
время жизни сессий указывается в секундах.
Например:
qsm_init("/tmp/sessions","myproject",1200);
Далее внутри cgiMain() используются следующие функции:
qsm_init_session() // Вставляется до вывода хидеров или во время их вывода
на stdout
qsm_set_param("<имя параметра>","<значение>");// Установить значение параметра.
qsm_get_param("<имя параметра>"); // Запросить значение параметра
Если не найдено, возвращает NULL.
qsm_del_param("<имя параметра>"); // Удалить значение и параметр
Для конкретной группы CGIX приложений всегда автоматически запускается демон,
который производит уборку мусора (удаление устаревших сессий).
(группа определяется во время вызова qsm_init() )
7. Заключение.
- У Вас появились новые идеи?
- Вы нашли ошибку в программе?
- Вы хотите принять участие в разработке платформы Q?
Пишите: [email protected]
About
No description, website, or topics provided.
Resources
License
Stars
Watchers
Forks
Releases
No releases published
Packages 0
No packages published