-
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