Статьи Королевства Дельфи

       

Некоторые решения с применением генераторов.


Раздел Подземелье Магов

Итак, поставлены две задачи для Interbase:

  1. 1. Отслеживать процентовку долго выполняющейся хранимой процедуры.
  2. 2. Прерывать безопасным способом слишком долго выполняющуюся процедуру.
Для задачи 1 потенциально возможны без изменения исходного кода Interbase два решения:
  • а) с применением специально написанных пользовательской функции, передающей "третьему лицу" значение отслеживаемого параметра.
  • б) использование генератора.
Генераторы - уникальные объекты Interbase. Уникальны они тем, что их значение изменяется и без вездесущего COMMIT. Стандартные и нестандартные способы применения генераторов описаны Д. Кузьменко в статье http://ib.demo.ru/DevInfo/generator.htm . Получается, что их можно использовать в качестве глобальных целочисленных переменных сервера. Итак, пусть даны две таблицы CREATE TABLE T1( F1 INTEGER ); CREATE TABLE T2( F1 INTEGER ); Отследить надо процесс перекачивания данных из первой таблицы во вторую. Конечно, этот пример слишком прост, так как для этой цели не обязательно использовать процедуры, перекачать можно простым INSERT-ом. Но на этом простом примере отработаем приемы, которые пригодятся в дальнейшем для отслеживания длительных процедур, выполняющих сложные расчеты и т.д.

Зададим три генератора:

генератор автоинкрементного поля для таблицы 1 CREATE GENERATOR j_gen; SET GENERATOR j_gen to 0;

генератор для процентовки CREATE GENERATOR PROC_gen; SET GENERATOR PROC_gen to 0;

генератор, обозначающий код ошибки (по ходу решаем задачу 2) CREATE GENERATOR error_code_gen; SET GENERATOR error_code_gen to 0;

Определим три процедуры

SET TERM ^ ; /* процедура заполнения таблицы 1 */ CREATE PROCEDURE FILL (x INTEGER) RETURNS (error_code INTEGER) /*Возвращающей код ошибки*/ AS declare variable j integer; BEGIN BEGIN /*Сначала обнулим безопасным способом код ошибки*/ error_code=gen_id(error_code_gen, 0); WHILE (error_code<0) DO error_code=gen_id(error_code_gen, 1); j=0; WHILE (j<x) DO begin /*вот здесь и обрабатывается "событие" ошибки, так как значение генератора доступно и другому пользователю*/ error_code=gen_id(error_code_gen, 0); if (error_code<0) then begin Exit; end /*автоинкремент и вставка*/ j=gen_id(j_gen, 1); INSERT INTO T1(F1) VALUES (:j); end END END ^ /*процедура, процентовка которй отслеживается*/ CREATE PROCEDURE TEST_PROC (x INTEGER) RETURNS (error_code INTEGER) AS declare variable i integer; declare variable j integer; declare variable maxj integer; declare variable f1 integer; BEGIN BEGIN /*Сначала обнулим безопасным способом код ошибки*/ error_code=gen_id(error_code_gen, 0); WHILE (error_code<0) DO error_code=gen_id(error_code_gen, 1); /*Сначала обнулим безопасным способом процентовку*/ i=gen_id(PROC_gen, 0); WHILE (I<>0) DO i=gen_id(PROC_gen, -1); /*Узнаем, чему равно 100%*/ SELECT COUNT(F1) FROM T1 INTO :MAXj; j=0; /*Началась процентовка*/ FOR SELECT F1 FROM T1 INTO :f1 do begin /*вот здесь и обрабатывается "событие" ошибки, так как значение генератора доступно и другому пользователю*/ error_code=gen_id(error_code_gen, 0); if (error_code<0) then begin Exit; end j=j+1; IF (j>(i*maxj/100)) THEN BEGIN /*Еще раз напомним, что значение генератора видно другим пользователям до вездесущего COMMIT-а*/ i=gen_id(PROC_gen, 1); END INSERT INTO T2(F1) VALUES (:f1); END END END ^ /* Процедура-останавливалка. Запускается другим пользователем */ CREATE PROCEDURE MAKE_ERROR (do_error_code INTEGER) /*Задаваемый код ошибки*/ RETURNS (error_code INTEGER) AS BEGIN BEGIN /*Сначала обнулим безопасным способом код ошибки*/ error_code=gen_id(error_code_gen, 0); WHILE (error_code<0) DO error_code=gen_id(error_code_gen, 1); /*Установим значение кода ошибки*/ WHILE (error_code<>do_error_code) DO error_code=gen_id(error_code_gen, -1); END END ^ SET TERM ;^

В архиве приведен подробный пример приложения на Delphi, вызывающего, эти процедуры. Отображается линейка процентовки, которую можно остановить.

Скачать архив (12 K)

Кубанычбек Тажмамат уулу,
30 мая 2001г.
Специально для



Содержание раздела