В системе есть объект DBIO (Database User-Intarface Object), которому известны состояния всех транзакций. Этот объект представляет собой множество, элементами которого являются объекты-агрегаты, описывающие контекст транзакции.
Таблица 9: Контекст транзакции
Имя поля | Размер в байтах | Значение |
TR_MESS | 4 | OID сообщения |
TR_KH | 4 | OID knowhow |
TR_PARAM | 4 | OID агрегата с параметрами |
TR_TARGET | 4 | OID целевого объекта сообщения |
TR_RES | 4 | OID результата |
TR_STACK | 4 | OID стека |
TR_N | 4 | Номер транзакции |
TR_HOSTN | 4 | Номер вызвавшей транзакции |
TR_STATUS | 1 | Состояние транзакции |
TR_POINT | 2 | Точка разрыва, в которой находимся |
Для каждой транзакции выделяется свой стек. Механизм сохранения и восстановления стеков описан в [7]. Стеки сохраняются в атомарных объектах.
[] DB.NEW [] -- создать новую БД
[] DB.OPEN [] -- открыть БД
[] DB.CLOSE [] -- закрыть БД
Операции клонирования:
[oid] CLONE [oid'] -- клонировать объект
[] CLONE_ROOT [oid'] -- Создать объект от "Корень"
[int] CLONE_INT [oid'] -- Создать объект "Целое"
["string"] CLONE_STR [oid'] -- Создать объект "Строка"
["string"] CLONE_AGG [oid'] -- Создать объек-агрегат
[oid_if oid_then oid_else]
CLONE_BIO [oid'] -- Создать объект-условие
[] CLONE_SET [oid'] -- Создать объект-множество
[] CLONE_SEQ [oid'] -- Создать объект-последовательность
OIDROOT, OIDINT, OIDAGG, …, OIDSEQ -– Узнать идентификаторы соотв. Объектов
[oid_bhr] SET_BHR [] -- переопределить поведение
[] GET_BHR [oid] -- узнать поведение
[oid_kh] SET_KH [] -- переопределить действие
[] GET_KH [oid] -- узнать действие
[oid] GET_INT [int] -- Получить целое число из объекта-целого
[int oid] SET_INT [] -- Занести целое число в объект-целое
[oid] PRINT_STR [] -- Печатать на экране содержимое строки
["string" oid] SET_STR [] -- Занести строку в объект-строку
[oid_super oid] SUPER+ [] -- наследовать данные из oid_super в oid
[oid] DELOBJ [] -- удалить объект
Операции над множеством:
[oid_el oid] SET+E [] -- добавить элемент в множество
[oid_el oid] SET-E [] -- удалить элемент из множества
[oid_el oid] SET?E [0/1] -- найти элемент в множестве
[oid1 oid] SET+ [] -- объединение
[oid1 oid] SET- [] -- разность
[oid1 oid] SET* [] -- пересечение
Операции над списком:
[oid_el n oid] SEQ+E [] -- добавить элемент в последовательность
[n oid] SEQ-E [] -- удалить n-й элемент из
последовательности
[oid_el oid] SEQ?E [0/n] -- найти позицию в последовательности
[n oid] SEQ?N [0/oid] -- определить oid n-го элемента послед-ти
Операции над агрегатом:
[fid oid_etalon oid] AGG+F [] -- добавить поле к объекту
[fid oid] AGG-F [] -- удалить поле из объекта
[fid oid] ETALON [oid] -- получить идентификатор объекта-эталона
[fid oid] FIELD [oid] -- получить идентификатор
объекта-значения
Операции над объектом-условием:
[oid] GET_BIO
[oid_else oid_then oid_if] -- Получить параметры объекта-условия
[oid_else oid_then oid_if oid]
SET_BIO [] -- Сохранить параметры объекта-условия
Специальные операции:
[oid_str oid] SET_NAMEOBJ [oid] -- именовать объект
[oid_str fid] SET_NAMEFID [fid] -- именовать поле
[oid_str] NAMEOBJ [oid] -- получить идентификатор по имени
[oid_str] NAMEFID [fid] -- получить идентификатор поля по имени
[oid_mess oid_par oid] SEND [] -- послать сообщение объекту
[oid_mess oid_obj] METHOD? [] -- определить идентификатор метода
[oid1 oid] CHIELD [1/0] -- определить, является ли oid1 потомком oid
[oid_kh] RUN_KH [] -- выполнить knowhow
[] NCHAN [chan] -- узнать номер текущего канала
[chan] !NCHAN [] -- переключиться на заданный канал
Операции просмотра:
[oid] JVIEW [] -- просмотр журнала
[] A.VIEW [] -- просмотр адресов объектов в БД
[] Q.VIEW [] -- просмотр очереди
[] IC [] -- просмотр состояния канала
ДССП реализована на множестве компьютерных платформ (VAX, PDP-11, IBM PC, R3000, MC68020, SPARC) и операционных систем (MSDOS, MSDOS-экстендеры, UNIX, RT-11, RSX, OS9, CPM и др.). В данный момент практически закончена разработка ДССП на Си, что обеспечивает перенос этой системы на любую платформу, где есть Си.
Аппаратные средства:
Любая платформа, на которой функционирует ДССП, с объемом оперативной памяти для нужд БД не менее 1 Мб.
Программные средства:
ДССП с диспетчером параллельных процессов (версия 4.42) и Операционная Система.
Разрабатываемая СУООБД может также работать в качестве host-программы на файл-сервере, обрабатывая команды с рабочих станций, поступающие в их персональные ящики на файл-сервере. Ответ рабочие станции получают также через почтовые ящики.
В дальнейшем, могут быть реализованы сетевые протоколы и тогда СУООБД будет являться сервером в клиент-серверных приложениях.
Использование отдельных почтовых ящиков для нескольких параллельно работающих пользователей позволяет возложить на СУООБД функции монитора [6], осуществляющего линеаризацию поступающих запросов к содержимому СУООБД.
LOAD TIMEM
LOAD M0
LOAD M2
LOAD Soms
LOAD CHMS
LOAD SYSOBJS
LOAD M3
LOAD LS_CASH
UNDEF
PROGRAM $KH_VOC
PROGRAM $M0
B16
1000 VALUE TOTMEMLEN
TOTMEMLEN BYTE VCTR MEMORY
: T-1 D -1 ;
: *4 SHL SHL ;
: &0FF 0FF & ;
: <= 1+ < ;
: >= 1- > ;
[20 WORD VCTR CHAN] [каналы. Начиная с 5-го]
VAR NCHAN [Номер текущего канала]
: !NCHAN ! NCHAN ;
5 VALUE NBASECH [Первый не базовый канал]
: GETDATA NCHAN 10 * + CHDATA ;
: PUTDATA NCHAN 10 * + ! CHDATA ;
[Размер заголовка блока в байтах]
FIX VAR HSIZE 10 ! HSIZE
: HSIZE+ HSIZE + ;
[Pred, Next, BusyLen, Len]
1 *4 VALUE ctfPREDADDR
[$M4] [как самодостаточный]
0 VALUE ctLOWCH [Нижний канал.]
[0=Оперативная/1=Дисковая память/2=Журнал/-1=свободен]
1 VALUE ctTEKADR [Логический адрес внутри участка (по данным)]
2 VALUE ctBUSYLEN [Длина фрагмента, занятая данными]
3 VALUE ctLEN [Максимальная допустимая длина данных фрагмента]
4 VALUE ctTEKADR0 [=TEKADR, когда TEKADR стоит на нулевом байте данных фрагм]
5 VALUE ctNEXTADDR [Адрес начала заголовка следующего фрагмента (пф)]
6 VALUE ctPREDADDR [Адрес начала заголовка предыдущего фрагмента (пф)]
7 VALUE ctSYNCADDR [Адрес начала заголовка фрагмента (пф)]
8 VALUE ctCHGCTX [признак изменения контекста]
9 VALUE ct1STLONG [Первое число в канале]
[в начальном блоке в начальном слове данных лежит адрес начала данных]
: LOWCH ctLOWCH GETDATA ; : !LOWCH ctLOWCH PUTDATA ;
: TEKADR ctTEKADR GETDATA ; : !TEKADR ctTEKADR PUTDATA ;
: TEKADR0 ctTEKADR0 GETDATA ; : !TEKADR0 ctTEKADR0 PUTDATA ;
: TEKADR++ TEKADR 1+ !TEKADR ; : !+TEKADR TEKADR + !TEKADR ;
: BUSYLEN ctBUSYLEN GETDATA ; : !BUSYLEN ctBUSYLEN PUTDATA ;
: LEN ctLEN GETDATA ; : !LEN ctLEN PUTDATA ;
: NEXTADDR ctNEXTADDR GETDATA ; : !NEXTADDR ctNEXTADDR PUTDATA ;
: PREDADDR ctPREDADDR GETDATA ; : !PREDADDR ctPREDADDR PUTDATA ;
: SYNCADDR ctSYNCADDR GETDATA ; : !SYNCADDR ctSYNCADDR PUTDATA ;
: CHGCTX ctCHGCTX GETDATA ; : !CHGCTX ctCHGCTX PUTDATA ;
: FSTLONG ct1STLONG GETDATA ; : !FSTLONG ct1STLONG PUTDATA ;
TRAP NOMEMORY NOMEMORY#
: NOMEMORY# ."
No free memory" ;
TRAP OUTDATA OUTDATA#
: OUTDATA# ."
Out of data. " ;
TRAP OUTMEM OUTMEM#
: OUTMEM# ."
Out of memory. " ;
TRAP UNKCH UNKCH#
: UNKCH# ."
Unknown primitive channel:" NCHAN .D CR ;
TRAP O_NOTFND NOTFND#
: NOTFND# ."
Object not found. OID=" . CR ;
[*** Информация по каналу ***]
: IC CR
." NCHAN=" NCHAN .D SP ." LOWCH=" LOWCH .D CR
."SYNCADDR=" SYNCADDR .D SP ."PREDADDR=" PREDADDR .D SP ."NEXTADDR="
NEXTADDR .D CR
." BUSYLEN=" BUSYLEN .D SP ." LEN=" LEN .D CR
." TEKADR0=" TEKADR0 .D SP ." TEKADR=" TEKADR .D CR ;
CHANNEL DATACH "DATA." CONNECT DATACH
PROGRAM $M2
B16 [физическая организация памяти]
[вычисление физического адреса и номера базового канала]
:: : POSIX [addr(i)] NCHAN C NBASECH < BR+ LEAVE [addr nchan] D
GOTO DELTA2 S( NCHAN ) TOLOW POSIX [addr(i-1)] ;
:: : TOLOW LOWCH !NCHAN ;
[Пересчет адреса в адрес нижнего уровня: TEKADR(i) -> TEKADR(i-1)]
:: : DELTA2 SYNCADDR HSIZE + TEKADR TEKADR0 - + ;
:: : IBS EON OUTDATA OUTDATA# LAST?
TEKADR POSIX TEKADR++ S( NCHAN ) !NCHAN BSGOTO
NCHAN BR 0 IBS0 1 IBS1 [2 IBS2] ELSE UNKCH ;
:: : OBS EON OUTDATA OUTDATA# LAST?
TEKADR POSIX TEKADR++ S( NCHAN ) !NCHAN BSGOTO
NCHAN BR 0 OBS0 1 OBS1 [2 OBS2] ELSE UNKCH ;
: LAST? TEKADR BUSYLEN TEKADR0 + = IF0 LEAVE NEXTBLK ;
[переход для базового канала ]
: BSGOTO [ADDR] NCHAN BR 0 BSGOTO0 1 BSGOTO1 [2 BSGOTO2] ELSE UNKCH ;
: BSGOTO0 !TEKADR ;
: BSGOTO1 C !TEKADR HSIZE+ SPOS DATACH ;
[ : BSGOTO2 C !TEKADR HSIZE+ SPOS JOURCH ;]
0 %IF
: ADDR [PARAGRAF OFFSET] + [address] ; [Сейчас пгф=1 байту]
[Для файлов можно сделать неск. файлов и распределить по ним пространство]
%FI
: IBS0 TEKADR HSIZE+ MEMORY &0FF TEKADR++ ;
: IBS1 IB DATACH &0FF TEKADR++ ;
[: IBS2 IB JOURCH &0FF TEKADR++ ;]
: OBS0 &0FF TEKADR HSIZE+ ! MEMORY TEKADR++ ;
: OBS1 &0FF OB DATACH TEKADR++ ; [Запись байта]
[: OBS2 &0FF OB JOURCH TEKADR++ ;] [Запись байта]
:: : GOTO NCHAN NBASECH < BR+ BSGOTO VGOTO ;
: VGOTO TEKADR - @GOTO ;
[Переход по смещению]
:: : @GOTO C BRS @GOTO- D @GOTO+ ;
: @GOTO+ DO @GOTO1+ ;
: @GOTO- NEG DO @GOTO1- ;
: @GOTO1+
EON OUTDATA OUTDATA#
TEKADR TEKADR0 BUSYLEN + =
IF+ NEXTBLK TEKADR 1+ !TEKADR ;
: @GOTO1-
EON OUTDATA OUTDATA#
TEKADR TEKADR0 =
IF+ PREDBLK TEKADR 1- !TEKADR ;
: NEXTBLK CHGCTX IF+ SCTX NEXTADDR NOEXIST? !SYNCADDR RELCTX
TEKADR !TEKADR0 ;
: NOEXIST? [ADDR] C -1 = IF+ OUTDATA [ADDR] ;
[Pred, Next, BusyLen, Len]
:: : LCTX' [UPCH] PUSH TEKADR ILS ILS ILS ILS POP
NCHAN E2 !NCHAN !LOWCH !LEN !BUSYLEN !NEXTADDR !PREDADDR !SYNCADDR
0 !CHGCTX ;
[Грузить параметры канала]
:: : LCTX [newch] LCTX' 0 !TEKADR 0 !TEKADR0 ;
: RELCTX TEKADR0 TEKADR NCHAN SYNCADDR TOLOW GOTO LCTX !TEKADR !TEKADR0 ;
: PREDBLK CHGCTX IF+ SCTX PREDADDR NOEXIST? !SYNCADDR RELCTX
TEKADR BUSYLEN - !TEKADR0 ;
: IBSC [CHAN] S( NCHAN ) !NCHAN IBS ;
: ILSC S( NCHAN ) !NCHAN ILS ;
: OBSC [N CHAN] S( NCHAN ) !NCHAN OBS ;
: IOBSCC [SRC DST] C2 IBSC C2 OBSC ;
: DO_IOBSCC [SRC_CH DST_CH N] S( NCHAN )
C3 !NCHAN 0 GOTO DO IOBSCC [SRC DST] ;
: IWS IBS IBS SWB &0 ;
: ILS IWS IWS SETHI ; [SWW &0]
: OWS C OBS SWB OBS ;
: OLS C OWS SWW OWS ;
[Перейти к конечному блоку]
: GOTOENDBK NEXTADDR -1 = EX+ BUSYLEN TEKADR0 +
NEXTADDR !SYNCADDR RELCTX C !TEKADR0 !TEKADR ;
: GOBOTTOM RP GOTOENDBK BUSYLEN TEKADR0 + GOTO ;
: LENVMEM GOBOTTOM TEKADR [LEN] ; [длина виртуальной памяти]
: LASTADDR SYNCADDR LEN + HSIZE+ ;