Главная ]
8.Работа с событиями
Программирование
Базы данных



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

 

Функция

Описание

1

isc_event_block()

Создать буфер параметров событий

2

isc_wait_for_event()

Ожидание синхронного события которое будет зарегистрировано

3

isc_que_events()

Установите асинхронное событие и возвратите управление приложению

4

isc_event_counts()

Определите изменение значения счетчика событий в буфере параметров событий

5

isc_cancel_events()

Отказаться от интересующего события

 

Для асинхронных событий, эта глава описывает, как создать асинхронное прерывание (СИНХРОННОЕ СИСТЕМНОЕ ПРЕРЫВАНИЕ), - функцию , которая отвечает на зарегистрированные события.

8.1.Понятие механизма событий

Механизм событий в InterBase состоит из  четырех частей.

-         Ядра InterBase, которое обслуживает очередь событий и уведомляет приложения, когда событие происходит.

-        Буфера параметров событий, созданного приложением, где оно может получать уведомление о событиях .

-          Приложение, которое регистрирует   одно или несколько интересующих определенных, именованных событиями и  ждет уведомление, когда произойдет синхронное событие, или передает указатель на функцию AST, которая обрабатывает уведомления так, чтобы работа приложения могла продолжаться (асинхронное событие).

-         Триггера или хранимой процедуры, которая уведомляет ядро что определенное, именованное событие произошло. Уведомление вызывается POSTING.

Механизм событий InterBase позволяет приложениям отвечать на действия и изменения базы данных, сделанные другими, одновременно выполняющимися  программами без потребности других приложений, для связи непосредственно друг с другом, и без траты ПРОЦЕССОРНОГО ВРЕМЕНИ, требуемого для периодического опроса, чтобы определить произошло событие или нет.

8.2.Буфера параметров событий

Если приложение должно получать уведомление о событиях, оно должно установить два буфера параметров событий одинакового размера (EPBs) используя  isc_event_block (). Первый буфер, event_buffer, используется, чтобы хранить счетчик возникновений события до того как приложение зарегистрирует заинтересованность в событии. Второй буфер, result_buffer, впоследствии заполняется изменениями счетчика возникновений события, когда наступает событие, представляющее интерес для приложения. Вторая функция API, isc_event_counts (), определяет различия между счетчиками в этих буферах, чтобы определить, которое событие или события произошло.

Уведомление о синхронном событии

Когда приложение зависит от возникновения определенного события для обработки, оно должно использовать синхронное уведомление события, чтобы приостановить свое собственное выполнение, пока событие не произойдет. Например, автоматизированное приложение торговли акциями, которое покупает или продает акции, когда происходят определенные изменения цен, оно могло бы начинать выполнение, установив EPB и зарегистрировав свой интерес в соответствующих событиях, а затем приостановить свое  выполнение, пока  изменения цен не происходят .

Isc_wait_for_event () функция обеспечивает синхронную обработку события для приложения.

8.3.Уведомление об асинхронном событии

Приложение должно реагировать на возможные события базы данных, но также и должно продолжать работу не ожидая возникновения события, в таком случае оно должно создать асинхронную функцию (AST) ловушку, и использовать асинхронное уведомление события, чтобы зарегистрировать интерес в событиях при продолжении своей работы. Например, акции, посредничающее приложение требует постоянного доступа к базе данных акций, чтобы позволить брокеру покупать и продавать акцию, но, в то же самое время, оно может  использовать события, чтобы привести в готовность брокера к особенно существенным  изменениям цен.

Isc_que_events () предоставляет асинхронную обработку событий

8.4.Управление событиями в транзакции

События происходят под управлением транзакции и могут поэтому быть подтверждены или откачены назад. Заинтересованные приложения не получают уведомление о событии пока транзакция в которой произошла регистрация события не завершиться подтверждением. Если регистрация события откачена назад, уведомления не происходит.

Транзакция может регистрировать то же самое событие не один раз перед подтверждением, но независимо от того сколько раз событие было зарегистрировано, это расценивается как единственное возникновение события при уведомлении о  событии.

Прежде, чем приложение зарегистрирует интерес в событии, оно должно установить и заполнить два буфера параметров событий (EPBs), один для хранения начальных значений счетчика возникновения события для каждого события  представляющего интерес, и другой для хранения измененных значений счетчика возникновения события. Эти буфера передаются как параметры в несколько API функций событий.

В C, каждый EPB объявлен как указатель на char следующим образом:

char *event_buffer, *result_buffer;

Как только буфера объявлены, isc_event_block () вызывается, чтобы выделить память для них, и заполнить их начальными значениями.

Isc_event_block() также требует по крайней мере двух дополнительных параметров: число событий, к которым приложение регистрирует свой интерес, и для каждого события, строка названия события. Один вызов isc_event_block () может передать 15 строк названий событий. Названия события должны соответствовать названиям событий, зарегистрированных хранимыми процедурами или триггерами. Isc_event_block () выделяет одинаковое количество памяти длякаждого EPB, достаточного, чтобы обработать каждое именованное событие. Она возвращает единственное значение, указывая размер в байтах каждого буфера.

Синтаксис для isc_event_block ():

ISC_LONG isc_event_block(

char **event_buffer,

char **result_buffer,

unsigned short id_count,

.. . );

Например, следующий код устанавливает EPB для трех событий:

#include <ibase.h>;

. . .

char *event_buffer, *result_buffer;

long blength;

. . .

blength = isc_event_block(&event_buffer, &result_buffer, 3,"BORL",

"INTEL","SUN");

.. .

Этот код предполагает, что имеются триггера или хранимые процедуры, определенные для базы данных, которые устанавливают события по имени “BORL”,“INTEL”, и “SUN”.

Приложения, которые должны ответить на больше чем 15 событий, могут делать множественные запросы к isc_event_block (), определяя различные EPB и списки событий для каждого запроса.

После установки EPB и определения событий, представляющих интерес с помощью isc_event_block (), приложение может использовать isc_wait_for_event () чтобы зарегистрировать интерес в этих событиях и приостанавливать свое выполнение, пока одно из событий не произойдет.

ПРИМЕЧАНИЕ: Isc_wait_for_event() не может использоваться в приложениях Microsoft Windows или под любой другой операционной системой, которая не разрешает процессам делать паузу. Приложения на этих платформах должны использовать асинхронную обработку события.

8.5.Синтаксис для isc_wait_for_event():

ISC_STATUS isc_wait_for_event(

ISC_STATUS *status_vector,

isc_db_handle *db_handle,

short length,

char *event_buffer,

char *result_buffer);

Например следующий код устанавливает EPB для трех событий, потом вызывает isc_wait_for_event() чтобы остановить выполнение программы пока одно их событий не произойдет.

#include <ibase.h>;

. . .

char *event_buffer, *result_buffer;

long blength;

ISC_STATUS status_vector[20];

isc_db_handle db1;

. . .

/* Assume database db1 is attached here and a transaction started. */

blength = isc_event_block(&event_buffer, &result_buffer, 3,"BORL",

"INTEL", "SUN");

isc_wait_for_event(status_vector, &db1, (short)blength,

event_buffer, result_buffer);

/* Application processing is suspended here until an event occurs. */

.. .

Как isc_wait_for_event () вызвана, так приложение останавливает обработку, пока одно из требуемых событий не произойдет. Когда событие происходит, приложение обрабатывает результат в следующей исполняемой инструкции после запроса к isc_wait_for_event (). Если приложение ожидает  больше чем одно событие, оно должно использовать isc_event_counts () чтобы определить, какое событие произошло

Один вызов isc_wait_for_event() может ожидать максимум 15событий.

Приложения которым нужно ожидать более чем 15 событий должны в другом вызове продолжать ожидание.

8.6.Продолжение обработки с помощью isc_que_event()

 Isc_que_events () вызывается, чтобы запрашивать асинхронное уведомление о событиях, перечисленных в буфере событий переданного как параметр. После завершения вызова, но перед тем как  любое событие произойдет, управление возвращается приложению , чтобы оно могло продолжать обработку.

Когда требуемое событие произошло, InterBase вызывает асинхронную функцию ловушку(AST) , также переданную как параметр в isc_que_events (), для обработки происшедшего события. СИНХРОННОЕ СИСТЕМНОЕ ПРЕРЫВАНИЕ (AST) - функция или подпрограмма в приложении запроса, единственная цель которого состоит в том, чтобы обработать наступление события для приложения.

Синтаксис для isc_que_events ()

ISC_STATUS isc_que_events(

ISC_STATUS *status_vector,

isc_db_handle *db_handle,

ISC_LONG *event_id,

short length,

char *event_buffer,

isc_callback event_function,

void *event_function_arg);

Event_id - длинный указатель, который используется как дескриптор в последующих запросах к isc_cancel_events() чтобы закончить уведомление о событии. Он должен быть проинициализирован когда передается. Параметр length - это размер event_buffer, который содержит текущий счетчик событий, которые нужно ждать. Event_function - указатель на функцию AST, которую InterBase должна вызывать, когда событие, представляющее интерес произошло.

It is up to the AST function to notify the application that it has been called, perhaps by setting a global flag of somekind. Event_function_arg - указатель на первый параметр, передаваемый AST

8.7.Создание AST

Функция события, event_function, должна быть написана с тремя входными параметрами:

1. Event_function_arg, указывается в вызове isc_que_events (). Обычно это указатель на буфер параметров событий, который должен быть заполнен измененными счетчиками события.

2. Длина  буфера events_list.

3.Указатель на буфер events_list, временный буфер параметров события совершенно сходен с переданным isc_que_events (), исключение для модификаций счетчиков события. Буфер результатов автоматически не модифицируется возникновением события;

 Это происходит до event_function, чтобы скопировать временный буфер events_list в постоянный буфер, который использует приложение.

Буфер результатов автоматически не обновляется при возникновении события; это - до event_function, чтобы копировать временный буфер events_list на более постоянный буфер, который приложение использует.

Event_function также должна разрешить приложению знать, что был вызов, например, устанавливая глобальный флажок.

Образец event_function представлен в следующем примере:

isc_callback event_function

(char *result, short length, char *updated)

{

/* Set the global event flag. */

event_flag++

/* Copy the temporary updated buffer to the result buffer. */

while (length--)

*result++ = *updated++;

return(0);

};

8.8.Полный пример с isc_que_events()

Следующий фрагмент программы иллюстрирует вызов isc_que_events ()  асинхронно ждущей возникновения события. В пределах цикла, она исполняет другую обработку, и проверяет флажок события(возможно установленный указанной функцией события) чтобы определить, когда событие было отмечено. Если событие отмечено, программа сбрасывает флажок события, вызывает isc_event_counts () чтобы определить, какие события были отмечены начиная с последнего вызова isc_que_events (), и вызывает isc_que_events () чтобы инициализировать другое асинхронное ожидание.

#include <ibase.h>

#define number_of_stocks 3;

#define MAX_LOOP 10

char *event_names[] = {"DEC","HP", "SUN"};

char *event_buffer, *result_buffer;

ISC_STATUS status_vector[20];

short length;

ISC_LONG event_id;

int i, counter;

int event_flag = 0;

length = (short)isc_event_block(

&event_buffer,

&result_buffer,

number_of_stocks,

"DEC", "HP", "SUN");

isc_que_events(

status_vector,

&database_handle, /* Set in previous isc_attach_database(). */

&event_id,

length, /* Returned from isc_event_block(). */

event_buffer,

(isc_callback)event_function,

result_buffer);

if (status_vector[0] == 1 && status_vector[1])

{

isc_print_status(status_vector); /* Display error message. */

return(1);

};

counter = 0;

while (counter < MAX_LOOP)

{

counter++;

if (!event_flag)

{

/* Do whatever other processing you want. */

;

}

else

{ event_flag = 0;

isc_event_counts(

status_vector,

length,

event_buffer,

result_buffer);

if (status_vector[0] == 1 && status_vector[1])

{

isc_print_status(status_vector); /*Display error message.*/

return(1);

};

for (i=0; i<number_of_stocks; i++)

if (status_vector[i])

{

/* The event has been posted. Do whatever is appropriate,

such as initiating a buy or sell order.

Note: event_names[i] tells the name of the event

corresponding to status_vector[i]. */

;

}

isc_que_events(

status_vector,

&database_handle,

&event_id,

length,

event_buffer,

(isc_callback)event_function,

result_buffer);

if (status_vector[0] == 1 && status_vector[1])

{

isc_print_status(status_vector); /*Display error message.*/

return(1);

}

} /* End of else. */

} /* End of while. */

/* Let InterBase know you no longer want to wait asynchronously. */

isc_cancel_events(

status_vector,

&database_handle,

&event_id);

if (status_vector[0] == 1 && status_vector[1])

{

isc_print_status(status_vector); /* Display error message. */

return(1);

}

8.9.Определение какое событие произошло с помощью isc_event_counts( )

 Когда приложение регистрирует заинтересованность в множественных событиях и получает уведомление, что событие произошло, дальше оно должно использовать isc_event_counts () чтобы определить, какое событие или события произошли. isc_event_counts () вычитает значения массива event_buffer из значений  массива result_buffer, чтобы определить сколько раз, каждый событие произошло начиная с того момента как приложения зарегистрировали интерес в наборе событий. Event_buffer и result_buffer - переменные, объявленные в приложении, и созданные и инициализированные isc_event_block ().

Разность длякаждого элемента возвращается в массиве состояний ошибок, который передан в isc_event_counts (). Чтобы определить, какие события произошли, приложение должно проверить каждый элемент массива на значения отличные от нуля. Счетчик отличный от нуля указывает число событий зарегистрированных между моментом вызова isc_event_block ()  и моментом времени когда событие было зарегистрировано, после вызовов isc_wait_for_event() или isc_que_events () . Где много приложений обращаются к той же самой базе данных, там определенный счетчик события может быть 1 или больше, и больше чем один элемент счетчика события может быть отличен от нуля.

Обратите внимание Когда первый раз устанавливают AST, чтобы поймать в ловушку события с помощью isc_que_events (), InterBase инициализирует все значения счетчика в статус векторе в 1, а не в 0. Чтобы убрать значения, вызовите isc_event_counts ().

В дополнение к определению которое событие произошло, isc_event_counts () повторно инициализирует массив event_buffer в ожидании другого вызова isc_wait_for_event() или isc_que_events (). Значения в event_buffer установлены в те же самые значения как переданные значения в result_buffer.

Полный синтаксис для isc_event_counts ():

void isc_event_counts(

ISC_STATUS status_vector,

short buffer_length,

char *event_buffer,

char *result_buffer);

Например, следующий код объявляет интерес в трех событиях, ожидает их, затем использует isc_event_counts() чтобы определить какое событие произошло.

#include <ibase.h>;

. . .

char *event_buffer, *result_buffer;

long blength;

ISC_STATUS status_vector[20];

isc_db_handle db1;

long count_array[3];

int i;

. . .

/* Assume database db1 is attached here and a transaction started. */

blength = isc_event_block(&event_buffer, &result_buffer, 3,"BORL",

"INTEL", "SUN");

isc_wait_for_event(status_vector, &db1, (short)blength,

event_buffer, result_buffer);

/* Application processing is suspended here until an event occurs. */

isc_event_counts(status_vector, (short)blength, event_buffer,

result_buffer);

for (i = 0; i < 3; i++)

{

if (status_vector[i])

{

/* Process the event here. */

;

}

}

8.10.Отказ от интереса в асинхронном событии с помощью isc_cancel_events( )

Приложение, которое требовало асинхронное уведомление о событии с помощью isc_que_events () может впоследствии отменять требование уведомления в любое время с помощью isc_cancel_events () используя следующий синтаксис:

ISC_STATUS isc_cancel_events(

ISC_STATUS *status_vector,

isc_db_handle *db_handle,

ISC_LONG *event_id);

Event_id - набор дескрипторов событий в предыдущем вызове isc_que_events(). Например, следующий код отменяет интерес в событии или событиях, идентифицированных event_id:

include <ibase.h>;

. . .

/* For example code leading up to this call, see the code example

in "Continuous Processing with isc_event_que(), earlier in this

chapter. */

isc_cancel_events(status_vector,&db_handle, &event_id);

 

<< Назад ] Главная ] Далее >> ]

 

Дизайн: Piton Alien
Rambler's Top100 Рейтинг@Mail.ru
Сайт создан в системе uCoz