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


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


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

Итак, поставлены две задачи для 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г.
Специально для




Начало  Назад  Вперед