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

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

Dima: Продолжаем тут

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

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

Dima: Pasha пишет: Да уже все равно сделано В смысле уже на CVS с учетом последних глючков ? В Index on почему не срабатывает предложение [EVAL <bBlock>] ? Без него плёхо будет , юзеры не поймут.

Pasha: Нет, на CVS не сбрасывал. Но это уже называется "осталось допилить" А индексация ведь выполняется на сервере, и во время индексации обмена между клиентом и сервером нет, поэтому EVAL и не поддерживается.


Dima: Pasha пишет: А индексация ведь выполняется на сервере, и во время индексации обмена между клиентом и сервером нет, поэтому EVAL и не поддерживается. Хммм а почему в ADS это работает ? [pre2] Предложение EVAL обычно содержит пользовательскую функцию (UDF), которая отображает состояние создания индекса. UDF доступна клиенту пока на сервере строится индекс. Если условие EVAL определено, оно будет вычисляться каждые 2 секунды у клиента. С такой частотой Advantage изменяет внутренний номер записи и количество ключей. Если используются функции RecNo() и/или AX_KeysIncluded(), будет возвращен корректный результат. [/pre2] По моему разумно сделано и юзеру можно показать что он не "висит". Пометил красным ключевую фразу.

Pasha: Это в клиппере ? Я смотрю, в харборе в rddads тоже это условие игнорируется Запускать его отдельным потоком во время ожидания завершения индексации, что ли Пока не представляю, как это сделать

Dima: Pasha пишет: Это в клиппере ? Да А вот так в RDDADS [pre2] INDEXING and Progress Displays: Remote server does not support the EVAL/EVERY clauses. Remember, there is an external process doing the indexing that knows nothing of Harbour expressions or codeblocks. Even with Local Server it's the DLLs doing all the indexing. So to do progress meters you need to implement <b>AdsRegCallback( bEval )</b>. It lets you set a codeblock that is eval'ed every 2 seconds. A numeric value of the "percent completed" is passed to the codeblock by the ADS server. <table> #include "inkey.ch" PROCEDURE Main() ... AdsRegCallback( {| nPercent | outputstuff( nPercent ) } ) /* The above codeblock will be called approximately every 2 seconds while indexing. The codeblock can return .T. to abort. */ INDEX ON First+LAST+LABEL1+LABEL2 TAG First AdsClrCallback() RETURN FUNCTION outputstuff( nPercent ) /* The "callback" function */ ? "output stuff", nPercent RETURN Inkey() == K_ESC /* If press ESC, returns .T. to abort. */ </table> [/pre2] На маленьких базах EVAL в индексе не нужен а вот если база широкая и толстая.......... Можно пойти по тому же пути как в описании выше к RDDADS Тебе виднее можно и нужно ли это. я просто высказал пожелание

Pasha: Отправил на CVS изменения по BM-фильтрам, о которых мы говорили, кроме учета настройки _SET_FORCEOPT на клиенте.

Dima: как бы все красиво но не все. нужно сбрасывать фильтра при установке LBM_DBSETFILTERARRAY() и не важно как они ставились через dbsetfilter или LBM_DBSETFILTERARRAY То есть если сделать так LBM_DBSETFILTERARRAY({1,2,3}) go top ? len(LBM_DBGETFILTERARRAY()) //3 LBM_DBSETFILTERARRAY({1}) go top ? len(LBM_DBGETFILTERARRAY()) //1 работает а если так нет и надо делать dbclearfilter перед LBM_DBSETFILTERARRAY Set filter to nomer==3 go top ? len(LBM_DBGETFILTERARRAY()) //36 LBM_DBSETFILTERARRAY({1}) go top ? len(LBM_DBGETFILTERARRAY()) //0 Pasha пишет: кроме учета настройки _SET_FORCEOPT на клиенте а что там еще не так ? А вообще отличная работа , спасибо !!!

Andrey: Dima пишет: На маленьких базах EVAL в индексе не нужен а вот если база широкая и толстая.......... Можно пойти по тому же пути как в описании выше к RDDADS Тебе виднее можно и нужно ли это. Нужно ! Как юзер увидет что идет индексация ? Что-то нужно делать с этим... Не сейчас, так чуть позже, все равно я только пробую...

Dima: Andrey пишет: Как юзер увидет что идет индексация ? как бы идея есть но она не самая хорошая и сам процесс индексирования конкретного файла юзер не увидит.

Pasha: Dima пишет: Pasha пишет: цитата: кроме учета настройки _SET_FORCEOPT на клиенте а что там еще не так ? Сейчас на сервере letodb+bm используется драйвер BMDBF*. По команде "set filter to ..." строится либо BM-фильтр (если включен FORCEOPT), либо обычный (если выключен). Реализация bm-фильтра в нынешнем варианте BMDBF* мне не нравится, поскольку фильтр строится для всех записей файла. Я об этом написал в devlist, но автор: Przemek - туда не заглянул. Поэтому я хочу дать возможность клиенту также установить эту опцию. Если на сервере FORCEOPT включен, то с клиента можно будет задавать для кажного фильтра его настройку: будет ли он обычный или bitmap. Конечно, можно переделать реализацию letodb+bm: на клиенте добавить еще один rdd: LETOBM, наследник LETO. При этом для первого сервер работал бы через BMDBFCDX, а для второго - через DBFCDX. Это был бы самый гибкий способ, но реализация его сложнее.

Dima: Dima пишет: нужно сбрасывать фильтра при установке LBM_DBSETFILTERARRAY() Pasha Это можно починить ?

Dima: Pasha А можно ли с клиента узнать время и дату на сервере Leto ? Можно ли это добавить в LETO_MGGETINFO() ?

Pasha: Dima пишет: Pasha Это можно починить ? Да, вечером сделаю А какая дата сервера нужна ? Текущая ? Можно самому сделать функцию в letoudf.hrb, примерно такую: Function Leto_Date( nUserStru ) Return DTOC(Date()) + " " + Time() и вызывать ее с клиента: leto_Udf("Leto_Date")

PSP: Дима, такая функция есть: Leto_MGGetTime() 2009-01-30 21:40 UTC+0200 Pavel Tsarenko (tpe2/at/mail.ru) * source/client/letomgmn.c * source/server/letofunc.c * Readme.txt + added LETO_MGGETTIME function. It's return array with server date and time (seconds after midnight): {dDate, nSeconds}

Dima: PSP пишет: Дима, такая функция есть: Leto_MGGetTime() Точно ;) Не увидел сразу. Pasha пишет: А какая дата сервера нужна ? Текущая ? Уже прояснился вопрос.

Pasha: Выложил на CVS сброс фильтра перед LBM_DBSETFILTERARRAY()

Andrey: Pasha пишет: Это был бы самый гибкий способ, но реализация его сложнее. Я за гибкость !

SergKis: Pasha пишет:А индексация ведь выполняется на сервере, и во время индексации обмена между клиентом и сервером нет, поэтому EVAL и не поддерживается. [pre2] Может использовать переменные сервера для процеса индексации: на клиенте: Leto_Progress(.T.) // создает на сервере 2 переменные на каждого nUserStru: // группа PROGRESS: 1. lProgres_+nUserStru := .T./.F. создание индекса идет // 2. nProgres_+nUserStru := счетчик // на сервере добавить в индекацию ведение счетчика. INDEX ON ... // будет работать с заполнением счетчика while leto_IsProgress() ? Leto_Progress() // возвращает счетчик inkey(2) end Leto_Progress(.F.) // убирает переменные [/pre2]

Dima: Pasha пишет: Выложил на CVS сброс фильтра перед LBM_DBSETFILTERARRAY() Спасибо , работает норм !!! Есть одна мысль по поводу BM фильтров и оптимальной их установке. Думаю она тебе тоже посещала. Изложу позже.

SergKis: help my. Первый раз попробовал hbmk2 при сборке letodb. letodb.exe получил, хотел __WIN_DAEMON__, а получил как __WIN_SERVICE__ что не срослось: запуск: hbmk2.exe -info -comp=bcc -trace rddleto.hbp letodb.hbp > _hbmk2.txt letodb.hbp # # $Id: letodb.hbp,v 1.8.2.5 2013/03/10 08:24:34 ptsarenko Exp $ # #-env:__BM=yes -inc -obin/letodb -iinclude -n -w -q0 -es2 #-warn=max #-prgflag={unix}-D__LINUX_DAEMON__ #-prgflag={unix}-D__LINUX__ {__BM}-prgflag=-D__BM -prgflag={win}-D__WIN_DAEMON__ #-prgflag={win}-D__WIN_SERVICE__ #-cflag={allmsvc}-D_CRT_SECURE_NO_DEPRECATE #-cflag={win}-D__WIN_SERVICE__ {__BM}-cflag=-D__BM -gui -mt {__BM}-lrddbm 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/letolist.c source/server/leto_2.c {__BM}source/server/letobm.prg source/common/blowfish.c source/common/common_c.c source/common/common.prg {__BM}source/common/letoserv.prg hbmk2 результат: hbmk2: Autodetected platform: win hbmk2: Using Harbour: d:\harbour\bin\win\bcc d:\harbour\include d:\harbour\lib\win\bcc d:\harbour\bin\win\bcc d:\harbour\contrib d:\harbour\addons hbmk2: Using C compiler: d:\bcc\bin\bcc32.exe hbmk2: Target up to date: lib\rddleto.lib hbmk2: Autodetected platform: win hbmk2: Using Harbour: d:\harbour\bin\win\bcc d:\harbour\include d:\harbour\lib\win\bcc d:\harbour\bin\win\bcc d:\harbour\contrib d:\harbour\addons hbmk2: Using C compiler: d:\bcc\bin\bcc32.exe hbmk2: Linking... bin\letodb.exe hbmk2: Linker command: ilink32.exe @C:\Users\Sams\AppData\Local\Temp\gt0li0.lnk hbmk2: Linker script: -Gn -Tpe -Ld:\bcc\Lib;d:\bcc\Lib\PSDK;d:\harbour\lib\win\bcc;d:\harbour\lib\3rd\win\bcc -aa c0w32.obj bin\.hbmk\win\bcc\server.obj bin\.hbmk\win\bcc\errorsys.obj bin\.hbmk\win\bcc\common.obj bin\.hbmk\win\bcc\errint.obj bin\.hbmk\win\bcc\leto_win.obj bin\.hbmk\win\bcc\letoacc.obj bin\.hbmk\win\bcc\letovars.obj bin\.hbmk\win\bcc\letofunc.obj bin\.hbmk\win\bcc\letolist.obj bin\.hbmk\win\bcc\leto_2.obj bin\.hbmk\win\bcc\blowfish.obj bin\.hbmk\win\bcc\common_c.obj, bin\letodb.exe, nul, hbextern.lib hbdebug.lib hbvmmt.lib hbrtl.lib hblang.lib hbcpage.lib gtcgi.lib gtpca.lib gtstd.lib gtwin.lib gtwvt.lib gtgui.lib hbrdd.lib hbuddall.lib hbusrrdd.lib rddntx.lib rddcdx.lib rddnsx.lib rddfpt.lib hbrdd.lib hbhsx.lib hbsix.lib hbmacro.lib hbcplr.lib hbpp.lib hbcommon.lib kernel32.lib user32.lib gdi32.lib advapi32.lib ws2_32.lib winspool.lib comctl32.lib comdlg32.lib shell32.lib uuid.lib ole32.lib oleaut32.lib mpr.lib winmm.lib mapi32.lib imm32.lib msimg32.lib wininet.lib hbpcre.lib hbzlib.lib cw32mt.lib import32.lib, , Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland запуск letodb.exe: 03/22/13 16:07:11: LetoDB service has had some problems: 1063 source letodb.prg (сюда попадаем): IF ! leto_serviceStart( "StartServer" ) WrLog( "LetoDB service has had some problems: " + Str( letowin_GetLastError() ) ) ENDIF

Dima: SergKis Видимо сервис Leto не остановлен

SergKis: Dima пишет:Видимо сервис Leto не остановлен Так я не запускал, для установки сервиса, а рабочая версия letodb.exe в ней нет сервиса вообще. letodb.exe uninstall выдает: 03/22/13 16:45:52: Error deleting LetoDB service: 1060 Мне не понятно как я попадаю на сообщение о сервисе, если строки в hbp закоментированы ?

Dima: ну тогда letodb.exe stop грохнуть letodb.exe и пересобрать потом letodb.exe

SergKis: Dima пишет:ну тогда letodb.exe stop грохнуть letodb.exe и пересобрать потом letodb.exe Так делал уже несколько раз то и то. letodb.exe stop выдает:03/22/13 17:17:30: Can't STOP the server (not started?)...

Dima: SergKis У меня так. Собрал и запустил нормально -inc -obin/letodb -iinclude -n -w -q0 -es2 #-warn=max #-prgflag={unix}-D__LINUX_DAEMON__ #-prgflag={unix}-D__LINUX__ {__BM}-prgflag=-D__BM -prgflag={win}-D__WIN_DAEMON__ #-prgflag={win}-D__WIN_SERVICE__ -cflag={allmsvc}-D_CRT_SECURE_NO_DEPRECATE #-cflag={win}-D__WIN_SERVICE__ {__BM}-cflag=-D__BM -gui -mt {__BM}-lrddbm

Dima: а перед сборкой ты удалял папку letodb\bin\.hbmk ?

SergKis: Dima пишет:У меня так. Собрал и запустил нормально У меня -inc -obin/letodb -iinclude -n -w -q0 -es2 #-warn=max #-prgflag={unix}-D__LINUX_DAEMON__ #-prgflag={unix}-D__LINUX__ {__BM}-prgflag=-D__BM -prgflag={win}-D__WIN_DAEMON__ #-prgflag={win}-D__WIN_SERVICE__ -cflag={allmsvc}-D_CRT_SECURE_NO_DEPRECATE #-cflag={win}-D__WIN_SERVICE__ {__BM}-cflag=-D__BM -gui -mt {__BM}-lrddbm собралось, но при запуске 03/22/13 17:45:10: LetoDB service has had some problems: 1063 Harbour Make (hbmk2) 3.2.0dev (Rev. 18911)

Dima: SergKis пишет: Harbour Make (hbmk2) 3.2.0dev (Rev. 18911) Фиг его знает...... У меня Harbour 3.2.0dev (Rev. 18899)

SergKis: Dima Как в hbmk2 ppo файл получить, что то не врублюсь в параметры

Pasha: По-видимому, остались obj-файлы от сборки с -D__WIN_SERVICE__. Надо удалить папку bin\.hbmk, и пересобрать сервер А чтобы получить *.ppo, надо в скрипт просто добавить ключ -p

SergKis: Pasha СПАСИБО !!! все получилось

SergKis: Dima Глаз замылился. Пропустил а перед сборкой ты удалял папку letodb\bin\.hbmk ?

SergKis: Pasha Попробовал собрать клиента LetoDB hb20 и msvc - получил: blowfish.C common_c.C common_c.C(119) : warning C4244: функция: преобразование 'HB_ULONG' в 'long', возможна потеря данных hbip.C net.C C:\BK9\MSVC\sdk\include\ws2def.h(91) : warning C4005: AF_IPX: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(460): см. предыдущее определение 'AF_IPX' C:\BK9\MSVC\sdk\include\ws2def.h(127) : warning C4005: AF_MAX: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(479): см. предыдущее определение 'AF_MAX' C:\BK9\MSVC\sdk\include\ws2def.h(163) : warning C4005: SO_DONTLINGER: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(402): см. предыдущее определение 'SO_DONTLINGER' C:\BK9\MSVC\sdk\include\ws2def.h(206) : error C2011: sockaddr: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(485): см. объявление 'sockaddr' C:\BK9\MSVC\sdk\include\ws2def.h(384) : error C2059: синтаксическая ошибка: константа C:\BK9\MSVC\sdk\include\ws2def.h(518) : warning C4005: IN_CLASSA: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(287): см. предыдущее определение 'IN_CLASSA' C:\BK9\MSVC\sdk\include\ws2def.h(524) : warning C4005: IN_CLASSB: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(293): см. предыдущее определение 'IN_CLASSB' C:\BK9\MSVC\sdk\include\ws2def.h(530) : warning C4005: IN_CLASSC: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(299): см. предыдущее определение 'IN_CLASSC' C:\BK9\MSVC\sdk\include\ws2def.h(541) : warning C4005: INADDR_ANY: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(304): см. предыдущее определение 'INADDR_ANY' C:\BK9\MSVC\sdk\include\ws2def.h(543) : warning C4005: INADDR_BROADCAST: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(306): см. предыдущее определение 'INADDR_BROADCAST' C:\BK9\MSVC\sdk\include\ws2def.h(577) : error C2011: sockaddr_in: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(312): см. объявление 'sockaddr_in' C:\BK9\MSVC\sdk\include\winsock2.h(132) : error C2011: fd_set: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(68): см. объявление 'fd_set' C:\BK9\MSVC\sdk\include\winsock2.h(167) : warning C4005: FD_SET: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(102): см. предыдущее определение 'FD_SET' C:\BK9\MSVC\sdk\include\winsock2.h(176) : error C2011: timeval: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(111): см. объявление 'timeval' C:\BK9\MSVC\sdk\include\winsock2.h(232) : error C2011: hostent: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(167): см. объявление 'hostent' C:\BK9\MSVC\sdk\include\winsock2.h(245) : error C2011: netent: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(180): см. объявление 'netent' C:\BK9\MSVC\sdk\include\winsock2.h(252) : error C2011: servent: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(187): см. объявление 'servent' C:\BK9\MSVC\sdk\include\winsock2.h(264) : error C2011: protoent: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(199): см. объявление 'protoent' C:\BK9\MSVC\sdk\include\winsock2.h(360) : error C2011: WSAData: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(322): см. объявление 'WSAData' C:\BK9\MSVC\sdk\include\winsock2.h(458) : error C2011: sockproto: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(494): см. объявление 'sockproto' C:\BK9\MSVC\sdk\include\winsock2.h(500) : error C2011: linger: переопределение типа "struct" C:\BK9\MSVC\sdk\include\winsock.h(531): см. объявление 'linger' C:\BK9\MSVC\sdk\include\winsock2.h(513) : warning C4005: SOMAXCONN: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(544): см. предыдущее определение 'SOMAXCONN' C:\BK9\MSVC\sdk\include\winsock2.h(542) : warning C4005: FD_READ: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(562): см. предыдущее определение 'FD_READ' C:\BK9\MSVC\sdk\include\winsock2.h(545) : warning C4005: FD_WRITE: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(563): см. предыдущее определение 'FD_WRITE' C:\BK9\MSVC\sdk\include\winsock2.h(548) : warning C4005: FD_OOB: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(564): см. предыдущее определение 'FD_OOB' C:\BK9\MSVC\sdk\include\winsock2.h(551) : warning C4005: FD_ACCEPT: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(565): см. предыдущее определение 'FD_ACCEPT' C:\BK9\MSVC\sdk\include\winsock2.h(554) : warning C4005: FD_CONNECT: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(566): см. предыдущее определение 'FD_CONNECT' C:\BK9\MSVC\sdk\include\winsock2.h(557) : warning C4005: FD_CLOSE: изменение макроопределения C:\BK9\MSVC\sdk\include\winsock.h(567): см. предыдущее определение 'FD_CLOSE' C:\BK9\MSVC\sdk\include\winsock2.h(1527) : error C2375: accept: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(735): см. объявление 'accept' C:\BK9\MSVC\sdk\include\winsock2.h(1548) : error C2375: bind: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(740): см. объявление 'bind' C:\BK9\MSVC\sdk\include\winsock2.h(1567) : error C2375: closesocket: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(745): см. объявление 'closesocket' C:\BK9\MSVC\sdk\include\winsock2.h(1586) : error C2375: connect: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(747): см. объявление 'connect' C:\BK9\MSVC\sdk\include\winsock2.h(1607) : error C2375: ioctlsocket: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(752): см. объявление 'ioctlsocket' C:\BK9\MSVC\sdk\include\winsock2.h(1628) : error C2375: getpeername: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(757): см. объявление 'getpeername' C:\BK9\MSVC\sdk\include\winsock2.h(1649) : error C2375: getsockname: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(762): см. объявление 'getsockname' C:\BK9\MSVC\sdk\include\winsock2.h(1672) : error C2375: getsockopt: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(767): см. объявление 'getsockopt' C:\BK9\MSVC\sdk\include\winsock2.h(1693) : error C2375: htonl: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(774): см. объявление 'htonl' C:\BK9\MSVC\sdk\include\winsock2.h(1710) : error C2375: htons: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(776): см. объявление 'htons' C:\BK9\MSVC\sdk\include\winsock2.h(1728) : error C2375: inet_addr: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(778): см. объявление 'inet_addr' C:\BK9\MSVC\sdk\include\winsock2.h(1745) : error C2375: inet_ntoa: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(780): см. объявление 'inet_ntoa' C:\BK9\MSVC\sdk\include\winsock2.h(1763) : error C2375: listen: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(782): см. объявление 'listen' C:\BK9\MSVC\sdk\include\winsock2.h(1781) : error C2375: ntohl: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(786): см. объявление 'ntohl' C:\BK9\MSVC\sdk\include\winsock2.h(1798) : error C2375: ntohs: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(788): см. объявление 'ntohs' C:\BK9\MSVC\sdk\include\winsock2.h(1818) : error C2375: recv: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(790): см. объявление 'recv' C:\BK9\MSVC\sdk\include\winsock2.h(1843) : error C2375: recvfrom: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(796): см. объявление 'recvfrom' C:\BK9\MSVC\sdk\include\winsock2.h(1869) : error C2375: select: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(804): см. объявление 'select' C:\BK9\MSVC\sdk\include\winsock2.h(1893) : error C2375: send: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(811): см. объявление 'send' C:\BK9\MSVC\sdk\include\winsock2.h(1918) : error C2375: sendto: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(817): см. объявление 'sendto' C:\BK9\MSVC\sdk\include\winsock2.h(1944) : error C2375: setsockopt: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(825): см. объявление 'setsockopt' C:\BK9\MSVC\sdk\include\winsock2.h(1966) : error C2375: shutdown: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(832): см. объявление 'shutdown' C:\BK9\MSVC\sdk\include\winsock2.h(1986) : error C2375: socket: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(836): см. объявление 'socket' C:\BK9\MSVC\sdk\include\winsock2.h(2009) : error C2375: gethostbyaddr: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(843): см. объявление 'gethostbyaddr' C:\BK9\MSVC\sdk\include\winsock2.h(2029) : error C2375: gethostbyname: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(848): см. объявление 'gethostbyname' C:\BK9\MSVC\sdk\include\winsock2.h(2047) : error C2375: gethostname: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(850): см. объявление 'gethostname' C:\BK9\MSVC\sdk\include\winsock2.h(2067) : error C2375: getservbyport: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(854): см. объявление 'getservbyport' C:\BK9\MSVC\sdk\include\winsock2.h(2087) : error C2375: getservbyname: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(858): см. объявление 'getservbyname' C:\BK9\MSVC\sdk\include\winsock2.h(2106) : error C2375: getprotobynumber: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(862): см. объявление 'getprotobynumber' C:\BK9\MSVC\sdk\include\winsock2.h(2124) : error C2375: getprotobyname: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(864): см. объявление 'getprotobyname' C:\BK9\MSVC\sdk\include\winsock2.h(2145) : error C2375: WSAStartup: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(868): см. объявление 'WSAStartup' C:\BK9\MSVC\sdk\include\winsock2.h(2163) : error C2375: WSACleanup: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(872): см. объявление 'WSACleanup' C:\BK9\MSVC\sdk\include\winsock2.h(2180) : error C2375: WSASetLastError: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(874): см. объявление 'WSASetLastError' C:\BK9\MSVC\sdk\include\winsock2.h(2197) : error C2375: WSAGetLastError: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(876): см. объявление 'WSAGetLastError' C:\BK9\MSVC\sdk\include\winsock2.h(2214) : error C2375: WSAIsBlocking: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(878): см. объявление 'WSAIsBlocking' C:\BK9\MSVC\sdk\include\winsock2.h(2231) : error C2375: WSAUnhookBlockingHook: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(880): см. объявление 'WSAUnhookBlockingHook' C:\BK9\MSVC\sdk\include\winsock2.h(2248) : error C2375: WSASetBlockingHook: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(882): см. объявление 'WSASetBlockingHook' C:\BK9\MSVC\sdk\include\winsock2.h(2265) : error C2375: WSACancelBlockingCall: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(884): см. объявление 'WSACancelBlockingCall' C:\BK9\MSVC\sdk\include\winsock2.h(2287) : error C2375: WSAAsyncGetServByName: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(886): см. объявление 'WSAAsyncGetServByName' C:\BK9\MSVC\sdk\include\winsock2.h(2314) : error C2375: WSAAsyncGetServByPort: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(894): см. объявление 'WSAAsyncGetServByPort' C:\BK9\MSVC\sdk\include\winsock2.h(2340) : error C2375: WSAAsyncGetProtoByName: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(902): см. объявление 'WSAAsyncGetProtoByName' C:\BK9\MSVC\sdk\include\winsock2.h(2365) : error C2375: WSAAsyncGetProtoByNumber: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(909): см. объявление 'WSAAsyncGetProtoByNumber' C:\BK9\MSVC\sdk\include\winsock2.h(2390) : error C2375: WSAAsyncGetHostByName: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(916): см. объявление 'WSAAsyncGetHostByName' C:\BK9\MSVC\sdk\include\winsock2.h(2417) : error C2375: WSAAsyncGetHostByAddr: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(923): см. объявление 'WSAAsyncGetHostByAddr' C:\BK9\MSVC\sdk\include\winsock2.h(2440) : error C2375: WSACancelAsyncRequest: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(932): см. объявление 'WSACancelAsyncRequest' C:\BK9\MSVC\sdk\include\winsock2.h(2461) : error C2375: WSAAsyncSelect: переопределение; другая компоновка C:\BK9\MSVC\sdk\include\winsock.h(934): см. объявление 'WSAAsyncSelect' Создание кода... С этим можно что то сделать или надо hb3.2 ?

Dima: SergKis пишет: или надо hb3.2 ? с ним нормально собирается ?

SergKis: Dima пишет:с ним нормально собирается ? hb3.2 пока не в работе - все на hb2.0. LetoDb сервер (xHb сборка) 2011 года, клиент letordd.lib: msvc, hb2.0 нормально идет, но на медленном соединении не хватает TimeOut, то разъединится, то функция на сервере не выполнится - наверно тоже из за timeout. Сервер bcc hb3.2 с твоей помощью и Pasha собрал, а у клиента бяка пошла.

Pasha: А клиент с harbour 3.x + msvc собирается ?

SergKis: Pasha пишет:А клиент с harbour 3.x + msvc собирается ? Сборки hb3.2+msvc нет - нет времени связываться, т.к. просто не пойдет, по опыту hb2.0. И проблема не решится т.к.: msvc ws2def.h : #define AF_NS 6 // XEROX NS protocols #define AF_IPX AF_NS // IPX protocols: IPX, SPX, etc. hb2.0 hbsocket.ch : #define HB_SOCKET_AF_IPX HB_SOCKET_PF_IPX hb3.2 hbsocket.ch : #define HB_SOCKET_AF_IPX 4 ... #define HB_SOCKET_PF_IPX HB_SOCKET_AF_IPX

Pasha: rddleto для hb20 + bcc, mingw собирается Проблема со сборкой hb20 + watcom, msvc Если в funcleto.h закомментировать строку #include <winsock2.h> то часть ошибок уходит. С остальными пока не знаю, как быть.

SergKis: Pasha пишет:rddleto для hb20 + bcc, mingw собирается Проблема со сборкой hb20 + watcom, msvc Если в funcleto.h закомментировать строку #include <winsock2.h> то часть ошибок уходит. С остальными пока не знаю, как быть. Мы тоже в задумчивости ...,пока не горит и останемся до лучших времен на старой версии letodb.

sashaBG: Pasha вот лог: User: 192.168.120.18 PLASMENT3 ccw.Exe Command: close Unrecoverable error 6005: Exception error: %s Exception Code:C0000005 Exception Address:0040CE5D EAX:202E7665 EBX:0000000A ECX:010B523C EDX:0000000A ESI:00E0AEC8 EDI:010B523C EBP:010AFD8C CS:EIP:001B:0040CE5D SS:ESP:0023:010AFD8C DS:0023 ES:0023 FS:003B GS:0000 Flags:00010206 CS:EIP: 3B 50 04 73 E9 33 C0 5D C3 55 8B EC 51 53 56 57 SS:ESP: 010AFDA8 00405C17 00E0AEC8 0000000A 010B523C 01161170 009D33D8 010AFDF8 004036D7 01161170 0000000A 010AFE6C 010B523C 009D33D0 010D3D44 010AFDD4 C stack: EIP: EBP: Frame: OldEBP, RetAddr, Params... 0040CE5D 010AFD8C 010AFDA8 00405C17 00E0AEC8 0000000A 010B523C 01161170 009D33D8 00405C17 010AFDA8 010AFDF8 004036D7 01161170 0000000A 010AFE6C 010B523C 009D33D0 010D3D44 010AFDD4 00430FC0 004036D7 010AFDF8 010AFE24 0040732A 00DFA58C 01161170 010B523C 009D33D5 00000040 010D3D44 010B523C 00DFA58C 0040732A 010AFE24 010AFE7C 00407605 010B523C 00DFA58C 01161170 010AFE6C 01375B96 00DFA58C 01375B9D 6C656B69 00407605 010AFE7C 010AFEA8 0040C8D1 00DFA58C 01375B9D 01375B96 00000015 00DFA58C 00000001 00000001 0000000C 0040C8D1 010AFEA8 010AFED4 0040D650 00DFA58C 004B4BFC 00FB0000 009D2C34 00012C94 00000138 83126E98 40DD3958 0040D650 010AFED4 010AFFA4 004B49F8 00000001 00000000 00000000 009D2C34 00000094 00000005 00000001 00000A28 004B49F8 010AFFA4 010AFFB4 004B4A2B 009D2C34 004B4BFC 004B4A2B 010AFFB4 010AFFEC 7C80B713 009D2C34 00000000 00000000 009D2C34 7FFDC000 8A62C600 010AFFC0 898616B8 Modules: 0x00400000 0x000DE000 d:\letodb\letodb.exe 0x7C900000 0x000AF000 C:\WINDOWS\system32\ntdll.dll 0x64D00000 0x0003F000 C:\Program Files\AVAST Software\Avast\snxhk.dll 0x7C800000 0x000F6000 C:\WINDOWS\system32\KERNEL32.dll 0x71AD0000 0x00009000 C:\WINDOWS\system32\WSOCK32.DLL 0x71AB0000 0x00017000 C:\WINDOWS\system32\WS2_32.dll 0x77DD0000 0x0009B000 C:\WINDOWS\system32\ADVAPI32.dll 0x77E70000 0x00092000 C:\WINDOWS\system32\RPCRT4.dll 0x77FE0000 0x00011000 C:\WINDOWS\system32\Secur32.dll 0x77C10000 0x00058000 C:\WINDOWS\system32\msvcrt.dll 0x71AA0000 0x00008000 C:\WINDOWS\system32\WS2HELP.dll 0x7E410000 0x00091000 C:\WINDOWS\system32\USER32.DLL 0x77F10000 0x00049000 C:\WINDOWS\system32\GDI32.dll 0x71A50000 0x0003F000 C:\WINDOWS\system32\mswsock.dll 0x662B0000 0x00058000 C:\WINDOWS\system32\hnetcfg.dll 0x71A90000 0x00008000 C:\WINDOWS\System32\wshtcpip.dll 0x69450000 0x00016000 C:\WINDOWS\system32\faultrep.dll 0x77C00000 0x00008000 C:\WINDOWS\system32\VERSION.dll 0x769C0000 0x000B4000 C:\WINDOWS\system32\USERENV.dll 0x76360000 0x00010000 C:\WINDOWS\system32\WINSTA.dll 0x5B860000 0x00055000 C:\WINDOWS\system32\NETAPI32.dll 0x76F50000 0x00008000 C:\WINDOWS\system32\WTSAPI32.dll 0x77920000 0x000F3000 C:\WINDOWS\system32\SETUPAPI.dll 0x77F60000 0x00076000 C:\WINDOWS\system32\SHLWAPI.dll 0x773D0000 0x00103000 C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll 0x5D090000 0x0009A000 C:\WINDOWS\system32\comctl32.dll 0x77B40000 0x00022000 C:\WINDOWS\system32\Apphelp.dll LetoDB у меня работает как демон а не как сервиз не знаю может в етом проблема сначала я кинулся убирать AVAST но не в нем проблема , несмотря что он враждебно относится к LetoDB . иногда падает при закрытии одной обласи или всех рабочих облостей со стороны клиента . Лечится ето через Leto_Commit() перед закрытием на локаьном соединении ето нельзя воспроизвести только через сеть. Ошибка получается не кажды раз . В етих модулях которые вызвали падение я не использую транзакции.

AlexMyr: При сборке manage.prg с помощью manage.hbp получаю hbmk2: Warning: Non-portable parameter: '{mingw|mingw64}-l../../lib/${hb_plat}/${hb_comp}/librddleto.a' in manage.hbp:18. Use '-L..\..\lib\win\mingw -lrddleto' option(s) instead. hbmk2: Warning: Non-portable parameter: '{mingw|mingw64}-l${hwgui_dir}lib/${hb_plat}/${hb_comp}/libhwgui.a' in manage.hbp:19. Use '-Llib\win\mingw -lhwgui' option(s) instead. hbmk2: Warning: Non-portable parameter: '{mingw|mingw64}-l${hwgui_dir}lib/${hb_plat}/${hb_comp}/libprocmisc.a' in manage.hbp:20. Use '-Llib\win\mingw -lprocmisc' option(s) instead. hbmk2: Warning: Non-portable parameter: '{mingw|mingw64}-l${hwgui_dir}lib/${hb_plat}/${hb_comp}/libhbxml.a' in manage.hbp:21. Use '-Llib\win\mingw -lhbxml' option(s) instead. hbmk2: Compiling Harbour sources... manage.prg(52) Error F0029 Can't open #include file 'hwgui.ch' hbmk2: Error: Running Harbour compiler (embedded). 1 (c:\dev\harbour\bin\harbour.exe) -n2 manage.prg -n -w -q0 -es2 -o..\..\bin\win\m ingw\.hbmk\win\mingw\ -ic:\dev\harbour\include -i..\..\include -iinclude Собираю таким hbp, с помощью соответствующих hbc файлов ${hwgui_dir}/hwgui.hbc ../../rddleto.hbc -inc -mt manage И еще, для свежего hwgui надо добавить hwg_ к след. ф-ям hbmk2: Error: Referenced, missing, but unknown function(s): SENDMESSAGE(), GETEDITTEXT(), MSGSTOP(), MSGYESNO()

santy: Скачал последнюю версию. (v 1.350.2.116 2013/03/24) Собрал под Harbour для Watcom. Создал daemon, service, lib, dll ошибок нет (с __BM и без). Под xHarbour нужно переделать BEGIN SEQUENCE на try catch в файле server.prg. Для теста взял VC2003 и Harbour создал сервис ошибок нет тольки варнинги.

SergKis: Pasha Есть такая ситуация (версия letodb $Id: Changelog,v 1.350 2011/04/21 18:00:52 ptsarenko Exp $). таблица letodb LastRec 2500, RecSize 1567 : 1-ый клиент листает MiniGui browse - соединение быстрый internet 2-ой клиент делает запросы с модемного соединения GPRS: [pre2] 1. время выполнения 30-40 сек., первый клиент нормально работает while ! eof() aAdd(aArr, {RecNo(), Fld1, Fld2, Fld3}) skip enddo 2. время выполнения 2-3 сек., у первого клиента клинит browse на это время leto_udf('UDF_RecordsNo') - возвращает массив записей {RecNo1, ...} 3. время выполнения 4-5 сек., у первого клиента клинит browse на это время leto_udf('UDF_RecordsNo', 'Fld1,Fld2,Fld3') - возвращает массив записей {{RecNo, Fld1,Fld2,Fld3}, ...} Function UDF_RecordsNo(nUseArea, cParam) ... while ! eof() aAdd(aArr, RecNo()) // или aAdd(aArr, {RecNo, Fld1, Fld2, Fld3}) skip enddo Return leto_AtoC(aArr) // или bk_A2S(aArr) [/pre2] Вопрос - есть ли механизм для применения в цикле while чтобы передавать управление letodb и не клинить работу др.клиента, может специальиный skip надо применять или это дохлое дело ... ?

Pasha: Так это же старая версия letodb с двумя потоками, в которой все запросы выполняет один поток. В этой версии ничего сделать нельзя. Надо использовать rel-1-mt ветвь

SergKis: Pasha пишет:В этой версии ничего сделать нельзя. Я так и думал.

Dima: Pasha А во сколько потоков сегодня работает Leto сервер ?

Pasha: Сейчас для каждого соединения создается отдельный поток

Dima: Pasha Юзер создал переменную на сервере leto_varSet( "main","var_int",100 ) И трах бах комп у него "упал" , переменная останется на сервере ?

Pasha: Dima пишет: И трах бах комп у него "упал" , переменная останется на сервере ? Нет, сервер увидит, что соединение отвалилось, и закроет его со всеми данными коннекта, в том числе очистит созданные переменные.

PSP: Паша, какой таймаут перед сбросом соединения отвалившегося клиента? И касается ли это заблокированных этим клиентом записей?

Dima: Pasha Это правильно А объявленная юзером переменная будет доступна другим юзерам ? То есть если с одной станции я создал переменную vasiapupkin а с другой пытаются войти и тоже создать такую же переменную , я могу проверить существование этой переменной созданной другим юзером ? Просто с помощью этих переменных хочу контролировать вход юзеров в программу. В программе не должно быть 2-х активных юзеров с одним логином.

Pasha: Dima пишет: А объявленная юзером переменная будет доступна другим юзерам ? Честно говоря, поддержку переменных делал не я, и сам я их не использую. Насколько я понял по сырцам, здесь важен флаг создания переменной: 4-й параметр функции leto_VarSet Если установлен флаг LETO_VOWN, то это переменная именно этого юзера, и при закрытии соединения она будет удалена. Иначе переменная останется.

Pasha: PSP пишет: Паша, какой таймаут перед сбросом соединения отвалившегося клиента? И касается ли это заблокированных этим клиентом записей? Точно не скажу, какое-то значение по умолчанию, предусмотренное в hbsocket. Но если я принудительно снимаю клиентскую программу, сервер сразу это видит и закрывает это соединение со всеми его данными, в том числе блокировками записей.

Dima: Pasha Хорошо а как тогда организовать на уровне Leto сервера что бы нельзя было зайти в программу с одним логином более 1 раза ? Кинулся было к варианту с переменными но как оказалось они не общедоступны... Можно конечно и по старинке сделать но хотелось более красиво реализовать.

Pasha: Почему не общедоступны ? Примерно так: if leto_VarGet("users", cUserID) == nil leto_VarSet("users", cUserID, value) // только надо флаги правильно указать else quit endif

Dima: Pasha Понял. Пробну. Спасибо ! Как часто вызывать LETO_CONNECT() ? Перед каждым USE или достаточно 1 раз в начале программы ? RddInfo( RDDI_REFRESHCOUNT, <lSet>,, [nConnection] ) это глобальная установка или нужно ее указывать при открытии каждой базы ?

Dima: Pasha пишет: // только надо флаги правильно указать Про флаги можно подробнее ?! Какой что означает... [pre2] #define LETO_VCREAT 1 #define LETO_VOWN 2 #define LETO_VDENYWR 4 #define LETO_VDENYRD 8 #define LETO_VPREVIOUS 1 [/pre2] Есть пожелание :) Добавить в возвращаемый массив LETO_MGGETINFO 18 элементом серийный номер винта с которого стартовал LetoDB сервер , ну или системного винта. Говорю о функции volserial() А еще лучше MAC адрес сетевой платы !!! То есть нужен любой уникальный ID оборудования , что бы прогу можно было привязать , зная что ее ни кто не упрет на лево (минуя разработчика).

Pasha: Dima пишет: Как часто вызывать LETO_CONNECT() ? Перед каждым USE или достаточно 1 раз в начале программы ? Надо один раз вызывать. RddInfo( RDDI_REFRESHCOUNT, <lSet>,, [nConnection] ) это глобальная установка или нужно ее указывать при открытии каждой базы ? Глобальная установка, для всех р/о

Dima: Pasha Понял. А что насчет этого ? Ну очень интересно Dima пишет: Про флаги можно подробнее ?! Какой что означает... Dima пишет: Есть пожелание :)

Pasha: Чуть позже напишу, сейчас некогда, надо самому глянуть, что за флаги Но скорее всего: #define LETO_VCREAT 1 если переменной нет, она создается #define LETO_VOWN 2 переменная этого пользователя (соединения) #define LETO_VDENYWR 4 запрет присвоения для другого пользователя #define LETO_VDENYRD 8 запрет чтения другим пользователем #define LETO_VPREVIOUS 1 надо смотреть

AlexMyr: Dima пишет: хочу контролировать вход юзеров Есть опция Pass_for_Login=.T., раньше с ней игрался, так вот какая мысль, если добавить еще опцию допустим Multi_login (по умолчанию .F. - один пользователь, сервер сам проверяет, если пользователь залогинился, такой уже не зайдет), если .T. - значит допускается больше одного коннекта для одного юзера. Если Pass_for_Login = .F., то MultiLogin не обрабатывается. Вроде так будет лучше и правильней чем игры с переменными и флагами со стороны клиента.

Dima: AlexMyr Начну с переменных а там посмотрим. Вроде и особо играться там не надо. При входе проверил переменную , если ее нет , завел. Если есть то юзер не войдет. Ее даже убивать не надо при выходе из программы (убивается на автомате после LETO_DISCONNECT если я верно понял)

Pasha: sashaBG пишет: LetoDB у меня работает как демон а не как сервиз не знаю может в етом проблема сначала я кинулся убирать AVAST но не в нем проблема , несмотря что он враждебно относится к LetoDB . иногда падает при закрытии одной обласи или всех рабочих облостей со стороны клиента . Лечится ето через Leto_Commit() перед закрытием на локаьном соединении ето нельзя воспроизвести только через сеть. Ошибка получается не кажды раз . У меня такая ошибка никогда не возникала. Судя по тому, что она лечится через Leto_Commit, возможно, перед dbCloseArea остались данные, которые не переданы на сервер, и блокированные записи. Хотя я таких ситуаций стараюсь избегать, смоделировал их, и ошибки не получил. Посмотрел по сырцам - если такая ситуация возникнет, то измененные записи перед закрытием будут переданы на сервер, и список блокированных записей очищается. Причина ошибки пока непонятна.

Pasha: Pasha пишет: #define LETO_VPREVIOUS 1 Функция leto_varset присваивает переменной новое значение, и возвращает ее предыдущее значение

Dima: Pasha пишет: Функция leto_varset присваивает переменной новое значение, и возвращает ее предыдущее значение Спасибо за разъяснения ! Pasha Порадуешь на счет MAC адреса ?

Pasha: Dima пишет: Порадуешь на счет MAC адреса ? А что надо с MAC-адресом ? Возврашать MAC-адрес сервера, что ли ?

Dima: Pasha пишет: Возврашать MAC-адрес сервера, что ли ? Да MAC адрес сетевой платы cервера. Или к примеру volserial() винта откуда стартовал LetoDB сервер.

Pasha: В source\server\server.prg надо добавить функцию: FUNCTION leto_VolSerial( nUserStru ) RETURN VolSerial() линковать сервер с hbct.lib Вызов с клиента: leto_UDF("leto_VolSerial") Тоже самое можно сделать с mac-адресом, надо только найти такую функцию в харборе. Только в сырцы letodb я это включать не хочу, все-таки другая специфика.

Dima: Pasha Спасибо. Pasha пишет: Тоже самое можно сделать с mac-адресом, надо только найти такую функцию в харборе. Уже искал и не нашел. Но есть GetAdaptersInfo в iphlpapi.lib , но одной прилинковки этой библы не достаточно. Видать что то еще надо. Как вариант можно так [pre2] #include "hbwin.ch" PROCEDURE Main LOCAL nHKey := WIN_HKEY_LOCAL_MACHINE LOCAL cRegPath := "SOFTWARE\Microsoft\Windows Genuine Advantage" LOCAL cRegKey := "MAC" ? GetRegistry( nHKey, cRegPath, cRegKey ) RETURN [/pre2]

Dima: Если EnableFileFunc = 1 То функция FILE() сможет определять наличие файла на сервере или нужно юзать LETO_FILE () ? Будут ли функции в будущем ? Leto_Fcreate() Leto_Fseek() Leto_Fopen() Как проверить существование папки на сервере ?

Pasha: Добавлять в letodb эту функциональность как-то не хочется, так как это несвойственные ему задачи, да и дублирование существующих возможностей. File() и прочие файловые функции будут работать: 1. Если есть файловый доступ к данному сетевому ресурсу: сетевой диск или через unc 2. Посредством netio. На сервере должен быть кроме letodb запущен netio-сервер, и тогда можно к нему сконнектиться и использовать файловые операции вида: Local nH := FOpen("net:" + cFileName, ...) Правда, для windows netiosrv работает как приложение, а не как служба, что создаст некоторые трудности. Дополню: конечно, в letodb это можно реализовать посредством udf-функций

Dima: Pasha пишет: File() и прочие файловые функции будут работать: 1. Если есть файловый доступ к данному сетевому ресурсу: сетевой диск или через unc Базу предполагалось спрятать от юзеров и папку с базой расшаривать не предполагалось. Спрошу иначе ;) Когда запускается программа (моя) она проверяет наличие баз данных. Если какой то базы нет ,она создается (проверяю с помощью FILE()) Что бы не париться с NET: мне достаточно с RDD LETO проверить существование файла на сервере Leto с помощью File() или надо юзать Leto_File() ?

Pasha: Если папка не расшарена, то file и все остальные файловые функции работать не будут. Надо использовать leto_file leto_file('//127.0.0.1:2812/' + cFile) путь к файлу надо указывать относительно DataPath из letodb.ini Для проверки существования папки можно использовать leto_Directory. Параметры такие же, что и Directory Все существующие файловые функции описаны в разделе 7.6 readme Можно написать свой набор функций, через механизм udf. Пример: На сервере добавляется функция Function leto_FCreate(nUserStru, cFileName, nAttr) Return FCreate(leto_GetAppOptions( 1 ) + cFileName, nAttr) leto_GetAppOptions( 1 ) возвращает DataPath Вызов с клиента: leto_UDF('leto_FCreate', cFileName, nAttr) и так далее

Dima: Pasha Спасибо за развернутый ответ.

SergKis: Dima пишет:Когда запускается программа (моя) она проверяет наличие баз данных. Если какой то базы нет ,она создается (проверяю с помощью FILE()) Может будет интересно. Т.к. у нас в прогах на clipper каталоги для баз создаются динамически и их много, то при переводе на letodb сохранили такую же схему работы, добавив в сервер в функцию hs_createtable(...) проверку и создание каталогов. Вот текст: [pre2] FUNCTION hs_createtable( nUserStru, cCommand ) ... IF Lower(cName) = "/mem:" cDataPath := "" cName := Substr(cName, 2) ELSE cDataPath := leto_GetAppOptions( 1 ) ENDIF cFileName := cDataPath + cName IF ! empty(cDataPath) // new _CreateDir( cFileName ) // new ENDIF // new BEGIN SEQUENCE WITH { |e|break( e ) } ... STATIC FUNCTION _CreateDir( cDBF ) LOCAL i, cCt, aCt := {} i := RAt('\', cDBF) cCt := Left( cDBF, i-1) DO WHILE ! hb_DirExists( cCt ) i := RAt('\', cCt) IF i == 0 ; EXIT ENDIF AAdd( aCt , subs(cCt, i+1) ) cCt := Left( cCt, i-1) ENDDO i := Len( aCt ) DO WHILE i > 0 cCt += ('\' + aCt[i--]) MakeDir( cCt ) ENDDO RETURN .T. [/pre2]

Dima: SergKis Спасибо !

Dima: Застрял на ерунде. ? leto_file(pathleto+"\dbf\test.dbf") // .t. set path to (pathleto+"\dbf\") ? leto_file("test.dbf") // почему то .f. с обычным RDD .t. впрочем как и в Clipper Куда копать ?

PSP: Видимо, сервер ничего не знает про установку SET PATH TO

Dima: PSP пишет: Видимо, сервер ничего не знает про установку SET PATH TO Вероятно должен знать Выдержка из доки [pre2] Для открытия файла dbf на сервере необходимо вставить в оператор SET PATH TO, или в команду USE путь к серверу в стандартной форме: //ip_address:port/data_path/file_name. [/pre2] Правда тут ни чего не сказано насчет файловых функций таких как File() к примеру. Но ведь в Harbour как и в Clipper SET PATH TO распространяется и на функцию File() в том числе.

PSP: Думаю, Павел научит Leto_File() учитывать SET PATH TO Надо подождать... :)

Dima: PSP пишет: Думаю, Павел научит Leto_File() учитывать SET PATH TO ;) Еще и эти тоже LETO_FERASE , LETO_FRENAME

Pasha: PSP пишет: Думаю, Павел научит Leto_File() учитывать SET PATH TO Надо подождать... :) Я специально избегаю в файловых функциях leto использование set path. Когда я в 2008-м только начинал использовать leto, эти настройки учитывал. Но заметил, что программа вдруг начинает работать необьяснимо медленно. Выяснилось, что обычные файловые функции вроде File(), тоже использующие set path, резко замедляют свою работу, так как по set path начинают искать в сети файл, а этого ресурса то нет. В set path же есть строка вроде //server:2812/path Пришлось убрать учет set path. Приходится разделять обычные файловые операции и запросы к letodb. Одна и таже настройка и для первого, и для второго конфликтует между собой. Если надо найти файл (один или несколько) на сервере letodb, который может быть в одной из нескольких папок, можно использовать функцию UDF_FilesExist из модуля letoudf.prg

Dima: Pasha пишет: использовать функцию UDF_FilesExist Вот так ? leto_udf("UDF_FilesExist",pathleto+"\dbf\","test.dbf")

Pasha: Нет, 2-й параметр - массив имен файлов, которые надо проверить И функция возвращает тоже массив, каждый элемент которого - или папка, в которой находится файл, или символ "-", если файл не найден. Одним вызовом можно проверить существование всех файлов БД, индексов, и что там еще надо проверить. т.е leto_udf("UDF_FilesExist",pathleto+"\dbf\"+pathleto+"\dbf2\"+...,{"test.dbf", "test2.dbf", ...})

PSP: Pasha пишет: Но заметил, что программа вдруг начинает работать необьяснимо медленно. Выяснилось, что обычные файловые функции вроде File(), тоже использующие set path, резко замедляют свою работу, так как по set path начинают искать в сети файл, а этого ресурса то нет. В set path же есть строка вроде //server:2812/path Кажись, припоминаю... Вроде была об этом речь. Забылось, конечно, за давностью так сказать... :)

Dima: PSP пишет: Забылось, конечно, за давностью так сказать... Давно Leto юзаешь ?

PSP: Чуть больше двух лет.

Dima: PSP пишет: Чуть больше двух лет. Спишь спокойно ? ;) Я когда на ADS+Clipper перелез стал спать спокойно. Ночные звонки прекратились. С Leto так же ?

PSP: Ни разу с сервером никаких проблем не было. Сервер на ВинХР Проф, шуршит сам по себе, доступ к нему ограничен. Все нормально. :)

Dima: PSP Понял , переделываю дальше свою прогу. PS 3 дня убил на перевод с Clipper+ADS на Harbour-ADS (12 часов в сутки пахал) и 3 недели на оптимизацию отчетов и фильтров. Теперь новый этап -> LetoDB. Переделаю , отпишу.

PSP: Удачи! :)

Dima: Pasha Ты уверен что переменные созданные юзером при выходе из программы + LETO_DISCONNECT() убиваются ? Кажется это не так.

Dima: Установка set autopen off вообще работает для Leto ? Похоже нет. Что делать ?

Pasha: Dima пишет: Ты уверен что переменные созданные юзером при выходе из программы + LETO_DISCONNECT() убиваются ? Кажется это не так. Надо создавать переменную с флагом LETO_VOWN, и все будет ок Запусти 2 раза тест: leto_connect(cPath) ? leto_varget('users', 'u3') ? leto_varset('users', 'u3', 1, LETO_VCREAT+LETO_VOWN) ? leto_varget('users', 'u3') wait при 2-м запуске переменной не будет.

Dima: Pasha пишет: LETO_VCREAT+LETO_VOWN Упс не знал что можно так , попробую. Спасибо. Установка Set path на DBCREATE то же не распространяется ? Что бы бровс не тормозил делаю такую установку RddInfo( RDDI_REFRESHCOUNT,.f.,,LETO_GETCURRENTCONNECTION()) но он все равно подтормаживает если сравнивать с обычным DBFCDX без LETO. Что не так делаю ? А как работать с mem: базами ? Падает прога с ошибкой LETO 1004 Базу создаю так [pre2] kad:="test" dbcreate("mem:"+kad,; {; {"data","d",8,0},; {"nakl","c",100,0},; {"prixs","n",17,2},; {"vozr","n",17,2},; {"p_dok","n",1,0},; {"oplata","n",17,2}},,.t.,"VREMS") [/pre2]

Pasha: Наколько я помню, для dbCreate используется set default А насчет бровса, dbfcdx локальный ? Локальный dbfcdx будет быстрее локального letodb, так как в letodb используется дополнительный слой. Но по сети letodb будет быстрее. Для оптимизации бровса в letodb надо еще задать размер skip-буфера по к-ву строк в бровсе. Да и можно проанализировать, насколько оптимизирован letodb: запустить сервер с параметром в letodb.ini Debug=10 и анализовать лог на сервере. В нем будут пакеты, которые идут с клиента.

Pasha: Dima пишет: А как работать с mem: базами ? Падает прога с ошибкой LETO 1004 Базу создаю так Файл в памяти на клиенте ? Тогда надо его создавать с DBFCDX, а не с letodb: dbcreate("mem:"+kad, aStru, "DBFCDX", .t., cAlias)

Dima: Pasha пишет: Наколько я помню, для dbCreate используется set default Верно. Мой косяк Pasha пишет: Файл в памяти на клиенте ? Тогда надо его создавать с DBFCDX, а не с letodb: И это тоже ;) остался вопрос с Set Autopen off Pasha пишет: Для оптимизации бровса в letodb надо еще задать размер skip-буфера по к-ву строк в бровсе Об этой функции ты говоришь LETO_SETSKIPBUFFER ?

Pasha: Dima пишет: Об этой функции ты говоришь LETO_SETSKIPBUFFER ? да

Dima: Блин еще косяк не понятный В цикле работает ordlistadd() C обычным DBFCDX после отработки цикла первым (управляющим) становится первый добавленный индекс А с LETO последний. Сколько таких не соответствий мне еще суждено поймать....... Что касается бровса. Если он голый (просто поля) без наворотов то работает нормально (нет тормоза). А вот если появляются вычисляемые поля да еще по другим базам то тормоз обеспечен. Локально без LETO этого тормоза нет , впрочем как и под ADS (там слегка заметное замедление)

Pasha: Dima пишет: остался вопрос с Set Autopen off рисую такой тест: #define _leto proc main #ifdef _leto local cPath := '//127.0.0.1:2812/' REQUEST LETO RDDSETDEFAULT( "LETO" ) #else local cPath := '' REQUEST DBFCDX RDDSETDEFAULT( "DBFCDX" ) #endif set autopen off #ifdef _leto leto_Connect(cPath) hb_rddinfo(101, .f.,, 1) #endif USE (cPath+'test') new ? rddname(), IndexOrd(), ordCount() set index to test ? rddname(), IndexOrd(), ordCount() wait retu Что leto, что dbfcdx ведут себя одинаково. Если индекс существует и autopen выключен, то индекс не открывается, надо принудительно выдать команду set index Если autopen включен, то индекс открывается автоматически. Дима, может быть ты что-то другое имеешь в ввиду ?

Pasha: Dima пишет: Что касается бровса. Если он голый (просто поля) без наворотов то работает нормально (нет тормоза). А вот если появляются вычисляемые поля да еще по другим базам то тормоз обеспечен. Локально без LETO этого тормоза нет , впрочем как и под ADS (там слегка заметное замедление) Если сравнить бровс с вычисляемыми полями по нескольким таблицам при работе в сети, то какой rdd быстрее: dbfcdx, ads или leto ? И какого вида вычисляемые поля ? Это seek по другой таблице и выборка из нее данных, или что-то сложнее ? Кстати, если это цикл с суммированием по другой таблице, то в leto для этого есть функция leto_sum, использование которой уберет тормоза, так как она выполняется одним запросом к серверу.

Dima: Pasha пишет: Дима, может быть ты что-то другое имеешь в ввиду ? НЕ LETO , ставлю set autopen off Открываю базу magaz3.dbf , в этой же папке есть magaz3.cdx и он к этой базе ни какого отношения не имеет. Тут он и не откроется. А в случае с LETO даже если установка set autopen off этот индекс будет открываться и понятное дело будет ошибка открытия базы так как индекс magaz3.cdx совсем из другой оперы.

Pasha: Dima пишет: НЕ LETO , ставлю set autopen off Открываю базу magaz3.dbf , в этой же папке есть magaz3.cdx и он к этой базе ни какого отношения не имеет. Тут он и не откроется. А в случае с LETO даже если установка set autopen off этот индекс будет открываться и понятное дело будет ошибка открытия базы так как индекс magaz3.cdx совсем из другой оперы. Понятно. На сервере set autopen всегда включен, и я думаю, это нельзя изменить. Представь ситуацию. Один клиент открыл таблицу с индексом, и другой без индекса, и оба обновляют таблицу. Что в таком случае будет с индексом ? Одно соединение его обновит, а другое нет. Получится битый индекс. Поэтому сервер всегда открывает индекс, даже если клиент это не просит.

Andrey: Pasha пишет: Поэтому сервер всегда открывает индекс, даже если клиент это не просит. Если не трудно - напишите это в доке ! А то потом забудешь про это и опять на те-же самые грабли наступишь...

alkresin: Павел, а можно виндовый letodb собрать не как службу ? Я его сегодня обновил с CVS, собрал, пытаюсь запустить - а он говорит, что "LetoDB service has had some problems: 1063". Мне служба совершенно не нужна...

AlexMyr: Александр, поправьте следующее #-prgflag={win}-D__WIN_DAEMON__ -prgflag={win}-D__WIN_SERVICE__ замениете на -prgflag={win}-D__WIN_DAEMON__ #-prgflag={win}-D__WIN_SERVICE__ Вот в reame Для ОС Windows сервер letodb может быть собран как служба Windows (должен быть инициализирован макрос __WIN_SERVICE__), или как демон (процесс), для чего надо установить макрос __WIN_DAEMON__.

alkresin: Спасибо. Не дочитал до этого места readme :)

Andrey: Pasha пишет в теме http://clipper.borda.ru/?1-6-0-00000001-000-10001-0: Я autoinc не использую, и насчет стабильности точно не скажу. Но мне кажется, что и без flock, т.е. по rlock, будет стабильнее, чем делать go bottom, выбирать последний ключ, и т.д, поскольку узких мест для autoinc меньше. В связи с переходом на LetoDb - как лучше реализовывать "счетчик" ID у себя в задачах ?

Панченко: В качестве пожелания. Паша, Александр что-то давненько не обновлялся архив на http://sourceforge.net/projects/letodb/. Ведь этот адрес заявлен в начале темы как адрес проекта. Густов в Вики тоже дает эту ссылку. Все, кто туда придут, скачают проект почти полугодичной давности.

Pasha: Andrey пишет: В связи с переходом на LetoDb - как лучше реализовывать "счетчик" ID у себя в задачах ? Только заметил этот вопрос. Можно использовать udf-функцию UDF_AppendRec( nUserStru, cFieldName, xOrder, xMin ) из модуля letoudf.prg она обеспечивает уникальность ключа с гарантией 100% Вызов с клиента: leto_ParseRec( leto_udf("UDF_AppendRec", <cFieldName>, <xOrder>[, <xMin>] ) ) Параметры: cFieldName - имя поля ключа xOrder - имя/номер индекса xMin - необязательное минимальное значение

Pasha: Панченко пишет: что-то давненько не обновлялся архив на http://sourceforge.net/projects/letodb/. Выложу сборку.

Andrey: Только не пинайте сильно.... Дайте адрес для обновления LetoDB через SVN. Заранее спасибо....

Dima: Andrey пишет: Дайте адрес для обновления LetoDB через SVN А его нет так как не переезжал туда если не ошибаюсь

AlexMyr: Dima пишет: А его нет так как не переезжал туда если не ошибаюсь правильно. Andrey пишет: Дайте адрес для обновления LetoDB cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb

Sergy: Подскажите плиз новичку: 1) с чего начать, откуда качать, что читать (кроме readme, скинутого в соседней теме) 2) возможна ли одновременная работа letodb сервера на одной базе параллельно со "старым" способом работы через DBFNTX rdd ? Т.е. есть желание попробовать оптимизировать сначала наиболее "медленные" выборки - чтобы обкатать методы работы. А потом потихоньку менять шаг за шагом, чтобы не раскорячить неожиданно основной процесс работы предприятия?

SergKis: Sergy пишет: с чего начать 1. со сборки LetoDb, настройка letodb.ini,запуска на localhost 2. с мало используемого справочника, Use перенацеливаешь на localhost, RDD LETO в use, если в текстах было Shared, то по идее все должно зашевелиться, иначе Rlock обработки добавляешь 3. если зашевелилось, можно переползти на сервер с localhost и потестить 4. попробовать совместную работу LetoDb со "старым" способом работы Sergy пишет:работа letodb сервера на одной базе параллельно со "старым" способом работы letodb.ini[pre2] ... Default_Driver = NTX - RDD по умолчанию для открытия файлов на сервере ( CDX/NTX ); ... Share_Tables = 1 - если 0 (по умолчанию, этот режим существует с момента старта проекта letodb), letodb открывает все таблицы в монопольном режиме, что позволяет увеличить производительность. Если 1 (новый режим, добавлен после 11.06.2009), таблицы открываются в том режима, в каком их открывает клиентское приложение, монопольном или режиме разделения, что позволяет letodb работать совместно с другими приложениями. [/pre2]

SergKis: Sergy посмотреть server.prg в Source и примеры в tests, utils - это святое

AlexMyr: Sergy пишет: 1) с чего начать, откуда качать, что читать (кроме readme, скинутого в соседней теме) Лучше начинать с этого форума. Брать через cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb По поводу почитать - поиск letodb по форуму. Sergy пишет: 2) возможна ли одновременная работа letodb сервера на одной базе параллельно со "старым" способом работы через DBFNTX rdd ? Т.е. есть желание попробовать оптимизировать сначала наиболее "медленные" выборки - чтобы обкатать методы работы. Смотреть опцию: [pre2]Share_Tables = 0 - если 0 (по умолчанию, этот режим существует с момента старта проекта letodb), letodb открывает все таблицы в монопольном режиме, что позволяет увеличить производительность. Если 1 (новый режим, добавлен после 11.06.2009), таблицы открываются в том режима, в каком их открывает клиентское приложение, монопольном или режиме разделения, что позволяет letodb работать совместно с другими приложениями.[/pre2] На практике можно поступить следующим образом (у меня так), взять базу, например справочник, и открывать его через letodb, т.е. use baza via rddleto, остальные базы как и открывали. Потом смотрите что получается, как работает прога и постепенно переносите оставшиеся базы на leto.

Sergy: AlexMyr пишет: cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb Пошел изучать cvs... AlexMyr пишет: На практике можно поступить следующим образом (у меня так), взять базу, например справочник, и открывать его через letodb, т.е. use baza via rddleto, остальные базы как и открывали. Потом смотрите что получается, как работает прога и постепенно переносите оставшиеся базы на leto. Именно это я и имел в виду. То что нужно.

Sergy: Правильно ли я понимаю, что вот отсюда: http://sourceforge.net/projects/letodb/files/bin/ я могу скачать рабочую сборку letodb cервера без плясок с бубном вокруг CVS ? Является ли эта сборка от 28 ноября 2012 актуальной ?

PSP: Sergy пишет: Правильно ли я понимаю, что вот отсюда: http://sourceforge.net/projects/letodb/files/bin/ я могу скачать рабочую сборку letodb cервера без плясок с бубном вокруг CVS ? Является ли эта сборка от 28 ноября 2012 актуальной ? Актуальная версия: Changelog,v 1.350.2.123 2013/08/26 06:13:57 ptsarenko А какие проблемы с cvs?

Sergy: PSP пишет: А какие проблемы с cvs? Не сталкивался никогда раньше. Посмотрел - куча версий: с GUI, с командной строкой, кроссплатформенные, бесплатные, коммерческие и тп... Подскажите плиз тогда простой и надежный.

Pasha: Sergy пишет: Является ли эта сборка от 28 ноября 2012 актуальной ? Для старта более чем сойдет, так как принципиальных изменений с тех пор не было. Но клиентскую библиотеку рекомендуется пересобрать, так как она была собрана с Harbour SVN на ноябрь прошлого года. С пересборкой проблем быть не должно, равно как и с cvs. Надо скачать бесплатный TortoiseCVS, установить и ввести параметры для скачивания сырцов letodb. Должен еще заметить, что, если программы работают в терминальном режиме, использование letodb бессмыссленно. Также режим Share_Tables=1 рекомендую использовать только на этапе тестирования, так как при этом производительность сервера будет заметно ниже.

Sergy: Pasha пишет: Для старта более чем сойдет, так как принципиальных изменений с тех пор не было. Но клиентскую библиотеку рекомендуется пересобрать, так как она была собрана с Harbour SVN на ноябрь прошлого года. С пересборкой проблем быть не должно, равно как и с cvs. Надо скачать бесплатный TortoiseCVS, установить и ввести параметры для скачивания сырцов letodb. Спасибо. Должен еще заметить, что, если программы работают в терминальном режиме, использование letodb бессмыссленно. Также режим Share_Tables=1 рекомендую использовать только на этапе тестирования, так как при этом производительность сервера будет заметно ниже. Это и ежу понятно, что использовать letodb на локальных таблицах смысла нет. Именно поэтому нужно различать режим работы базы с файлами и переключать в зависимости от... Как раз oб этом я решил поднять тему тут: http://clipper.borda.ru/?1-0-0-00000336-000-0-0-1378125566 Точно так-же понятно, что в работа letodb в shared будет существенно медленнее чем exclusive. Но перекинуть проект с сотнями функций в один присест я не готов. Начну с самых времязатратных участков в режиме тестирования. Сравню результаты - стоит ли овчинка выделки. А там посмотрим...

Sergy: Pasha пишет: Надо скачать бесплатный TortoiseCVS, установить и ввести параметры для скачивания сырцов letodb Установил. Ввел строку cvs -d:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb Спрашивает пароль: В C:\Users\Sergy\AppData\Local\Temp\: "C:\Program Files (x86)\CVSNT\cvs.exe" -q -Q co -c CVSROOT=:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb Empty password used - try 'cvs login' with a real password cvs [checkout aborted]: authorization failed: server letodb.cvs.sourceforge.net rejected access to /cvsroot/letodb co -P -r rel-1-mt letodb for user anonymous Ошибка, CVS операция не удалась В : "C:\Program Files (x86)\CVSNT\cvs.exe" -q login CVSROOT=:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb Logging in to :pserver:anonymous@letodb.cvs.sourceforge.net:2401:/cvsroot/letodb co -P -r rel-1-mt letodb cvs [login aborted]: authorization failed: server letodb.cvs.sourceforge.net rejected access to /cvsroot/letodb co -P -r rel-1-mt letodb for user anonymous Ошибка, CVS операция не удалась В : "C:\Program Files (x86)\CVSNT\cvs.exe" -q login CVSROOT=:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb co -P -r rel-1-mt letodb Logging in to :pserver:anonymous@letodb.cvs.sourceforge.net:2401:/cvsroot/letodb co -P -r rel-1-mt letodb Чего не хватает ?

Andrey: У меня тоже показывает: Нажимаешь Ок и обновляется (создает папку letodb - если не было) НОРМАЛЬНО !!! Собирал библиотеку для xHarbour 1.2.3 (Build 20130705) выдал вот что: MAKE Version 5.2 Copyright (c) 1987, 2000 Borland bcc32 -c -Iinclude;Z:\xHarbour\include -d -tWM -D__WIN32__ -D__WIN_SERVICE__ -oobj\b32\leto1.obj source\client\leto1.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland source\client\leto1.c: Warning W8012 source\client\leto1.c 1131: Comparing signed and unsigned values in function leto_HotBuffer Warning W8060 source\client\leto1.c 3882: Possibly incorrect assignment in function letoOpen Warning W8075 source\client\leto1.c 5994: Suspicious pointer conversion bcc32 -c -Iinclude;Z:\xHarbour\include -d -tWM -D__WIN32__ -D__WIN_SERVICE__ -oobj\b32\letomgmn.obj source\client\letomgmn.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland source\client\letomgmn.c: bcc32 -c -Iinclude;Z:\xHarbour\include -d -tWM -D__WIN32__ -D__WIN_SERVICE__ -oobj\b32\hbip.obj source\common\hbip.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland source\common\hbip.c: bcc32 -c -Iinclude;Z:\xHarbour\include -d -tWM -D__WIN32__ -D__WIN_SERVICE__ -oobj\b32\net.obj source\common\net.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland source\common\net.c: bcc32 -c -Iinclude;Z:\xHarbour\include -d -tWM -D__WIN32__ -D__WIN_SERVICE__ -oobj\b32\common_c.obj source\common\common_c.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland source\common\common_c.c: bcc32 -c -Iinclude;Z:\xHarbour\include -d -tWM -D__WIN32__ -D__WIN_SERVICE__ -oobj\b32\blowfish.obj source\common\blowfish.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland source\common\blowfish.c: Z:\xHarbour\bin\harbour.exe -iinclude;Z:\xHarbour\include -n -q0 -w -es2 -gc0 -d__WIN_SERVICE__ source\client\rddsys.prg -oobj\b32\rddsys.c bcc32 -c -Iinclude;Z:\xHarbour\include -d -tWM -D__WIN32__ -D__WIN_SERVICE__ -oobj\b32\rddsys.obj obj\b32\rddsys.c Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland obj\b32\rddsys.c: IF EXIST "lib\rddleto.lib" del "lib\rddleto.lib" > NUL TLIB "lib\rddleto.lib" /0 @MAKE0000.@@@ TLIB 4.5 Copyright (c) 1987, 1999 Inprise Corporation +obj\b32\leto1.obj & +obj\b32\letomgmn.obj & +obj\b32\hbip.obj & +obj\b32\net.obj & +obj\b32\common_c.obj & +obj\b32\blowfish.obj & +obj\b32\rddsys.obj & + Z:\xHarbour\bin\harbour.exe -iinclude;Z:\xHarbour\include -n -q0 -w -es2 -gc0 -d__WIN_SERVICE__ source\server\server.prg -oobj\b32\server.c ** error 1 ** deleting obj\b32\server.c Будет ли работать ?

Sergy: Andrey пишет: Нажимаешь Ок и обновляется (создает папку letodb - если не было) НОРМАЛЬНО !!! У меня немного не так. Идет окно, в которое транслируется лог, который я привел в цитате. Сверху возникает окно с полем для ввода пароля. Оставляю пустым и нажимаю OK - все повторяется снова. В окне с логом есть кнопка OK (неактивна) и ПРЕРВАТЬ. И само собой, ничего не обновляется (у меня обновлять-то пока нечего, хочу скачать для начала).

Dima: Sergy Да все норм работает. Налил исходники вот сюда http://zalil.ru/34728143 PS winrar 5.0

AlexMyr: Sergy пишет: И само собой, ничего не обновляется (у меня обновлять-то пока нечего, хочу скачать для начала). Использую консольный cvs, первый раз с пустым паролем, потом уже без пароля.

AlexMyr: Andrey пишет: ** error 1 ** deleting obj\b32\server.c Будет ли работать ? а библа собралась то? При error не должна.

Pasha: Сервер letodb не собирается с xHarbour. Надо собирать с Harbour. См. раздел 2 readme

Sergy: Dima пишет: Налил исходники вот сюда http://zalil.ru/34728143 Спасибо. Скачал.

Andrey: AlexMyr пишет: а библа собралась то? При error не должна. Собралась ! Pasha пишет: Сервер letodb не собирается с xHarbour. Надо собирать с Harbour. А клиент на хХарборе будет работать с сервером letodb собранным на Харборе ?

Pasha: Добавил поддержку выполнения блока кода в опции EVAL команды INDEX во время выполнения индексации

Dima: Pasha пишет: Добавил поддержку выполнения блока кода в опции EVAL команды INDEX во время выполнения индексации Ну наконец то :) Спасибо !

Pasha: Andrey пишет: клиент на хХарборе будет работать с сервером letodb собранным на Харборе ? Да

sashaBG: Вот такой код RDDSETDEFAULT( "LETO" ) USE ( _Data + 'DECL70' ) NEW EXCLUSIVE ZAP RDDSETDEFAULT( "DBFCDX" ) APPEND FROM DECL70.TXT DELIMITED WITH TAB RDDSETDEFAULT( "LETO" ) PPO последней части __dbZap() RDDSETDEFAULT( "DBFCDX" ) __dbDelim( .F., "DECL70.TXT", "TAB", { },,,,, .F., ) RDDSETDEFAULT( "LETO" ) на обычном Harbor-е черз DBFCDX все правильно переносится а под LetoDB какая то "КЕСЯ МЕСЯ" :) P.S. Без RDDSETDEFAULT( "DBFCDX" ) и RDDSETDEFAULT( "LETO" ) ТОЖЕ САМОЕ

sashaBG: Пытаюсь собрать но, не получается Пробую hbmk2-x64 из HB30 , так как там есть 64 битовые библиотеки но компилятор и меня MINGW64 4.8.1 Паша помоги пожалуйста ! Заодно скажи есть смысл ето делать или остатся на 32 разрядную верию вот bat файл: setlocal set path=C:\hb30\comp\MINGW64\bin;c:\hb30\bin SET HB_COMPILER=mingw64 hbmk2-x64 rddleto.hbp letodb.hbp -rebuild -trace endlocal

Pasha: А что за ошибки при сборке ? Я собирал без проблем letodb-64 с Harbour 3.0/3.2dev и mingw64 tdm 4.6 А смысл есть, если на сервере стоит 64-битная ОС.

sashaBG: Mingw64 у меня был какойто неправильный . Заметил что hbmak2 ищет x86_64-w64-mingw32-ar.exe а в папке bin есть ar.exe Взял и копираовал ar.exe в x86_64-w64-mingw32-ar.exe И все заработало :)

alkresin: Я начал понемножку просматривать код letodb, сравнивая его со своей рабочей версией ( от 20.08.2010 ). Вот такой вопрос: почему теперь leto_disconnect() закрывает не текущее соединение, что было бы логично, а первое соединение из letoConnPool ?

alkresin: А... теперь увидел. 1 - это номер параметра, передаваемого функции. А зачем так запутанно - то ?

Pasha: По умолчанию, без параметра (или как раньше) закрывается текущее соединение. А при наличии параметра можно закрыть любое соединение по его номеру.

alkresin: Это я уже понял. Просто было бы лучше, понятнее, если бы в leto_getConnection() передавался не номер параметра, а сам параметр hb_param( n, HB_IT_ANY ). Мелочь, но ...

alkresin: Продолжаю разбираться с leto1.c. В функции letoSetFilter() раньше строка фильтра конвертировалась в codepage базы данных - в случае, если эта codepage отличалась от codepage клиентского приложения. Теперь эта конвертация где-то в другом месте делается ?

alkresin: И еще, в letoOpen(): if( pOpenInfo->abName[0] != '+' && pOpenInfo->abName[0] != '-' ) Это для чего ?

Pasha: alkresin пишет: В функции letoSetFilter() раньше строка фильтра конвертировалась в codepage базы данных - в случае, если эта codepage отличалась от codepage клиентского приложения. Теперь эта конвертация где-то в другом месте делается ? Эта конвертация и раньше была не нужна, я ее пару лет назад убрал. Пусть таблица открыта в cp866, а кодировка программы - cp1251 Клиент передает на сервер строку фильтра в cp1251. Поскольку таблица на сервере открыта в cp866, при выполнении выражения фильтра: а именно - чтении полей таблицы методом GetValue данные будут конвертированы из cp866 в cp1251, которую установит функция leto_SetUserEnv, и сравнение строк будет выполняться cp1251 с cp1251

Pasha: alkresin пишет: И еще, в letoOpen(): if( pOpenInfo->abName[0] != '+' && pOpenInfo->abName[0] != '-' ) Это для чего ? Это для пакетного открытия нескольких таблиц одним запросом к серверу. Пример использования см. в tests\letoudf.prg, функция UDF_OpenTables

alkresin: Эта конвертация и раньше была не нужна, я ее пару лет назад убрал. Действительно. Еще вопрос: для чего эта структура в LETOCONNECTION - pCdpTable, она , похоже, нигде не инициализируется, и функция leto_GetServerCdp() просто возвращает код, который получает в качестве параметра ?

Pasha: Она инициализируется в функции LETO_ADDCDPTRANSLATE, используется для тех случаев, когда одна и та же кодовая страница на клиенте и на сервере называется по разному: к примеру, RU1251 и RUWIN. Из-за многочисленных переименований кодовых страниц в разных версиях Harbour и xHarbour такое может произойти.

Pasha: Александр, посмотрите пожалуйста manage.exe, собранный по windows: Harbout git + mingw tdm 4.6.1, hwgui и manage.prg последние сырцы с SVN и CVS http://files.mail.ru/327FCEB4B20541EC90551C0BC65D8F95 Ненормально работает combobox для адреса сервера: не показывает список Items Только из-за этого я не выкладываю сборку letodb на sourceforge, сам не могу понять причину.

alkresin: Pasha пишет: Ненормально работает combobox для адреса сервера: не показывает список Items Исправил.

alkresin: Павел, напомните мне, пожалуйста, предназначение RDD методов drop, exists и rename.

alkresin: Разобрался, вопрос снят.

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

Pasha: Все собрал, запустил - вроде бы полет нормальный. Увидел одно изменение на клиенте: в leto_ParseRec после if( pArea->area.fEof ) { leto_SetBlankRecord( pArea, FALSE ); раньше стоял возврат, сейчас его нет. Но это и правильно, чтобы считался reccount Еще я не понял, зачем в leto_gotoEof стоит вызов SELF_RECCOUNT ? Еще один ньюанс: раньше в leto_writelog можно было передать длину строки, и выдавать в лог бинарные данные. Сейчас этого нет. Может быть, стоит вернуть ? И наверное, стоит изменить версию.

alkresin: Pasha пишет: if( pArea->area.fEof ) { leto_SetBlankRecord( pArea, FALSE ); раньше стоял возврат, сейчас его нет. Но это и правильно, чтобы считался reccount Мне показалось, что так будет безопаснее. Еще я не понял, зачем в leto_gotoEof стоит вызов SELF_RECCOUNT ? Старая версия сервера ( а этот вызов именно для нее ) не передает в каждом пакете записей ulRecCount, клиент его получает только в результате вызова SELF_RECCOUNT, а в leto_gotoEof он требуется. Еще один ньюанс: раньше в leto_writelog можно было передать длину строки, и выдавать в лог бинарные данные. Сейчас этого нет. Может быть, стоит вернуть ? Да, стоит - вторым параметром, наверное. Сделаю. И наверное, стоит изменить версию. Не уверен. Протокол не изменился, сервер тот же, новые функции не добавились.

alkresin: Думаю, можно убрать уже все эти HARBOUR_VER_AFTER_101, HARBOUR_VER_BEFORE_100 - Harbour ниже 2.0 вряд ли кто использует.

Pasha: Согласен. А в исходниках сервера можно убрать ветки для xHarbour. Только ветки с __OLDRDD__ я еще использую (для xHarbour)

alkresin: Что-то до меня никак не доходит смысл конструкции в leto_ConnectionClose(): pConnection->bCloseAll = 0; hb_rddIterateWorkAreas( leto_CheckAreas, (void *) pConnection ); if( pConnection->bCloseAll ) leto_CloseAll( pConnection ); leto_CheckAreas() проверяет, принадлежит ли area этому соединению и является ли она leto area. Если хоть одна такая area находится, то тогда выполняется leto_closeall() - а там опять такая же проверка ( в leto_doclose() ). Почему нельзя сразу вызвать leto_closeall() ? И непонятно, зачем в leto_closeall() перед и после вызова hb_rddIterateWorkAreas() устанавливается pConnection->bCloseAll ?

Pasha: leto_ConnectionClose() вызывается по leto_disconnect(), или при завершении программы. Должно быть закрыто только указанное соединение, или текущее. При вызове leto_disconnect() могут быть открыты рабочие области на нескольких серверах letodb, и локальные р.о. По hb_rddIterateWorkAreas проверяется, открыта ли хотя бы одна р.о. на этом сервере. Если открыта - тогда надо выдать команду этому серверу, и только этому: close_all. Если нет открытых р.о. - то такую команду именно этому серверу выдавать незачем. Все остальные р.о. - с других серверов letodb и локальные - должны остаться открытыми.

alkresin: Pasha пишет: Если открыта - тогда надо выдать команду этому серверу, и только этому: close_all Но ведь такая же проверка осуществляется еще раз в leto_doClose(). Т.е. можно в leto_doClose() добавить строчку: if( leto_CheckAreaConn( pArea, ( LETOCONNECTION * ) p ) ) { SELF_CLOSE( pArea ); pConnection->bCloseAll = 1; } и в leto_CloseAll() выдавать команду close_all, если установлен pConnection->bCloseAll: if( pConnection->bCloseAll ) Тогда мы избавляемся от того лишнего кода в leto_ConnectionClose() и от функции leto_CheckAreas(), которая только оттуда вызывается. Или я что-то упустил ?

Pasha: leto_closeAll безусловно выдает команду серверу "close_all". А если уже все р/о с этого сервера закрыты, то эта команда не нужна. Вот и делается дополнительная проверка перед вызовом leto_closeAll(), нужен ли вообще этот вызов. Хотя конечно, можно объединить все в hb_rddIterateWorkAreas. Но тогда в pConnection надо добавить еще один флаг, дополнительно к bCloseAll

alkresin: Зачем еще один флаг ? static ERRCODE leto_doClose( AREAP pArea, void * p ) { if( leto_CheckAreaConn( pArea, ( LETOCONNECTION * ) p ) ) { SELF_CLOSE( pArea ); pConnection->bCloseAll = 1; } return SUCCESS; } BOOL leto_CloseAll( LETOCONNECTION * pConnection ) { char szData[16]; hb_rddIterateWorkAreas( leto_doClose, (void *) pConnection ); if( pConnection->bCloseAll ) { if( leto_CheckServerVer( pConnection, 100 ) ) sprintf( szData,"close_all;\r\n" ); else sprintf( szData,"close;00;\r\n" ); pConnection->bCloseAll = 0; if( leto_DataSendRecv( pConnection, szData, 0 ) ) return TRUE; else return FALSE; } else return TRUE; } void leto_ConnectionClose( LETOCONNECTION * pConnection ) { if( pConnection->pAddr ) { leto_CloseAll( pConnection ); ... } }

Pasha: Так в SELF_CLOSE( pArea ) используется флаг bCloseAll, чтобы не выдавать серверу команды close. А тут он используется еще и для того, чтобы отметить, есть ли открытые р/о с этого сервера. Вот поэтому и нужны 2 флага: один для SELF_CLOSE, а второй - чтобы затем определить, выдавать или нет команду close_all.

alkresin: Так в SELF_CLOSE( pArea ) используется флаг bCloseAll, чтобы не выдавать серверу команды close. Ну так поменяем местами строчки в предлагаемом варианте leto_doClose() и этот флаг выполнит обе функции: static ERRCODE leto_doClose( AREAP pArea, void * p ) { if( leto_CheckAreaConn( pArea, ( LETOCONNECTION * ) p ) ) { pConnection->bCloseAll = 1; SELF_CLOSE( pArea ); } return SUCCESS; }

Pasha: Да, так сработает.

Pasha: Хотя нет. Вызов то будет для всех р.о, в том числе с других серверов. Тогда будут закрыты р.о., которые закрывать не надо.

alkresin: Хотя нет. Вызов то будет для всех р.о, в том числе с других серверов Какой вызов ? Сигнал close_all ? Так он посылается по одному определенному соединению, на один сервер.

Pasha: Это я уже туплю. Все там в порядке.

alkresin: Ok. Я сейчас в этом копаюсь, потому что хочу разбить клиентский модуль на две части, выделить client engine, который не будет содержать вызовов Harbour функций и может использоваться в приложениях на других языках. К тому же это позволит упростить и лучше структуировать код.

Pasha: Хорошее дело, и нужное, только сложное. А какие есть планы по клиентской библиотеке ? Просто сделать dll по типу ace32 ?

alkresin: Хорошее дело, и нужное, только сложное. Буду делать постепенно - сначала connect/disconnect, management функции, запись/чтение переменных - уже в таком наборе это можно использовать. Потом одну за другой функции для работы с БД. А какие есть планы по клиентской библиотеке ? Просто сделать dll по типу ace32 ? Есть 3 C файла - letoclient.c, common_c.c, blowfish.c, их можно непосредственно включить в проект, или построить из них dll или lib. А какие еще варианты ?

alkresin: Объясните мне, пожалуйста, еще такую вещь: leto_GetServerCdp() вызывается только из leto_ConnectionNew(), т.е. когда pConnection только создан и pConnection->pCdpTable пуста - и leto_GetServerCdp() ничего там найти не может ...

Pasha: Я уже с трудом вспоминаю тот алгоритм. Кажется, предусматривалось вот что: Сначала надо установить текущее соединение через вызов RDDI_CONNECTION. Затем задать таблицу соответствия кодовых страниц вызовами LETO_ADDCDPTRANSLATE И только после этого коннектиться к серверу.

alkresin: RDDI_CONNECTION закомментарен. Но, в любом случае, это не может работать, поскольку leto_GetServerCdp() вызывается только из leto_ConnectionNew(), т.е. до того как LETO_ADDCDPTRANSLATE могла бы отработать.

Pasha: В функции leto_writelog может быть стоит оставить одну ветку, с вызовами hb_fs* ? Эта ветка выполняет все необходимые функции. Зачем тянуть лишнюю ссылку на hb_fopen ?

Pasha: alkresin пишет: RDDI_CONNECTION закомментарен. Но, в любом случае, это не может работать, поскольку leto_GetServerCdp() вызывается только из leto_ConnectionNew(), т.е. до того как LETO_ADDCDPTRANSLATE могла бы отработать. Да нет там комментария: case RDDI_CONNECTION: ... А структура letoConnPool выделяется в letoInit, т.е до вызова leto_ConnectionNew(). По RDDI_CONNECTION можно установить текущее соединение, тоже до первого коннекта. И LETO_ADDCDPTRANSLATE сможет отработать.

alkresin: Павел, а зачем leto_writelog() урезали ?

Pasha: Там было 2 ветки: одна через функции hb_fs*, другая - через hb_fopen Первая ветка выполняет все, что нужно. Тогда зачем нужна вторая ? Только лишний модуль цепляется.

alkresin: Вторая ветка нужна для того, чтобы реализовать синтаксис, как в printf, например: leto_writelog( NULL, 0, "Name: %s Number: %d\r\n", szFile, iNum ); Это часто бывает очень удобно - вся нужная информация одной строчкой кода.

Pasha: Верну

Pasha: А как сделать dll из letocl.c ? Прицепить к проекту src\vm\maindllh.c, и добавить префикс для экспортируемых функций ? А надо предусмотреть и создание so-библиотеки для *nix

Pasha: Я в своих программах использую вызов hb_iperrorcode, для диагностики ошибок коннекта с сервером. Сейчас этой функции нет. Может быть, на клиенте стоит добавить модуль вроде такого: hbiph.c #include "hbapi.h" int hb_iperrorcode( void ); HB_FUNC( HB_IPERRORCODE ) { hb_retni( hb_iperrorcode( ) ); } HB_FUNC( HB_IPERRORDESC ) { hb_retc( strerror( hb_iperrorcode( ) ) ); } Тогда переменная errorDesc из hbip.c получается не нужна, ее можно будет убрать.

Pasha: Для LetoMemoRead нужен еще параметр - размер файла (для возможности передачи файлов, содержащих нулевой байт): char * LetoMemoRead( LETOCONNECTION * pConnection, char * szFile, unsigned long * ulLen ) И у меня что-то сваливается leto_MemoRead, размер файла десятки килобайт. Пока ищу причину.

alkresin: Pasha пишет: А как сделать dll из letocl.c ? Прицепить к проекту src\vm\maindllh.c, и добавить префикс для экспортируемых функций ? Еще не думал на эту тему. Наверное, просто поставить соответствующую опцию линкера. Maindllh.c тут, скорее всего, не нужен. Я в своих программах использую вызов hb_iperrorcode, для диагностики ошибок коннекта с сервером. Сейчас этой функции нет. Может быть, на клиенте стоит добавить модуль вроде такого: Да, стоит. Для LetoMemoRead нужен еще параметр - размер файла (для возможности передачи файлов, содержащих нулевой байт): Добавлю.

Pasha: Кажется, я понял причину падения leto_MemoRead. Падение происходит на файлах размером больше 16К В leto_Recv() в этом случае вызывается realloc для перевыделения памяти s_szBuffer. А ниже стоит вызов iRet = hb_ipRecv( hSocket, ptr, lMsgLen ); У меня в рабочей программе падение есть, а в тестах - нет. После вызова realloc адрес в s_szBuffer может измениться, а может остаться прежним. Если он изменился, то ptr указывает на уже освобожденный участок памяти, и в результате происходит крэш.

alkresin: Да, вполне вероятно, с realloc бывают такие неприятности. Я вставил там ptr = s_szBuffer; после realloc - теперь, может, заработает. Заодно и часть функций по работе с dbf через C client сделал - пока, правда, ходить по таблице еще нельзя.

Pasha: Да, теперь работает Думается, со временем из LETOAREA в LETOTABLE перекочует все, кроме area, pTable и lpdbPendingRel

alkresin: Да, наверное, по мере необходимости.

Pasha: Есть предложение переименовать несколько функций: LetoIsFileExist --> LetoFileExist LetoMakeDir --> LetoDirMake для выполнения соответствия LetoFile* / LetoDir* и LetoDbOpen --> LetoDbOpenTable LetoDbClose --> LetoDbCloseTable так как еще будут функции Open/Close Index

alkresin: Согласен.

alkresin: Павел, не могли бы вы пояснить мне строчки 1230-1239 из leto1.c, letoSeek(): if( pArea->area.dbfi.itmCobExpr != NULL && !pArea->area.dbfi.fOptimized ) { if( SELF_SKIPFILTER( ( AREAP ) pArea, ( bFindLast ? -1 : 1 ) ) == SUCCESS ) { PHB_ITEM pItem = leto_KeyEval( pArea, pTagInfo ); if( itmCompare( pItem, pKey, FALSE ) != 0 && ! bSoftSeek ) SELF_GOTO( ( AREAP ) pArea, 0 ); } }

Pasha: Если фильтр не оптимизирован, то надо сделать seek на сервере, и затем отработать фильтр на клиенте с проверкой ключа.

alkresin: А что это за поля в LETOTAGINFO - uiFCount и puiFields ? Они инициализируются, но нигде не используются.

Pasha: Я планирую в дальнейшем их использовать, поэтому и добавил. Сейчас при обновлении записи сбрасывается skip-буфер. Но, если обновляются неиндексные поля, его можно не сбрасывать, а использовать и далее, только пометить данную запись как измененную. Порядок записей в текущем ордере ведь не изменился. Это позволило бы существенно оптимизировать циклы вроде dbEval, while ! eof(), в которых выполняется обновление данных.

alkresin: Ну что ж, выделение С клиента для letodb в значительной мере сделано - можно ходить по базе ( go, skip, filter, seek ), добавлять и менять записи. Еще надо кое-что доделать и почистить, но основная часть готова.

Andrey: alkresin пишет: но основная часть готова Не смотря на праздники - работа идет !

alkresin: Andrey пишет: Не смотря на праздники - работа идет ! Погода не очень - выходить из дома неохота. Слоняясь по квартире, иногда и к компьютеру подходишь... :) С созданием dll вопрос решился просто - hbmk, все-таки, иногда бывает полезен.

alkresin: По поводу добавления bAutOpen: лучше, наверное, сделать так же, как и с остальными установками (SetDeleted, SetCentury, etc.) - добавить в letocl.c static unsigned int s_uiAutOpen, соответствующую функцию LetoSetAutOpen(), добавить вызов этой функции в leto1.c в leto_SetOptions() и вызывать leto_SetOptions() из LetoOpen()

Pasha: Переделаю

alkresin: Добавил англоязычный форум по letodb: https://sourceforge.net/apps/phpbb/letodb/index.php, надо будет и на сайте ( letodb.sourceforge.net ) что-нибудь вразумительное написать, а то новым пользователям непонятно даже, какую ветку использовать, как код брать.

Pasha: Можно было бы дать ссылку на этот форум в Harbour Users

alkresin: Дал. Хочу еще написать php client. Попробовал уже простейшие вещи - присоединиться, получить management информацию - работает.

Andrey: alkresin пишет: Хочу еще написать php client Поддерживаем ! И что будет в результате: доступ через Харбор и доступ к базе на сайте через php client ?

kia: Александр, Паша в процессе тестирования LetoDb (v 1.350.2.172 2014/01/15 10:57:57) сервер - linux, клиент - win7, обнаружил несколько ошибок. Первые две ошибки, при попытке открыть не существующий в данный момент dbf-файл, вызывают падение программы с "Exception error". В зависимости от наличия алиаса в вызове функции DbUseArea происходят разные ошибки. Контрольный пример прилагается. Надо раскоментировать строку с нужной ошибкой /* test_error.prg letoDbSrc - $Id: Changelog,v 1.350.2.172 2014/01/15 10:57:57 alkresin Exp $ Harbour Build Info --------------------------- Version: Harbour 3.2.0dev (r1401142236) Compiler: MinGW GNU C 4.8 (32-bit) Platform: Windows 7 6.1.7600 PCode version: 0.3 ChangeLog last entry: 2014-01-14 23:36 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) ChangeLog ID: 89da1a2b87be5b1553225eba6b378c318c4a09ce Built on: Jan 17 2014 14:28:19 Build options: (Clipper 5.3b) (Clipper 5.x undoc) --------------------------- letoDb server - linux client - win7 */ REQUEST HB_CODEPAGE_RU866 REQUEST HB_LANG_RU866 REQUEST LETO function Main( ... ) Hb_CDPSelect( "RU866" ) Hb_LangSelect( "RU866" ) HB_GtInfo( /*HB_GTI_CODEPAGE*/ 25, 255 ) // #define OEM_CHARSET 255 - from wingdi.h RDDSETDEFAULT( "LETO" ) setcolor('14/1') cls ? 'begin test LetoDb' ? leto_Connect( "//192.168.1.1:2812/" ) //existing path on LetoDb server //error № 1 DbUseArea(.t.,,'dummy','DUMMY') //function commonError leto1c.c //line 181 - hb_errPutFileName( pError, szFileName ); //szFileName - не инициализированный указатель //вызывается из letoOpen line 2272 указатель ptr - не используется //до самого вызова commonError если указан алиас в DbUseArea //error № 2 //DbUseArea(.t.,,'dummy') //function letoClose leto1c.c //line 1816 - if( pTable->pTagInfo ) //pTable==null в это время, в строке 1809 есть проверка указателя //line 1809 - if( pTable && pTable->uiUpdated ) ? Alias() inkey(0) DbCloseAll() quit return NIL //end Main() ps Большое спасибо за вашу работу.

alkresin: kia пишет: в процессе тестирования LetoDb (v 1.350.2.172 2014/01/15 10:57:57) сервер - linux, клиент - win7, обнаружил несколько ошибок. Спасибо за информацию. Поправлю.

alkresin: Andrey пишет: И что будет в результате: доступ через Харбор и доступ к базе на сайте через php client ? Да. Собственно, кое-что уже работает, пример - на CVS.

kia: alkresin пишет: Спасибо за информацию. Поправлю. Вот еще одно странное поведение сервера, похоже связанное с наследованием глобальных установок в тредах. В настойках letodb.ini LOWER_PATH = 1 но эта настройка не работает как надо. тестовый пример (исходные данные как в предыдущем посте) function Main( ... ) ... ? leto_Connect( "//192.168.1.1:2812/" ) //existing path on LetoDb server DbCreate('tmptest',{{'test','C',10,0}}) DbUseArea(.t.,,'tmptest') ? Alias() DbCloseArea() inkey(0) DbUseArea(.t.,,'tmpTest') //здесь возникает ошибка! Error DBFCDX/1001 Open error: tmpTest.dbf //код дос ошибки - 2 (File not found) ? Alias() DbCloseArea() inkey(0) return NIL //end Main() Если в файл server.prg после кода line 909 IF ::lLower SET( _SET_FILECASE, 1 ) SET( _SET_DIRCASE, 1 ) ENDIF добавить wrlog(str(set(_SET_FILECASE))) то в логе увидим результат 1, т.е. в этом месте установка сработала но та же стока wrlog(str(set(_SET_FILECASE))) в функции hs_opentable line 368 покажет что _SET_FILECASE установлен в 0 (уже правда в логе letodb_0.log а не в letodb.log) если в функции hs_opentable добавить не только получение но и установку _SET_FILECASE wrlog(str(set(_SET_FILECASE,1))) то эта фича "LOWER_PATH" начинает работать правильно. Спасибо за вашу работу.

alkresin: kia пишет: Вот еще одно странное поведение сервера, похоже связанное с наследованием глобальных установок в тредах. Похоже, что при создании нового потока на С уровне с помощью hb_threadCreate() ( а именно так это делается в letodb ) текущее состояние не наследуется. Посмотрю, что можно сделать. Кстати, ошибки с открытием несуществующей таблицы сегодня исправил.

alkresin: Павел, мне непонятно предназначение опции TIMEOUT в letodb.ini. Похоже, что если клиент не будет непрерывно посылать запросы серверу, соединение разорвется ?

kia: alkresin пишет: Кстати, ошибки с открытием несуществующей таблицы сегодня исправил. Спасибо большое, завтра с утра проверю. Нашел еще описку в функции leto_BagCheck файл common_c.c ... line 171 p1 = ptr = szTable; p2 = p4 = NULL; while( ( c = *ptr) != 0 ) { if( c == '/' || c == '\\' ) p2 = ptr; <---должно быть p1 = ptr+1; //ptr+1 т.к. ptr указывает на "\" а не на начало имени else if( c == '.' ) p2 = ptr; ptr ++; } if( !p2 || p2 < p1 ) p2 = ptr; p3 = ptr = szBagName; while( ( c = *ptr) != 0 ) { if( c == '/' || c == '\\' ) p4 = ptr; <---должно быть p3 = ptr+1; //ptr+1 т.к. ptr указывает на "\" а не на начало имени else if( c == '.' ) p4 = ptr; ptr ++; } ... Ошибка проявлялась на структурных индексах (закрывались там где не должны были), если в имени dbf был указан путь а в имени индекса нет или наоборот. На сервере не устанавливался pIStru->bCompound а на клиенте неправильно отрабатывала функция letoOrderListClear

Andrey: Можно ли на стороне сервера открыть файл, расшифровать его и передать как массив - клиенту ?

Pasha: Можно, с помощью udf-функции

Pasha: Пользователи letodb жалуются, что неправильно работает LETO_ISFLTOPTIM для фильтра типа: .T. .AND. At (I2Bin(n_field), "ABCD") <> 0 выяснилось, что причина этого - неправильная работа движка харбора, а именно: вызов hb_macroGetType для выражения At (I2Bin(n_field), "ABCD") <> 0 дает результат не "L", как должно быть, а "UI" точно так же работает движок клиппера, пример: request L2Bin Type('At (I2Bin(n_field), "ABCD") <> 0') // UI Вывод из всего этого такой: для определения типа макровыражения недостаточно вызвать hb_macroGetType. Если этот вызов дает "UI", то для определения типа выражения придется его выполнить, и определить тип результата.

Dima: Pasha пишет: hb_macroGetType Эта функция еще рабочая ? Harbour (точнее Hbmk2) ее не видит...

Pasha: Dima пишет: Эта функция еще рабочая ? Harbour (точнее Hbmk2) ее не видит... Это сишная функция, для харбор-кода надо использовать Type(...)

Pasha: Просьба собрать и запустить такой тест: proc main Local cPath := "//127.0.0.1:2812/" REQUEST LETO RDDSETDEFAULT( "LETO" ) cls leto_connect(cPath) if ! leto_File(cPath + "test.dbf") dbCreate(cPath + "test.dbf", {{"C1", "C", 10, 0}, {"N1", "N", 10, 0}}) ? "test.dbf created" endif use (cPath + "test") exclusive new if ! NetErr() ? "Success" append blank Field->C1 := "test" dbCommit() wait close else ? "Open failed" ? "Quit succesfully, without crash" endif leto_disconnect(cPath) return Запустите один экземпляр программы. Будет выдано сообщение: Success Press any key to continue... Не закрывая программу, запустите ее второй экземпляр. Должно быть выдано сообщение: Open failed Quit succesfully, without crash Если второй экземпляр программы так отработает, значит - все в порядке. У меня так и происходит Если упадет с gpf - значит, есть какая-то проблема. Пользователи на нее жалуются, а я даже не могу воспроизвести ситуацию.

sashaBG: У меня отработало правильно как у тебя Паша но у меня LetoDB версии /* $Id: Changelog,v 1.350.2.133 2013/11/22 10:09:31 ptsarenko Exp $ */

Pasha: Жалуются на проблему в LetoDB c CVS. У меня и с последней версией тест отрабатывает нормально. В чем проблема, и почему ее не удается воспроизвести - пока непонятно.

sashaBG: Хорошо попробую CVS версию У меня дома есть два компа попробую и через сеть

sashaBG: Слил последнее из CVS . Скомпилировал тест указывая на адрес моего рутера , затащил тест на одном сервере к которому имею remote доступ и зпустил тест от туда . Все сработало

Pasha: Похоже, надо внести изменение в протокол для выполнение команд блокировки. Тест ниже демонстрирует, что dbfcdx при выполнении rlock/flock/dbrlock перечитывает запись. Необходимо запустить 2 экземпляра программы. Такое же поведение показывает и Ads Думается, что в letodb вместе с результатом команд блокировки надо передавать и текущую запись. proc main Field f1 request dbfcdx rddSetDefault( "DBFCDX" ) cls if ! File("test.dbf") dbCreate("test", {{"C1", "C", 10, 0}, {"F1", "N", 10, 0}}) endif use test new shared if RecCount() == 0 dbAppend() endif ? F1 while inkey(0) # 27 ? 'Before lock', F1 if rlock() // dbRlock(RecNo()), or flock() ? 'After lock', F1 F1 ++ dbUnlock() dbCommit() ? 'After commit', F1 endif enddo use retu

kia: Pasha пишет: Просьба собрать и запустить такой тест: У меня не gpf а штатная ошибка dos error 32. Запускаю сервер и тест на одном компе - win7. Сервер - с cvs последний, клиент - предпоследний. И сервер и клиент с доработками, поэтому может быть и нет gpf. Ошибка возникает из-за повторного вызова dbCreate(cPath + "test.dbf", {{"C1", "C", 10, 0}, {"N1", "N", 10, 0}}) т.к. leto_File(cPath + "test.dbf") == .f. (не находит ранее созданный файл) Ошибка возникает в двух случаях (из-за настроек в letodb.ini) : - если EnableFileFunc = 0 (что логично); - если не задан DataPath, или задан типа DataPath = / Причина думаю где-то в функции (letodb\source\server\letofunc.c line 3275 ) void leto_filef( PUSERSTRU pUStru, const char* szData ) Проверил из под дебагера В строке 3304 hb_snprintf( szData1, 16, "+%s;", ( hb_spFile( szFile, NULL ) )? "T" : "F" ); при вызове hb_spFile если не задан DataPath или DataPath = / и возникает ошибка szFile == "test.dbf\000..." а если задан то (например DataPath =\_leto.tst) szFile == "\_leto.tst\test.dbf\000..." и функция hb_spFile возвращает T - все ок. Похоже, при не заданном пути, файл ищется где-то в текущем каталоге а не там где файл. Надеюсь мой тест поможет разобраться. Спасибо за работу!

sashaBG: Паша Мне очень нравится функция leto_groupby , хотелось бы ее использовать и под DBFCDX но не смог "Выковырять" из изходниках LetoDB Очень быстро работает :)

Pasha: Я, кстати, так и делаю. У меня есть локальный вариант для GroupBy, и я для dbfcdx его и использую. Как раз в самой функции выполняется эта проверка. Функция оптимизирована, часть кода написана на С, так что работает быстро. Мне пришлось убрать/заменить некоторые свои функции, чтобы собрать эту функцию. Именно этот вариант я не проверял, но надеюсь, что он рабочий: http://gfile.ru/a4Je0

sashaBG: Спасибо Попробую !

sashaBG: Паша а как можно сделать Группу составную например: aDvig := LETO_GROUPBY('sme+ska', 'debit,kredit') срабарывает (массив загружается) но потом при следующем обращении к серверу или зависает программа или сервер падает в логе letodb_1.log вот ето: 24.03.2014 00:32:15: Error BASE/1004 No exported method: EVAL Arguments: ( [ 1] = Type: U) a в letodb_crash.log : в конце ------------------------------------------------------------------------ User: 127.0.0.1 SAVOVS ccw.Exe Command: open следующая команда у меня открывает другой файл на сервере а так: aDvig := LETO_GROUPBY('sme', 'debit,kredit') работает но мне нужна составная группа

sashaBG: Паша вот такой тест отработал как надо procedure main() REQUEST DBFCDX RDDSETDEFAULT( "DBFCDX" ) Set AUTOPEN ON use dvig new set order to "sme+ska" aGroup:=dbGroupBy(, , {||sme+ska}, "debit,kredit") ?Len(aGroup) DBCloseArea() return а без блока возвращает пустой массив я в _groupby.prg сделал такую замену //xKey := if((nPos := FieldPos(cGroup)) # 0, nPos, cGroup) xKey := if((nPos := FieldPos(cGroup)) # 0, nPos, GetBlock(cGroup)) так работает и когда группа единичная 'sme' когда составна я тоже 'sme+ska'

Pasha: Если в качестве фильтра передавать блок кода, то отрабатывает локальный вариант, а не leto_GroupBy А при повторном вызове leto_GroupBy действительно не срабатывает. Разбираюсь, причина пока непонятна.

Pasha: Разобрался, вечером выложу исправление

sashaBG: Работает Супер Быстро! Задачка была обработать 2,5 млн записей для отчета , старый алгоритм работал 20 мин. а спомощию leto_groupby и dbgroupby всего 16 секунд Спасибо Паша !

SergKis: Pasha Попробовал в Leto в работе новые поля типа + и ^ (сборка сервера с RddInfo( RDDI_TABLETYPE, DB_DBF_VFP )). Сервер понимает и заполняет эти поля ok!, а клиент нет. После dbStruct() эти поля типа 'U'. Это лечится ? Версия hb 2.0, Leto /* $Id: readme_rus.txt,v 1.12 2011/04/19 16:04:58 ptsarenko Exp $ */

Pasha: Сделал, вечером скину на CVS

Srdjan: Меня зовут Срджьан Я новичок в использовании LetoDB. В чем разница между dbSeek и LetoDBSeek?

Pasha: dbSeek - это вызов операции seek для харбора, один из методов rdd LETO LetoDBSeek - это реализация вызова операции seek на языке С. С помощью LetoDBSeek можно разрабатывать клиенты для LetoDB для других языков программирования, не только для харбора. Функция харбора dbSeek как раз выполняет операцию seek через вызов LetoDBSeek

Srdjan: Я пошел олл старую программу Clipper с водителем SIX3 на день letoDB. Все прекрасно работает, но у меня есть одна проблема, когда клиент покидает программу с Alt-C других покупателей иногда блока (нужно остановить программу с Ctrl-Alt-Del). Я добавил следующий код: #define K_ALTC 302 SETCANCEL(.F.) SET KEY K_ALTC TO AltC() EXIT PROCEDURE ZavrsiRad() CLOSE ALL leto_disconnect() RETURN PROCEDURE AltC() CLOSE ALL leto_disconnect() QUIT RETURN Что вы думаете?

Srdjan: Есть ли это программный код: #xtranslate Sx_SetScope(<a>,<b>) => ordScope( <a>,<b> ) #xtranslate Sx_SetScope(<a>,) => ordScope( <a>, ) #xtranslate Sx_ClrScope() => (ordScope(0,),ordScope(1,)) n := Sifre->( LastRec() ) a1 := Array( n ) a2 := Array( n ) aFill( a1, 0 ) aFill( a2, 0 ) RobMat->( OrdSetFocus( 'Datum' ) ) RobMat->( Sx_SetScope( 0, dOd ), Sx_SetScope( 1, dDo ), dbGoTop() ) WHILE !RobMat->( EOF() ) IF LEFT(RobMat->Dokument,1)=='H' .AND. RobMat->Sifra<>0 .AND. RobMat->Radnik==nVoz .AND. RobMat->Magacin == 1 a2[ RobMat->Sifra ] += RobMat->Ulaz a1[ RobMat->Sifra ] += RobMat->Izlaz END RobMat->( dbSkip() ) END с следующий код программы: RobMat->( OrdSetFocus( 'Datum' ) ) a:=RobMat->( LETO_GROUPBY("Sifra", "Ulaz, Izlaz", "LEFT(Dokument,1)=='H' .AND. Sifra<>0 .AND. Radnik=="+ALLTRIM(STR(nVoz,5,0))+" .AND. Magacin == 1", dOd, dDo) )

Pasha: Srdjan пишет: Есть ли это программный код: #xtranslate Sx_SetScope(<a>,<b>) => ordScope( <a>,<b> ) #xtranslate Sx_SetScope(<a>,) => ordScope( <a>, ) #xtranslate Sx_ClrScope() => (ordScope(0,),ordScope(1,)) n := Sifre->( LastRec() ) a1 := Array( n ) a2 := Array( n ) aFill( a1, 0 ) aFill( a2, 0 ) RobMat->( OrdSetFocus( 'Datum' ) ) RobMat->( Sx_SetScope( 0, dOd ), Sx_SetScope( 1, dDo ), dbGoTop() ) WHILE !RobMat->( EOF() ) IF LEFT(RobMat->Dokument,1)=='H' .AND. RobMat->Sifra<>0 .AND. RobMat->Radnik==nVoz .AND. RobMat->Magacin == 1 a2[ RobMat->Sifra ] += RobMat->Ulaz a1[ RobMat->Sifra ] += RobMat->Izlaz END RobMat->( dbSkip() ) END с следующий код программы: RobMat->( OrdSetFocus( 'Datum' ) ) a:=RobMat->( LETO_GROUPBY("Sifra", "Ulaz, Izlaz", "LEFT(Dokument,1)=='H' .AND. Sifra<>0 .AND. Radnik=="+ALLTRIM(STR(nVoz,5,0))+" .AND. Magacin == 1", dOd, dDo) ) Результат leto_GroupBy будет немного другой: не 2 одномерных массива a1 и a2, а один двумерный массив вида: { {Sifra1, Ulaz1, Izlaz1}, {Sifra2, Ulaz2, Izlaz2}, ...}

nbatocanin: Здравствуйте! Какие факторы определяют скорость Letodb? Я пробовал различные комбинации (Windows 7, XP, Windows Server) - измерил время некоторых обработки. Обычно Letodb работает в 4-5 раз быстрее, чем обычный доступ к файловой-сервере (LAN). Но Letodb иногда до 2-3 раз становится медленнее. Я использую NTX RDD. Есть ли CDX быстрее, чем NTX? Спасибо, Ненад

Srdjan: Спасибо Паша, Я вас понимаю. Результат leto_GroupBy будет немного другой: не 2 одномерных массива a1 и a2, а один двумерный массив вида: { {Sifra1, Ulaz1, Izlaz1}, {Sifra2, Ulaz2, Izlaz2}, ... Вместо двух строк, то функция возвращает матрицу. Я проверил, вместо 10 минут, результат получается за 30 секунд на клиентском компьютере.

Pasha: Здравствуйте! Какие факторы определяют скорость Letodb? Я пробовал различные комбинации (Windows 7, XP, Windows Server) - измерил время некоторых обработки. Обычно Letodb работает в 4-5 раз быстрее, чем обычный доступ к файловой-сервере (LAN). Но Letodb иногда до 2-3 раз становится медленнее. Я использую NTX RDD. Есть ли CDX быстрее, чем NTX? Спасибо, Ненад Вопрос многоплановый. Основной фактор, определяющий производительность - это открытие БД на сервере в монопольном режиме, в отличие от CDX/NTX. Поэтому режим Share_Tables рекомендуеся использовать только на этапе отладки. Другой фактор - буферизация операций skip. Этим можно управлять: с помошью функции leto_SetSkipBuffer можно задать размер skip-буфера, размер которого по умолчанию равен 10 записям. Можно также использовать seek буфер (по умолчанию он выключен). Для увеличения производительности рекомендуется использовать scope и серверные фильтры. LetoDB конечно лучше сравнивать не с dbfcdx/dbfntx, а с Ads. Узкие места letodb - это relations и обновление данных. Туь он уступает ads Если задействовать функции leto_sum, leto_groupby, и udf-функции (это полноценное программирование на сервере, примерный аналог stored proc), можно добиться намного более значительного результата.

nbatocanin: Я попробую этих параметров, спасибо большое! Ненад

nbatocanin: Я сделал несколько тестов различных RDD (LAN - прямой доступ к серверу, LetoDB, HBNetIO, ADS). Результаты и тестовая программа: https://www.dropbox.com/s/u3g9cpa4cpuiwsl/test3.xls https://www.dropbox.com/s/g4uvhu1f6wwjiqy/TEST3.TXT Я заметил, что на некоторых машинах результаты были очень плохые для LetoDB. Тест я работал на нескольких серверах: Win Server 2003 и Server 2008 (новый и лучший компьютер.). Тест состоит из простых операций (APPEND, SKIP, SEEK, REPLACE) . Результаты очень интересны:  - XP работать быстрее, чем Win7, даже когда Win 7 компьютер является более мощным (например, строка 4 и 9). - прямой доступ к серверу иногда намного быстрее, чем клиент-сервер! Например, линия 14/19. Интересно, что результаты ADS/Leto такие же, независимо от того что сервер работает быстрее. - APPEND: Leto/ADS работает медленнее, чем LAN/HBNetIO.  - Leto/ADS/HBNetIO дают сходные результаты во всех случаях , независимо от изменений окружающей среды. Очевидно, что прямой подход LAN использует некоторый тип кэша, что не влияет на Leto/ADS/HBNetIO. Я попробовал тоже параметры, которы дал Паша, но я не заметил разницы, за исключением Leto_SetFastAppend. С уважением, Ненад (Извините за ошибки)

Srdjan: Почему я вижу эту ошибку при использовании команды Use (cPath+"Users") New ALIAS USERS -------------------- Internal Error Handling Information --------------------- Subsystem Call ....: LETO System Code .......: 1021 Default Status ....: .F. Description .......: Data type error Operation .........: Arguments .........: Involved File .....: //127.0.0.1:2812\hz\Users Dos Error Code ....: 0 Trace Through: ---------------- DBUSEAREA : 0 in Module: users.dbf

Pasha: Почему я вижу эту ошибку при использовании команды Use Что-то users.dbf не скачивается. Поставьте еще в letodb.ini параметр Debug=10 Перезапустите службу letodb, и посмотрите, какие команды появятся в letodb.log. Так будет понятнее ситуация.

dimao: Как собрать LETO ночной сборкой харбора? Что-то ничего не получается. [pre2]C:\hb-old\letodb>..\bin\hbmk2 -info -trace rddleto.hbp letodb.hbp hbmk2: Autodetected platform: win hbmk2: Autodetected C compiler: mingw hbmk2: Using Harbour: C:\hb-old\bin C:\hb-old\include C:\hb-old\lib\win\mingw C:\hb-old\bin C:\hb-old\contrib C:\hb-old\addons hbmk2: Using C compiler: c:\hb-old\comp\mingw\bin\gcc.exe hbmk2: Compiling... hbmk2: 'cd' to: lib\.hbmk\win\mingw hbmk2: C/C++ compiler command: gcc.exe -c -O3 -march=i586 -mtune=pentiumpro -fomit-frame-pointer -W -Wall -pipe -I"C:/hb-old/include" -I../../../../include ../../../../source/common/net.c ../../../../source/common/net.c: In function 'leto_NetName': ../../../../source/common/net.c:144:18: error: 'MAX_COMPUTERNAME_LENGTH' undeclared (first use in this function) ../../../../source/common/net.c:144:18: note: each undeclared identifier is reported only once for each function it appears in ../../../../source/common/net.c:148:4: warning: implicit declaration of function 'GetComputerName' [-Wimplicit-function-declar ation] ../../../../source/common/net.c:145:9: warning: unused variable 'szValue' [-Wunused-variable] hbmk2[rddleto]: Error: Running C/C++ compiler. 1 gcc.exe -c -O3 -march=i586 -mtune=pentiumpro -fomit-frame-pointer -W -Wall -pipe -I"C:/hb-old/include" -I../../../../include ../../../../source/common/net.c hbmk2: 'cd' back.[/pre2] PPS:и вот еще, когда описал явно константу #define MAX_COMPUTERNAME_LENGTH 15 получаю ошибки вида: ../../../../source/server/letofunc.c:339:13: error: expected '(' before 'ISBYREF' ../../../../source/server/letofunc.c:374:10: error: expected '(' before 'ISBYREF' Это в С коде ошибки? или как-то можно это обработать?

nbatocanin: Паша, Можете ли вы исправить эти ошибки, пожалуйста? http://sourceforge.net/apps/phpbb/letodb/viewtopic.php?f=1&t=10 http://sourceforge.net/apps/phpbb/letodb/viewtopic.php?f=1&t=25 С уважением, Ненад

Pasha: dimao пишет Как собрать LETO ночной сборкой харбора? Что-то ничего не получается. source/common/net.c для сборки теперь не нужен. Его надо удалить из скрипта для hbp

Pasha: nbatocanin пишет: Паша, Можете ли вы исправить эти ошибки, пожалуйста? http://sourceforge.net/apps/phpbb/letodb/viewtopic.php?f=1&t=10 http://sourceforge.net/apps/phpbb/letodb/viewtopic.php?f=1&t=25 С уважением, Ненад По второму вопросу - исправил. А по первому - разве не помог патч ? Вопрос еще остался ?

nbatocanin: Я попробовал его, и кажется, что он делает хорошо. Спасибо! Ненад

Pasha: Александр, я обнаружил, что ordBagExt() aka IndexExt() с конца прошлого года стал выдавать результат на верхнем регистре, а раньше выдавал на нижнем. Это сделано намеренно ?

SergKis: Pasha как правильно включить в версию v 1.350.2.199 2014/08/05 работу с AutoIncrement: RddInfo( RDDI_TABLETYPE, DB_DBF_VFP ) ? раньше делал так:[pre2] FUNCTION hs_InitSet() rddSetDefault( "DBFCDX" ) RddInfo( RDDI_TABLETYPE, DB_DBF_VFP ) // New SET AUTOPEN ON SET DELETE OFF RETURN Nil [/pre2]

Pasha: Это и не обязательно. Достаточно просто создать таблицу с полем AUTOINC - "+" для dbCreate

SergKis: Pasha СПАСИБО

SergKis: Pasha начали пробовать LetoDb (v.m. 1.350.2.199 2014/08/05) и кое что поковыряли, может будет полезным 1. letomgmn.c: line 901: char ** pRetValue; она объявлена, но не инициализирована, а в line 927 используется: ((cType=='3')? (char*)hb_parc(3) : szValue), uiFlags, ((bPrev)? pRetValue : NULL) ); а в line 949: free( *pRetValue ); т.е. освободить память, которую не выделяли, что, наверное, не есть хорошо ? 2. несколько сервисов (от имени exe) на pc (с разных каталогов, переименовав letodb.exe в др. имя). leto_win.c изменения помечены // BAA [pre2] #ifdef __WIN_SERVICE__ #include "hbapi.h" #include "hbapiitm.h" #include "hbvm.h" //#include "hbxvm.h" //#include "hbset.h" //#include "hbthread.h" #include "srvleto.h" #define _SERVICE_NAME "LetoDB_Service" #define _SERVICE_DISPLAY_NAME "LetoDB Service" #define _SERVICE_DESCRIPTION "Leto DB Server is a multiplatform database server or a database management system, chiefly intended for client programs, written on Harbour." // BAA static SERVICE_STATUS_HANDLE hServiceHandle = 0; static char ServiceEntryFunc[ HB_SYMBOL_NAME_LEN + 1 ]; // BAA static TCHAR ServiceName[] = _SERVICE_NAME; // BAA static TCHAR ServiceDisplayName[] = _SERVICE_DISPLAY_NAME; // BAA static TCHAR ServiceName[64]; static TCHAR ServiceDisplayName[64]; static TCHAR ServiceDescription[] = _SERVICE_DESCRIPTION; // BAA extern int leto_GlobalExit; static ULONG ulSvcError = 0; void leto_SetServiceStatus( DWORD State ) { SERVICE_STATUS SrvStatus; SrvStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; SrvStatus.dwCurrentState = State; SrvStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; SrvStatus.dwWin32ExitCode = 0; SrvStatus.dwServiceSpecificExitCode = 0; SrvStatus.dwCheckPoint = 0; SrvStatus.dwWaitHint = 0; if( hServiceHandle ) SetServiceStatus( hServiceHandle, &SrvStatus ); } void WINAPI leto_ServiceControlHandler( DWORD dwCtrlCode ) { DWORD State = SERVICE_RUNNING; switch( dwCtrlCode ) { case SERVICE_CONTROL_STOP: State = SERVICE_STOPPED; leto_GlobalExit = 1; return; // BAA - ??? Probably break; case SERVICE_CONTROL_SHUTDOWN: State = SERVICE_STOPPED; leto_GlobalExit = 1; return; // BAA - ??? Probably break; } leto_SetServiceStatus( State ); } void WINAPI leto_ServiceMainFunction( DWORD dwArgc, LPTSTR * lpszArgv ) { HB_SYMBOL_UNUSED( dwArgc ); HB_SYMBOL_UNUSED( lpszArgv ); hServiceHandle = RegisterServiceCtrlHandler( ServiceName, ( LPHANDLER_FUNCTION ) leto_ServiceControlHandler ); if( hServiceHandle != (SERVICE_STATUS_HANDLE) 0 ) { PHB_DYNS pDynSym; leto_SetServiceStatus( SERVICE_RUNNING ); hb_vmThreadInit( NULL ); pDynSym = hb_dynsymFindName( ServiceEntryFunc ); if( pDynSym ) { if( hb_vmRequestReenter() ) { hb_vmPushSymbol( hb_dynsymSymbol( pDynSym ) ); hb_vmPushNil(); hb_vmProc( 0 ); hb_vmRequestRestore(); } } leto_SetServiceStatus( SERVICE_STOPPED ); hb_vmThreadQuit(); } } // BAA - New function static DWORD leto_GetNameService( TCHAR *szBuf) { DWORD sz, i; TCHAR *ptr; sz = GetModuleFileName( NULL, szBuf, MAX_PATH ); if( sz > 0) { // BAA : ServiceName == ExecName without Extendet. ptr = &szBuf[sz]; while( *ptr != 0x5C ) ptr--; // BAA 0x5C == '\' ptr++; i = 0; while( *ptr != '.' ) { ServiceDisplayName[ i ] = *ptr; ServiceName[ i++ ] = *ptr++; } ServiceName[ i ] = 0; ServiceDisplayName[ i++ ] = ' '; strcpy( &ServiceDisplayName[ i ], "Service" ); } return sz; } HB_FUNC( LETO_SERVICESTART ) { DWORD n; TCHAR szPath[ MAX_PATH ]; HB_BOOL bRetVal = HB_FALSE; SERVICE_TABLE_ENTRY lpServiceTable[ 2 ] = { { ServiceName, ( LPSERVICE_MAIN_FUNCTION ) leto_ServiceMainFunction }, { NULL, NULL } }; leto_GetNameService( szPath ); // BAA - define ServiceName, ... // hb_strncpy( ServiceEntryFunc, hb_parcx( 1 ), HB_SIZEOFARRAY( ServiceEntryFunc ) - 1 ); // BAA n = hb_parclen(1); memcpy( ServiceEntryFunc, hb_parc(1), n); ServiceEntryFunc[n] = 0; if( StartServiceCtrlDispatcher( lpServiceTable ) ) bRetVal = HB_TRUE; else ulSvcError = ( ULONG ) GetLastError(); hb_retl( bRetVal ); } HB_FUNC( LETO_SERVICEINSTALL ) { HB_BOOL bRetVal = HB_FALSE; TCHAR szPath[ MAX_PATH ]; SC_HANDLE schSrv, schSCM; DWORD sz; // BAA SERVICE_DESCRIPTION sd; // BAA sz = leto_GetNameService( szPath ); // BAA if( sz ) { schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if( schSCM ) { schSrv = CreateService( schSCM, ServiceName, ServiceDisplayName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, //SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, szPath, NULL, NULL, NULL, NULL, NULL ); if( schSrv ) { // BAA - Set Description sd.lpDescription = ServiceDescription; ChangeServiceConfig2( schSrv, SERVICE_CONFIG_DESCRIPTION, &sd); // BAA CloseServiceHandle( schSrv ); bRetVal = HB_TRUE; } else { ulSvcError = ( ULONG ) GetLastError(); } CloseServiceHandle( schSCM ); } else ulSvcError = ( ULONG ) GetLastError(); } hb_retl( bRetVal ); } HB_FUNC( LETO_SERVICEDELETE ) { TCHAR szPath[ MAX_PATH ]; HB_BOOL bRetVal = HB_FALSE; SC_HANDLE schSCM = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if( schSCM ) { SC_HANDLE schService; SERVICE_STATUS_PROCESS ssp; DWORD dwStartTime, dwTimeout, dwWaitTime; DWORD dwBytesNeeded; leto_GetNameService( szPath ); // BAA - define ServiceName, ... // check and stop schService = OpenService( schSCM, ServiceName, SERVICE_STOP | SERVICE_QUERY_STATUS ); if( schService ) { dwStartTime = GetTickCount(); dwTimeout = 30000; // BAA moved, 30-seconds time-out // Make sure the service is not already stopped. if( QueryServiceStatusEx( schService, SC_STATUS_PROCESS_INFO, (LPBYTE) &ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded ) ) { // If a stop is pending, wait for it. while( ssp.dwCurrentState == SERVICE_STOP_PENDING ) { dwWaitTime = ssp.dwWaitHint / 10; if( dwWaitTime < 1000 ) dwWaitTime = 1000; else if( dwWaitTime > 10000 ) dwWaitTime = 10000; Sleep( dwWaitTime ); if( !QueryServiceStatusEx( schService, SC_STATUS_PROCESS_INFO, (LPBYTE) &ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded ) ) { break; } if( ssp.dwCurrentState == SERVICE_STOPPED ) break; if( GetTickCount() - dwStartTime > dwTimeout ) break; } } // Send a stop code to the service. if( ControlService( schService, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS) &ssp ) ) { // Wait for the service to stop. while( ssp.dwCurrentState != SERVICE_STOPPED ) { dwWaitTime = ssp.dwWaitHint / 10; if( dwWaitTime < 1000 ) dwWaitTime = 1000; else if( dwWaitTime > 10000 ) dwWaitTime = 10000; // Sleep( ssp.dwWaitHint ); Sleep( dwWaitTime ); // BAA - define checked WaitTime if( !QueryServiceStatusEx( schService, SC_STATUS_PROCESS_INFO, (LPBYTE) &ssp, sizeof(SERVICE_STATUS_PROCESS), &dwBytesNeeded ) ) { break; } if( ssp.dwCurrentState == SERVICE_STOPPED ) break; if( GetTickCount() - dwStartTime > dwTimeout ) break; } } CloseServiceHandle( schService ); } // delete schService = OpenService( schSCM, ServiceName, DELETE ); if( schService ) { bRetVal = ( HB_BOOL ) DeleteService( schService ); CloseServiceHandle( schService ); if( ! bRetVal ) { ulSvcError = ( ULONG ) GetLastError(); } } else ulSvcError = ( ULONG ) GetLastError(); CloseServiceHandle( schSCM ); } hb_retl( bRetVal ); } HB_FUNC( LETOWIN_GETLASTERROR ) { hb_retnl( ulSvcError ); } #endif /* extern char carr1[40][40]; extern USHORT uiarr1len; extern char carr2[100][40]; extern USHORT uiarr2len; typedef struct { HANDLE hMem; LPVOID lpView; BOOL bNewArea; } MEMAREA; static MEMAREA s_MemArea = { 0,0,0 }; HB_FUNC( LETO_MSG ) { LPTSTR lpMsg = HB_TCHAR_CONVTO( hb_parcx( 1 ) ); MessageBox( GetActiveWindow(), lpMsg, TEXT( "Leto db server" ), MB_OK ); HB_TCHAR_FREE( lpMsg ); } HB_FUNC( LETO_CREATEMEMAREA ) { char szId[16]; sprintf( szId, "%s%d", "Leto_DB_", hb_parni(1) ); s_MemArea.hMem = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 1024, (LPCTSTR)szId ); if( s_MemArea.hMem ) { s_MemArea.bNewArea = !( GetLastError() == ERROR_ALREADY_EXISTS ); s_MemArea.lpView = MapViewOfFile( s_MemArea.hMem, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0 ); if( s_MemArea.bNewArea ) ((char*)s_MemArea.lpView)[0] = 'L'; } hb_retni( (s_MemArea.hMem)? s_MemArea.bNewArea : -1 ); } void leto_CloseMemArea( void ) { if( s_MemArea.lpView ) UnmapViewOfFile( s_MemArea.lpView ); if( s_MemArea.hMem ) CloseHandle( s_MemArea.hMem ); } HB_FUNC( LETO_CLOSEMEMAREA ) { leto_CloseMemArea(); } BOOL leto_ReadMemArea( char * szBuffer, int iAddr, int iLength ) { if( !s_MemArea.lpView ) return FALSE; memcpy( szBuffer, ((char*)s_MemArea.lpView)+iAddr, iLength ); szBuffer[iLength] = '\0'; return TRUE; } BOOL leto_WriteMemArea( const char * szBuffer, int iAddr, int iLength ) { if( !s_MemArea.lpView ) return FALSE; memcpy( ((char*)s_MemArea.lpView)+iAddr, szBuffer, iLength ); return TRUE; } BOOL leto_ThreadCreate( unsigned int (__stdcall *ThreadFunc)(void*) ) { unsigned int uiThreadID; if( _beginthreadex( NULL, 0, ThreadFunc, (void *) NULL, 0, &uiThreadID ) ) { return TRUE; } else return FALSE; } BOOL leto_ThreadMutexInit( LETO_MUTEX * pMutex ) { InitializeCriticalSection( pMutex ); return TRUE; } void leto_ThreadMutexDestroy( LETO_MUTEX * pMutex ) { DeleteCriticalSection( pMutex ); } BOOL leto_ThreadMutexLock( LETO_MUTEX * pMutex ) { EnterCriticalSection( pMutex ); return TRUE; } BOOL leto_ThreadMutexUnlock( LETO_MUTEX * pMutex ) { LeaveCriticalSection( pMutex ); return TRUE; } BOOL leto_ThreadCondInit( LETO_COND * pCond ) { if( ( pCond->hEvent = CreateEvent( NULL, FALSE, FALSE, NULL ) ) == 0 ) return FALSE; else return TRUE; } void leto_ThreadCondDestroy( LETO_COND * pCond ) { CloseHandle( pCond->hEvent ); } int leto_ThreadCondWait( LETO_COND * pCond, int iMilliseconds ) { DWORD dw; InterlockedExchange( &(pCond->ulLocked), 1 ); dw = WaitForSingleObject( pCond->hEvent, (iMilliseconds<0)? INFINITE : (DWORD)iMilliseconds ); switch( dw ) { case WAIT_OBJECT_0: { InterlockedExchange( &(pCond->ulLocked), 0 ); return 1; } case WAIT_TIMEOUT: return 0; } return -1; } BOOL leto_ThreadCondUnlock( LETO_COND * pCond ) { BOOL bRes; if( pCond->ulLocked ) { bRes = SetEvent( pCond->hEvent ); if (!bRes) InterlockedExchange( &(pCond->ulLocked), 0 ); return bRes; } return FALSE; } */ [/pre2]

Pasha: pRetValue - это ссылка на ссылку. Память в *pRetValue выделяется в функции LetoVarSet, и ее надо освободить. Так что здесь все нормально.

SergKis: Pasha пишет:Так что здесь все нормально. Это да, но лезет WARNING, а без него лучше.

Pasha: А зачем может понадобиться несколько служб LetoDB ?

SergKis: Pasha пишет:А зачем может понадобиться несколько служб LetoDB ? Службами разделены клиенты (их базы) по требованиям безопасности.

Andrey: SergKis пишет: Службами разделены клиенты (их базы) по требованиям безопасности. Вообще то это было бы интересней - несколько служб LetoDB. И сколько ресурсов (в среднем) будет "отъедать" одна служба LetoDB на сервере ?

SergKis: Pasha Возможна ли работа LetoDb клиента в потоках ?

Dima: SergKis пишет: Возможна ли работа LetoDb клиента в потоках ? Сам чекани. Из своих наблюдений: 1. Объект EXCEL создать в отдельном потоке не возможно. 2. Пробовал в ADS юзать одни и те же базы в разных потоках одновременно , падает. Если в порядке очереди все нормально.

Pasha: Наверное, нельзя. Сейчас у клиента rdd leto имеются статические данные, и в результате клиент не сможет работать в разных потоках. Эту проблему, положим, решить довольно легко. Но сам сервер для обслуживания клиента создает отдельный поток, и, если запросы с клиента будут поступать с нескольких потоков этого клиента, сервер не сможет их обслужить.

SergKis: Pasha пишет:Наверное, нельзя Сегодня у нас есть CDX в потоках+Leto сервер (старая версия) с Share_Tables = 1. Сейчас пробуем переползти на последнюю версию Leto и хотелось бы отказаться от CDX в потоках. Эту проблему, положим, решить довольно легко это было бы здорово , особенно, если коннект один (общий), а работа с таблицами в потоках.

SergKis: Dima с EXCEL и OpenOffis работаем через: http://www.libxl.com/

nbatocanin: Здравствуйте, Mне нужно, чтобы отфильтровать таблицу ARTIKLI по содержанию другой таблице (MAGKOL). Таблица MAGKOL содержать информацию о количестве каждого элемента на складах. Я хочу показать только элементы которые существуют на складе. Я знаю, что LETODB не поддерживается SET RELATION отношении в SET FILTER. Что бы Вы посоветовали? Ненад

Dima: разве что выкинуть все во временную базу и ее показать (вариант видится не один) PS Не очень корректно видимо изначально спроектирована сама база.

nbatocanin: У меня есть следующие таблицы: [pre2]ARTIKLI: a_id a_name ------ ------------- 1 Milk 2 Cookie 3 Chocolate MAGACIN: m_id m_name ------ -------------- 1 Magacin 1 X 2 Magacin 2 X 3 Magacin 3 MAGKOL mk_mag mk_art mk_kol ------- -------- -------- 1 1 10 1 2 0 1 3 0 2 1 5 2 2 0 2 3 12 3 1 100 3 2 100 3 3 100[/pre2] Например, первая запись в magkol означает склад ID = 1 имеет 10 штук молока. Пользователь выбирает несколько складов (скажем, 1 и 2). Я хочу все элементы в склад, который имеет 1 или 2: [pre2]TBrowse: Name Quant. ----------- ------ Chocolate 12 (= 0 + 12) Cookie 0 (= 0 + 0) Milk 15 (= 10 + 5)[/pre2] В этом случае, не нада показывать вторую строку (=0). Теперь у меня есть функция, которая вычисляет сумму в выбранный и я пишу: [pre2]SELECT Artikli SET FILTER TO CalcMagKol() <> 0 [/pre2] Я надеюсь, что это теперь яснее. Привет, NB

Pasha: Сейчас средствами стандартного серверного фильтра этого сделать нельзя. Посмотрите в сторону функции UDF_getFields, которая находится в модуле letoudf.hrb Она фильтр не установит, но с ее помощью можно вернуть массив с данными обеих таблиц. Массив формируется одним запросом к серверу.

nbatocanin: Я не могу найти эту функцию? Где она точно находится? Спасибо, Ненад

sashaBG: находится в test\letoudf.prg строка 304 Класная функция . Возмещает отсутствия SQL запросов . Спасибо Паша !

Pasha: см. tests/letoudf.prg Этот модуль надо скомпилировать командой harbour letoudf.prg -gh -n -w -i\harbour\include и поместить letoudf.hrb в папку, в которой расположен letodb.exe

nbatocanin: Спасибо!

nbatocanin: Я хочу сделать сервер функцию которая изменяет DBF: клиент: USE test Leto_UDF ("Udf_Test") сервер: FUNCTION Udf_Test (nUserStru) cTest := leto_Alias (nUserStru, "Test") // cTest = NIL?? ... Почему это не работает?

Pasha: Проверил - работает. С такими поправками: Пусть cPath - строка коннекта к серверу, f.e.: cPath:="//127.0.0.1:2812/" 1. Надо или выдать: if (nConnect:=leto_connect(cPath))<>-1 или при вызове udf-функции напрямую указывать параметры сервера: ? leto_udf(cPath + 'UDF_Test') 2. Открывать файл с параметрами коннекта: use (cPath + 'test') В целом, такой пример получается рабочим: if (nConnect:=leto_connect(cPath))<>-1 use (cPath + 'test') ? leto_udf('UDF_Test') wait endif

nbatocanin: Вот то, что я делаю: добавил следующее в конце server.prg: FUNCTION Udf_ArtKol (nUserStru) LOCAL cLetoArt cLetoArt := leto_Alias (nUserStru, "Artikli") RETURN cLetoArt Тогда я произвел LetoDB (hbmk2 letodbc.hbp). Затем я активировал тестовую программу: REQUEST LETO PROC Main RddSetDefault ("LETO") cPath := "//192.168.99.1:2807/LetoDB/" USE (cPath + "Artikli") ALIAS Artikli NEW DbSetIndex (cPath + "Art_ID") x := Leto_UDFExist("//192.168.99.1:2807/Udf_ArtKol") y := Leto_UDF ("//192.168.99.1:2807/Udf_ArtKol") ? "ret=", x, y Inkey(0) CLOSE Artikli RETURN Программа возвращается "ret=.T. NIL", а в letodb.log пишет: 12/04/14 04:07:07: Leto DB Server has been started. Leto DB Server v.2.14 ! INIT: DataPath=d:\test, ShareTables=0, MaxUsers=500, Max Tables=5000, CacheRecords=500 DEBUG! new connect 192.168.99.10 (0 : 1 : 1) leto_errInternal!!!!!!!!!!!!!!!!!!

sashaBG: 1. Функцию Udf_ArtKol (nUserStru) надо добавить в tests\letoudf.prg 2. Откомпилировать kоманндой harbour /gh letoudf.prg 3. Полученый фаил letoudf.hrb поставить в папку где у тебя лежит letodb.exe 4. При старте letodb загрузит letoudf.hrb ( етого можно увидить в логе) 5. Възов UDF функции должен осуществлятся только через имя функции : x := Leto_UDFExist("Udf_ArtKol") y := Leto_UDF ("Udf_ArtKol") если есть параметры вот так : Leto_UDF ("Udf_ArtKol", Param1, Param2)

nbatocanin: Спасибо! Проблема решается, если задания функции через hrb, все работает как надо. Я изменил server.prg (потому что нам нужна функция VolSerial), так что я сделал функцию UDF_VolSerial в server.prg и все работало должным образом. Я не знаю, почему функция UDF_ArtKol не будет работать. Функции также работать нормально при использовании так (как сказал Паша): x := Leto_UdfExist("//192.168.99.1:2807/Udf_ArtKol")

nbatocanin: Функция сервера, второй раз: [pre]FUNCTION Udf_ArtKol (nUserStru) LOCAL cLetoMagKol, cLetoArt cLetoArt := leto_Alias (nUserStru, "Artikli") cLetoMagKol := leto_Alias (nUserStru, "MagKol") SELECT (cLetoMagKol) OrdSetFocus ("Mag_AM") SELECT (cLetoArt) IF (x := Leto_TableLock (nUserStru, 1)) GO TOP WHILE !Eof() (cLetoArt)->a_mk := "ABC" SKIP END DO Leto_TableUnlock (nUserStru, 1) END IF RETURN x[/pre] Эта функция не изменяет файл ARTIKLI и возвращает NIL. Я ожидал, что результате Leto_TableLock будет T или F? Что означает вторые параметр в Leto_TableLock? Readme говорит только, что это число 1-32.

Pasha: Функция leto_TableLock - это не аналог FLock. Она предназначена для блокировки таблицы при выполнении некоторых действий, к примеру - получения уникального ключа для новой записи. См. пример использования в letoudf.prg, функция UDF_AppendRec Для ваших целей используйте функции leto_RecLock / leto_recUnlock

nbatocanin: Большое спасибо! Сейчас все работает. Я сделал функцию, которая указывает, какие записи должны быть отфильтрованы (для замены RELATION TO). Функция работает очень быстро: 110.000 записей завершено в 1,6 секунды! [pre]FUNCTION Udf_ArtKol (nUserStru, aMag, nId) LOCAL cLetoMagKol, cLetoArt, i, lImaKol LOCAL nArt, x cLetoArt := leto_Alias (nUserStru, "Artikli") cLetoMagKol := leto_Alias (nUserStru, "MagKol") SELECT (cLetoMagKol) OrdSetFocus ("Mag_AM") x := 0 SELECT (cLetoArt) GO TOP WHILE !Eof() nArt := (cLetoArt)->a_id SELECT (cLetoMagKol) lImaKol := .F. FOR i := 1 TO Len(aMag) SEEK Str(nArt,10) + Str(aMag,10) IF Found() .AND. (cLetoMagKol)->k_kol <> 0 lImaKol := .T. EXIT END IF NEXT IF Leto_RecLock (nUserStru) (cLetoArt)->a_mk := Left((cLetoArt)->a_mk,nId-1) + IIF (lImaKol, "1", " ") + SubStr((cLetoArt)->a_mk,nId+1) Leto_RecUnlock (nUserStru) x++ END IF SELECT (cLetoArt) SKIP END DO RETURN x [/pre]

nbatocanin: Я вижу, что есть функция Leto_MakeDir, но если функция Leto_RemoveDir?

sashaBG: Вот такой тест: procedure main() local _Server := '//127.0.0.1:2812/' REQUEST DBFCDX REQUEST LETO RDDSETDEFAULT( "DBFCDX" ) use ('file') new copy to ('file1') dbclosearea() RDDSETDEFAULT( "LETO" ) use (_Server+'file1') excl new zap APPEND FROM ('file') VIA "DBFCDX" go top browse() return в первое текстовое поле начинается с пробелом и все текстовые поля смещаются на один символ в право версия LetoDB последняя вроде ! 2014-11-17 17:10 UTC+0300 Pavel Tsarenko (tpe2/at/mail.ru) * source/client/leto1.c ! fixed gpf in some functions, that occured with no leto area

sashaBG: А если делаем APPEND FROM из LETODB все ОК :) procedure main() local _Server := '//127.0.0.1:2812/' REQUEST DBFCDX REQUEST LETO RDDSETDEFAULT( "LETO" ) use (_Server+'file') new copy to (_Server+'file1') browse() dbclosearea() RDDSETDEFAULT( "DBFCDX" ) use ('file1') excl new zap APPEND FROM (_Server+'file') VIA "LETO" go top browse() return

Pasha: Вопрос в том, что буфер записи leto и dbfcdx несовместим, в leto он не содержит 1-й байт deleted. Думаю, надо в leto сделать такой же формат, как и в dbfcdx

Pasha: Сделал. Теперь APPEND FROM будет работать

alkresin: Сделал небольшое исправление в server.prg, hs_createindex() - добавил строчки после IF !Empty( cBagName ): IF Empty( cTagName ) cTagName := hb_FNameName( cBagName ) ENDIF Это связано с проблемой, изложенной на [url=https://groups.google.com/forum/#!topic/harbour-users/p2f9ffWM0sk]harbour-users[/url]. Когда индекс создавался командой INDEX ON ... TO ... имя тэга было пустое, leto_addTag() его не добавлял и leto_FindTag(), соответственно, потом ничего не находил.

sashaBG: Паша ! Добавление данных в сторону Letodb опять не работает и при COPY TO и при APPEND FROM если первое поле тип C в нем все ОК но остальных нету если первое поле тип N - остаются оно и второе , а остальные Тю Тю :) **************** procedure main() local _Server := '//127.0.0.1:2812/' REQUEST DBFCDX REQUEST LETO //CDX use ('file') new VIA "DBFCDX" browse() copy to (_Server+'file_leto') VIA "LETO" dbclosearea() //LETO use (_Server+'file_leto') excl new VIA "LETO" go top browse() zap APPEND FROM ('file') VIA "DBFCDX" go top browse() return

alkresin: Да, действительно, есть проблема. Попробую разобраться.

alkresin: Исправил. Теперь должно работать.

sashaBG: Благодарю г-н Кресин ! Извиняюсь за поздний ответ ! Теперь все работает отлично ! Я высоко оцениваю Ваш труд и Пашин тоже ! И думаю, что проекту нужна какая-то финансовая подмога на его дальнейшее развитие . Ребята кто пользуются етим сервером давайте ето обсудим ! у нас в Болгарии говорят , попробую перевести ( Дружба есть дружба , но брынза стоит денег ) :)

alkresin: sashaBG пишет: Благодарю г-н Кресин ! Лучше - товарищ :). "Господа" у нас даже через 25 лет после переворота 1991г. как-то не привились.

nbatocanin: sashaBG пишет: Я высоко оцениваю Ваш труд и Пашин тоже ! И думаю, что проекту нужна какая-то финансовая подмога на его дальнейшее развитие . Ребята кто пользуются етим сервером давайте ето обсудим ! Я согласен с этим. Будет хорошо, чтобы открыть счет для помощи. Если вы хотите, я могу зарегистрировать сайт LetoDB.com?

alkresin: nbatocanin пишет: Если вы хотите, я могу зарегистрировать сайт LetoDB.com? Сайтом надо заниматься, чем-то его наполнять, регулярно обновлять, чтобы он жил. На это нужны в первую очередь человеческие ресурсы, которых не хватает. Когда Letodb появился на свет, Patrick Mast зарегистрировал letodb.org, но сайт мы так и не создали - не было времени и мотивации.

SergKis: Режим: RddInfo( RDDI_TABLETYPE, DB_DBF_VFP ) - работа с новыми полями, сервер делает все ok, а клиент нет. за основу взял test_dbf.prg из tests для CDX: [pre2] Function Main( cPath ) Local aNames := { "Petr", "Ivan", "Alexander", "Pavel", "Alexey", "Fedor", ; "Konstantin", "Vladimir", "Nikolay", "Andrey", "Dmitry", "Sergey" } Local i, aStru SET DATE FORMAT "dd/mm/yy" RDDSETDEFAULT( "DBFCDX" ) RddInfo( RDDI_TABLETYPE, DB_DBF_VFP ) cPath := 'temp' MakeDir(cPath) cPath += '\' fErase(cPath+"test1"+".dbf") dbCreate( cPath+"test1", { {"NAME" , "C", 10, 0}, ; {"NUM" , "N", 4, 0}, ; {"INFO" , "C", 32, 0}, ; {"DINFO" , "D", 8, 0}, ; {"TM" , "@", 8, 0}, ; {"TS" , "=", 8, 0}, ; {"VM" , "^", 8, 0}, ; {"ID" , "+", 4, 0} ; } ) ? "File has been created, tabletype", RddInfo( RDDI_TABLETYPE ), rddSetDefault() USE ( cPath+"test1" ) New aStru := dbStruct() ? "Fields:", Len( aStru ) FOR i := 1 TO Len( aStru ) ? i, padr(aStru[i,1], 10), aStru[i,2], aStru[i,3], aStru[i,4], hb_FieldType( i ) NEXT ? 'Press any key ...' inkey(0) FOR i := 1 TO Len( aNames ) APPEND BLANK REPLACE NUM WITH i+1000 dbSkip(0) // modify VM, sets ID, sets TS REPLACE NAME WITH aNames[ i ], ; INFO WITH "This is a record number "+Ltrim(Str(i)), ; DINFO WITH Date()+i-1 dbSkip(0) // modify VM ? str(RecNo(),3), NAME, NUM, TM, TS, str(VM,5), str(ID,5) NEXT ? "Records has been added" inkey(0) dbCloseArea() Return [/pre2] для LETO: [pre2] Function Main( cPath ) Local aNames := { "Petr", "Ivan", "Alexander", "Pavel", "Alexey", "Fedor", ; "Konstantin", "Vladimir", "Nikolay", "Andrey", "Dmitry", "Sergey" } Local i, aStru SET DATE FORMAT "dd/mm/yy" RDDSETDEFAULT( "LETO" ) cPath := "//127.0.0.1:2812/temp/" leto_fErase(cPath+"test1"+".dbf") dbCreate( cPath+"test1", { {"NAME" , "C", 10, 0}, ; {"NUM" , "N", 4, 0}, ; {"INFO" , "C", 32, 0}, ; {"DINFO" , "D", 8, 0}, ; {"TM" , "@", 8, 0}, ; {"TS" , "=", 8, 0}, ; {"VM" , "^", 8, 0}, ; {"ID" , "+", 4, 0} ; } ) ? "File has been created, tabletype", RddInfo( RDDI_TABLETYPE ), rddSetDefault() USE ( cPath+"test1" ) New aStru := dbStruct() ? "Fields:", Len( aStru ) FOR i := 1 TO Len( aStru ) ? i, padr(aStru[i,1], 10), aStru[i,2], aStru[i,3], aStru[i,4], hb_FieldType( i ) NEXT ? 'Press any key ...' inkey(0) FOR i := 1 TO Len( aNames ) APPEND BLANK REPLACE NUM WITH i+1000 dbSkip(0) // modify VM, sets ID, sets TS REPLACE NAME WITH aNames[ i ], ; INFO WITH "This is a record number "+Ltrim(Str(i)), ; DINFO WITH Date()+i-1 dbSkip(0) // modify VM ? str(RecNo(),3), NAME, NUM, TM, TS, VM, ID NEXT ? "Records has been added" inkey(0) dbCloseArea() Return [/pre2] в LETO: - типы T, @ превращаются в = - пустое поле типа = не заполняется значением TimeStamp - значения VM и ID не отображаются, видим NIL или я что то не так делаю ?

SergKis: PS сервер делает все ok для полей типа ^ и +

SergKis: смотрю в сервере отключены триггера - это специально или нарочно ? [pre2] PROCEDURE StartServer() PUBLIC oApp := HApp():New() REQUEST DBFNTX REQUEST DBFCDX #ifdef __BM REQUEST BMDBFNTX REQUEST BMDBFCDX #endif WrLog( "Leto DB Server has been started." ) leto_InitSet() leto_CreateData() leto_HrbLoad() IF ! leto_Server( oApp:nPort, oApp:nTimeOut ) #if __HARBOUR__ > 0x020100 WrLog( "Socket error " + hb_socketErrorString() ) #else WrLog( "Socket error " ) #endif ENDIF WrLog( "Server has been closed." ) // !!!!!!! уже конец работы IF ! EMPTY( oApp:cTrigger ) HB_RddInfo( RDDI_TRIGGER, oApp:cTrigger, leto_Driver( oApp:nDriver ) ) ENDIF IF ! EMPTY( oApp:cPendingTrigger ) HB_RddInfo( RDDI_PENDINGTRIGGER, oApp:cPendingTrigger, leto_Driver( oApp:nDriver ) ) ENDIF RETURN [/pre2]

nbatocanin: alkresin пишет: Сайтом надо заниматься, чем-то его наполнять, регулярно обновлять, чтобы он жил. На это нужны в первую очередь человеческие ресурсы, которых не хватает. Когда Letodb появился на свет, Patrick Mast зарегистрировал letodb.org, но сайт мы так и не создали - не было времени и мотивации. Я согласен с этим, но я хотел бы кое-что, чтобы помочь. Я мог бы начать, зарегистрироваться сайт и установить основное содержание: установки программы, инструкции для начинающих, форум и т.д. Letodb очень важны для меня, и я хочу, что он имеет больше пользователей. Я думаю, что самая большая проблема для Letodb сейчас это то, что новые пользователи не могут найти основные информации. Ненад



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