Архив рубрики: Статьи Руденко Олега

NAME(File) или File

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

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

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

Возвращаюсь у своему вопросу: необходимо подключиться к серверу Velocis программой на Кларионе.

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

Правильно ли я выбрал формат Dbf. Может, кто предложит что лучше?

Опять-же — для чего «сливаются» данные? Если для дальнейшей работы с ними прямо в этих базах, то — сойдет. Если же предполагается простая закачка данных из этих баз уже в рабочую базу, то в качестве альтернативы я бы предложил рассмотреть простой ASCII-файл.
Чтение из него не медленнее чем из DBF, а то и быстрее. Зато точно не будет никаких сюрпризов, как это бывает при работе с DBF из Клариона. Читать далее

Внутренняя реализация Клариона

Уфф! Разобрался, наконец, с внутренней структурой VIEW.
Теперь можно делать динамические View в любом кол-ве без предварительного описания. И, что самое главное, формировать их структуру «на лету», под конкретную задачу или запрос юзверя!

На днях напишу небольшой класс для реализации этого дела. Будет только одно
ограничение — работать будет ПОКА только с файлами, описанными явно в приложении. Т.е. — как обычно. Класс работы с динамическими файлами пока задерживается — дюже сложная штука «файл»! Намного сложнее GROUP/QUEUE/VIEW вместе взятых. Читать далее

Отследить закрытие потока

>> Самый красивый и универсальный способ, имхо, это — переопределить
>> OLE-хук RTL Клариона:
>> Wsl$OleTermHook
VY> Похоже, это то что надо. А как его переопределить, научи, плиз?

Глобальная секция программы

  MAP
    OleTermHookProc(),TYPE
    MyProcOfEndThread()
    CallOleTermHook(OleTermHookProc _OrigProc),NAME('CallOleTermHook')
    MODULE('')
      CallHookByAddr(LONG _HookAddr),NAME('CallOleTermHook')
    END
  END

GLO:SaveOleTermHook LONG
OleTermHook         LONG,EXTERNAL,DLL(dll_mode),NAME('Wsl$OleTermHook')

Читать далее

А можно ли узнать тип ANY-параметра

AN> вроде этот вопрос уже поднимался, но я не могу найти: можно ли при передаче
AN> в процедуру ANY-параметра определить в процедуре его тип, т.е. чё было было
AN> передано STRING, LONG али ещё чего:

AN> Пример:

AN> SomeProc PROCEDURE(? Param)
AN> code
AN> !вот здесь хочется узнать тип переданного Param и в зависимости от этого
AN> учинить определённые действия

Легально можно узнать только, что переменная, скрытая под ANY, является строкой или нет. Для получения более детальной информации необходимо уже работать непосредственно с самим UFO-обьектом, который скрыт под ANY-оберткой. Проще всего воспользоваться INTERFACE-механизмом и с его помощью использовать методы UFO-обьекта. Уже на протяжении трех версий C50/C55/C60 структура VMT для UFO-обьекта остается неизменной, что позволяет использовать единый INTERFACE для этих версий. Измениться-ли он в будущих версиях — х/з, но хочется надеятся, что нет. Читать далее

Драйвер 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()
НЕ является необходимым. Спокойно можно обойтись и без него.