Драйвер TPS — прикольно!!!

Все таки решил до конца разобраться с работой процесса транзакции на TPS-драйвере.

Сначала некоторые уточнения и дополнения к предыдущим моим письмам по этой теме.

Во время выполнения оператора COMMIT() физическая запись данных в файлы производится поочередно в порядке, обратном порядку их задания в операторе LOGOUT().

Все это происходит в четыре этапа:

Создается TCF-файл и в него записывается информация о таблицах, участвующих в транзакции. Данные, накопленные в транзакционном буфере, записываются во ВСЕ таблицы в резервные(временные) страницы. Некоторые особенности этих страниц будут описаны ниже. Происходит модификация TCF-файла. В чем она заключается — не разбирался, но это — единственная модификация TCF-файла в рамках транзакции. Очевидно, что при этом записывается информация об окончании этапа N2.
Записи из резервных страниц во ВСЕХ таблицах переписываются в нормальные(постоянные) страницы. Резервные страницы при этом не удаляются. Это произойдет лишь во время закрытия таблиц оператором CLOSE(). Читать далее

Возможна ли замена Driver

BD> Возможно ли поменять Driver файла во время выполнения?
BD> FileXXX{PROP:Driver} =
BD> Почему то не помогает.

Нет, легально не получится. Свойство PROP:Driver ТОЛЬКО возвращает наименование драйвера для данного файла. Но не меняет его.

В принципе, есть два варианта:

  1. использовать библиотеки третьих разработчиков, например, что-то типа MetaDriver.
    Там это сделано через подстановку в качестве драйвера своей «пустышки». А уже в пустышке» они перенаправляют запрос нужному драйверу.
  2. делать это самому, просто меняя в заголовке файла адрес точки входа в нужный драйвер.

Второй вариант, имхо, более предпочтителен. Хотя-бы потому, что использует ТОЛЬКО ЛЕГАЛЬНЫЕ средства самого Клариона.
Нет необходимости в подключении самописных драйверов, которые, к тому-же, необходимо корректировать в зависимости от версии Клриона. Читать далее

TPSFIX

ЧС>> У меня он появлялся в разных местах 🙂
ЧС>> Обычно в корневом каталоге диска «C» или в текущем каталоге для программы
ЧС>> или в каталоге где располагаются базы.
ЧС>> Но, что самое интересное, он был под 5-кой и 4-кой.
ЧС>> Под 55 я его не вижу — видать удаляется, если все нормально…
ЧС>> Попробуй в момент транзакции «грохнуть» прогу — TCF должен остаться,

ЧС>> т.к. транзакция не завершилась. Только не запускай прогу, после того как
ЧС>> грохнеш, — по идее при следующем запуске проги, должен произойти откат базы
ЧС>> и после отката TCF может быть удален драйвером. И опять его не найдешь 🙂
DmVB> Обстановка — именно С55!
DmVB> Грохнул прогу — файла всё одно нету… 🙁
DmVB> И во время её самой (транзакции его тоже нет)… Ни на С, ни возле
DmVB> программы, ни возле таблиц…

DmVB> Переносил базы на локальный диск, полагая, что на сервере включаются
DmVB> другие механизмы — не помогает… (сеть NetWare 4.11)

DmVB> Операционка — Вин2000…. Может, действительно, TCF создаётся только
DmVB> если на уровне ОС транзакции не поддерживаются???

Я как-то разбирался с этим механизмом. До конца, правда, так и не разобрался — время поджимало. Итак, как понятно из темы, разговор идет о драйвере TPS. Читать далее

NAME(File) или File

ОАР>> А вот {PROP:Name} прекрасно возвращает текущее имя файла.

VS> Но вот у {PROP:Name} есть другая проблема (по крайней мере была на C5
VS> и ранних релизах C55) — инициализировать {PROP:Name} нужно перед
VS> каждой «глобальной» операцией типа OPEN/CREATE/BUILD etc
VS> Так что пользовать {PROP:Name} нужно тоже с осторожностью.

Да тут надо просто понимать, как этот механизм работает!
А все довольно просто. Как всегда — дело в трейдовости файлов и в потоках, в которых эти файлы работают. Читать далее

Когда уничтожаешь созданную через NEW() очередь

AP> 3. Когда уничтожаешь созданную через NEW() очередь — обязательно ли перед
AP> DISPOSE делать FREE()? ANY полей — нет, только обычные STRING/LONG итд

Для очередей оператор Dispose() транслируется компилятором в вызов отдельной функции ядра, предназначенной именно для уничтожения очередей. Так как очередь «изнутри» представляет собой обычный обьект (класс), то для его уничтожения вызывается деструктор этого обьекта. А в числе первых операторов этого деструктора стоит вызов «ядренного» эквивалента оператора FREE(). Разница между этими функциями следующая:

Обычный оператор FREE()

вызывает метод-деструктор для объекта — списка записей очереди.
вызывает метод-деструктор для объектов — ключей очереди.
вызывает метод-конструктор для объекта — списка записей очереди.

метод FREE деструктора очереди

выполняет первые два шага обычного оператора FREE().
вызывает методы-деструкторы для вспомогательных объектов очереди.
освобождает ВСЕ занятые при инициализации области памяти.

Так что, как видно, вызов оператора FREE() перед DISPOSE()
НЕ является необходимым. Спокойно можно обойтись и без него.

модификация QUEUE и пр..

AA> А как бы почитать сии дебаты, учитывая, что я позжее подписался на
AA> КлаЛист? 🙂

ВНИМАНИЕ!!!

Все нижесказанное справедливо ТОЛЬКО для C55!
В версии C50 есть некоторые, незначительные, отличия.
Которые, впрочем, запросто могут привести к GPF!
Правда, надо заметить, что эти отличия касаются ТОЛЬКО правильного определения адреса UFO-обьекта, который в C55 определяетя просто через Address(Any).
В C50 необходимо немного «извратиться».
Если кому необходимо именно для С50 — пишите, подскажу.
Что-же касается описания INTERFACE и всех остальных структур, то они идентичны для обеих версий.
Как это работает в C56 — не знаю, нет ее у меня. Читать далее

Кстати, еще о новинках в C55

Здесь уже шел разговор о новых функциях ядра C55.

Вот еще несколько полезных:

  MAP
    MODULE('Clarion RTL')
      GROUP::PutINI(*GROUP _Group,STRING _Section,STRING _INIFileName),NAME('Cla$PUTINIGROUP'),DLL(dll_mode)
      GROUP::GetINI(*GROUP _Group,STRING _Section,STRING _INIFileName),NAME('Cla$GETINIGROUP'),DLL(dll_mode)

      sLen(*STRING _Str),LONG,NAME('Cla$FastClip'),DLL(dll_mode)
      sLen(LONG _Size,LONG _Addr),LONG,NAME('Cla$FastClip'),DLL(dll_mode)
    END
  END

sLen — быстрый вариант определения длины строки STRING. Данная функция быстрее LEN(CLIP(STRING)) ~2 раза. Во-первых, за счет того, что не использует строковый стек, и Во-вторых, для строк длиннее 16 байт использует оригинальный алгоритм с наложением 4-байтной маски из пробелов.

К сожалению, не допускает форму использования (STRING _Str).

Процедуры GROUP::xxx позволяют сохранять/восстанавливать сразу всю группу. Группа автоматически «разворачивается» по полям:

TstGrp  GROUP,PRE(TST)
Name      STRING(60)
Code      LONG
Price     DECIMAL(12,2)
        END

  TST:Name = 'Зубная паста'
  TST:Code = 12345
  TST:Price = 35.00
  GROUP::PutINI(TstGrp,'TstGrp',GLO:stNameINIFile)

запишет в файл GLO:stNameINIFile строки:

[TstGrp]
TST:Name=Зубная паста
TST:Code=12345
TST:Price=35

Копирование элементов очереди в массив

SK> Возник вопрос, а возможно ли копировать значения
SK> из очереди в массив быстрее чем с использование
SK> стандартного оператора GET(Que,Ind)

Вообще-то, не так давно в этом списке уже был подобный вопрос. И ответ на него был вполне определенный — НЕТ. Читать далее

Update

A> c55, clarion
A> Как форма Update — Change узнает, какую запись ей обрабатывать?
A> Как заставить эту форму обрабатывать конкретную нужную мне запись не
A> используя броуз?

Форма «Update» обрабатывает ТЕКУЩУЮ запись Главного файла формы.
Т.е., если в файловой схеме формы, в качестве Primary файла задан, например, файл «Members», то необходимо:

1. Выполнить чтение нужной записи:

   - GET(Members,...)
   - SET(Members) - NEXT(Members)/PREVIOUS(Members)

2. Выставить глобальный флаг операции:

   GlobalRequest=ChangeRecord

3. Вызвать процедуру формы.

Как именно закончилась работа формы (Ok/Cancel) обычно можно через переменную GlobalResponce. «Обычно» — если используешь стандартную форму. В других случаях — зависит от логики разработчика программы.

TPS & SQL

Как-то несколько раз в данной рассылке обсуждались вопросы, связанные с переходом на SQL-базы. И, в частности, всегда довольно бурно обсуждался вопрос о скорости выборок и загрузке сети при использовании SQL-баз и других «локальных» драйверов.

Но, обсуждая все эти вопросы, мы почему-то всегда упускали из виду одну особенность TPS-драйвера, которая ОЧЕНЬ существенно влияет именно на сетевой трафик и, как следствие, на скорость выборки из TPS-таблиц! А именно — информация в TPS-таблицах ВСЕГДА хранится в сжатом виде! И, следственно, по сетке передается именно в сжатом виде. Читать далее