Иcходный текст процессора событий Ultima-S

Как уже отмечалось выше задача об вызове каскада обработчиков событий ложится на процессор событий Ultima-S.

Например, по команде exec @ret=EvProcess 'off',@Class,'',0,1, @UDN,0,0

Процессор событий должен вызвать все обработчики события off (удалить объект) для данного экземпляра @UDN. При этом будут вызываться как обработчики предков, так и перехватчики событий созданные за счет мод событий.

Следует отметить, что хотя идея обработчика событий построенная на анализе заголовков процедур очень проста, но полностью функциональный вариант процессора событий является очень сложным, особенно в системе где срабатываний событий очень много. Ниже приведен упрощенный вариант процессора событий по состоянию декабрь 1996г. Такой вариант вполне приемлим для БД, где презентативная логика (формы объектов) находятся на клиенте. В Ultima-S где потенциально любое дейтсвие влечет за собой каскад срабатывающих обработчиков, что отрицательно сказвается на производительности. Процессор событий Ultima-S прошел длительную оптимизацию. В отличие от приведенного варианта от стал фактически прокси-сервером объектов со следующими технологиями кеширования:

  1. Текущий вариант обращается не в sysobjects, а строит работу через VMT-таблицы (таблицы виртуальных методов)
  2. Процессор событий кеширует результаты работы обработчиков через объектный протокол обмена. Если обработчик не даст команду сбросить кеш для себя, то он не будет вызван, а будет использован его предыдущий результат из кеша.

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

CREATE PROCEDURE EvProcess

@EvName varchar(32), -- имя события E

@ClassName varchar(32), -- название класса T

@ViewMode varchar(32), -- название моды

@Before smallint, -- 1, если есть событие ДО

@After smallint, -- 1, если есть событие ПОСЛЕ, 2 для ViewMode

@p1 integer, @p2 integer, @p3 integer -- параметры

AS

-- рассылка сообщений

declare @cnt int, @Name varchar(32), @PName varchar(32), @ret int, @masterUDN int, @saved int, e @maxpr int

-- формирование таблицы иерархий классов

create table #Hier (Name varchar(24), Lev int)

select @cnt=0

while @ClassName<>NULL and @ClassName<>'' begin

insert into #Hier (Name,Lev) select @ClassName,@cnt

select @ClassName=BasedOn from Class where Name=@ClassName

select @cnt=@cnt+1

end

 

declare H cursor for select Name from #Hier order by Lev

open H

fetch next from H into @Name

while @@FETCH_STATUS <> -1 begin if @@FETCH_STATUS <> -2 begin

-- для данного класса ищем процедуры

declare Pr cursor for select name from sysobjects where (sysstat & 0xf = 4) and type='P' and name like ('%[_]'+@EvName+'[_]'+@Name)

open Pr

fetch next from Pr into @PName

while @@FETCH_STATUS <> -1 begin if @@FETCH_STATUS <> -2 begin

-- для процедур

exec @ret=@PName @p1,@p2,@p3

end fetch next from Pr into @PName end deallocate Pr

end fetch next from H into @Name end deallocate H

GO