Форум » LetoDB, HbNetio. » Leto DB Server (продолжение 8) » Ответить

Leto DB Server (продолжение 8)

Pasha: Немного доработал документацию к letodb

Ответов - 273, стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 All

Andrey: Pasha пишет: Немного доработал документацию к letodb Спасибо.

alex_II: Использую CDX Если в индексом выражении используется фунция Doy(), получаю ошибку: Error LETO/1001 Неизвестная функция: e:\Sou.may\Letodb\Data\letomay\oplata INDEX ON Doy(dtopl) TO oplata

Pasha: alex_II пишет: Если в индексом выражении используется фунция Doy(), получаю ошибку: DOY - это функция из ct. Сервер естественно собран без этой функции, как и без любых других специфических функций, которые могут встречаться в индексных выражениях. Добавьте в source\server.prg строку: request doy В этой строке перечислите все необходимые Вам функции, и пересоберите сервер. В скрипт сборки сервера (letodb.hbp) в этом случае необходимо будет включить библиотеку hbct, и (возможно) другие сторонние библиотеки: -lhbct


alex_II: Спасибо, буду пробовать

alex_II: Библиотеку hbct подключил подправив файл makefile.bc и всё заработало. Через скрипт сборки сервера letodb.hbp не хватило тяму. Pasha можно пример на пальцах в студию?

Pasha: alex_II пишет: Pasha можно пример на пальцах в студию? Сделайте батник сборки: set path=%path%;d:\bcc55\bin \harbour\bin\win\bcc\hbmk2 letodb.hbp \harbour\bin\win\bcc\hbmk2 rddleto.hbp или set path=%path%;d:\mingw32\bin \harbour\bin\win\mingw\hbmk2 letodb.hbp \harbour\bin\win\mingw\hbmk2 rddleto.hbp или set path=%path%;d:\mingw64\bin \harbour\bin\win\mingw64\hbmk2 letodb.hbp \harbour\bin\win\mingw64\hbmk2 rddleto.hbp

alex_II: Пардон, но я имел ввиду другое Как в файле letodb.hbp описывать дополнительные библиотеки Ниже приведено содержимое этого файла -inc -obin/letodb -iinclude -n -w -q0 -es2 #-warn=max -prgflag={unix}-D__LINUX_DAEMON__ -prgflag={unix}-D__LINUX__ #-prgflag={win}-D__WIN_DAEMON__ -prgflag={win}-D__WIN_SERVICE__ -cflag={allmsvc}-D_CRT_SECURE_NO_DEPRECATE -cflag={win}-D__WIN_SERVICE__ -gui -mt source/server/server.prg source/server/errorsys.prg source/server/errint.c {unix}source/server/leto_lnx.c {win}source/server/leto_win.c source/server/letoacc.c source/server/letovars.c source/server/letofunc.c source/server/leto_2.c source/common/blowfish.c source/common/common_c.c #source/common/hbip.c source/common/common.prg

Pasha: Просто добавить строку: -l<имя библиотеки> в произвольное место этого скрипта, лучше перед списком модулей

alex_II: Понял, спасибо

AlexMyr: варнинги... ../../../../source/client/leto1.c:1816:24: warning: 'pData' may be used uninitialized in this function [-Wuninitialized] ../../../../source/client/leto1.c:1829:12: warning: 'uiKeyLen' may be used uninitialized in this function [-Wuninitialized] ... ../../../../source/server/letofunc.c:6110:10: warning: 'pArea' may be used uninitialized in this function [-Wuninitialized] Инфа: Letodb /* $Id: Changelog,v 1.350.2.68 2012/06/22 14:17:23 ptsarenko Exp $ */ Harbour Version: Harbour 3.2.0dev (Rev. 17728) Compiler: MinGW GNU C 4.6.2 (32-bit) Platform: Windows XP 5.1.2600 Service Pack 3

Pasha: AlexMyr пишет: варнинги... ../../../../source/client/leto1.c:1816:24: warning: 'pData' may be used uninitialized in this function [-Wuninitialized] ../../../../source/client/leto1.c:1829:12: warning: 'uiKeyLen' may be used uninitialized in this function [-Wuninitialized] ... ../../../../source/server/letofunc.c:6110:10: warning: 'pArea' may be used uninitialized in this function [-Wuninitialized] Да я эти варнинги знаю давно, не знаю как их убрать. Компилятор не может раскрутить сложную логику, и видит неинициализированные переменные, хотя по алгоритму они инициализируются в любом случае. А рабочий алгоритм переписывать не хочется. Я кое-что поправил для custom-индексов, вызовы OrdKeyAdd, OrdKeyDel

Pasha: У меня есть предложение к уже использующим letodb. Прочтите документацию (readme.txt), какая она есть в нынешнем виде, и попробуйте в ней что-нибудь дополнить. Может быть, там не отражен какой-то момент, который был существенным для вас. Можно дополнить какой-либо раздел, или создать новый. Это было бы полезно тем, кто только планирует использовать этот продукт. Выкладывать можно сюда. На русском или английском языке.

AlexMyr: 1. Пункт 2.5 (readme.txt) гласит, что при сборке letodb можно собрать и тесты опция -target, НО для этого нужен файл hbmk.hbm в папке letodb с таким содержимым: rddleto.hbc без этого файла тесты не соберутся. 2. Нужно добавить, что letodb для windows может быть собран в двух вариантах - 1) служба, 2) демон (процесс). И по умолчанию letodb собирается как служба, из чего вытекает, что letodb надо установить как службу, и потом ее запустить.

AlexMyr: 3. 5. Соединение с сервером клиентских программ Чтобы сконнектиться с сервером, прежде всего необходимо прилинковать rddleto.lib (Windows) или librddleto.a (Linux) к своему приложению ... предлагаю упростить: Чтобы сконнектиться с сервером, прежде всего необходимо прилинковать библиотеку rddleto к своему приложению ...

Pasha: Спасибо, добавил в доку. Меня удивило, что сервер еще можно собрать как демон под Windows. Сам я это не делал, с тех пор как была добавлена поддержка службы.

alex_II: Не могу переименовать файл В ini-файле сервера указан путь: DataPath = e:\Sou.may\Letodb\Data В программе указан путь: Path_Dbf := '//localhost:2812/LetoMay/' Leto_Frename(Path_Dbf+'zar1.dbf', Path_Dbf+'zar3.dbf') возвращает -1 Leto_Frename(Path_Dbf+'zar1.dbf', 'zar3.dbf') отрабатывает и переносит файл на уровень вверх в папку Data

AlexMyr: alex_II пишет: Не могу переименовать файл Читаем readme.txt или readme_rus.txt п.5, из последнего выдержка: Если задан параметр 'DataPath' в конфигурационном файле сервера, и он имеет непустое значение, необходимо указывать не полный путь к файлу на сервере, а путь относительный ( относительно значению 'DataPath' ). Например, если необходимо открыть файл test.dbf, который расположен на сервере 192.168.5.22 в каталоге /data/mydir и значение параметра 'DataPath' ( в файле конфигурации сервере letodb.ini ) '/data', синтаксис должен быть таким: USE "//192.168.5.22:2812/mydir/test" Если сервер не запущен или Вы указали неверный путь, будет сгенерирована ошибка открытия. Возможно проверить доступность сервера перед открытием файлов вызовом функции leto_Connect( cAddress ), которая вернет -1 в случае неудачной попытки: IF leto_Connect( "//192.168.5.22:2812/mydir/" ) == -1 Alert( "Can't connect to server ..." ) ENDIF Я думаю тут все ясно.

alex_II: Ничего не ясно Переменная Path_Dbf := '//localhost:2812/LetoMay/' как раз и описывает относительный путь и цитирование лишний раз файла readme понимания ситуации не добавляет. Если я неверно описываю путь доступа к файлу, почему тогда без ошибок отрабатывают другие функции: Leto_File(Path_Dbf+'zar.dbf') Leto_Ferase(Path_Dbf+'zar.dbf') ?

AlexMyr: alex_II пишет: и цитирование лишний раз файла readme понимания ситуации не добавляет. потому как мало кто его читает Дайте самодостаточный пример и конкретно где лежат файлы из Вашего поста выше не ясно

Pasha: alex_II пишет: Не могу переименовать файл В ini-файле сервера указан путь: DataPath = e:\Sou.may\Letodb\Data В программе указан путь: Path_Dbf := '//localhost:2812/LetoMay/' Leto_Frename(Path_Dbf+'zar1.dbf', Path_Dbf+'zar3.dbf') возвращает -1 2-й параметр надо указывать без строки коннента, т.е: Path_Srv := '//localhost:2812' Path_Dbf := '/LetoMay/' Leto_Frename(Path_Srv + Path_Dbf+'zar1.dbf', Path_Dbf+'zar3.dbf') Leto_Frename(Path_Dbf+'zar1.dbf', 'zar3.dbf') отрабатывает и переносит файл на уровень вверх в папку Data Так и должно быть, поскольку все файловые операции на сервере выполняются относительно DataPath

AlexMyr: Паша, эти нюансы тоже хорошо бы в readme* описать.

Pasha: AlexMyr пишет: Паша, эти нюансы тоже хорошо бы в readme* описать. Согласен, напишу

AlexMyr: Паша, предлагаю адаптировать к harbour доке: [pre2] /* $DOC$ * $TEMPLATE$ * Function * $NAME$ * LETO_FRENAME( ) * $CATEGORY$ * * $SUBCATEGORY$ * * $ONELINER$ * Renames a file * $SYNTAX$ * LETO_FRENAME( cFileName, cFileNewName ) --> -1 if failed * $ARGUMENTS$ * <cFileName> Old filenarne to he changed * <cFileNewName> New filename * $RETURNS$ * <nSuccess> If sucessful, a 0 will be returned otherwise, * a -1 will be returned. * $DESCRIPTION$ * This function renames the specified file <cFileName> to <cFileNewName>. * If the file specified in <cNewFile> exists or the file is open, * the function will be unable to rename the file. If the function * is unable to complete its operation,it will return a value of -1. * If it is able to rename the file, the return value for the function * will be 0. A call to LETO_FERROR() function will give additional infor- * mation about any error found. * $EXAMPLES$ * nResult := LETO_FRENAME( "x.txt", "x1.txt" ) * IF nResult < 0 * ? "File could not be renamed." * ENDIF * $STATUS$ * R * $COMPLIANCE$ * * $FILES$ * Library is letodb * $SEEALSO$ * LETO_FERASE(),LETO_FERROR(),LETO_FILE() * $END$ */[/pre2]

Pasha: AlexMyr пишет: Паша, предлагаю адаптировать к harbour доке: Принципиальных возражений конечно нет, но... это же надо все сделать, а когда - не знаю. А делать надо к тому же в 2-х экземплярах. Это мне еще повезло, что я португальского не знаю, а то пришлось бы 3-й экземпляр доки поддерживать.

AlexMyr: Pasha пишет: Принципиальных возражений конечно нет, но... это же надо все сделать, а когда - не знаю. Так как спешки большой нет, то я могу взять на себя эти ф-ии LETO_FERASE(),LETO_FERROR(),LETO_FILE(), сделаю diff файл и выложу, потом внесем правки если надо. Может тогда уже в отдельный файл затолкать letofile.txt?

Pasha: AlexMyr пишет: Так как спешки большой нет, то я могу взять на себя эти ф-ии LETO_FERASE(),LETO_FERROR(),LETO_FILE(), сделаю diff файл и выложу, потом внесем правки если надо. Может тогда уже в отдельный файл затолкать letofile.txt? Да спешки конечно нет. Можно создать в проекте папки doc\en, doc\ru, и туда выкладывать описание функций по разделам, примерно как это сделано в contrib\hbct\doc, файловые функции как раз пойдут в letofile.txt А в readme оставить краткий перечень функций Жаль, что А.Кресин не откликается, добавил бы вас в девелоперы. Я ему кстати в феврале писал, и даже получил от него ответ, но только один раз, больше он не отвечал.

AlexMyr: Pasha пишет: Жаль, что А.Кресин не откликается в hwgui он появился в 06.06.2012, внес изменения о снова молчит.

Pasha: Выложил пример LetoDB COM сервера: utils\olelsrv letosrv может использоваться для доступа к LetoDB из любых приложений, не только из харбора. Пока, конечно, это только "зародыш", а не полноценный сервер. Его еще надо нагрузить методами. Да и не со всем я еще разобрался, почему-то не работает метод OnError для непосредственного доступа к полям.

AlexMyr: Неприятная ситуация снова (пропали данные в базе), уже писал про нее, сейчас повторилась - суть следующая, letodb крутится на win98 (круглосуточно), там же запущена прога, к-я собирает данные с весов и записывает в базу, в какой-то момент комп завис, перезагрузка, и из базы пропали данные до даты когда последний раз перезапускалась прога, а прогу перезапускал 26.06.2012, и получилось что с 04.07 по 26.06 данных нету. Вот кусок кода где записываю в базу[pre2] leto_BeginTransaction() dbAppend() field -> res_str := res_vagy field -> res_date := Date() field -> res_time := Time() field -> res_vaga := nVaga leto_CommitTransaction()[/pre2] может что надо дописать? Получается, что на диск не сбрасывает, но такого быть не может И что делать?

Pasha: Я предполагаю, что эта ситауция связана с настройкой Optimize=1 в letodb.ini При этом на сервере выставляется set hardcommit off. При такой настройке сервер работает значительно быстрее, но данные на диск сбрасываются не сразу, и при внезапном падении сервера возможна подобная ситуация. Можно, конечно, выключить эту настройку, сервер будет работать помедленнее, но данные на диск будут сбрасываться сразу, вернее, такая команда поступит в windows, а в windows есть еще своя буферизация. Можно поступить по-другому: по leto_CommitTransaction() принудительно сбрасывать буфера для всех рабочих областей пользователя.

AlexMyr: В readme указано Optimize = 0 - if 1, SET HARDCOMMIT OFF 0 по умолчанию, правильно? Вот мой конф. файл: [pre2]DataPath = c:\cars\ Default_Driver = CDX EnableFileFunc = 1 Share_Tables = 0[/pre2] т.е. Optimize тут не влияет, так?

Pasha: AlexMyr пишет: т.е. Optimize тут не влияет, так? Да, не влияет. Значит, дело в буферизации windows, letodb выдает flush сразу. Надо пробовать, добавлять записи, нажимать на кнопку reset и смотреть на результат.

AlexMyr: Pasha пишет: нажимать на кнопку reset и смотреть на результат. винт жалко попробую достать старый комп, там потренеруюсь.

PSP: Паш, как-то не верится, что винда больше недели буфера на диск не записывала...

AlexMyr: Еще забыл заметить, посмотрел на файл базы, так дата файла тоже была 26.06.2012 года, вариант что прога не работала, отпадает, юзера каждый день смотрят на данные с этой базы и сразу бы сказали, т.к. по данным с весов выписывается накладная.

Pasha: AlexMyr пишет: Паш, как-то не верится, что винда больше недели буфера на диск не записывала... Погонял тест, посмотрел код. Увидел, что если делать обновление без транзакции, то все в порядке. А с транзакцией не выдается flush, поэтому на диск она сразу не сбрасывается, и висит в буфере rdd на сервере. Добавлю принудительный flush, да еще без различия к настройке Optimize, чтобы с гарантией.

AlexMyr: Паша, спасибо, будем работать дальше

Pasha: Некоторые rdd-команды не требуют получения результата на клиенте. Это к примеру set filter to, set scope, вызов leto_setSkipBuffer() Тем не менее, для каждой из них клиент выдает отдельный запрос серверу. В связи с этим возникла идея буферизации таких запросов. К примеру, последовательность: set filter to ... set scope.. leto_setSkipBuffer(...) go top Требует 4 запросов к серверу. Можно 3 первых запроса не передавать серверу сразу, а накапливать в буфере. Передавать этот блок запросов можно тогда, когда будет выдан запрос, требующий получения результата, или запрос для другой рабочей области, или команда управления. А на сервере обрабатывать эти запросы последовательно в одном пакете. Насколько я знаю, в ads подобной фичи нет. Такая оптимизация будет полезной для тонкого клиента. Какие могут быть при этом подводные камни ?

alex_II: Помогите решить проблему! Использую: Harbour+LetoDB+MiniGUI+TSBrowse В одном из дочерних окон открываю в TSBrowse таблицу с CDX-индексом. В индексе 4 тега, между которыми могу переключаться и TSBrowse все прекрасно показывает, но стоит окну с таблицей потерять фокус то при возвращении обратно вне зависимости от того какой тег был активным всегда устанавливается активным ПЕРВЫЙ по порядку тег.

Dima: alex_II Возможно тут дело не в LetoDB а в TSBrowse

Andrey: А почему ссылки на LetoDB нет на самом главном сайте: http://harbour-project.sourceforge.net/download_contrib.html Это же большой промах...

Pasha: Andrey пишет: А почему ссылки на LetoDB нет на самом главном сайте: http://harbour-project.sourceforge.net/download_contrib.html Это же большой промах... Там перечисляются только библиотеки, которые входят в поставку Harbour. А letodb - это отдельный проект. У меня была мысль передать letodb в harbour\contrib, как один из вариантов, поскольку положение с проектом сейчас явно ненормальное, даже если кто-то захочет присоединиться к проекту - он не сможет этого сделать. Но тогда может быть прекращена поддержка клиентской библиотеки для xHarbour, да и делать это без согласия автора проекта не хотелось бы.

Andrey: Все равно надо там разместить ссылки на LetoDB и выложить что-нибудь, пускай знают что есть классный продукт под Harbour. И решить вопрос с автором проекта...

Pasha: Dima пишет: Возможно тут дело не в LetoDB а в TSBrowse Скорее всего, надо сделать что-то вроде: oB:bTagOrder := {|| ordNumber()} для восстановления тэга при получении фокуса

Pasha: Andrey пишет: Все равно надо там разместить ссылки на LetoDB и выложить что-нибудь, Разве что здесь: http://harbour-project.sourceforge.net/third-party.html#RDD

Andrey: Pasha пишет: Разве что здесь: http://harbour-project.sourceforge.net/third-party.html#RDD Да хотя бы туда.

alex_II: Pasha пишет: Скорее всего, надо сделать что-то вроде: oB:bTagOrder := {|| ordNumber()} для восстановления тэга при получении фокуса Спасибо за подсказку, помогло! Проверил вариант без letoDB, получил тот же глюк, значит дело в TSBrowse

Pasha: Новости проекта: 1. Если открывается большая БД, содержащая много (десятки и сотни) таблиц, появилась возможность открывать все таблицы одним запросом, а не множеством запросов, каждый отдельный для команды use Для этого надо вызвать udf-функцию UDF_OpenTables, и передать ей массив с описанием открываемых таблиц. Эта функция вернет массив строк, каждый элемент которого надо передать команде use вместо имени таблицы. При этом use не будет делать запрос к серверу, а заполнит данные rdd, используя элемент массива. Использование алиаса при этом обязательно. Пример: if leto_UDFExist( "UDF_OpenTables" ) aAreas := leto_UDF( ""UDF_OpenTables"", {{"table1",, .t.}, {"table2",, .t.}, {"table3",, .t.}} ) use (aAreas[1]) alias table1 shared new use (aAreas[2]) alias table2 shared new use (aAreas[3]) alias table3 shared new else use table1 alias table1 shared new use table2 alias table2 shared new use table3 alias table3 shared new endif 2. Добавлена функция на сервере leto_RecLockList( nUserStru, aRecNo ) --> lSuccess Функция leto_RecLockList блокирует записи с номерами, указанными в массиве aRecNo. Если блокировка какой-либо записи не удалась, блокировки снимаются, и возвращается результат .F. Эту функцию можно вызывать на сервере в модуле letoudf.prg, или с клиента вызовом leto_UDF( "leto_RecLockList", aRecNo ) Вместо множества вызовов dbRLock можно использовать один вызов leto_RecLockList. У меня при некоторых операциях блокируется свыше тысячи записей, и новая функция позволит резко сократить количество запросов к серверу.

Andrey: Хорошее решение ! Классно !

Pasha: Вопрос касается выделения памяти для списка блокированных записей в letodb сервере В dbfcdx/dbfntx список построен как простой массив значений типа unsigned long (это номера блокированных записей) При блокировке записи память под массив перевыделяется (его размер увеличивается), при снятии блокировки - размер уменьшается В letodb сделано примерно аналогично, только память под массив увеличивается порциями по 50 элементов, а при снятии блокировки - размер не уменьшается. В letodb это может привести к коллизиям при многопоточной обработке: при перевыделении памяти адрес массива может измениться, а в это время другой поток может к нему обращаться. Предложите другой способ организации этого списка. Пока я вижу только простейший список со ссылкой на следующий элемент. Может быть есть способ поэффективнее ?

Pasha: Остановился на однонаправленном отсортированном списке. Структура такая: typedef struct { ULONG ulRecNo; PLETO_LOCK_ITEM pNext; } LETO_LOCK_ITEM, *PLETO_LOCK_ITEM; typedef struct { BOOL bLocked; PLETO_LOCK_ITEM pItem; } LETO_LOCK_LIST, *PLETO_LOCK_LIST; 3 функции для нее: Поиск в списке static BOOL letoIsRecInList( PLETO_LOCK_LIST pLockList, ULONG ulRecNo ) Добавление в список static void letoAddRecToList( PLETO_LOCK_LIST pLockList, ULONG ulRecNo ) Удаление из списка static void letoDelRecFromList( PLETO_LOCK_LIST pLockList, ULONG ulRecNo ) Ну и функция очистки всего списка. Каждая функция перед тем, как работать со списком, выполняет цикл с проверкой pLockList->bLocked: static void letoLockWait( PLETO_LOCK_LIST pLockList ) { while( pLockList->bLocked ) ; } 2 последние функции перед добавлением/удалением элемента блокируют список: pLockList->bLocked = TRUE; После чего разблокируют его. Вопрос. Не может ли быть здесь коллизий при многопоточной работе ? Пусть один поток что-то делает со списком, и заблокировал его. Другой поток перед поиском в списке вызывает цикл letoLockWait( pLockList ); Зацикливания, даже теоретически, не произойдет ?

Pasha: Переделал списки блокированных записей, списки индексов, рабочих областей вместо массивов, которые могут перевыделяться в памяти, на однонаправленные списки. Но все-таки, меня терзают смутные сомнения. Если один поток что-то делает со списком, добавляет и в него элемент или удаляет, то надо на время операции блокировать список для доступа на чтение и запись другим потокам, во избежание неприятностей в виде гпф. А как это сделать ? Я в список добавляю 2 флага: bLockRead и bLockWrite: typedef struct { BOOL bLockRead; BOOL bLockWrite; ULONG ulSize; PLETO_LIST_ITEM pItem; } LETO_LIST, *PLETO_LIST; и перед доступом к списку проверяю эти флаги: void letoWaitWrite( PLETO_LIST pLockList ) { while( pLockList->bLockWrite || pLockList->bLockRead ) pLockList->bLockWrite += 0 ; } void letoWaitRead( PLETO_LIST pLockList ) { while( pLockList->bLockWrite ) pLockList->bLockWrite += 0 ; } Но эта зараза, а именно компилятор C, оптимизирует эти циклы, и ничего не делает. Специально дизассемблировал на предмет посмотреть. Оно не понимает, что к структуре имеет доступ другой поток, который может изменять значение флагов Как сделать блокировку списка ? Может быть, у потоков есть стандартный механизм для этого ?

Andrey: Pasha спасибо за совершенствование LetoDB. Жалко что не могу помочь в таких сложных решениях. Поспрашивай, может на других Си-шных форумах помогут.

PSP: Ну, а если в тело цикла вставить дополнительные строки, не нарушающие логики, которые смогут убедить компилятор не оптимизировать цикл? К примеру: [pre2] typedef struct { BOOL bLockRead; BOOL bLockWrite; int nTemp; ULONG ulSize; PLETO_LIST_ITEM pItem; } LETO_LIST, *PLETO_LIST; void letoWaitWrite( PLETO_LIST pLockList ) { while( pLockList->bLockWrite || pLockList->bLockRead ) { pLockList->bLockWrite += 0 ; if ( pLockList->nTemp ) { pLockList->nTemp := 0 ;} else { pLockList->nTemp := 1 ;} } } [/pre2] Upd: опечатка. Вместо pLockList->i д.б. pLockList->nTemp. Исправил.

santy: Паша, а если попробовать использовать мьютекси. Примеры можна посмотреть здесь : http://habrahabr.ru/post/72929/ http://www.sofmos.com/lyosha/Articles/multithreading1.html http://docs.oracle.com/cd/E19253-01/816-5137/sync-12/index.html Пример использования мьютексов к списку: http://maxim.int.ru/bookshelf/PthreadsProgram/htm/r_27.html

Pasha: santy пишет: Паша, а если попробовать использовать мьютекси. Спасибо, это то что надо. Я чувствовал, что делаю что-то не то. Надо использовать мютексы.

AlexMyr: Хочу узнать дату последнего обновления базы, dbinfo(4) возвращает пустую дату. Что делать?

Pasha: Сейчас LastUpdate не передается с сервера. Надо будет добавить. Только это связано с изменением протокола, вот думаю, как сделать, чтобы новые версии сервера и клиента при этом работали со старыми.

AlexMyr: Pasha пишет: Сейчас LastUpdate не передается с сервера. Надо будет добавить. Спасибо, работает!

AlexMyr: Паша! Команда append from я так понимаю не сработает с letodb сервера на локальный диск, надо через массив записи переганять?

Pasha: Почему не сработает ? Должна. Но, поскольку используются разные rdd, то драйвер надо указать в команде напрямую. Если в файл, открытый через dbfcdx, и надо добавить записи с letodb, то append from (cFile) via LETO где cFile должен быть с параметрами коннекта Если наоборот, то: append from (cFile) via DBFCDX

AlexMyr: Пробовал сначала без параметров коннекта, вылетал по ошибке. Добавил параметры коннекта, ошибок нет, но и записи не переносятся, буду копать дальше.

AlexMyr: Еще один момент: dbcreate("temp",{...},"DBFCDX",.T.) файл создался но не открывается, надо dbuseare("temp",...) использовать.

Pasha: AlexMyr пишет: Пробовал сначала без параметров коннекта, вылетал по ошибке. Добавил параметры коннекта, ошибок нет, но и записи не переносятся, буду копать дальше. Так файл открывается через dbfcdx, и записи добавляются с leto ? А насчет временного файла, надо еще алиас в dbCreate указывать

AlexMyr: Pasha пишет: Так файл открывается через dbfcdx, и записи добавляются с leto ? основная задача на leto, потом копируются записи с leto в локальную базу, открытую через dbfcdx, и потом локальная база улетает по почте. Pasha пишет: А насчет временного файла, надо еще алиас в dbCreate указывать спасибо, попробую

AlexMyr: Вот что выяснил, если создать локально файл и добавить одну пустую запись в него, то с leto все нормально переноситься по append from, если не добавлять, а сразу после dbcreate() делать append from, то добавляется одна запись в базу на leto. Вот!

Pasha: Не очень понятно. Алексей, а можно код показать, что не так работает ?

AlexMyr: Pasha пишет: Не очень понятно. Алексей, а можно код показать, что не так работает ? Сейчас попробую минимальный примерчик собрать.

AlexMyr: На тестовом примере в базу на leto записи не добавляются, видно где-то у меня в коде что-то не так. Дальше, если dbappend() закомментировано, записи не переносятся, если раскомментировано, то все нормально. [pre2] Function Main Local cPath := "//127.0.0.1:2812/temp/" REQUEST DBFCDX REQUEST LETO RDDSETDEFAULT( "LETO" ) ? "Start" dbCreate( cPath+"Nakl1", { {"NORD","N",10,0},{"DORD","D",8,0},{"SUMMA","N",12,2} } ) ? "Files has been created" use ( cPath+"Nakl1" ) New ? "Files has been opened and indexed" AddNakl( 1, Date(), { 1400.5, 28632.28, 800.51 } ) AddNakl( 2, Date(), { 58003, 930.5 } ) dbcloseall() altd() dbCreate("temp1",{ {"NORD","N",10,0},{"DORD","D",8,0},{"SUMMA","N",12,2} },"DBFCDX",.T.,"temp1") // dbappend() // uncomment for append from append from (cPath+"nakl1") via "LETO" Return Nil Function AddNakl( n_ord, d_ord, aSumm ) Local i, sumAll := 0 leto_BeginTransaction() select NAKL1 append blank replace NORD with n_ord, DORD with d_ord, SUMMA with sumAll leto_CommitTransaction() Return .T. [/pre2]

Pasha: AlexMyr пишет: Дальше, если dbappend() закомментировано, записи не переносятся, если раскомментировано, то все нормально. Что очень странно, так как в файл открыт через dbfcdx, и команду append from отрабатывает dbfcdx, а не leto dbfcdx должен просто открыть файл через указанный драйвер, и в цикле по записям добавить их. Вставлю-ка я в свой dbedit выполнение append from через другой драйвер, и посмотрю, как он отработает.

Pasha: Я нашел глюк в leto для случая копирования записей между разными драйверами client\leto1.c строка 4026 надо добавить проверку: if( !leto_CheckArea( pAreaDst ) || вечером скину

AlexMyr: Pasha пишет: вечером скину будем ждать!

AlexMyr: Pasha Спасибо, работает

sashaBG: Привет Всем кто использует LetoDB ! Сервер LetoDB работает отлично ! У меня все программы уже на етой базе. Все работает безпроблемно . Самый большой клиент у меня имеет 25 р. мест. за год работы не наблюдались никакие пропажи информации и нарушение логической стр. данных , благодаря транзакций. Большое спасибо г-ну Крезину и Паше конечно за професионально проделную работу ! Но вот клиенты начали заекатся на возможность подключeния к базе через WEB . Так как я не знаток C у меня вопрос к Паше : Возможно ли написание PHP Extention для LetoDB ? Если да - Я БУДУ Хорошим тестером :) P.S. тут я читал как пишется такая щука

AlexMyr: sashaBG пишет: Но вот клиенты начали заекатся на возможность подключeния к базе через WEB Но клиентская прога и есть своеобразный браузер для letodb, а через web как по мне то это уже лишнее.

Andrey: sashaBG пишет: за год работы не наблюдались никакие пропажи информации и нарушение логической стр. данных , благодаря транзакций. Будьте так добры, напишите схематично как правильно надо писать транзакции. Заранее спасибо.

Pasha: sashaBG пишет: Возможно ли написание PHP Extention для LetoDB ? Из php можно обращаться к COM-серверу. А пример LetoDB COM сервера я делал: см. utils\olesrv Правда, это будет работать только в windows Может быть, такой вариант подойдет ?

alkresin: sashaBG пишет: Но вот клиенты начали заекатся на возможность подключeния к базе через WEB . Так как я не знаток C у меня вопрос к Паше : Возможно ли написание PHP Extention для LetoDB ? Я не Паша, но постараюсь ответить. Чтобы сделать PHP Extention, надо сначала существенно переработать код Leto RDD - отделить, собственно, RDD от функций, осуществляющих обмен с сервером - создать слой, API, к которому можно обращаться из не-Харборовских программ. Это вполне реальная, но довольно трудоемкая задача. Я бы вам посоветовал для подключения через Web использовать CGI интерфейс. Компьютеры сейчас довольно мощные - потянут, если только у вас не сотни одновременых подключений через Web. Я сам использую CGI, Javascript и Ajax, все нормально работает.

Pasha: Александр, а что если прикрутить запросы query из dbc к letodb ? Хотя бы в качестве readonly запросов

AlexMyr: Andrey пишет: Будьте так добры, напишите схематично как правильно надо писать транзакции. Смотрим пример letodb\tests\test_ta.prg

sashaBG: Спасибо за ответы ! Pasha пишет: Правда, это будет работать только в windows Паша ты имееш виду IIS Сервер или можно и через например XAMPP под Windows? Андрей вот етот код у меня сейчас работает сначало немножко раскажу конкретно етот Документ сохраняется в двух файлах (Нулевая так я назвал ) 0-ая часть ( или Master часть) и N-ая часть (или Detail часть) //Начало транзакции-------------------------------------------- LETO_BEGINTRANSACTION( ) lSaveN := _N_SAVE() //Сохраняем (Detail часть) IF lNew0 // если у нас новы документ или новая Master часть lSave0 := _0_SAVE() // Сохранеям Master часть SET_SCOPE() // Устанавливаем зону видимости от Мастер к Детаил ENDIF IF lSaveN .and. lSave0 // если все удачно сохранилось IF ! LETO_COMMITTRANSACTION() msgstop( "НЕУДАЧНАЯ Транзакция !" ) ENDIF ELSE LETO_ROLLBACK() //откат ENDIF //Конец транзакции-------------------------------------------- Пока так работает К спецам: Если что-то не так СОВЕТУЙТЕ ! P.S. Не могу отформатировать текст :(

Andrey: alkresin пишет: Я бы вам посоветовал для подключения через Web использовать CGI интерфейс. Компьютеры сейчас довольно мощные - потянут, если только у вас не сотни одновременых подключений через Web. Я сам использую CGI, Javascript и Ajax, все нормально работает. Очень интересно ! Давно хочу такое... Никто и не ответил мне в этой теме http://clipper.borda.ru/?1-3-20-00000218-000-0-0-1342804573 А чуть подробней по "подключению через Web используя CGI интерфейс" можно отписаться в другой теме, чтобы здесь не "мусорить" ! Заранее спасибо за ответ !

alkresin: Pasha пишет: Александр, а что если прикрутить запросы query из dbc к letodb ? Хотя бы в качестве readonly запросов Я так и хотел сделать - может, помните, писал когда-то о планах реализовать SQL - запросы в letodb. Даже начал переводить тот фрагмент кода из dbc на C - но потом что-то отвлекло и забыл про это дело...

santy: Вот это интересно. SQL на letodb - прекрасная идея. Потом уже на уровне ядра (x)Harbour.

Pasha: alkresin пишет: Я так и хотел сделать - может, помните, писал когда-то о планах реализовать SQL - запросы в letodb. Даже начал переводить тот фрагмент кода из dbc на C - но потом что-то отвлекло и забыл про это дело... Я планировал это сделать в виде отдельного rdd - наследника DBFCDX/DBFNTX. Для простых запросов по одной или нескольким таблицам в этом rdd можно было бы добавлять/удалять поля (FIELD), для более сложных - формировать таблицу в памяти (временный файл) и заполнять ее. Этот rdd можно прикрутить к серверу letodb, а клиентская часть leto в таком случае почти не меняется.

Pasha: Александр, а можно ли перенести проект с CVS на SVN ?

alkresin: Pasha пишет: Александр, а можно ли перенести проект с CVS на SVN ? А как это делается ?

Pasha: Не знаю. Наверное, надо спросить в harbour dev, они же переносили головной проект. В любом случае у меня прав на это нет.

santy: Заходите под админом во вкладке Project Admin/Feature Settings установите галочку для SVN уберите для CVS. Последнюю версию с CVS сберегите. Попробуйте закачать туда данные через SVN Можна конечно почитать инструкцию https://sourceforge.net/apps/trac/sourceforge/wiki/Subversion%20import%20instructions Но у меня вышло по простому.

alkresin: Pasha пишет: Не знаю. Наверное, надо спросить в harbour dev, они же переносили головной проект. В любом случае у меня прав на это нет. Теперь есть, я вас добавил в project admins.

Pasha: Спасибо !

sashaBG: Вот финкция из примерчика TEST_TA.PRG: Function AddNakl( n_ord, d_ord, aSumm ) Local i, sumAll := 0 leto_BeginTransaction() select NAKL2 for i := 1 to Len( aSumm ) append blank replace NORD with n_ord, DORD with d_ord, NPROD with i, SUMMA with aSumm sumAll += aSumm next select NAKL1 append blank replace NORD with n_ord, DORD with d_ord, SUMMA with sumAll leto_CommitTransaction() // Я добавил етот кусок select NAKL2 leto_commit() ?"NAKL2 recno() ->",recno() // Выходит 0 select NAKL1 leto_commit() ?"NAKL1 recno() ->",recno()// здесь тоже 0 Return .T. А нужно показать номер новодобавленой записи !

SergKis: Andrey пишет: Очень интересно ! Давно хочу такое... Путь к этому: - подобрать под себя CMS - изучить - научиться подключать CGI интерфейс в CMS - возможно подправить под себя CMS Мы используем CMS с MySql и php. CGI интерфейс hb2.0 с использованием scripta (см.hb20\examples\hscript\hscript.prg). Базы на LetoDb и cdx. CMS обеспечивает внешний вид (css), меню, данные пользователя, пароли ... В CGI из MySql подчитываются данные сессии (user, password, css-ы и т.д.) Все нормально работает. Задача: Ввод жильцами данных по счетчикам учета воды в квартплате

Andrey: SergKis Чтобы не разводить здесь лишнего, я перенес свой вопрос к вам в тему http://clipper.borda.ru/?1-3-0-00000218-000-0-1-1353420057

Pasha: sashaBG пишет: А нужно показать номер новодобавленой записи ! Вызов leto_commit в данном случае не поможет, он будет просто проигнорирован. Сейчас leto_CommitTransaction просто возвращает результат выполнения: успешно или нет. Надо добавить возврат массива номеров последних добавленных записей для каждой рабочей области, которая задействована в транзакции. А на клиенте обрабатывать этот массив, устанавливая номера добавленных записей. Сделаю.

sashaBG: Паша, наверное не стой усложнять leto_CommitTransaction Все дело было потому что в моем проекте после добавления нового документа я показываю в статус линии данные о текущей записи и так замаетил что после транзакции добавления нового документа показывает 0. я пока в своем проекте справился делая после leto_CommitTransaction , DBSEEK(cNewDOK) и все о.к. После етого показывает все нормально . Спасибо !

Pasha: Дело в том, что если после транзакции указатель остается на добавленной записи, то будут неправильно работать операции навигации по этой рабоче области (skip). Так что лучше эти данные все-таки передавать и отрабатывать их.

alkresin: Pasha пишет: Дело в том, что если после транзакции указатель остается на добавленной записи, то будут неправильно работать операции навигации по этой рабоче области (skip). Так что лучше эти данные все-таки передавать и отрабатывать их. А как именно обрабатывать ? По-моему, указатель записи после транзакции должен быть там же, где и в том случае, если этот фрагмент кода исполняется без транзакции. Т.е., если речь идеь о добавлении группы записей, то - на последней добавленной записи.

Pasha: Алгоритм примерно такой. Сервер пусть формирует массив вида ulAreaID, ulRecNo, ... и заполняет при добавлении последний номер добавленной записи (только один для р/о) Клиент после транзакции просматривает этот массив, и, если для указанной в нем р/о номер записи на клиенте 0, заменяет его на принятый номер записи. Иначе получится, что если после транзакции с добавленной записью клиент выполняет какое-то действие, то сервер ее просто не найдет.

alkresin: А почему о массиве речь идет, а не об одной последней добавленной записи ?

Pasha: Так я и имел в ввиду номер последней добавленной записи для каждой р/о, в которой производилось добавление во время транзакции. Если на клиенте текущей останется добавленная запись, то для нее заменять номер записи 0 на полученный с сервера. Надо еще подумать, какая еще информация нужна клиенту по результату транзакции, чтобы сразу все сделать.

Pasha: На сайте проекта я добавил сборку letodb для windows для различных компиляторов: Cервер и менеджер - для bcc55, mingw и mingw64. Клиентская библиотека: Harbour - для bcc55, mingw, mingw64 и watcom, xHarbour - для bcc55.

Andrey: Pasha пишет: сборку letodb для windows А сборка для Linux можно будет в дальнейшем сделать ? А то хочется сделать сервер на Ubuntu, а клиента под windows. Спасибо ОГРОМНОЕ Pasha за твой труд !

Pasha: Andrey пишет: А сборка для Linux можно будет в дальнейшем сделать ? А то хочется сделать сервер на Ubuntu, а клиента под windows. Как появится под рукой Ubuntu, сделаю А самому сделать не получается ?

dimao: Вот, может поможет. http://dimao.blogspot.ru/p/blog-page.html

alex_II: Pasha пишет: На сайте проекта я добавил сборку letodb Не могу выкачать дистрибутив, просит пароль Раньше всё было нормально

Pasha: Пароль на скачивание архива или пароль на архив ? Я без авторизации на sf только что скачал http://sourceforge.net/projects/letodb/files/bin/letodb-2.09-win.7z/download на архив тоже пароля нет или нужен пароль при доступе к CVS ? anonymous не работает, что ли ?

AlexMyr: Вчера и сегодня тоже не могу: cvs [login aborted]: recv() from server letodb.cvs.sourceforge.net: Connection r eset by peer C:\dev\_svn>cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb cvs [checkout aborted]: recv() from server letodb.cvs.sourceforge.net: Connectio n reset by peer

Pasha: Новости с sf от 28.11.2012: http://sourceforge.net/blog/viewvc-and-anonymous-pserver-access-for-cvs-offline/ ViewVC and anonymous pserver access for CVS offline Greetings, Since the CVS downtime yesterday, we’ve been experiencing poor performance for CVS. As such, we’ve disabled ViewVC and anonymous pserver access for the time being to prioritize developer read/write access while we address the performance issue. We do not have an estimate for the completion of this yet, but we will keep this post updated as this develops. UPDATE: ViewVC is now available again, however, the data in ViewVC is still from before the previous downtime. Anonymous pserver is still offline. We’re working to get both these caught up with the latest updates as soon as we can. Best Regards, Chris Tsai, SourceForge.net Support

AlexMyr: Pasha пишет: Александр, а можно ли перенести проект с CVS на SVN ? Может быть пора?

alkresin: Павел, мне тут написали: OP system : Win 7, Win XP, Win 2008 bcc, mingv, mingv64 letodb v 1.350.2.90 2012/11/23 16:11:46 bug: 12/03/12 09:41:37: LetoDB service has had some problems: 1063 Я такого сообщения не припомню. Что бы это могло значить ?

Pasha: Ошибка возникает при неудачной попытке запуска службы letodb Код ошибки 1063 расшифровывается так: Процесс службы не может установить связь с контроллером службы. С именно такой ошибкой я не сталкивался. Мне встречались проблемы с правами при установке службы (нужны права администратора). Еще службу нельзя запускать с сетевого диска, что тоже понятно. Встречалась проблема, когда после какого-то обновления avast служба letodb при запуске просто висла, в диспетчере служб в колонке состояние было что-то вроде running или starting Лечилось заменой антивируса на другой. Возможно, тут что-то тоже связано с антивирусом. Или сам модуль letodb.exe поврежден. Хотя, видно что скачан уже собранный letodb, который я выложил. Может быть, пользователь просто не установил службу ? Т.е. не отработал letodb install ? В инструкции про это есть.

AlexMyr: AlexMyr пишет: Вчера и сегодня тоже не могу: cvs [login aborted]: recv() from server letodb.cvs.sourceforge.net: Connection r eset by peer C:\dev\_svn>cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb cvs [checkout aborted]: recv() from server letodb.cvs.sourceforge.net: Connectio n reset by peer Уже работает!

Pasha: Александр, мне пришло письмо с sf, они предлагают проапгрейдить проект на новую платформу. Пишут, что старая скоро не будет поддерживаться. Делать ?

alkresin: Pasha пишет: Александр, мне пришло письмо с sf, они предлагают проапгрейдить проект на новую платформу. Да, я тоже получил. Делать ? Ну а куда деваться ...

alkresin: Я сделал Upgrade, посмотрим, что получится.

alkresin: Я думал, этот upgrade имеет какое-то отношение к переходу с CVS на SVN - но, вроде, это не так.

Andrey: А откуда качать исходники LetoDB ? с CVS или SVN ? Адрес дайте пожалуйста. И готовые бинарники есть ?

Pasha: Как и раньше, с CVS, ничего не изменилось. А бинарники я же только выложил, неделя с небольшим прошла, на этой странице чуть выше все есть.

Pasha: Просьба тем, у кого есть msvc, проверить сборку сервера letodb с правкой: include/funcleto.h строка 81 #include <winsock2.h> заменить на #ifndef HB_SOCKET_H_ #include <winsock2.h> #endif С этой заменой сборка для openwatcom выполняется успешно (раньше были ошибки). А msvc у меня не установлен. Хотелось бы знать, поможет ли этот фикс для msvc

Pasha: Сейчас время актуальности skip и seek буфера - 1 секунда. Для медленного удаленного интернет-соединения это может быть недостаточно. Поэтому я добавил возможность задать это время: 5-й параметр leto_Connect

alkresin: Это время, как я понимаю, сейчас имеет одно значение для всех файлов ? Мне кажется, тут нужен более гибкий подход - возможность установки и общего значения, и - для каждой таблицы в отдельности. И должно быть значение, равное 0 как эквивалент бесконечности, т.е., чтобы это время актуальности было бесконечным. Я бы в своих приложениях ( пока это теоретическое предположение, поскольку у меня стоит пока старая версия, где этого времени нет вообще ) поставил бы общее значение 0 и, возможно, только для некоторых файлов какое-то фиксированное - например, 5 сек.

Pasha: Добавлю еще в LETOAREA это параметр, знаковый. -1 будет означать общую настройку для соединения, 0 - бесконечность. Для установки добавлю новую константу для dbInfo: DBI_XXX. Кстати, сейчас проверю, насколько поможет увеличение этого параметра для удаленного соединения.

alkresin: Этот -1 для LETOAREA должен быть, по идее, значением по умолчанию.

Pasha: Увеличение времени актуальности буфера немного помолго, но оказалось далеко не решающим фактором. Пришлось оптимизировать еще несколько действий. Включил использование seek-буфера там, где это необходимо, доработал его: теперь если dbSeek(xKey) возвращает .F., результат все равно сохраняется в seek-буфере и затем используется. Убрал несколько лишних операций. В результате количество запросов к серверу сократилось с 265 до 29-ти, т.е. почти на порядок.

alkresin: Отлично. А что это за seek-буфер ? Какие записи он хранит, тем более когда dbSeek возвращает .f. ?

Pasha: Я использую seek-буфер к примеру для выборки данных из небольшого справочника размером несколько десятков-сотен записей. Среди них есть как правило наиболее часто используемые. Определяю размер seek-буфера 20-30 записей вызовом leto_SetSeekBufer(20) При этом результат работы dbSeek: значение ключа и копия полученной с сервера записи будет сохранен в буфере, и при следующем вызове seek с тем же значением ключа запись будет браться из буфера без обращения к серверу. Вызов leto_SetSeekBufer без параметров вернет количество попаданий в буфер. А вчера я добавил сохранение в буфер ненайденной записи. Если будет еще раз seek с тем же значеним ключа, запись будет перемещена на eof() без запроса к серверу. Механизм примерно такой же, как и для skip-буфера. Можно использовать к примеру в случае использования set relation, или просто для dbSeek

Pasha: Меня спрашивают, что предпочтительнее по производительности, использование dbfcdx в терминалке или letodb ? А я не знаю, что ответить, так как сам терминал-сервер не использую. Кто может сказать, большой траффик получается в случае использования терминал-сервера windows ?

Andrey: Pasha пишет: Кто может сказать, большой траффик получается в случае использования терминал-сервера windows Я использую на нескольких фирмах терминал-сервера. Так как сервер для терминалов используют как правило более мощный, то задача с использованием обычного dbfcdx - просто летает.... Но по цене и простоте лучше использовать конечно LetoDb (экономим на обслуживание и настройке терминал-сервера windows ) !

PSP: Да, тут главное - цена. Терминальный сервер легально можно поднять только на MS Server 20xx. Про его цену вместе с лицензиями говорить не обязательно. Думаю, что вариант с терминалом будет побыстрее, особенно через интернет соединение, но и затраты несоизмеримо выше.

Vlad04: Есть платные терминалы , работают и на Win 7 64, других разработчиков, цены доступные

Vlad04: Но под терминалом не работает ADS local.

Pasha: Я давно косо смотрел на выборку из таблицы с использованием scope и filter. Для нее необходимо сделать несколько запросов: set scope set filter seek skip (один или несколько) clear scope clear filter Получается как минимум 6 запросов к серверу. Мне хотелось их минимизировать, до одного запроса.. Сначала возникла идея сделать обработку блоков команд. Но таких команд немного: set filter и set scope, и в конце концов я от этой идеи отказался. Но вопрос как-то решать надо. Решил использовать возможности skip-буфера: его заполнение одной командой и обработка результата на клиенте обычными вызовами навигационых функций. Я не стал добавлять новую команду для сервера, а сделал через механизм udf-функций, для которых есть аналогичный, но более гибкий интерфейс. Теперь вместо кода: set index to <indexname> set scopetop to <s1> set scopebottom to <s2> set filter to <f> go top while ! eof() ... skip enddo set scope to set filter to можно использовать код: leto_ParseRecords(leto_Udf('UDF_dbEval', <s1>, <s2>, <indexname>, <f>)) while ! eof() ... skip enddo Это делается одним запросом к серверу. Конечно, большую выборку надо использовать с осторожностью, поскольку вся она передается одним запросом. дока будет чуть позже.

alkresin: Дело хорошее! Leto_ParseRecords() - это новая функция, которая разбирает результат, присланный UDF_dbEval ?

Pasha: alkresin пишет: Leto_ParseRecords() - это новая функция, которая разбирает результат, присланный UDF_dbEval ? Да, именно так. Она заполняет skip-буфер (без ограничения на размер, сколько получится), и затем команды dbSeek(1) ... while ! eof() могут выбирать из него данные без обращения к серверу. Послу выборки желательно сбросить skip-буфер командой dbInfo(DBI_CLEARBUFFER) чтобы случайно командами skip(-1) не выбрать не те данные. Мне еще хочется в skip-буфере сделать такое изменение. Сейчас при обновлении данных он просто сбрасывается. Если обновлялись неиндексные поля текущей записи, можно это не делать, а прямо в буфере в поле флагов записи, которая обновилась, делать пометку, что именно эту запись из буфера брать не надо. Тогда skip-буфер можно быдет полноценно использовать при обновлении данных.

SergKis: alkresin пишет:Дело хорошее Дело ОЧЕНЬ ХОРОШЕЕ !!! А добавив aFields, можно и без вызова UDF работать, добавив возврат в буфере массива Recno записей выборки (для больших и неопределенных в объеме выборок), получится вариант SELECT ... ! И если такое добавить в версию LETO, собираемую xHabour - совсем ЗАМЕЧАТЕЛЬНО !

Pasha: Я вчера забыл сделать коммит для server.prg, там небольшое изменение - надо добавить request для leto_dbEval. Сегодня сброшу. Кстати, в mail dev list почему-то не проходят письма. А насчет aFields: я не очень понял, что имеется в виду. Можно подробнее ?

SergKis: Pasha пишет: А насчет aFields: я не очень понял, что имеется в виду. Можно подробнее ? Как я понял, сейчас в skip-буфере находится все поля записи. При помощи aFields := {"Field1", "Field10"} - только нужные.

Pasha: Добавить к UDB_dbEval еще один параметр aFields, что ли ? И передавать с сервера только значения тех полей, которые есть в этом массиве ? Тогда значения остальных полей будут пустыми, и в skip буфере, и при считывании записей. Конечно, для передачи даже пустых полей требуется один-два байта. Это можно сделать, но пользоваться таким запросом надо с осторожностью, понимая, что делаешь. Обращение к полям, которых нет в aFields, даст пустое значние, а ведь значение у них есть. Если в массиве не будет ключевых полей, то не получится вычисление ключевого выражения.

SergKis: Pasha пишет но пользоваться таким запросом надо с осторожностью Конечно - это для тех, кто понимает, что происходит ! Зато можно значительно уменьшить трафик в различных расчетах где символьные данные не нужны и т.д. и т.п. Еще можно добавить параметр .T./.F., что в skip буфере: записи с полями или ссылки на записи, участвующие в запросе и работать вместо skip через goto.

Pasha: SergKis пишет: Еще можно добавить параметр .T./.F., что в skip буфере: записи с полями или ссылки на записи, участвующие в запросе и работать вместо skip через goto. Это как раз наоборот увеличит траффик. Если в skip-буфере хранятся записи, то они выбираются из него без обращения к серверу. Если номера записей (ссылки), то каждый goto потребует запроса к серверу, что нивелирует саму идею буфера.

SergKis: Pasha пишет:что нивелирует саму идею буфера Это как применять имеющиеся возможности. Если запрос к данным за несколько лет , т.е. для больших и неопределенных в объеме выборок, я бы предпочел быстро получить ссылки и потом работать по ним, а при работе с карточками, документами конечно skip-буфер. И что особенно нравится, не надо городить функции UDF, которые появившись, начинают жить вместе с проектом, но где то на сервере, и в общей куче, и хорошо если делал их сам. Функция Leto_ParseRecords() - это реальный вариант команды SELECT ... FROM ..., что радует. Pasha пишет: Тогда skip-буфер можно будет полноценно использовать при обновлении данных Наверно и эта возможность интересна, но как она будет сочетаться с транзакциями? Сегодня мы делаем так: - делаем выборку (select функция) - сохраняем в MemIO - даем для работы клиенту (Browse) - если были изменения, в транзакции сбрасываем на сервер как это будет выглядеть со skip буфером ?

Pasha: SergKis пишет: Это как применять имеющиеся возможности. Если запрос к данным за несколько лет , т.е. для больших и неопределенных в объеме выборок, я бы предпочел быстро получить ссылки и потом работать по ним, а при работе с карточками, документами конечно skip-буфер. И что особенно нравится, не надо городить функции UDF, которые появившись, начинают жить вместе с проектом, но где то на сервере, и в общей куче, и хорошо если делал их сам. Функция Leto_ParseRecords() - это реальный вариант команды SELECT ... FROM ..., что радует. Если установить фильтр: обычный и scope, то в skip-буфер как раз будут занесены только те записи, которые ему удовлетворяют, и нет необходимости в ссылках на номера записей с их дальнейшей выборкой Наверно и эта возможность интересна, но как она будет сочетаться с транзакциями? Смысл skip-буфера в том, чтобы прочитать с сервера сразу блок записей и затем его использовать без обращения к серверу. Как только запись изменяется, то skip-блок полностью очищается, и при обращении к следующей записи она будет вновь считана с сервера. Это относится к изменениям как в рамках транзации, так и без нее. Я при изменении записи хочу не очищать полностью skip-блок, а только помечать измененную запись в нем. Если потребуется выбрать запись, которая есть в буфере и не изменялась, то она будет выбрана из буфера, а если изменялась - считана вновь с сервера. Есть транзакция или нет - при этом роли не играет. К примеру, пусть в таблице 10 записей. Как сейчас обрабатывается выражение вида: go top while ! eof() if RLock() Field->FName := 'fsdfsdfsd' commit unlock endif skip enddo Сейчас: 1. Считано 10 записей в буфер, текущая запись номер 1 2. Запрос на update, буфер очищается 3. Skip - считывается 9 записей 4. Запрос на update, буфер очищается 5. Skip - считывается 8 записей ... Если изменить алгоритм: 1. Считано 10 записей в буфер, текущая запись номер 1 2. Запрос на update, буфер не очищается, в нем делается пометка для записи 1 3. Skip - берется следующая запись из буфера 4. Запрос на update, буфер не очищается, в нем делается пометка для записи 2 5. Skip - берется следующая запись из буфера ... Транзакция только влияет на то, как выполняется update: сразу или по commit transaction

SergKis: Pasha пишет:К примеру, пусть в таблице 10 записей. Как сейчас обрабатывается выражение вида go top while ! eof() ... Я правильно понял, что если написать на эти 10 записей Browse: go top Browse(...) и в функции пользователя при корректировке: if RLock() Field->FName := 'fsdfsdfsd' commit unlock endif ... Return REFRESH такая схема будет работать !

Pasha: Работать то будет, но неоптимально. До корректировки будет использоваться skip-буфер. При корректировке он будет очищен, и вся страница browse опять будет считана с сервера. Я хочу сделать, чтобы буфер полностью не очищался, а считывалась только измененная запись при повторном обращении к ней.

SergKis: Pasha спасибо за объяснения !!!

SergKis: Паша, еще вопрос по skip-буферу. Сейчас некоторые справочники читаю в массивы и потом, работаю по AScan(...), со skip-буфером можно ли делать так: select AAA; leto_SetSeekBufer(LastRec()); leto_ParseRecords(...) // справочник 1 select BBB; leto_SetSeekBufer(LastRec()); leto_ParseRecords(...) // справочник 2 потом, по надобности делать: select AAA; LOCATE ... select BBB; LOCATE ... или skip-буфер один, а не для каждой области ?

Pasha: skip-буфер создается для каждой рабочей области, а seek-буфер - для каждого индекса рабочей области. Но по умолчанию seek-буфер не создается, его надо задать. Но это разные буфера, один для операции skip, второй - для seek leto_ParseRecords заполняет именно skip-буфер, к seek-буферу он не имеет отношения. Если locate хочется использовать данных skip-буфера, полученных после leto_ParseRecords, то так просто это не сделаешь. locate первым делом сделает go top, что сразу сбросит skip-буфер и испортит весь кайф. Поэтому надо делать locate с опцией rest В результате locate переместится на найденную запись или на eof, если запись не найдена, и последующий locate в этом skip-буфере без его сброса будет сделать затруднительно. Поэтому предпочтительнее все-таки будет алгоритм с просмотром всего полученного skip-буфера сразу: while ! eof() и в цикле делать все нужные сравнения skip enddo все равно этот skip буфер уже получен с сервера и находится на клиенте.

SergKis: Pasha пишет:все равно этот skip буфер уже получен с сервера и находится на клиенте Это все очень ЗДОРОВО ! Тогда вместо memio можно использовать следующее: select DOKUM; leto_SetSkipBufer(100); leto_ParseRecords(...) while ! eof() RLock() skip enddo Browse(...) // с корректировкой если изменения были в нескольких RecNo, то while ! eof() commit skip enddo Unlock() Как в таком случае быть с dbAppend() ?

Pasha: leto_SetSkipBufer(100) перед leto_ParseRecords(...) делать необязательно, так как в буфер заносятся все данные, удовлетворяющие заданному условию. После всех операций изменения данных сейчас буфер сбрасывается. Я только собираюсь сделать другой алгоритм: не сброс буфера, а пометку в нем измененных записей, но еще это не сделал.

Pasha: Я так понимаю, вы хотите сделать что-то вроде аналога fetch для результатов sql-запроса. Я думаю, может стоит сделать отдельный набор функций для навигации по skip-буферу: текущая позиция в буфере, перемещение вперед/назад Но это вопрос дискуссинный. Может достаточно будет обойтись функцией, которая бы возвращала позицию текущей записи в буфере.

SergKis: Pasha пишет:Я так понимаю, вы хотите сделать что-то вроде аналога fetch для результатов sql-запроса Как конечный результат - да, а как промежуточный - избавится от кода закачки справочников в массивы и работа с документами, карточками со skip-буфером вместо закачки в memio, т.е. значительно сократить код в программе. Я думаю, может стоит сделать отдельный набор функций для навигации по skip-буферу это не принципиально, если будет какой-то базовый набор функций - обвесить можно всегда.

Andrey: sashaBG пишет: Привет Всем кто использует LetoDB ! Сервер LetoDB работает отлично ! sashaBG пишет: Кстати в letodbtray но для моего проекта е сделал исправление : потому что Letodb падает из за постоянного подключение и отключения я в цикле по таймеру сделал възов функцию IsAlive() вместо IsConnected(): FUNCTION IsAlive() Return leto_file( _Server+"USER.DBF" ) и таким образом серввер не падает. но для общего использования она не подойдет , нельзя ли сделать на C leto_islive() ? И еще интересное наблюдение : на серверах ( я пробую на windows Serwer 2008 ) скорость работы letodb заметно ниже чем на обычном XP процессор на сервере нагружается небольше 5% а под XP и Win7 доходит до 60% и больше , наверное ето потому что letodb не серверный процесс. Как решились эти проблемы ? Есть ли новая версия letodbtray ? Если можно, то поделитесь пожалуйста. В вашей предыдущей программе не хватает информации по Номеру версии (сборки) LetoDB и и заодно и Номера версии вашей программы. Я так понял Вы пишите программы с LetoDB на МиниГуи. Как МиниГуи работает с базами, какие тонкости есть при использовании МиниГуи ?

sashaBG: Андрей прошло много времени с того поста что в цитате , сервер сайчас работает намного лучше. Когда у меня будет болше времени , обещаю сделать небольшой пример СЕРВЕРА(комбинация между letodb + HBNETIO + MiniGUI) и КЛИЕНТА(MiniGUI + rddleto) В принципе нет большой разницы при работе letodb чем с другими RDD . Я постараюсь показать кое чего в примере :)

Andrey: sashaBG пишет: Я постараюсь показать кое чего в примере :) Заранее спасибо, буду ждать. С наступающим Новым Годом !

Andrey: Что-то не хочет запускаться letodb.exe на Win8 (32bit) из под администратора. Версия letodb-2.09-win, пробовал из папки Bin\BCC и Bin\MinGW D:\@TEST_LETODB\letodb.log 12/29/12 02:14:16: Error installing LetoDB service: 5 12/29/12 02:18:20: LetoDB service has had some problems: 1063 12/29/12 02:20:20: LetoDB service has had some problems: 1063 12/29/12 02:22:11: LetoDB service has had some problems: 1063 12/30/12 12:00:11: LetoDB service has had some problems: 1063 12/30/12 12:01:53: LetoDB service has had some problems: 1063 Старая версия letodb.exe (672256) 14.06.10 - запускается. 12/30/12 12:04:34: Leto DB Server has been started.

sashaBG: Ето потому что сервер откомпилирован как (SERVICE) сначало сделай letodb install , потом в срвисах найди запусти и (SERVICE) LetoDB Service после етого даже после рестарта компьютера служба будет работать я тоже на WIN8 почитай readme_rus.txt там все написано :) потом из командной строки или из программы можно останавливать и запускать net start "LetoDB Service" - СТАРТ net stop "LetoDB Service" - СТОП

Andrey: sashaBG пишет: сначало сделай letodb install Да читал я доку: Для установки и удаления службы необходимы права администратора. Для установки службы вызовите letodb с параметром 'install': letodb.exe install Делаю, пишет вот это: 12/30/12 21:54:00: Error installing LetoDB service: 5

Pasha: Andrey пишет: Делаю, пишет вот это: 12/30/12 21:54:00: Error installing LetoDB service: 5 Ошибка 5 - это ERROR_ACCESS_DENIED, что однозначно идентифицирует причину ошибки как недостаток прав доступа для установки службы. Убедитесь, что есть права админа. В конце концов, создайте ярлык на "letodb install" и запустите его с правами администратора, если такое возможно под win8

Andrey: Pasha пишет: В конце концов, создайте ярлык на "letodb install" и запустите его с правами администратора, если такое возможно под win8 Спасибо БОЛЬШОЕ !

Pasha: Обнаружилось, что при создании дочерних потоков в mt-версии letodb не копируются настройки set и некоторые другие из основного потока, что вызывает некоторые неудобства. Команды SET, установленные для основного потока, не действуют в дочерних Как бы это поправить ? Вроде бы надо задать параметр для вызова в leto_2.c: hb_vmThreadInit( NULL ); Просто указать: PHB_THREADSTATE pThread = hb_threadStateClone( 0, NULL ); hb_vmThreadInit( ( void * ) pThread ); я не могу, так как структуры вида PHB_THREADSTATE требуют установки #define _HB_API_INTERNAL_ Чего хотелось бы избежать. Есть ли другой способ ?

Pasha: С копированием структуры set возникли некоторые проблемы, поэтому пока я просто обавлю новый параметр настройки в letodb.ini: AutOrder = ... Мне собственно был нужен этот параметр

Панченко: Pasha, "добавлю" или "добавил"?

Pasha: Панченко пишет: "добавлю" или "добавил"? На своей локальной копии уже добавил. На CVS сброшу вечером.

Панченко: Pasha пишет: На CVS сброшу вечером. А можно повторить адрес CVS LetoDB? А то у меня версия 2.09 от 07.12.12 с Sourceforge :(

Pasha: Адрес CVS - это не url. Надо установить какой-нибудь CVS-клиент под windows, например TortoiseCVS (он бесплатный), и затем сделать checkout с параметрами: cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb checkout -r rel-1-mt letodb

Andrey:

Pasha: Надо вводить адрес: :pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb и ревизия: rel-1-mt

Панченко: Pasha, а можно подробнее: AutOrder = 0 - настройка для SET AUTORDER Что будет при о, а что при 1?

PSP: Панченко пишет: Что будет при о, а что при 1? http://www.creasolgroup.com/xOraclipLanguageReferenceGuide/xOraClip%20Language%20Reference/Commands/Set_autorder.en.html

Панченко: to PSP My English is very-very poor - это одна из тех немногих фраз, которые я вынес из уроков английского. Поэтому хочу уточнить: речь идет о том, будет ли по USE автоматически открываться индекс. Правильно я понял?

Pasha: Панченко пишет: Что будет при о, а что при 1? SET AUTORDER - это стандартная настройка харбора. Она определяет, какой индекс по номеру будет активен после открытия файла, и по какому будет отработан go top. По умолчанию это 0. Я хочу, чтобы сразу был установлен 1-й индекс, чтобы не делать лишних действий при открытии БД Я это делаю для оптимизации открытия БД Предположим, БД состоит из 50 таблиц, с индексом в каждой Раньше открытие БД заключалось в действиях: 1) проверка существования таблицы через leto_File (2 запроса - для таблицы и для индекса) 2) открытие через use 3) вызов ordSetFocus(1), go top Для такой БД получалось 50*(2+1+1) = 200 запросов к серверу (на самом деле еще больше). Сейчас я обхожусь двумя запросами: 1. Вызов UDF_FilesExist 2. Вызов UDF_OpenTables Разница есть ? Мне так кажется, что есть маленькая :)

PSP: Да. Есть команда SET AUTOPEN. Используется для автоматического открытия индекса при открытии dbf. По-умолчанию она в OFF. Так вот, если выполнить SET AUTOPEN ON, то с помощью SET AUTORDER можно указать, какой индекс станет управляющим в составном индексном файле. По-умолчанию установлена в 0.

Панченко: Pasha пишет: Раньше открытие БД заключалось в действиях: 1) проверка существования таблицы через leto_File (2 запроса - для таблицы и для индекса) 2) открытие через use 3) вызов ordSetFocus(1), go top Т.е., теперь по умолчанию (AutOrder=0) выполняются только 1 и 2 пункты?

Pasha: Панченко пишет: Т.е., теперь по умолчанию (AutOrder=0) выполняются только 1 и 2 пункты? Вместо 1 я проверяю существование всех таблиц и индексов одним вызовом UDF_FilesExist, а вместо 2 - открываю все существующие таблицы одним вызовом UDF_OpenTables.

Панченко: Pasha пишет: Разница есть ? Мне так кажется, что есть маленькая :) НУ тогда конечно :))

AlexMyr: PSP пишет: Да. Есть команда SET AUTOPEN. Используется для автоматического открытия индекса при открытии dbf. По-умолчанию она в OFF. Вроде всегда была .T., или я не прав?

PSP: AlexMyr пишет: Вроде всегда была .T., или я не прав? Да, я ошибся

Andrey: Проясните пожалуйста вопрос взаимодействия LetoDB и FastReport. Мне нужно будет для построения отчетов FastrReport делать выгрузку из базы на локальный комп ?

AlexMyr: Andrey пишет: Мне нужно будет для построения отчетов FastrReport делать выгрузку из базы на локальный комп ? смотрим внимательно, уже было обсуждение http://clipper.borda.ru/?1-4-0-00000756-000-60-0#043

Andrey: Pasha пишет: Можно создать в проекте папки doc\en, doc\ru, и туда выкладывать описание функций по разделам, примерно как это сделано в contrib\hbct\doc, файловые функции как раз пойдут в letofile.txt Когда появиться дока хотя бы на русском ? Пытаюсь пользоваться letodb-2.09-win Пока тормоз полнейший по хХарбору. Переписал lib.xharbour\rddleto.lib в xHarbour\lib, include в xHarbour\include Пытаюсь собрать пример \letodb-2.09-win\tests\test_var.prg, выдает ошибку: Error: Unresolved external '_hb_setGetAutOrder' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|leto1 Error: Unresolved external '_hb_arraySetCL' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|leto1 Error: Unresolved external '_hb_arraySetND' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|leto1 Error: Unresolved external '_hb_arraySetDS' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|leto1 Error: Unresolved external '_hb_arraySetL' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|leto1 Error: Unresolved external '_hb_arraySetNL' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|leto1 Error: Unresolved external '_hb_setGetDeleted' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|leto1 Error: Unresolved external '_hb_arraySetC' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|letomgmn Error: Unresolved external '_hb_arraySetNInt' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|letomgmn Error: Unresolved external '_hb_arraySetDL' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|letomgmn Error: Unresolved external '_hb_itemReturnRelease' referenced from Z:\XHARBOUR\LIB\RDDLETO.LIB|letomgmn

Pasha: Andrey пишет: Когда появится дока хотя бы на русском ? Дока на русском есть. Это было предложение по ее переработке, а не созданию. А переработана она будет, когда это кто-нибудь сделает. У меня сейчас таких планов нет. Пытаюсь пользоваться letodb-2.09-win Пока тормоз полнейший по хХарбору. Переписал lib.xharbour\rddleto.lib в xHarbour\lib, include в xHarbour\include Пытаюсь собрать пример \letodb-2.09-win\tests\test_var.prg, выдает ошибку: Все ошибки связаны со стандартными функциями xHarbour из vm.lib. Проверьте свои правила сборки, эта библиотека должна быть указана. Она обязательна для сборки любой xHarbour-программы, не только использующей rddleto.

Andrey: Pasha пишет: Все ошибки связаны со стандартными функциями xHarbour из vm.lib. Проверьте свои правила сборки, эта библиотека должна быть указана. Она обязательна для сборки любой xHarbour-программы Любая другая программа собирается. xHarbour Compiler build 1.0.0 (SimpLex) собираю стандартно, через - HBMAKE test_var.bc #BCC VERSION=BCB.01 !ifndef CC_DIR CC_DIR = $(MAKE_DIR) !endif !ifndef HB_DIR HB_DIR = $(HARBOUR_DIR) !endif RECURSE= NO SHELL = COMPRESS = NO EXTERNALLIB = NO XFWH = NO FILESTOADD = 5 WARNINGLEVEL = 2 USERDEFINE = USERINCLUDE = USERLIBS = EDITOR = notepad GUI = NO MT = NO SRC02 = obj PROJECT = test_var.exe $(PR) OBJFILES = $(SRC02)\TEST_VAR.obj $(OB) PRGFILES = TEST_VAR.PRG $(PS) OBJCFILES = $(OBC) CFILES = $(CF) RESFILES = RESDEPEN = TOPMODULE = TEST_VAR.PRG LIBFILES = lang.lib vm.lib rtl.lib rdd.lib macro.lib pp.lib dbfntx.lib dbfcdx.lib dbffpt.lib common.lib gtwin.lib codepage.lib ct.lib tip.lib pcrepos.lib hsx.lib hbsix.lib rddleto.lib EXTLIBFILES = DEFFILE = HARBOURFLAGS = -m -w2 CFLAG1 = -OS $(SHELL) $(CFLAGS) -d -c -L$(HB_DIR)\lib CFLAG2 = -I$(HB_DIR)\include;$(CC_DIR)\include RFLAGS = LFLAGS = -L$(CC_DIR)\lib\obj;$(CC_DIR)\lib;$(HB_DIR)\lib -Gn -M -m -s -Tpe -x -ap IFLAGS = LINKER = ilink32 ALLOBJ = c0x32.obj $(OBJFILES) $(OBJCFILES) ALLRES = $(RESDEPEN) ALLLIB = $(USERLIBS) $(LIBFILES) import32.lib cw32.lib .autodepend #DEPENDS #COMMANDS .cpp.obj: $(CC_DIR)\BIN\bcc32 $(CFLAG1) $(CFLAG2) -o$* $** .c.obj: $(CC_DIR)\BIN\bcc32 -I$(HB_DIR)\include $(CFLAG1) $(CFLAG2) -o$* $** .prg.obj: $(HB_DIR)\bin\harbour -D__EXPORT__ -n -go -I$(HB_DIR)\include $(HARBOURFLAGS) -o$* $** .rc.res: $(CC_DIR)\BIN\brcc32 $(RFLAGS) $< #BUILD $(PROJECT): $(CFILES) $(OBJFILES) $(RESDEPEN) $(DEFFILE) $(CC_DIR)\BIN\$(LINKER) @&&! $(LFLAGS) + $(ALLOBJ), + $(PROJECT),, + $(ALLLIB), + $(DEFFILE), + $(ALLRES) ! makefile.lnk -LZ:\BCC55\lib\obj;Z:\BCC55\lib;Z:\xHARBOUR\lib -Gn -M -m -s -Tpe -x -ap + c0x32.obj obj\TEST_VAR.obj, + test_var.exe,, + rddleto.lib lang.lib vm.lib rtl.lib rdd.lib macro.lib pp.lib dbfntx.lib dbfcdx.lib dbffpt.lib common.lib gtwin.lib codepage.lib ct.lib tip.lib pcrepos.lib hsx.lib hbsix.lib import32.lib cw32.lib, + , + Менял положение rddleto.lib и в начале и в конце, ошибка та же. Pasha я понимаю что вопрос у меня тупой (не собирается и все тут), но я сейчас пытаюсь для новичков составить инструкцию работы на LetoDB. Пока начал с хХарбора. А то у нас получается что LetoDb используют только "продвинутые программеры" ...

PSP: Может проблема в установке "MT = NO"?

Andrey: PSP пишет: Может проблема в установке "MT = NO"? Поставил MT = YES, не помогает ....

Pasha: rddleto.lib из letodb-2.09-win был собран для xHarbour SVN bcc55 У Вас наверняка другая версия xHarbour. rddleto.lib должен быть совместим с ней, если она конечно не очень древняя. Но лучше пересобрать rddleto.lib своим xHarbour, все-таки время от времени в api вносятся изменения, которые приводят к несовместмости. Что касается этих ошибок линкера, то поищите в vm.lib например строку "_hb_itemReturnRelease" (можно любую из списка). Если она есть, то сборка должна выполняться, надо копаться в правилах сборки. Если нет, или имя функции немного другое, к примеру без символа '_': просто "hb_itemReturnRelease", то однозначно надо пересобирать rddleto.lib

k_dima: Использует ли кто DBFNTX с мемо полями и файлом .dbt ? Я глянул в исходники, в leto1. letoRddInfo() похоже для мемо забит только .fpt case RDDI_MEMOEXT: hb_itemPutC( pItem, ".fpt" ); break; Можно ли это поправить, или это не приведет к ошибке ?

Pasha: k_dima пишет: Можно ли это поправить ? Традиционно со времен клиппера считается, что DBFNTX работает с форматои dbf, а DBFCDX - с fpt. В Харборе и DBFNTX, и DBFCDX понимает как dbt, так и fpt мемо-файл. Формат memo не привязан к формату индекса. И в letodb можно работать и с форматом dbt, и с fpt Настройка RDDI_MEMOEXT - это используемый формат memo по умолчанию. Для DBFNTX/DBFCDX эту настройку можно изменять, для letodb - нельзя. Кстати, если вызвать: hb_rddinfo(RDDI_MEMOEXT,, "DBFNTX") результат будет ".dbt" Вызов hb_rddinfo(RDDI_MEMOEXT,, "DBFCDX") дает пустую строку. Сейчас hb_rddinfo(RDDI_MEMOEXT,, "LETO") возвращает ".fpt". Это ни на что не влияет, но конечно немного некорректно. Можно было бы анализировать, с каким драйвером работает по умолчанию сервер letodb. и для DBFNTX возвращать ".ntx", а в случае DBFCDX - непонятно. То ли ".fpt", то ли для совместимости тоже пустую строку. Для полной совместимости конечно можно в letodb тоже дать возможность задавать эту настройку, но с клиента это делать было бы некорректно, так как один клиент смог бы влиять на настройки другого. Можно добавить настройку формата memo по умолчанию в letodb.ini. Какие будут соображения ?

AlexMyr: Если не задана настройка формата memo в letodb.ini, то возвращать логически ожидаемое для DBFCDX - fpt, DBFNTX - dbt, если задан формат, то это значение.

Andrey: Pasha пишет: У Вас наверняка другая версия xHarbour. rddleto.lib должен быть совместим с ней, если она конечно не очень древняя. xHarbour не очень древний, всего 1.0.0 Но вот на нем и не собирался. Перешел на версию 1.2.1 - все нормально собирается. Вот открыл примеры в папке tests - всего 4 примера... Так и получается что LetoDb предназначен для профи ! В доках конечно описано многое, но вот примеров как правильно делать нет... Хотя бы простого, с обработкой ошибок открытия, созданием базы (обработка ошибки создания), поиском, фильтрацией... Ну блин не пойдет такой продукт в массы... Почему так об этом пишу: D:\@TEST_LETODB\PRG>test_var.exe Connect to //127.0.0.1:2812/temp/test - Ok Adding 'var_int' = 100 to [main] - Err (3) Adding 'var_int' = 100 to [main] - Ok Adding 'var_log' = .T. to [main] - Ok Adding 'var_char' = 'Just a small test;' to [main] - Ok Ну нет у меня такой папки - temp/test, а пишет что все Ok... Если сервер не запущен или Вы указали неверный путь, будет сгенерирована ошибка открытия. Возможно проверить доступность сервера перед открытием файлов вызовом функции leto_Connect( cAddress ), которая вернет -1 в случае неудачной попытки: Ну не "догоняю" я пока простых вещей... Вот код и ошибка: http://files.mail.ru/CA12B2402E4F44FBA16846354711523C Собрано на хХарборе 1.2.1 Народ, дайте хоть исходник любой как надо работать с LetoDb ....

PSP: Андрей, для начала посмотри что в letodb.ini присвоено в DataPath К примеру, файл BaseName.dbf лежит в c:\work\dbf Делаем в letodb.ini: DataPath=c:\work в программе: USE "//127.0.0.1:2812/dbf/BaseName.dbf" Если, к примеру, тот же файл лежит на компе с адресом 192.168.0.100, то в программе: USE "//192.168.0.100:2812/dbf/BaseName.dbf" (соответственно, на компе 192.168.0.100 должен быть запущен сервер letodb и брандмауэр/антивирусник должен разрешать серверу letodb общение с внешним миром)

Pasha: Andrey пишет: Вот открыл примеры в папке tests - всего 4 примера... Так и получается что LetoDb предназначен для профи ! В доках конечно описано многое, но вот примеров как правильно делать нет... Хотя бы простого, с обработкой ошибок открытия, созданием базы (обработка ошибки создания), поиском, фильтрацией... Ну блин не пойдет такой продукт в массы... Андрей, у нас же уже был подобный разговор. Все эти действия - обработка ошибок, создание (dbCreate), поиск, фильтрация и прочее выполняются точно так же, как и для стандартных rdd харбора, DBFNTX/DBFCDX Приводить примеры стандартных операций для rdd в описании letodb бессмыссленно. Это необходимое условие использования letodb. Если програмист с этим не знаком, то ему надо сначала выучить язык. А для опытного клиппериста такие проблемы выглядят странно. Ну нет у меня такой папки - temp/test, а пишет что все Ok... Если сервер не запущен или Вы указали неверный путь, будет сгенерирована ошибка открытия. Возможно проверить доступность сервера перед открытием файлов вызовом функции leto_Connect( cAddress ), которая вернет -1 в случае неудачной попытки: Ну не "догоняю" я пока простых вещей... Описание "Если сервер не запущен или Вы указали неверный путь, будет сгенерирована ошибка открытия. " вырвано из контекста и относится к команде use, а не к leto_connect, которая только проверяет доступность сервера и коннектится с ним. Насколько я понимаю, с коннектом уже проблем нет. А с чем тогда есть ? С созданием папки ? Это что, очень сложно ?

SergKis: Andrey пишет:Народ, дайте хоть исходник любой как надо работать с LetoDb Пример:

AlexMyr: Andrey пишет: Народ, дайте хоть исходник любой как надо работать с LetoDb .... А чем не устраивают те, которые идут вместе с LetoDB?

Andrey: SergKis пишет: Пример: Спасибо БОЛЬШОЕ ! Буду разбираться... AlexMyr пишет: А чем не устраивают те, которые идут вместе с LetoDB? Потому что не понятно как LetoDB работает .... Запустил LetoDb.exe на Win8 с тупизмом присущим 8-ке, через батник. Установил как службу. D:\@TEST_LETODB\letodb.ini [MAIN] Port=2812 Log=letodb.log DataPath=D:\@TEST_LETODB\DATA Служба запущена нормально: D:\@TEST_LETODB\letodb.log 02/27/13 10:45:22: Leto DB Server has been started. Leto DB Server v.2.09 ! INIT: DataPath=D:\@TEST_LETODB\DATA, ShareTables=0, MaxUsers=500, MaxTables=5000, CacheRecords=10 Собираю на хХарборе 1.2.1 пример test_var.exe, запускаю: D:\@TEST_LETODB\PRG>test_var.exe Connect to //127.0.0.1:2812/temp/test - Ok Adding 'var_int' = 100 to [main] - Err (3) Adding 'var_int' = 100 to [main] - Ok Adding 'var_log' = .T. to [main] - Ok Adding 'var_char' = 'Just a small test;' to [main] - Ok Ну нет у меня такой папки - temp/test, а пишет что все Ok... У меня возращает - Connect to //127.0.0.1:2812/temp/test - Ok Это правило действует ТОЛЬКО на удаленные адреса ? На локальном компе ошибка генерироваться будет или нет ? Может 8-ка тупит ? Далее создаю еще папку D:\@TEST_LETODB\DATA\MyDir Делаю свой пример: Function Main Local cPath := "//127.0.0.1:2812/mydir" Local lRes ...... // создаю 2-тестовые базы.... Не могу создать базы, вешается программа - мертво с системной ошибкой... Ссылка на пример и ошибка, приведена выше ! Pasha пишет: Андрей, у нас же уже был подобный разговор. Все эти действия - обработка ошибок, создание (dbCreate), поиск, фильтрация и прочее выполняются точно так же, как и для стандартных rdd харбора, Может был, уже и не помню. Простите меня, памяти не хватает на все. С чем столкнулся, о том и пишу... Pasha пишет: вырвано из контекста и относится к команде use, а не к leto_connect, которая только проверяет доступность сервера и коннектится с ним. Насколько я понимаю, с коннектом уже проблем нет. А с чем тогда есть ? С созданием папки ? Это что, очень сложно ? Понял, спасибо. Видать по доке ошибся... Коннект есть. Папку ручками создал. Не могу создать файл DBF в папке MyDir ! Где и что не так делаю ? Как проверить, что можно в папке на сервере создать файл ?

AlexMyr: Andrey пишет: Ну нет у меня такой папки - temp/test, а пишет что все Ok... У меня возращает - Connect to //127.0.0.1:2812/temp/test - Ok И правильно пишет, что ОК, это значит, что Вы успешно присоединились к серверу по ip адресу 127.0.0.1, на порту 2812. А /temp/... это уже где искать базы. В вашем случае temp/test не папка, а файл test в папке temp. Сначала попробуйте test_ta.prg покрутить.

AlexMyr: Andrey пишет: Далее создаю еще папку D:\@TEST_LETODB\DATA\MyDir Делаю свой пример: Function Main Local cPath := "//127.0.0.1:2812/mydir" Local lRes ...... // создаю 2-тестовые базы.... Не могу создать базы, вешается программа - мертво с системной ошибкой... Ссылка на пример и ошибка, приведена выше ! Правильно будет Local cPath := "//127.0.0.1:2812/mydir/"

Andrey: AlexMyr пишет: Правильно будет Local cPath := "//127.0.0.1:2812/mydir/" Поправил, все равно "ВЕШАЕТСЯ" программа ... Исходник и сборка здесь - http://files.mail.ru/29A0DCDAC71941ADB959D116726D9521 Что я не так делаю ?

Pasha: Andrey пишет: Что я не так делаю ? Мне кажется, надо все-таки пересобрать rddleto.lib своей версией xHarbour. Я выкладывал сборку этой библиотеки с xHarbour SVN, и она может быть несовместима с более ранней версией xHarbour.

Andrey: Спасибо.Понял. Буду пробовать.

Andrey: Pasha пишет: Я выкладывал сборку этой библиотеки с xHarbour SVN, и она может быть несовместима с более ранней версией xHarbour. Точно, не совместима ! Скачал xHarbour 1.2.3 SVN и ВСЕ ЗАРАБОТАЛО.... Блин, как баран в стенку долбился... Pasha а нельзя где нибудь файлик к этой либе ( lib.xharbour\rddleto.lib ) приложить - типа "совместимо/собрано только для xHarbour 1.2.3 SVN" ? Другие чтобы не залетали... А еще лучше запросить версию rddleto.lib из своей программы, функцию какую нибудь. Так можно ?

Dima: Pasha А в LetoDB есть серверные (оптимизированные) фильтры как в ADS ?

Pasha: Andrey пишет: Pasha а нельзя где нибудь файлик к этой либе ( lib.xharbour\rddleto.lib ) приложить - типа "совместимо/собрано только для xHarbour 1.2.3 SVN" ? Другие чтобы не залетали... Мое упущение. Сейчас уже архив перезаливать не буду, учту на следующий раз. А еще лучше запросить версию rddleto.lib из своей программы, функцию какую нибудь. Так можно ? Версию клиента можно запросить вызовом dbinfo(DBI_RDD_VERSION) версию letodb сервера, к которому выполнен коннект: LETO_GETSERVERVERSION() Но это все не для случая сборки программы и клиентской библиотеки разными версиями харбора.

Pasha: Dima пишет: А в LetoDB есть серверные (оптимизированные) фильтры как в ADS ? Да, конечно. При установке фильтра командой set filter сервер пытается выполнить выражение фильтра. Если попытка успешна, то устанавливается серверный фильтр, если нет - фильтр выполняется на клиенте.

Dima: Pasha Понял. А как узнать успешна ли попытка установки фильтра на сервере ?

Pasha: После dbSetFilter надо вызвать проверку: LETO_ISFLTOPTIM() Фильтр может быть неоптимальным (клиентским), если в нем присутствуют переменные памяти или вызовы функций, незарегистрированных на сервере. Еще сервер не поймет ссылки на другие рабочие области. Я не рассматриваю случай просто неверного выражения.

Andrey: На МиниГуи с ходу стало собираться и конектиться... Вопрос по путям: D:\@TEST_LETODB\letodb.ini [MAIN] Port=2812 Log=letodb.log DataPath=D:\@TEST_LETODB\DATA Посмотрел лог-файл на всякий случай: 02/28/13 23:11:37: Leto DB Server has been started. Leto DB Server v.2.09 ! INIT: DataPath=D:\@TEST_LETODB\DATA, ShareTables=.... У меня в программе: #include "rddleto.ch" #include "minigui.ch" Local cPath := "//127.0.0.1:2812/" ..... // Создать базу перед формой, иначе данные будут недоступны MyDbf866(cPath) .... ITEMS LoadDbf866(cPath) ; // загрузить базу на форму // далее эти 2 функции //////////////////////////////////////////////////////////// Procedure MyDbf866(cPath) LOCAL cFileDbf, aDbf := {}, nI cFileDbf := cPath + "test866.dbf" AADD( aDbf , {"FIO" ,"C", 25,0 } ) AADD( aDbf , {"STATUS" ,"C", 10,0 } ) AADD( aDbf , {"CLASS" ,"C", 4,0 } ) DBCreate( cFileDbf, aDbf ) USE ( cFileDbf ) Alias TEMP866 CODEPAGE "RU866" NEW EXCLUSIVE aDbf := {} AADD( aDbf , {"Петров Артем" ,"ученик" ,"1a"} ) ........................... AADD( aDbf , {"Куликов Сергей Борисович" ,"учитель","-"} ) SELECT TEMP866 FOR nI := 1 TO LEN(aDbf) APPEND BLANK TEMP866->FIO := aDbf[nI,1] TEMP866->STATUS := aDbf[nI,2] TEMP866->CLASS := aDbf[nI,3] NEXT CLOSE TEMP866 Return //////////////////////////////////////////////////////////// FUNCTION LoadDbf866(cPath) LOCAL aRows := {}, cFileDbf, cNum cFileDbf := cPath + "test866.dbf" MsgInfo("LETO_FILE( "+cFileDbf+" )=" ) MsgInfo( LETO_FILE( cFileDbf ) ) IF !LETO_FILE( cFileDbf ) AAdd( aRows, {"", "Нет базы / No Base !" , "" , "" } ) AAdd( aRows, {"", cPath , "test866.dbf" , "" } ) ELSE // открытие базы 866 / open base 866 USE ( cFileDbf ) Alias TEMP866 CODEPAGE "RU866" //NEW SHARED SELECT TEMP866 GOTO TOP DO WHILE !EOF() cNum := ALLTRIM(STR( RECNO() ))+"." AAdd( aRows, {cNum, ALLTRIM(FIELD->FIO) , FIELD->STATUS, FIELD->CLASS } ) SKIP ENDDO CLOSE TEMP866 ENDIF RETURN aRows Так вот сам вопрос. База успешно создается по пути: D:\@TEST_LETODB\DATA\test866.dbf А почему при открытии в функции LoadDbf866(cPath) cFileDbf := cPath + "test866.dbf" IF !LETO_FILE( cFileDbf ) -> возвращает .F. Что я не так делаю ?

AlexMyr: Andrey пишет: IF !LETO_FILE( cFileDbf ) -> возвращает .F. в letodb.ini надо EnableFileFunc = 0 - если 1, разрешено использование файловых функций ( leto_file(), leto_ferase(), leto_frename(); читаем readme

Andrey: AlexMyr пишет: читаем readme Спасибо БОЛЬШОЕ ! Пропустил.... А как заставить запущенную службу LETODB перечитать заново letodb.ini ?

AlexMyr: Andrey пишет: А как заставить администрирование-службы-letodb-перезапустить

Andrey: AlexMyr пишет: администрирование-службы-letodb-перезапустить Это понятно, а как на ходу перечитать конфигурацию сервера ? Если удаленно нужно это сделать ?

Pasha: Только перезапуск службы Его можно автоматизировать батником: net stop "LetoDB Service" net start "LetoDB Service"

Andrey: Pasha пишет: Его можно автоматизировать батником: Спасибо БОЛЬШОЕ ! А не планируется ли какая то хитрая команда на сервер LetoDB чтобы на "ходу" править конфигурацию его. А то если нет доступа по удаленке на комп, то труба... Ножками топать придется к заказчику...

PSP: Андрей, зачем?

Pasha: Andrey пишет: А не планируется ли какая то хитрая команда на сервер LetoDB чтобы на "ходу" править конфигурацию его. А то если нет доступа по удаленке на комп, то труба... Ножками топать придется к заказчику... Не планируется. Этих настроек всего-то 3-4 позиции, и выставить их правильно изначально труда не составляет.

Dima: PSP пишет: А не планируется ли какая то хитрая команда на сервер LetoDB чтобы на "ходу" править конфигурацию его Даже в ADS нет такого.

Andrey: Уже и сразу запинали....

Dima: Что то не могу обновиться. Может кто чего подскажет... http://shot.qip.ru/00bVmc-3vwdt63nm/ http://shot.qip.ru/00bVmb-3V4IuUaS2/ http://shot.qip.ru/00bVma-3d3R3GdrE/

Pasha: Только что успешно обновился с точно такими же параметрами. Но у меня очень старая версия TortoiseCVS: 1.8.3 2004 года С тех пор, как начал работать с харбором (делать коммиты) - не обновлял ее. А это было 9 лет назад

Pasha: AlexMyr пишет: Если не задана настройка формата memo в letodb.ini, то возвращать логически ожидаемое для DBFCDX - fpt, DBFNTX - dbt, если задан формат, то это значение. Наконец-то дошли руки, и сделал поддержку параметра Memo_Type в letodb.ini

Dima: Dima пишет: Что то не могу обновиться Переустановил TortoiseCVS , заработало ;)

Dima: Pasha А какие то требования к OS Windows есть , там где будет крутится LetoDB Server ? Это должна быть серверная OS или нет ? Я имею в виду что на обычной винде не серверной есть ограничение на кол-во подключений по сети.

PSP: LetoDB не создает клиентскую сессию Windows. Так что эти ограничения его не касаются.

Dima: PSP Спасиб

Dima: Pasha пишет: Да, конечно. При установке фильтра командой set filter сервер пытается выполнить выражение фильтра. Если попытка успешна, то устанавливается серверный фильтр, если нет - фильтр выполняется на клиенте. Это понятно. А серверные фильтры оптимизированы (при наличии соответствующего индекса) как в ADS или SIX ?

Pasha: Dima пишет: А серверные фильтры оптимизированы (при наличии соответствующего индекса) как в ADS или SIX ? Нет, не оптимизированы, поскольку их не поддерживает сам харбор В этом случае фильтр надо самому разделить на 2 части: для индексных полей использовать set scope, для неиндексных - set filter

Dima: Pasha пишет: Нет, не оптимизированы, поскольку их не поддерживает сам харбор А планируется ли такая фича ? По ходу харбор их не поддерживает но ведь они все же поддерживаются в RDDADS а точнее сказать наверное в ADS сервере.

Dima: Pasha пишет: Нет, не оптимизированы, поскольку их не поддерживает сам харбор А это что тогда ? [pre2] SET OPTIMIZE ON | OFF | (<lToggle>) Arguments ON enables optimization. OFF disables optimization. <lToggle> is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF. Note: The initial default of this setting depends on the RDD. Description The SET OPTIMIZE command determines whether or not to optimize filters in the current work area. Optimization is based on index expressions of indexes open in the current work area. When a filter condition matches with an index expression, the RDD, such as DBFCDX, compares values stored in the index rather than the database. This leads to an enhanced performance since less disk I/O is required during database navigation. [/pre2]

Pasha: Dima пишет: А планируется ли такая фича ? По ходу харбор их не поддерживает но ведь они все же поддерживаются в RDDADS а точнее сказать наверное в ADS сервере. Даже Przemek не упоминал об этом. А rddads поддерживает такие фильтры, поскольку их поддерживает сам Ads.

Dima: Dima пишет: SET OPTIMIZE ON Не фига она не оптимизирует. Нужный индекс есть , ставлю фильтр и получаю такой же тормоз как и без индекса. Упс ;) Не прав. Не ту доку смотрел. Оптимизирует но только "BMDBFCDX"

Andrey: Dima пишет: SET OPTIMIZE ON | OFF | (<lToggle>) Я тоже расстраивался, когда перешел с Клипера на Харбор. Pasha пишет: Вопрос по НАСТРОЙКЕ LetoDB. Как настроить его для внешней и внутренней сети одновременно. Т.е. нужно, чтобы часть рабочих станций работала через внешний IP, а часть по локальной сети предприятия. Как быть в этом случае ?

a_sidorov: Так ты настраивай программу, а не LetoDB. LetoDB будет свой на каждом сервере. А как и где открывать файлы решать программе. Можно часть файлов открывать без Letodb. Я определяю это в зависимости от пути к файлам. Если путь к серверу с LetoDВ, открываю файл VIA LETO. Программе все равно, сколько серверов и сколько LetoDB используется. Я таким образом синхронизирую данные на удаленном сервере со своим сервером, оба на разных LetoDB. Для программы это просто разные пути к файлам, открытые VIA LETO и все.

Pasha: Andrey пишет: Как настроить его для внешней и внутренней сети одновременно. Т.е. нужно, чтобы часть рабочих станций работала через внешний IP, а часть по локальной сети предприятия. Если я правильно понял, letodb сервер планируется поставить один, но часть клиентов будет к нему обращаться по ЛВС, а часть - через интернет. В любом случае на клиенте должна быть настройка адреса сервера. Если это для ЛВС - то это должен быть ip или имя компьютера внутри ЛВС, если через интернет - то внешний ip компьютера, на котором работает сервер letodb.

Andrey: Pasha пишет: Если я правильно понял, letodb сервер планируется поставить один Да, именно так ! А кто так работает, поделитесь статистикой, нормально ли работает ? Можно ли по сотовому модему (медленному) работать с базой через LetoDB ?

Pasha: Andrey пишет: А кто так работает, поделитесь статистикой, нормально ли работает ? Можно ли по сотовому модему (медленному) работать с базой через LetoDB ? Все зависит от того, насколько медленному. Я работал через инет соединение только в качестве теста. С обеих сторон скорость была не очень высокой. Кое-какие операции пришлось оптимизировать. Я в letodb.ini включал опцию "Debug=10", и анализировал лог запросов. Сразу становилось видно, что неоптимально. Те операции, которые в локалке были некритичными, через инет тормозили работу. В результате оптимизации получилось более-менее приемлемо. Но это был только тест.

SergKis: Andrey пишет:А кто так работает, поделитесь статистикой, нормально ли работает ? Можно ли по сотовому модему (медленному) работать с базой через LetoDB ? LetoDB от 21.04.2011, hb 2.0, bcc. Тесты проводил под Петербургом (10 км) операторы Bilain, MTC, в Риге и 40 км от нее (примерно 1.5 года назад). Сервер в Риге. Скорости соединения примерно одинаковые (в Риге чуть быстрее). Про загрузку dbf на сервер я уже писал и там же были базовые исходники тестов. Browse (WVT, 80, 25) длина записи в базе ~3K предел скорости просмотра, добавленный relation к др. области - это все встало. Browse на длину записи в базе ~1K и два relation держит приемлемо, длина записи в базе 50-300 байт - можно сказать летают. Самые быстрые операции - выборка, длина записи в базе 400-1000 байт за 1.5 сек. отбираются ~2000-4000 записей. После тестирования, мы стали использовать rdd MEMIO, куда делаем выборки и Browse работает на MEMIO, связывая MEMIO relation по RecNo или ключам с сервером или с dbf на MEMIO (справочники). Сейчас такую штуку используем при переводе Clipper,WVT на MiniGui MDI (правда пока без сервера - надо интерфейс и алгоритмы перевести и потом подключать сервер). В связи с такой методикой работы, показался очень интересным использовать skip буфер, в новой версии LetoDB (приставал к Паше с вопросами где то выше), что бы в skip буфере использовать список нужных полей и сразу колонку с RecNo dbf сервера, а не весь буфер записи.

Pasha: Добавлю, что надо правильно использовать skip-буфер: скажем, для browse задавать его не меньше кол-ва строк для просмотра. Еще я стал активно использовать seek-буфер, в каких-то случаях очень помогает. В целом все зависит от скорости соединения и от того, как написана программа. Можно и для скорости в десятки мегабит сделать программу так талантливо, что она будет висеть. Для медленного gprs соединения надо уж очень постараться. Для скорости порядка сотен KB - единиц MB тоже надо хорошо приложить руки, чтобы добиться нормальной работы.

a_sidorov: Опыт следующий: Три сервера Letodb, с добавленными функциями и транслированные на xHarbour 1.2.1, расположенными в разных точках Москвы(2 сервера и 1 локалка с сервером LetoDB , подключенная через Синтерра). Пользователи (программа на XHarbour 1.2.1) работают на трех независимых БД из соображения надежности как по питанию, так и по другим критериям. Программа синхронизации на xHarbour 1.2.1 (доступ к серверам через Letodb) раз в час синхронизирует все данные на трех серверах (двух серверах и локалке), перенося измененные данные. Программа синхронизации установлена на одном из серверов, где больше данных. Поскольку это СРМ, считается, что один клиент в течение времени синхронизации не покупает в разных офисах. Индексы NTX.

Dima: По поводу ошибки leto_errInternal!!!!!!!!!!!!!!!!!! в letodb.log [pre2] 1. letodb.exe install (перед этим я остановил и удалил сервис Leto) 2. Лезем в панель управления в службы и стартуем LetoDB (это окно у меня уже было открыто) 3. Запускаем приложение и оно как бы подвисает на строке leto_Connect( "//127.0.0.1:2812/" ) , затем пара-тройка виндовых ошибок вылазит и прога падает при открытии базы с месагой Error leto/1000 data type error В логе видим leto_errInternal!!!!!!!!!!!!!!!!!! [/pre2] А вот так ошибки нет [pre2] 1. letodb.exe install (перед этим я остановил и удалил сервис Leto) 2. net start "LetoDB Service" [/pre2] PS Не понятно кто виновник , винда (XP SP 3) или сервис Leto При чем происходит так через раз.

Dima: Dima пишет: 2. Лезем в панель управления в службы и стартуем LetoDB (это окно у меня уже было открыто) Похоже в этом причина. Окно с сервисами не автообновляется. И если я вижу что сервис запущен то на самом деле он может быть и не запущен вовсе. Что бы увидеть реальную картину окно надо обновить ручками или закрыть/открыть.

SergKis: Паша, в версии Changelog,v 1.350 2011/04/21 18:00:52 есть LETO_SETSKIPBUFFER( nSkip ), но в readme нет как использовать, что дает nSkip ? Если можно разъясните.

Pasha: В текущем readme есть описание: Skip-буфер предназначен для оптимизации множественных вызовов skip Эта функция задает размер в записях для skip-буфера для текущей рабочей области. По умолчанию размер skip-буфера 10 записей. Skip-буфер является двунаправленным. skip-буфер сбрасывается после BUFF_REFRESH_TIME (1 сек) Если параметр функции опущен, она возвращает статистику использования буфера (количество попаданий) Проще говоря, при выполнении команд skip(1), skip(-1) сервер передает клиенту не одну запись, а nSkip записей, и при последующих вызовах skip обращения к серверу не будет, клиент возьмет запись из буфера.

SergKis: Pasha пишет:Skip-буфер предназначен ... СПАСИБО за разъяснение. Pasha пишет:В текущем readme есть описание У меня версия: readme_rus.txt,v 1.12.2.16 2012/02/23 15:38:35. В ней только: LETO_SETSKIPBUFFER( nSkip ) --> nCount (статистика использования буфера) LETO_SETSEEKBUFFER( nRecsInBuf ) --> nCount (статистика использования буфера) Буду обновляться.

Dima: SergKis пишет: readme_rus.txt,v 1.12.2.16 2012/02/23 15:38:35 последняя вроде такая /* $Id: readme_rus.txt,v 1.12.2.29 2013/03/02 18:45:45 ptsarenko Exp $ */

Dima: Pasha А если в Leto юзать RDD DBFSIX или BMDBFCDX , Leto будет так же эффективно работать как и с DBFCDX ?

Pasha: В харборе функциональность six в основном включена в DBFCDX, так что она и сейчас в основном доступна через вызовы dbInfo и dbOrderInfo "В основном" я говорю потому, что не все команды DBI_* и DBOI_* реализованы в rdd leto. Каких не хватает - надо смотреть. А насчет BMDBFCDX - можно было бы сделать возможность сборки сервера letodb, в котором в качестве стандартных rdd вместо DBFCDX/DBFNTX использовались бы BMDBFCDX/BMDBFNTX, тем более они их наследники. Еще конечно нужно реализовать семейство функций BM_*, причем и на клиенте, и на сервере. Сделать это лучше через вызовы UDF-функций, чтобы не перегружать существующий низкоуровневый протокол передачи между клиентом и сервером. Думаю, как это лучше прикрутить.

Dima: В большей степени конечно интересен BMDBFCDX/BMDBFNTX , про SIX это я так просто спросил "паровозиком".

Dima: Как можно объяснить медленный SKIP по базе (чем то похож на медленный Skip в ADS) ? Для примера взял базу 700000 записей DBFCDX Скипал всю базу Время 0.23 сек Leto (локально 127.0.0.1) на том же тесте 75 секунд Соответственно если юзать бровс то с Leto заметны задержки Dima пишет: Соответственно если юзать бровс то с Leto заметны задержки Упс. LETO_SETSKIPBUFFER в какой то мере решает эту проблему.

Pasha: Еще tbrowse любит все время опрашивать RecCount(), на каждой записи, а это дополнительные обращения к серверу, причем много. Для буферизации этих вызовов надо после коннекта к серверу задать настройку: RddInfo( RDDI_REFRESHCOUNT, .F.,, 1 ) В ads тоже есть подобная настройка.

Dima: Pasha пишет: RddInfo( RDDI_REFRESHCOUNT, .F.,, 1 ) Помогло , спасибо !

Dima: Pasha пишет: В ads тоже есть подобная настройка В Harbour ? Не нашел. А в Clipper есть ?

Pasha: Она есть в самом Ads. Год назад я ее добавил для xHarbour: 2012-03-19 18:55 UTC+0200 Pavel Tsarenko (tpe2/at/mail.ru) * contrib/rdd_ads/ads.ch * contrib/rdd_ads/ads1.c * contrib/rdd_ads/rddads.h * added new flag for RddInfo: RDDI_REFRESHCOUNT. By default, this flag is set to true. This flag is used for management of ADS_REFRESHCOUNT flag in adsRecCount function. в Harbour ее действительно не перетянули. Для клиппера даже не знаю, как она используется, если используется вообще. Клиент то совсем другой, старый, закрытый.

Dima: Проверил работу Leto через инет. Leto База в одном городе , Leto клиент в другом. Относительно не плохо работает. В частности проверил удаленно BM фильтра , ставятся моментально. Установки на клиенте RddInfo( 101, .F.,, 1 ) LETO_SETSKIPBUFFER(10000) Бровс конечно подтормаживает. Будут какие то рекомендации ? ЗЫ Если LetoDB.ini нет в папке откуда стартовал LetoDB Server , разве LetoDB Server не должен сам его создать с установками по умолчанию ?

Pasha: Dima пишет: LETO_SETSKIPBUFFER(10000) Бровс конечно подтормаживает. Будут какие то рекомендации ? Не надо 10000 задавать. За раз передается 10000 записей, а это много, пакет большой. Да и не надо столько, ведь время актуальности буфера 1 секунда. Достаточно задать размер, равный к-ву строк в бровсе, ну или maxrow() Дополню. Это для ЛВС для времени актуальности буфера 1 сек достаточно. Для медленного соединения лучше задать побольше. Это или глобальная установка: 5-й параметр функции leto_Connect, или для конкретной рабочей области задается вызовом dbInfo( DBI_BUFREFRESHTIME[, nNewVal]) Значение задается в 0.01 сек. ЗЫ Если LetoDB.ini нет в папке откуда стартовал LetoDB Server , разве LetoDB Server не должен сам его создать с установками по умолчанию ? Файл ini не создается, просто задаются установки по умолчанию. Но ini файл нужен хотя бы для указания DataPath Мой стандартный letodb.ini: DataPath = <path> EnableFileFunc = 1 EnableAnyExt = 1 Optimize = 1 AutOrder = 1

Dima: Лето собран как сервис. Периодически падает прога на строке LETO_CONNECT("//127.0.0.1:2812/") В логе [pre2] DEBUG! new connect 127.0.0.1 (0 : 1 : 1) leto_errInternal!!!!!!!!!!!!!!!!!! [/pre2] А винда пишет [pre2] szAppName : letodb.exe szAppVer : 0.0.0.0 szModName : letodb.exe szModVer : 0.0.0.0 offset : 000b23dc [/pre2] После этого сервис лето падает. Как я это получил ? Остановил и удалил сервис Затем Letodb install , net start "LetoDB Service" Запустил свой примерчик пару тройку раз (все норм но только порой долго думает прога на строке LETO_CONNECT) и на 4 раз вот такое вылазит . PS еще наблюдение. если пересобрать клиентское приложение то в 30% после первого запуска LETO_CONNECT выдаст -1 Dima пишет: PS еще наблюдение. если пересобрать клиентское приложение то в 30% после первого запуска LETO_CONNECT выдаст -1 PS1 Интенсивно мучаю Leto уже 30 минут и такого больше не повторяется.....странно

Dima: А как быть с копированием файлов на Leto Server ? cserv:="//127.0.0.1:2812/" copy file test.txt to (cserv+"test1.txt") Получаю Dos error 1231 Среди лето функций что типа leto_copyfile в описании не увидел. Вполне устроила бы функция позволяющая копировать файлы "внутри" сервера , что то типа Leto_filecopy(cserv+"test.txt",cserv+"test1.txt")

Andrey: Dima пишет: А как быть с копированием файлов на Leto Server ? Я тоже на этом залетал... Я бы тоже не отказался от функций: Leto_filecopy(cServer+"test.txt",cServer+"test1.txt") Leto_filecopy(cLocal+"test.txt",cServer+"test1.txt") Leto_filecopy(cServer+"test.txt",cLocal+"test1.txt") AlexMyr пишет: в letodb.ini надо EnableFileFunc = 0 - если 1, разрешено использование файловых функций ( leto_file(), leto_ferase(), leto_frename(); читаем readme

Dima: Pasha А в чем разница между leto_RecLock() и RLock() если база открыта с RDD Leto и нужно залочить текущую запись ? ЗЫ Что то Пашу мы завалили вопросами , надо взять таймаут В свое время я был тестером Winpint и тоже заваливал автора вопросами и пожеланиями. В итоге продукт получился отличный

Pasha: Dima пишет: Периодически падает прога на строке LETO_CONNECT("//127.0.0.1:2812/") Чего-чего, а такой нестабильной работы с letodb у меня никогда не было, да еще на элементарном коннекте. Если бы сервер где-нибудь упал, шума было бы много. Но такого не было. Конечно, это версия letodb+bm, она только что появилась. Но все фичи bmdbf при коннекте еще не задействованы. Непонятно.

Pasha: Dima пишет: А как быть с копированием файлов на Leto Server ? Надо использовать функции leto_MemoWrite и leto_FileWrite

Pasha: Dima пишет: А в чем разница между leto_RecLock() и RLock() если база открыта с RDD Leto и нужно залочить текущую запись ? leto_RecLock предназначена для использования исключительно на сервере, в udf-функциях. А с клиента надо работать стандартными средствами rlock/flock/dbRLock На сервере их использовать нельзя, поскольку смысл блокировок на сервере другой. Сервер открывает файлы (при стандартном режиме) монопольно, и блокировки там выполняются логически.

Dima: Pasha Спасибо за разъяснения !

Pasha: Dima пишет: еще наблюдение. если пересобрать клиентское приложение то в 30% после первого запуска LETO_CONNECT выдаст -1 Я тоже напоролся на это. Пока 2 предположения: или служба "еще не до конца запустилась", а клиент уже коннектится к ней и валит ее (я службу постоянно останавливаю-пересобираю-запускаю-запускаю тест). Либо все-таки есть какой то баг в операциях с памятью, связанный с BM Но у меня эта ситуация возникает только в момент первого запуска теста после старта службы.

Dima: Pasha пишет: Но у меня эта ситуация возникает только в момент первого запуска теста после старта службы я тоже обратил на это внимание , закономерности пока не понял. в течении дня таких глюков больше не было. Pasha пишет: Либо все-таки есть какой то баг в операциях с памятью, связанный с BM Не знаю. Еще до того как начинаю юзать BM то падало на LETO_CONNECT() Если мне не изменяет память то еще до ввода BM такой глюк имел место , возможно сервис LetoDB еще не до конца запустился. В свое время именно из за этого я и не стал тестить Leto. Поживем , посмотрим , может и найдем что. А вообще LetoDB мне уже начинает нравиться ;) Мне вот просто интересно. В плане надежности имеет значение как юзать сервер Leto , как SERVICE или DAEMON ? Чисто в теории разницы в надежности и стабильности быть не должно.

Pasha: Сбросил изменения на CVS Для того, чтобы по команде SET FILTER формировался bitmap-фильтр, надо в letodb.ini задать параметр: ForceOpt = 1 А насчет демона - я, как только появилась служба, демон не использовал ни разу. Служба намного удобнее. Нет проблем с правами доступа. Запускает ее сама система, не нужен вход пользователя.

Dima: Pasha пишет: Сбросил изменения на CVS Спасибо , завтра проверю. Отпишу тут.

Pasha: Кстати, маленький ньюанс Я службу останавливать/запускать батником стал недавно, а до этого делал это через диспетчер служб. Там процесс запуска отображается на экране, и видно, когда служба запустилась. Поэтому тест "в процессе" никогда не коннектился. Если это делать из батника, то окончания запуска не видно, вот наверное и возникают накладки.

Dima: Pasha пишет: Я службу останавливать/запускать батником стал недавно Ну смотря как батник устроен. Если echo off то не видать ни чего а если echo on тогда виндец ошибку выдаст если что. Что то типа такого [pre2] The requested service has already been started. More help is available by typing NET HELPMSG 2182. [/pre2]

Pasha: Есть еще пара моментов. Во первых, при вызове LBM_dbSetFilterArray(), надо сбрасывать skip-буфер. Это я добавлю вечером. Во-вторых, я хочу все-таки сделать, чтобы не всякий фильтр строился как bitmap, а только если на клиенте также установлен _SET_FORCEOPT. Для этого эту настройку надо передавать серверу вместе с фильтром. Таким образом, на клиенте можно будет управлять, какой фильтр будет bitmap, а какой - обычный.

Dima: Да все заработало. По команде Set filter to так же ставится опт. фильтр. Но в этом случае LBM_DBGETFILTERARRAY() вернет 0 а это не правильно. Со сбросом фильтра все нормально. Есть правда не удобство но к нему можно и привыкнуть. LBM_DBSETFILTERARRAY({1,590,234,2345,7899,9000,700000}) go top // видим 7 записей LBM_DBSETFILTERARRAY({1,590) go top // видим 2 записи Тут все норм. А вот так нет Set filter to nomer==5 go top // видим 30 записей dbclearfilter() // нужно принудительно сбросить фильтр после Set filter to....... LBM_DBSETFILTERARRAY({1,590) go top // если фильтр не снять не увидим ни чего То есть поведение LBM_DBSETFILTERARRAY и у dbsetfilter() разное а должно быть одинаковое. В BMDBFCDX именно так

Dima: Dima пишет: copy file test.txt to (cserv+"test1.txt") Pasha пишет: Надо использовать функции leto_MemoWrite и leto_FileWrite Да работает leto_memowrite(cserv+"test1.txt",leto_memoread(cserv+"test.txt")) или же можно поблочно , считывать и писать с помощью Leto_FileRead , Leto_FileWrite

Dima: Pasha Закроешь эту тему когда посчитаешь нужным. Продолжение будет в Leto DB Server (продолжение 9)

Dima: Pasha я тут подумал. может оставить в покое DBsetfilter и пусть он работает как и работал до введения BM , если это сложно. для установки BM фильтра вполне достаточно иметь LBM_DBSETFILTERARRAY а оптимально заполнить массив как бы и не проблема.



полная версия страницы