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

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

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

Ответов - 191, стр: 1 2 3 4 5 6 7 8 9 10 All

SergKis: SergKis пишет: leto сервер делает все ok для полей типа ^ и + - типы T, @ превращаются в = - пустое поле типа = не заполняется значением TimeStamp причина в разном case:[pre2] leto1.c(line 1950) case HB_FT_MODTIME: cType = '@'; break; case HB_FT_DATETIME: case HB_FT_DAYTIME: cType = 'T'; break; rdd\dbf1.c(line 3050) case HB_FT_TIMESTAMP: pThisField->bType = pArea->bTableType == DB_DBF_VFP ? 'T' : '@'; pField->uiLen = 8; pThisField->bLen = ( BYTE ) pField->uiLen; pThisField->bFieldFlags = HB_FF_BINARY; pArea->uiRecordLen += pField->uiLen; break; case HB_FT_MODTIME: pThisField->bType = '='; pField->uiLen = 8; pThisField->bLen = ( BYTE ) pField->uiLen; pArea->uiRecordLen += pField->uiLen; pArea->fModStamp = TRUE; break; [/pre2] т.е. в cdx типы T,@ - HB_FT_TIMESTAMP, тип = HB_FT_MODTIME, в leto другие

SergKis: полная катавасия со структурой (поля типа TIMESTAMP, MODTIME): - на клиенте подаем в dbCreate ..., {"TM", "@", 8, 0}, {"TS", "=", 8, 0},... - на сервере имеем в HS_CREATETABLE (пришло с клиента) ..., {"TM", "T", 8, 0}, {"TS", "@", 8, 0},... - на сервере имеем в HS_OPENTABLE (после dbStruct)..., {"TM", "@", 8, 0}, {"TS", "@", 8, 0},... - на клиенте после dbStruct имеем ..., {"TM", "=", 8, 0}, {"TS", "=", 8, 0},... придется остатья на старой версии (двухпотчной)

Pasha: SegKis пишет: смотрю в сервере отключены триггера - это специально или нарочно ? Конечно, не специально, и не нарочно. Эта реализация была пропущена при реорганизации кода почти 4 года назад. Поправил.


SergKis: Pasha добавил в server.prg: [pre2] #include "hbsxdef.ch" ... leto_HrbLoad() IF ! EMPTY( oApp:cTrigger ) WrLog( "Trigger "+oApp:cTrigger+" "+_u2s(leto_Driver( oApp:nDriver )) ) HB_RddInfo( RDDI_TRIGGER, oApp:cTrigger, leto_Driver( oApp:nDriver ) ) ENDIF IF ! EMPTY( oApp:cPendingTrigger ) WrLog( "pendingTrigger "+oApp:cTrigger+" "+_u2s(leto_Driver( oApp:nDriver )) ) HB_RddInfo( RDDI_PENDINGTRIGGER, oApp:cPendingTrigger, leto_Driver( oApp:nDriver ) ) ENDIF ... /////////////////////////////////////////////////////////////////////////////// FUNCTION tst_Trigger( nEvent, nArea, nPos, xTrigVal ) LOCAL i := nEvent, j := '', k k := _u2s(nEvent)+':'+_u2s(nArea)+':'+_u2s(nPos)+':'+_u2s(xTrigVal) WrLog(procname()+':'+k) IF nEvent == EVENT_POSTUSE // 2 dbInfo(DBI_TRIGGER, .F.) j := 'EVENT_POSTUSE' k := _u2s(nEvent)+':'+j+':'+_u2s(nArea)+':'+_u2s(nPos)+':'+_u2s(xTrigVal) WrLog(procname()+':'+k) dbInfo(DBI_TRIGGER, .T.) RETURN .T. ELSEIF nEvent == EVENT_PRECLOSE // 11 dbInfo(DBI_TRIGGER, .F.) j := 'EVENT_PRECLOSE' k := _u2s(nEvent)+':'+j+':'+_u2s(nArea)+':'+_u2s(nPos)+':'+_u2s(xTrigVal) WrLog(procname()+':'+k) dbInfo(DBI_TRIGGER, .T.) RETURN .T. ELSEIF nEvent < EVENT_UPDATE .or. nEvent > EVENT_ZAP dbInfo(DBI_TRIGGER, .F.) j := 'EVENT_UPDATE-EVENT_ZAP' k := _u2s(nEvent)+':'+j+':'+_u2s(nArea)+':'+_u2s(nPos)+':'+_u2s(xTrigVal) WrLog(procname()+':'+k) dbInfo(DBI_TRIGGER, .T.) RETURN .T. ENDIF dbInfo(DBI_TRIGGER, .F.) DO CASE CASE nEvent == EVENT_UPDATE // 3 j := 'EVENT_UPDATE' CASE nEvent == EVENT_APPEND // 4 j := 'EVENT_APPEND' CASE nEvent == EVENT_DELETE // 5 j := 'EVENT_DELETE' CASE nEvent == EVENT_RECALL // 6 j := 'EVENT_RECALL' CASE nEvent == EVENT_PACK // 7 j := 'EVENT_PACK' CASE nEvent == EVENT_ZAP // 8 j := 'EVENT_ZAP' ENDCASE k := _u2s(nEvent)+':'+j+':'+_u2s(nArea)+':'+_u2s(nPos)+':'+_u2s(xTrigVal) WrLog(procname()+':'+k) * CASE nEvent == EVENT_PREUSE // 1 * CASE nEvent == EVENT_POSTUSE // 2 * CASE nEvent == EVENT_PACK // 7 * CASE nEvent == EVENT_ZAP // 8 * CASE nEvent == EVENT_PUT // 9 * CASE nEvent == EVENT_GET // 10 * CASE nEvent == EVENT_PRECLOSE // 11 * CASE nEvent == EVENT_POSTCLOSE // 12 * CASE nEvent == EVENT_PREMEMOPACK // 13 * CASE nEvent == EVENT_POSTMEMOPACK // 14 dbInfo(DBI_TRIGGER, .T.) RETURN .T. /////////////////////////////////////////////////////////////////////////////// STATIC FUNCTION _u2s( uValue ) LOCAL cType := ValType( uValue ) IF cType == "L" RETURN iif( uValue, ".T.", ".F." ) ELSEIF cType == "N" RETURN AllTrim( Str( uValue ) ) ELSEIF cType == "D" RETURN Dtoc( uValue ) ELSEIF cType == "A" RETURN 'ARRAY['+AllTrim( Str( len(uValue) ) )+']' ELSEIF cType == "C" RETURN trim(uValue) ELSEIF cType == "U" RETURN 'NIL' ELSE uValue := 'VALTYPE='+cType ENDIF RETURN uValue letodb.ini: [Main] Port = 2812 DataPath = . EnableFileFunc = 1 Trigger = tst_Trigger ;PendingTrigger = tst_Trigger [/pre2] тестовая test_dbf.prg: [pre2] #include "wvtwin.ch" #include "hbgtinfo.ch" #include "rddleto.ch" #include "dbinfo.ch" REQUEST HB_GT_WVT REQUEST HB_GT_WVT_DEFAULT REQUEST HB_CODEPAGE_LV866 REQUEST LETO, DBFCDX Function Main( cPath ) Local aNames := { "Petr", "Ivan", "Alexander", "Pavel", "Alexey", "Fedor", ; "Konstantin", "Vladimir", "Nikolay", "Andrey", "Dmitry", "Sergey" } Local i, aStru Local cFont Field NAME, NUM, INFO, DINFO hb_gtInfo( HB_GTI_CODEPAGE, 866) hb_setCodePage( "LV866" ) hb_setTermCP( "LV866" ) hb_GtInfo( HB_GTI_FONTNAME , cFont ) hb_gtInfo( HB_GTI_FONTQUALITY, 3 ) RDDSETDEFAULT( "LETO" ) SET DATE FORMAT "dd/mm/yy" cPath := "//127.0.0.1:2812/temp/" ? "Connect to " + cPath + " - " IF ( leto_Connect( cPath ) ) == -1 nRes := leto_Connect_Err() IF nRes == LETO_ERR_LOGIN ?? "Login failed" ELSEIF nRes == LETO_ERR_RECV ?? "Recv Error" ELSEIF nRes == LETO_ERR_SEND ?? "Send Error" ELSE ?? "No connection" ENDIF Return Nil ELSE ?? "Ok" ENDIF 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" USE ( cPath+"test1" ) New ? "File has been opened", used(), alias() 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 inkey(0) FOR i := 1 TO Len( aNames ) APPEND BLANK REPLACE NAME WITH aNames, NUM WITH i+1000, ; INFO WITH "This is a record number "+Ltrim(Str(i)), ; DINFO WITH Date()+i-1 // dbCommit() // dbGoto(RecNo()) // dbSkip(0) dbGoto(RecNo()) ? str(RecNo(), 3), NAME, NUM, TM, TS, VM, ID NEXT ? ? "Records has been added", LastRec() ? "Press any key to finish..." Inkey(0) Return Nil получаем letodb.log: 02/23/15 12:03:17: Leto DB Server has been started. Leto DB Server v.2.15 ! INIT: DataPath=., ShareTables=0, MaxUsers=500, MaxTables=5000, CacheRecords=10 02/23/15 12:03:17: Trigger tst_Trigger DBFCDX 02/23/15 12:18:09: Send STOP to server... 02/23/15 12:18:12: Server has been closed. [/pre2] т.е. триггер ставится, но работает, для PendingTrigger такой же результат.

SergKis: PS. повторяю искаженное:[pre2] FOR i := 1 TO Len( aNames ) APPEND BLANK REPLACE NAME WITH aNames[ i ], NUM WITH i+1000, ; ... [/pre2]

SergKis: SergKis пишет:т.е. триггер ставится, но работает, для PendingTrigger такой же результат. что то буквы съелись. Должно быть: т.е. триггер ставится, но НЕ работает, для PendingTrigger такой же результат.

alkresin: SergKis пишет: полная катавасия со структурой (поля типа TIMESTAMP, MODTIME): - на клиенте подаем в dbCreate ..., {"TM", "@", 8, 0}, {"TS", "=", 8, 0},... - на сервере имеем в HS_CREATETABLE (пришло с клиента) ..., {"TM", "T", 8, 0}, {"TS", "@", 8, 0},... А можно короткий тестовый пример, чтоб сразу откомпилировать и проверить ?

SergKis: alkresin пишет:А можно короткий тестовый пример, чтоб сразу откомпилировать и проверить ? Отправлено: 10.02.15 00:02. Заголовок: Режим: RddInfo( RDDI..

SergKis: alkresin letodb..prg добавил: ... [pre2] hs_createtable(...) ... aStru := Array( nLen, 4 ) FOR i := 1 TO nLen aStru[i,1] := GetCmdItem( cCommand, nPos + 1, @nPos ) aStru[i,2] := GetCmdItem( cCommand, nPos + 1, @nPos ) aStru[i,3] := Val( GetCmdItem( cCommand,nPos + 1,@nPos ) ) aStru[i,4] := Val( GetCmdItem( cCommand,nPos + 1,@nPos ) ) NEXT WLog(procname()+":"+hb_valtoexp(aStru)) // добавил ... hs_opentable(...) ... // line: ~457 aStru := dbStruct() WLog(procname()+":"+hb_valtoexp(aStru)) // добавил ... [/pre2]

SergKis: PS опять буква сълась WrLog(...) добавлял

alkresin: Ту небольшую путаницу я, вроде, исправил. Остается один неприятный момент с теми полями, которые формируются автоматически на сервере при добавлении записи. Поскольку на клиентской стороне работает буферизация, то если добавить запись и потом сразу прочитать, то она берется не с сервера. а из буфера - и значения тех полей пустые.

SergKis: alkresin пишет:на клиентской стороне работает буферизация,... как правило, сразу может понадобится поле "+" для заполнения в другую таблицу, в массив ключей, ... как осуществлять доступ ? делать dbcommit, leto_commit, закрывать\открывать таблицу ? на даты типа Timestamp и "^" запрос, как првило отложенный (могут быть в тегах индекса)

SergKis: PS. всегда в cdx, ntx, six было dbSkip(0) - перечитать\перезаполнить буфер

SergKis: alkresin пишет:Ту небольшую путаницу я, вроде, исправил. Работает. Большое СПАСИБО Вместо dbSkip(0) обновляет буфер на клиенте dbGoto(RecNo())

SergKis: SergKis пишет:Работает поторопился, timestamp работает, а "^" и "+" - что то не то при отображении в dbf все хорошо ? str(RecNo(), 3), NAME, str(NUM, 4), TS, VM, ID дает: [pre2] Rec NAME NUM TS VM ID === ========== ==== ===================== ==================== ========== 1 Petr 1001 05/03/15 14:26:54.731 16660054396318011 1413165115 2 Ivan 1002 05/03/15 14:26:54.731 16660054396318267 1413165115 3 Alexander 1003 05/03/15 14:26:54.731 16660054396318523 943406395 4 Pavel 1004 05/03/15 14:26:54.747 16660054396318779 3878971 5 Alexey 1005 05/03/15 14:26:54.747 16660054396319035 989870896 6 Fedor 1006 05/03/15 14:26:54.747 16660054396319291 3878912 7 Konstantin 1007 05/03/15 14:26:54.762 16660054396319547 993540925 8 Vladimir 1008 05/03/15 14:26:54.762 16660054396319803 993853499 9 Nikolay 1009 05/03/15 14:26:54.762 16660054396320059 1023425280 10 Andrey 1010 05/03/15 14:26:54.778 4264973925457342779 993853440 11 Dmitry 1011 05/03/15 14:26:54.778 4264973925457408315 993853440 12 Sergey 1012 05/03/15 14:26:54.778 4264973925457473851 993853440 [/pre2]

alkresin: А у меня все нормально отображается. Это ведь тот ваш пример, только dbSkip(0) заменено на go Recno() ?

alkresin: Все ясно. Это я небольшое исправление в серверной части не выложил на CVS - думал, оно не имеет значение, а в моем рабочеи каталоге оно осталось. Теперь выложил.

SergKis: alkresin пишет:Теперь выложил. Работает. Большое СПАСИБО.

Andrey: Установил наконец то сервер на Win2012. Вроде работает. Пытаюсь дальше разбираться.... Как можно отловить перезагрузку и работоспособность сервера LetoDB ? Т.е. при обращениях к ЛетоДБ как проверять, доступен он или нет (инет упал, сервер перегрузился и т.д.) - как обрабатывать ошибки ?

Dima: Andrey пишет: Установил наконец то сервер на Win2012. Вроде работает. Только он глючит порой не по теме , пытались его тоже юзать , откатились на 2008. Andrey пишет: Как можно отловить перезагрузку и работоспособность сервера LetoDB ? Не читал letodb\readme_rus.txt ? Цитата [pre2] Возможно проверить доступность сервера перед открытием файлов вызовом функции leto_Connect( cAddress ), которая вернет -1 в случае неудачной попытки: IF leto_Connect( "//192.168.5.22:2812/mydir/" ) == -1 Alert( "Can't connect to server ..." ) ENDIF + пункт 7.1 Управление соединением [/pre2] В LETODB в этом плане масса способов что бы проверить запущен ли (работает) LETODB по сравнению с ADS

SergKis: alkresin, Pasha, а можно добавить в letodb аналог функций: Local date, time // time идет с миллисекундами hb_fGetDateTime(cPath+"test1"+".dbf", @date, @time) hb_fSetDateTime(cPath+"test1"+".dbf", @date, @time) например: aDateTime := leto_fGetDateTime(cPath+"test1"+".dbf") leto_fSetDateTime(cPath+"test1"+".dbf", date, time) если data и time не заданы - ставить дату времемя сервера таким образом можно отслеживаить менялясь таблица или нет без открытия оной

Pasha: Andrey пишет: Как можно отловить перезагрузку и работоспособность сервера LetoDB ? Т.е. при обращениях к ЛетоДБ как проверять, доступен он или нет (инет упал, сервер перегрузился и т.д.) - как обрабатывать ошибки ? Можно после вызова leto_Conntct (или без него, соединение автоматически будет установлено при первом вызове команды use) опрашивать сервер вызовом функции LETO_MGGETINFO. Если ответ получен - значит, сервер работает, если нет - упал, тогда надо пробовать переконнектиться. Конечно, letodb не рассчитан на нестабильное соединение. Если работать с ним в таком режиме, то надо обязательно для любых изменений БД использовать транзакции.

Pasha: SergKis пишет: а можно добавить в letodb аналог функций: Local date, time // time идет с миллисекундами hb_fGetDateTime(cPath+"test1"+".dbf", @date, @time) hb_fSetDateTime(cPath+"test1"+".dbf", @date, @time) например: aDateTime := leto_fGetDateTime(cPath+"test1"+".dbf") leto_fSetDateTime(cPath+"test1"+".dbf", date, time) если data и time не заданы - ставить дату времемя сервера таким образом можно отслеживаить менялясь таблица или нет без открытия оной Формат dbf предусматривает только хранение даты изменения файла, но не времени. Поэтому стандартными средствами rdd это не сделаешь. Ну а нестандартными - можно создать отдельную таблицу dbf на сервере с полями: имя файла, дата и время изменения. Поскольку это нестандартное решение, то включать его в базовую функциональность letodb я смысла не вижу. Такие функции можно сделать в модуле letoudf.hrb.

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

SergKis: Pasha пишет:Поэтому стандартными средствами rdd это не сделаешь. Вы правы, но есть стандартные средства windows, хранящие данные о времени создания файла, модификации, последненго использования (с миллисекундами) - почему не воспользоваться этим - это все без открытия файла, что несомненное преимущество по скорости в сравнении с различными таблицами. Давно использую такую методу на cdx и ntx файлах и в двух поточной старой версии letodb (с исп. триггера), конечно, есть особенности применения. Например: если Share_Tables = 1, то можно цепляться к самой таблице (dbf), dbCommit() и dbCloseArea() меняют дату, время в файле и эти изменения видны с др. клиента. если Share_Tables = 0, тогда надо использовать файл рядом с таблицей и расширением (например) .dtm (когда создаем dbCreate(...) сразу создаем рядом файл Leto_MemoWrite( cFileName+'.dtm', "for TimeStamp" )) и всегда, когда надо, делаем типа leto_fSetDateTime(cFileName+'.dtm'), с др. клиента читаем leto_fGetDateTime(cFileName+'.dtm') и сравниваем с запомненнным ранее значением ... на мой взгляд эти функции относятся к файловым как leto_fErase, leto_file, ... сколько было споров о нужности функции Leto_MemoWrite ... конечно добавить такой функционал в свою версию - это будет, я подумал может еще кому такое надо - потому и предложил

SergKis: Dima пишет:Можно ведь сделать по аналогии мас адрес и VolSerial никакого отношения к таблице сервера не имеют, я говорю о работе с конкретной таблицой и ее данными

Dima: SergKis Да согласен.

Andrey: Pasha пишет: опрашивать сервер вызовом функции LETO_MGGETINFO. Если ответ получен - значит, сервер работает, если нет - упал, тогда надо пробовать переконнектиться. Спасибо, я про это и спрашивал !

Andrey: Всем доброй ночи.... Пробовать новое получается только по ночам... Начал пробовать LetoDB+MiniGui. Еле запустил простой пример создания базы... По разному пробовал и без letodb.ini и с ним, сообщает об успехе коннекта, а базу создать не может: Error DBFCDX/1004 Create error: \DATA\test866.dbf Error DBFCDX/1004 Create error: \DATA\\127.0.0.1:2812test866.dbf Error DBFCDX/1004 Create error: \DATA\test866.dbf Error DBFCDX/1004 Create error: ..\DATA\test866.dbf Решил кардинально, через letodb.ini - указав DataPath=C:\LetoDB\DATA Установил на сервер в инете, попытался 4000 записей сразу создать, результат 8 минут и AVI-ка ожидания висит... Ладно, фиг с ней. Можно как то бегунок отражать на экране, допустим при создании базы ? Это не критично, но просто для примера, понять как можно делать. И второй вопрос, а как можно создать/открыть базу на локальном компе одновременно с LetoDB и скопировать записи с сервера, к себе на комп в локальную базу ?

SkyNET: Здравствуйте! Пытаюсь собрать LetoDB 2.09 под Harbour 3.0.0 (Rev. 16951) на CentOS release 6.5 (Final). Harbour 3.0.0 собрался прекрасно, никаких ошибок нет. LetoDB вроде тоже нормально собирается, но на стадии линковки выдаёт следующую ошибку: [pre2][root@57461-6 letodb-2.09-win]# make -f Makefile.linux gcc obj/linux/server.o obj/linux/common.o obj/linux/hbip.o obj/linux/common_c.o obj/linux/blowfish.o obj/linux/leto_2.o obj/linux/letofunc.o obj/linux/letolist.o obj/linux/letoacc.o obj/linux/letovars.o obj/linux/leto_lnx.o obj/linux/errint.o obj/linux/errorsys.o -obin/letodb -L/apps/harbour/lib -Wl,--start-group -lhbvm -lhbrtl -lhbcpage -lhblang -lhbrdd -lhbrtl -lhbmacro -lhbpp -lgtstd -lrddntx -lrddcdx -lrddfpt -lhbcommon -lhbsix -Wl,--end-group -lm -lpthread /usr/bin/ld: cannot find -lhbvm collect2: ld returned 1 exit status[/pre2] С путями вроде всё нормально, файл /apps/harbour/lib/linux/gcc/libhbvm.a существует. В чём может быть проблема?

alkresin: Andrey пишет: Установил на сервер в инете, попытался 4000 записей сразу создать, результат 8 минут Естественно, это же 4000 обращений к серверу и 4000 ответов. Оформите это как транзакцию, или серию транзакций по группе записей в пакете - и количество обращений туда-сюда, а, соответственно, и затраченное время в разы уменьшится. Можно как то бегунок отражать на экране, допустим при создании базы ? Отражайте, кто вам мешает ? LetoDB тут ни при чем, он предназначен только для операций с БД и не знает, какой интерфейс у вас используется ( консоль, та или иная GUI библиотека ). а как можно создать/открыть базу на локальном компе одновременно с LetoDB и скопировать записи с сервера, к себе на комп use (cRemotePath + "db1") new via LETO use (cLocalPath + "db2") new via DBFCDX append from db1

alkresin: SkyNET пишет: gcc ... -obin/letodb -L/apps/harbour/lib ... /usr/bin/ld: cannot find -lhbvm Путь к библиотекам прописан: /apps/harbour/lib, а они у вас, по вашим словам, в /apps/harbour/lib/linux/gcc/libhbvm.a

Dima: alkresin пишет: Естественно, это же 4000 обращений к серверу и 4000 ответов. Оформите это как транзакцию Это как ? Было к примеру. [pre2] For J=1 to 4000 dbappend() Next [/pre2]

SergKis: Andrey пишет: letodb.ini - указав DataPath=C:\LetoDB\DATA мой letodb.ini : [Main] Port = 2812 DataPath = . EnableFileFunc = 1 каталог DATA создаешь сам, дальше LETO_MAKEDIR( cDirName ) загрузку примерно так делаю:[pre2] ... // таблица LETO открыта exclusive nLenRec := ... // длина записи передаваемой на сервер nKolBuf := 500 // кол-во записей в буфере транзакции nMaxBuf := (nKolBuf+1) * nLenRec // размер буфера транзакции nKol := 0 // счетчик записей для транзакции nCnt := 0 // общий счетчик записей nDel := 0 // счетчик удаленных // текущий alias это LETO таблица leto_BeginTransaction(nMaxBuf) DO WHILE ! ( nInp )->( EOF() ) IF nKol >= nKolBuf nKol := 0 IF leto_InTransaction(); leto_CommitTransaction() ENDIF leto_BeginTransaction(nMaxBuf) ENDIF nCnt++ nKol++ dbAppend() IF ! NetErr() // из ( nInp )-> .... переносим данные Fields IF ( nInp )->( deleted() ) // на входе запись удаленная dbDelete() nDel++ ENDIF ENDIF ( nInp )->dbSkip(1) ENDDO IF leto_InTransaction(); leto_CommitTransaction() ENDIF dbCommit() ... [/pre2]

alkresin: Dima пишет: Это как ? Было к примеру. For J=1 to 4000 dbappend() Next Например, так: For J=1 to 40 begin transaction for j1 := 1 to 100 dbappend() next end transaction Next Все, что между begin transaction ... end transaction отправляется на сервер одним пакетом.

Andrey: SergKis пишет: загрузку примерно так делаю alkresin пишет: Все, что между begin transaction ... end transaction отправляется на сервер одним пакетом. Спасибо БОЛЬШОЕ !!!

Dima: alkresin пишет: Все, что между begin transaction ... end transaction отправляется на сервер одним пакетом А если вот так , это оптимально будет или нет ? На других станциях юзеры не испытают проблем с этой базой ? [pre2] begin transaction do While !test->(eof()) sum+=test->summa test->(dbskip()) enddo end transaction [/pre2]

alkresin: Dima пишет: А если вот так , это оптимально будет или нет ? Транзакции применяются исключительно для записи данных. После begin transaction все операции добавления/изменения накапливаются в буфере и после end transaction передаются на сервер, где и исполняются - или все, или ни одна. Операции чтения при транзакциях работают также, как и без них, так что в приведенном вами коде begin transaction, end transaction ничего не изменят.

Dima: alkresin Понял. Спасибо.

alkresin: Для ускорения операций чтения возможен другой вариант: LETO_SETSKIPBUFFER( nSkip ) - установить размер буфера чтения. Если, например, вы установили его в 100 ( по умолчанию, кажется 10 ) - то при dbSkip(1), если следующей записи нет в буфере, считываются сразу 100 записей - и, соответственно, следующие 100 dbskip(1) не будут обращаться к серверу. Потом лучше, наверное, опять уменьшить буфер - если читать помногу записей без надобности, это может затормозить работу.

Dima: Я пробовал играться с аналогом LETO_SETSKIPBUFFER , в ADS и особого ускорения не увидел. Пробовал руками разные значения и спец функцию........ Функция такая , для определения кол-ва кэшируемых записей [pre2] Func LenReCash(als) local ret:=0 local i FOR i = 1 TO (als)->(fcount()) ret+=(als)->(FIELDSIZE(i)) NEXT ret+=4 return int((65535/ret)/5.4) [/pre2]

alkresin: Честно говоря, не понял, как это определяет количество кэшируемых записей и что это за магические числа = 65535 и 5.4 :). Не помню уже аналог из ADS, но для LetoDB эта функция ( leto_setskipbuffer()) реально работает, если применять ее по назначению - например, увеличить буфер при последовательном чтении dbf.

Dima: alkresin пишет: Не помню уже аналог из ADS AdsCacheRecords()

SkyNET: alkresin пишет: Путь к библиотекам прописан: /apps/harbour/lib, а они у вас, по вашим словам, в /apps/harbour/lib/linux/gcc/libhbvm.a Спасибо, действительно, не обратил внимания. Но теперь возникла другая ошибка: [pre2]gcc obj/linux/server.o obj/linux/common.o obj/linux/hbip.o obj/linux/common_c.o obj/linux/blowfish.o obj/linux/leto_2.o obj/linux/letofunc.o obj/linux/letolist.o obj/linux/letoacc.o obj/linux/letovars.o obj/linux/leto_lnx.o obj/linux/errint.o obj/linux/errorsys.o -obin/letodb -L/apps/harbour/lib -Wl,--start-group -lhbvm -lhbrtl -lhbcpage -lhblang -lhbrdd -lhbrtl -lhbmacro -lhbpp -lgtstd -lrddntx -lrddcdx -lrddfpt -lhbcommon -lhbsix -Wl,--end-group -lm -lpthread obj/linux/leto_2.o: In function `thread2': leto_2.c:(.text+0x79d): undefined reference to `hb_vmThreadInit' leto_2.c:(.text+0x918): undefined reference to `hb_vmThreadQuit' collect2: ld returned 1 exit status make: *** [bin/letodb] Error 1[/pre2]

alkresin: SkyNET пишет: gcc ... -obin/letodb -L/apps/harbour/lib -Wl,--start-group -lhbvm -lhbrtl ... Вообще-то здесь должна быть hbvmmt, а не hbvm. Какая у вас версия letodb и где вы ее взяли ?

alkresin: alkresin пишет: Какая у вас версия letodb и где вы ее взяли ? Ясно, у нас там лежит для скачивания старая версия. Воспользуйтесь CVS: @echo off SET CVSROOT=:pserver:anonymous@letodb.cvs.sourceforge.net:/cvsroot/letodb SET HOME=C:\CVS\ c:\cvs\cvs login c:\cvs\cvs checkout -r rel-1-mt -P letodb Или на Sourceforge вот тут: http://letodb.cvs.sourceforge.net/viewvc/letodb/letodb/?pathrev=rel-1-mt внизу страницы - Download GNU tarball

alkresin: Загрузил на Sourceforge letodb-2.15-src.zip - самые свежие исходники.

SkyNET: alkresin пишет: Ясно, у нас там лежит для скачивания старая версия. alkresin пишет: Или на Sourceforge вот тут: http://letodb.cvs.sourceforge.net/viewvc/letodb/letodb/?pathrev=rel-1-mt внизу страницы - Download GNU tarball Спасибо, с новой версией собралось без проблем.

Andrey: alkresin пишет: Все, что между begin transaction ... end transaction отправляется на сервер одним пакетом. Что то не компилируется... Выдает ошибку: Harbour 3.2.0dev (r1503131756) Copyright (c) 1999-2015, http://harbour-project.org/ demo_letodb.prg(269) Error E0030 Syntax error "syntax error at 'TRANSACTION'" demo_letodb.prg(298) Error E0010 ENDIF does not match IF 2 errors Может в коде неправильно ставлю ? bErrHandler := ErrorBlock( { | VAR | BREAK( VAR ) } ) BEGIN SEQUENCE USE ( cFileDbf2 ) Alias TEMP866 NEW VIA "DBFCDX" CODEPAGE "RU866" SHARED RECOVER MsgStop( "БАЗА (BASE)" + cFileDbf2 + " уже открыта (now open) !", "Ошибка ! Error !" ) RETURN END SEQUENCE ErrorBlock( bErrHandler ) SELECT TEMP866 aDbf := DbStruct() // создание базы 1251 / create a database 1251 cFileDbf := cPathServer + "test1251.dbf" DBCreate( cFileDbf, aDbf, "LETO" ) USE ( cFileDbf ) Alias TEMP1251 NEW VIA "LETO" CODEPAGE "RU1251" EXCLUSIVE begin transaction SELECT TEMP866 GOTO TOP DO WHILE !EOF() // считываем значение полей в массив aFieldArray := {} FOR nI := 1 TO FCOUNT() AADD( aFieldArray, FIELDGET( nI ) ) NEXT SELECT TEMP1251 APPEND BLANK FOR nI := 1 TO FCOUNT() FIELDPUT( nI, aFieldArray[ nI ] ) NEXT SELECT TEMP866 SKIP ENDDO end transaction CLOSE TEMP866 CLOSE TEMP1251

PSP: 1. REQUEST LETO не забыл? 2. И может на самом деле проблема в "demo_letodb.prg(298) Error E0010 ENDIF does not match IF" ?

alkresin: Это я уже подзабыл. Правильно будет: LETO_BEGINTRANSACTION() ... LETO_COMMITTRANSACTION()

PSP: alkresin пишет: Правильно будет: LETO_BEGINTRANSACTION() ... LETO_COMMITTRANSACTION() Да, точно. )

SergKis: Andrey а мой пример не смотрел ? там же все есть, даже с буфером для транзакции (его размер по умолчанию, раньше был небольшой и при широкой записи были проблемы - буфер перевыделялся и загрузка шла долго, потом Pasha подправлял) я всегда использую буфер

Dima: Andrey Заведи #command BEGIN TRANSACTION => LETO_BEGINTRANSACTION() #command END TRANSACTION => LETO_COMMITTRANSACTION()

Andrey: Dima пишет: а мой пример не смотрел ? Смотрел, просто решил маленький пример сначала сделать, а потом уж поболее делать. PSP пишет: 1. REQUEST LETO не забыл? 2. И может на самом деле проблема в "demo_letodb.prg(298) Error E0010 ENDIF does not match IF" ? 1) Стоит. 2) до этого не доходить, ошибка компиляции до этого, а эта ошибка неправильно вылазит..

Andrey: alkresin пишет: LETO_BEGINTRANSACTION() ... LETO_COMMITTRANSACTION() Компилирует нормально, но вылетает при работе: Error DBFCDX/1031 Синтаксическая ошибка</p><BR> Called from LETO_COMMITTRANSACTION(0) Called from CREATEDBF1251(290) Called from (b)MAIN(87) Called from _DOCONTROLEVENTPROCEDURE(1651) Called from EVENTS(1516) Called from _DOMESSAGELOOP(0) Called from _ACTIVATEWINDOW(1373) Called from MAIN(125) Строка (290) - LETO_COMMITTRANSACTION()

Andrey: alkresin пишет: Естественно, это же 4000 обращений к серверу и 4000 ответов. Оформите это как транзакцию, или серию транзакций по группе записей в пакете - и количество обращений туда-сюда, а, соответственно, и затраченное время в разы уменьшится. Я был не прав. Тормоза в тесте были от показа GRID'a ! Сделал правильный тест, 5000 записей (4 поля) : 1) отправка на сервер в инете (в моем городе) БЕЗ транзакций: 15 сек. 2) отправка на сервер в инете (в Москву) БЕЗ транзакций: 1 мин. 57 сек. Просто супер... Не знаю как дальше будет, если базу увеличить... Бегунок тоже сделал.... Только AVI-ка замирает при передаче... Не особенно красиво, хотя собираю с ключом -mt. Кому интересно - вот пример на МиниГуи https://cloud.mail.ru/public/0a167351289f/LetoDB-demo-MiniGui.7z

SergKis: Andey пишет: вот пример на МиниГуи 1. вынеси connect до окна (если его нет, то сообщение и конец) или в oninit (тогда сначала контрлы hide или disable, если connect есть переводи в рабочее соостояние, иначе сообщение ...). 2. в цикл загрузки ставь do events 3. если файл на сервере постоянный и с индексами, то делай OrdSetFocus(0), zap, загрузку, reindex, OrdSetFocus(1) 4. не мучай grid перезагрузкой Item-ов, используй browse (skipbuffer устанавливай в кол-во строк в browse (default 10)) 5. получить длину записи области RecSize()+1, или посчитать длины из dbStruct() и +1.

alkresin: Andrey пишет: Компилирует нормально, но вылетает при работе: Error DBFCDX/1031 Синтаксическая ошибка</p><BR> Called from LETO_COMMITTRANSACTION(0) Вставьте перед LETO_COMMITTRANSACTION(): SELECT TEMP1251 Уж не помню, почему это было сделано, но при committransaction текущей должна быть удаленная таблица.

SergKis: Andrey пишет:Строка (290) - LETO_COMMITTRANSACTION() транзакция leto для областей rdd LETO, для др. rdd могут быть свои механизмы транзакций ... SELECT TEMP866 SKIP ENDDO // здесь DBFCDX !!! LETO_COMMITTRANSACTION() //end transaction alkresin пишет:Вставьте перед LETO_COMMITTRANSACTION(): SELECT TEMP1251 +1 SergKis пишет: // текущий alias это LETO таблица - leto_BeginTransaction(nMaxBuf)... просто Андрею немного внимательней надо см. примеры

Andrey: SergKis пишет: просто Андрею немного внимательней надо см. примеры Да это уж точно... Просто внимания уже не хватает, раньше быстрей схватывал.

Dima: Andrey Так может тебе сюда уже ;) http://clipper.borda.ru/?1-1-0-00000427-000-140-0#060

marrinass: Dima пишет: Продолжаем тут Как-то странно создано продолжение. А где начало? Открываешь тему, жмёшь на стр. 2 или 3 и остальные стр. в перечислении пропадают!

Andrey: Dima пишет: Andrey Так может тебе сюда уже Согласен ! Нечего засорять ветку другими сообщениями... marrinass пишет: Открываешь тему, жмёшь на стр. 2 или 3 и остальные стр. в перечислении пропадают! Ага, и у меня так же...

Andrey: Тест, 5000 записей (4 поля) : 1) отправка на сервер через инете (в моем городе) БЕЗ транзакций: 13 сек. отправка на сервер через инете (в моем городе) С транзакцией: 4 сек. 2) отправка на сервер через инете (сервер в Москве) БЕЗ транзакций: 2 мин. 01 сек. отправка на сервер через инете (сервер в Москве) С транзакций: 3 сек.

Softlog86: Вопрос к гуру : Есть - WEB-сайт . Крутится вроде на LINUX (точную версию пока не знаю) . Там есть MySQL и кой-какие базы (для сайта) работают . Хочется использовать сайт для обмена данными с программами на Harbour : Запись информации в БД на сервер , Скачивание , выборка по параметрам , и т д . Он-лайн торговля (через клиентское приложение ) Отсюда два варианта : 1) Использовать MySQL 2) Использовать LETO_DB По первому варианту - не могу понять в какую сторону рыть для начала .... По второму - видимо нужно скомпилировать LETO_DB для работы в LINUX .... опять-же - трудности с этим .... Если кто-то может дать подробную инструкцию - буду благодарен ! Сам склоняюсь к использованию LETO_DB .... :)

Andrey: Softlog86 пишет: По второму - видимо нужно скомпилировать LETO_DB для работы в LINUX .... опять-же - трудности с этим .... Если кто-то может дать подробную инструкцию - буду благодарен ! http://dimao.blogspot.ru/p/blog-page.html Без точной версии LINUX собрать невозможно.

Softlog86: Версию узнаем .... Вопрос - кто соберет под нужную ОС ? : и поможет с запуском sm20: Server Type : Apache/2.2.14 (FreeBSD) PHP/5.2.12 with Suhosin-Patch mod_fcgid/2.3.5 mod_ssl/2.2.14 OpenSSL/0.9.7e-p1

SergKis: Andrey ты просил набросать. вот что то набрал (дополняй сам): [pre2] STATIC lLetoConnect := .F. FUNCTION MAIN() LOCAL cTable, cAlias, nSkip, hBrowse LOCAL cFileDbf .... IF ! myConnnect() RETURN NIL ENDIF cFileDbf := cPathLocal + "test866.dbf" cTable := cPathServer+"test1251.dbf" cAlias := "TEST_1251" // ------ я выношу проверку и создание таблиц в отдельный модуль aStru := { ; { "FIO" , "C", 25, 0 }, ; { "STATUS" , "C", 10, 0 }, ; { "CLASS" , "C", 4, 0 }, ; { "ID" , "+", 4, 0 } ; } aIndex := { ; {'FIO', 'UPPER(FIO)', .F.} ; } IF ! file(cFileDbf) // ... // создаем файл cFileDbf !!! // ... ENDIF IF ! Table_Create( cTable, aStru, aIndex) MsgStop('Table not create :'+ chr(10))+cTable, 'ERROR') RETURN NIL ENDIF // ------ IF ! Table_Open(cTable, cAlias, .T.) MsgStop('Table not open :'+ chr(10))+cTable, 'ERROR') RETURN NIL ENDIF DEFINE WINDOW Form_6 ; ... @ 55, 10 BROWSE Browse_1 WIDTH 575 HEIGHT 130 ; HEADERS { '№№', 'ФИО/FIO', 'Статус/Status', 'Класс/Class' } ; WORKAREA &cAlias ; WIDTHS { 60, 280, 110, 100 } ; FIELDS {"ID", "FIO", "STATUS", "CLASS"} ; FONT "Tahoma" SIZE 10 BOLD ; BACKCOLOR aGrColor ; DYNAMICFORECOLOR { fColor , fColor, fColor, fColor } ; DYNAMICBACKCOLOR { fColor2, fColor2, fColor2, fColor2 } // ставим размер skip buffer (можно в on init это сделать) hBrowse := Form_6.Browse_1.Handle // GetControlHandle("Browse_1", ThisWindow.Name) nSkip := ListViewGetCountPerPage(hBrowse) // строк на browse ( cAlias )->( LETO_SETSKIPBUFFER( nSkip ) ) // // ... END WINDOW ... RETURN NIL /////////////////////////////////////////////////////////////////////////// FUNC myConnect() LOCAL nRes IF ( leto_Connect( cPathServer ) ) == - 1 nRes := leto_Connect_Err() IF nRes == LETO_ERR_LOGIN cMsg := "Login failed to LetoDB" ELSEIF nRes == LETO_ERR_RECV cMsg := "Recv Error to LetoDB" ELSEIF nRes == LETO_ERR_SEND cMsg := "Send Error to LetoDB" ELSE cMsg := "No connection to LetoDB" ENDIF MsgStop( cMsg , "Error" ) RETURN .F. ENDIF lLetoConnect := .T. // connect есть RETURN .T. /////////////////////////////////////////////////////////////////////////// FUNC Table_Open( cTable, cAlias, lShared ) // открываем таблицу LOCAL lRet IF ! lLetoConnect; RETURN .F. ENDIF Default lShared := .T. lRet := UseArea( cTable, cAlias, lShared, 'LETO') IF lRet .and. OrdCount() > 0 // есть индекс подключаем OrdSetFocus(1) dbGotop() ENDIF RETURN lRet /////////////////////////////////////////////////////////////////////////// FUNC Table_Create( cTable, aStru, aIndex ) // создание таблицы LOCAL lTable, cPath, cFile, cExt, cTag, cKey, lUnique, i,j,k IF ! lLetoConnect; RETURN .F. ENDIF hb_FNameSplit(cTable, @cPath, @cFile, @cExt) IF empty(cExt); cTable += '.dbf' ENDIF lTable := leto_file(cTable) IF ! lTable leto-fErase(cPath+cFile+'.cdx') dbCreate(cTable, aStru, 'LETO', .T., "") // можно задать алиас вместо "" IF hb_IsArray(aIndex) k := len(aIndex) FOR i := 1 TO k cTag := aIndex[ i ][1] // Tag Name cKey := aIndex[ i ][2] // Tag Key lUnq := aIndex[ i ][3] // Tag Unique OrdCreate( , cTag, cKey, &( "{||" + cKey + "}" ), lUnq ) NEXT ENDIF dbCloseArea() lTable := .T. ENDIF RETURN lTable FUNC Dbf_2_Table( cFileDbf, cTable, lZap ) // load dbf 866 в таблицу LOCAL nInp, nKol, nCnt, nDel, nAdd, i, k LOCAL nLenRec, nMaxBuf, nKolBuf IF ! file(cFileDbf) MsgStop('File not found !'+chr(10)+cFileDbf, "ERROR") RETURN .F. ENDIF USE ( cFileDbf ) ALIAS TEMP866 CODEPAGE "RU866" VIA "DBFCDX" //NEW SHARED IF ! Used() MsgStop('File not open !'+chr(10)+cFileDbf, "ERROR") RETURN .F. ENDIF nInp := select() IF ! Table_Open(cTable, , .T.) // exclusive ( nInp )->( dbClosearea() ) MsgStop('Table not open !'+chr(10)+cTable, "ERROR") RETURN .F. ENDIF IF OrdCount() > 0 // есть индекс отключаем OrdSetFocus(0) dbGotop() ENDIF IF ! empty(lZap) // очистим таблицу ZAP ENDIF k := fCount() - 1 // последнее поле (ID) не учитываем - заполняет rdd // таблица LETO открыта exclusive nLenRec := RecSize()+1 // длина записи передаваемой на сервер (Как считать ?) = кол-ву символов полей в БД ? nKolBuf := 1000 // кол-во записей в буфере транзакции nMaxBuf := (nKolBuf+1) * nLenRec // размер буфера транзакции nKol := 0 // счетчик записей для транзакции nCnt := 0 // общий счетчик записей nDel := 0 // счетчик удаленных nAdd := 0 // счетчик реально добавленных // текущий alias это LETO таблица - // ------ здесь уст. начальную позицию бегунка - индикатора leto_BeginTransaction(nMaxBuf) DO WHILE ! ( nInp )->( EOF() ) IF nKol >= nKolBuf nKol := 0 IF leto_InTransaction(); leto_CommitTransaction() ENDIF // ------ здесь меняем позицию бегунка - индикатора DO EVENTS // ------ leto_BeginTransaction(nMaxBuf) ENDIF nCnt++ nKol++ dbAppend() IF ! NetErr() nAdd++ FOR i := 1 TO k // из ( nInp )-> .... переносим данные Fields FieldPut( i, ( nInp )->FieldGet(i) ) NEXT IF ( nInp )->( deleted() ) // на входе запись удаленная dbDelete() nDel++ ENDIF ENDIF ( nInp )->dbSkip(1) ENDDO IF leto_InTransaction(); leto_CommitTransaction() ENDIF dbCommit() dbGotop() IF OrdCount() > 0 // есть индекс REINDEX OrdSetFocus(1) dbGotop() ENDIF ( nInp )->( dbCloseArea() ) // ------ здесь завершаем позицию бегунка - индикатора Form_6.Browse_1.Refresh RETURN .T. /////////////////////////////////////////////////////////////////////////// FUNC UseArea( cFile, cAls, lShare, cRdd, nWhl ) // Открыть таблицу или DBF LOCAL w := 10, lRet, oError, bOldError, lAuto, lLeto LOCAL cPth, cFil, cExt IF hb_IsNumeric(nWhl) .and. nWhl > 0; w := nWhl ENDIF IF ! hb_IsChar(cRdd); cRdd := RddSetDefault() ENDIF lLeto := ( cRdd == 'LETO' ) IF lLeto; lAuto := Set( _SET_AUTOPEN, .T. ) ENDIF select 0 IF empty(cAls) .or. ! hb_IsChar(cAls) // алиас не задан - формируем сами hb_FNameSplit(cFile, @cPth, @cFil, @cExt) cAls := upper(cFil) IF select(cAls) > 0; cAls := '_XYZ_'+hb_ntos(select()) ENDIF ENDIF IF ! hb_IsLogical(lShare); lShare := .T. ENDIF NetErr( .F. ) bOldError := ErrorBlock({ |oErr| break(oErr) }) DO WHILE w-- > 0 BEGIN SEQUENCE lRet := DbUseArea(.F., cRdd, cFile, cAls, lShare, .F.) RECOVER USING oError lRet := .F. END SEQUENCE IF lRet .AND. ! NetErr() lRet := Used() EXIT ENDIF hb_IdleSleep(0.2) ENDDO ErrorBlock( bOldError ) IF lLeto; Set( _SET_AUTOPEN, lAuto ) ENDIF RETURN lRet [/pre2] если что спрашивай

SergKis: Andrey вместо LOCAL ... lUnique надо lUnq в FUNC Table_Create(...)

SergKis: Dima не увидел про перенос темы, извини и перекинь мои крайние посты тоже. Спасибо

SergKis: Softlog86 Есть - WEB-сайт 1. он Ваш или сторонний и у вас только hosting ? 2. он на CMS или как то иначе ? 3. Он-лайн торговля (через клиентское приложение ) на hb или как то иначе ?

Andrey: SergKis пишет: если что спрашивай Слишком много буковок... Пошёл разбираться.... СПАСИБО БОЛЬШОЕ !

Softlog86: 2 SergKis отвечаю : 1. он Ваш или сторонний и у вас только hosting ? -> НАШ - связь с автором сайта ЕСТЬ 2. он на CMS или как то иначе ? -> не знаю что это такое :( спросим у автора 3. Он-лайн торговля (через клиентское приложение ) на hb или как то иначе ? -> есть клиентское приложение на HARBOUR+MINIGUI - программа прайс-лист с возможностью заказов (плюс базы данных по кросс-кодам и тд - .DBF) собственно это приложение и хочу переделать для работы не по FTP а сразу с БД на сервере ....

SergKis: Softlog86 Спасибо. понятно, что в данном случае все в ваших руках. и если используется cms (инструмент создания сайтов) с mysql, то из своего приложения туда тоже можно достучаться, есть rdd в hb для работы с mysql

Dima: marrinass пишет: Открываешь тему, жмёшь на стр. 2 или 3 и остальные стр. в перечислении пропадают! Это косяк движка форума.

SergKis: Dima пишет:Это косяк движка форума в GUI потыкал некоторые темы, там нормально.

alkresin: Softlog86 пишет: Запись информации в БД на сервер , Скачивание , выборка по параметрам , и т д . Он-лайн торговля (через клиентское приложение ) Отсюда два варианта : 1) Использовать MySQL 2) Использовать LETO_DB Слишком мало конкретной информации, чтобы посоветовать тот или иной вариант. Вот, например, клиентское приложение для онлайн торговли - что имется ввиду, веб-магазин ? По первому варианту - не могу понять в какую сторону рыть для начала .... contrib/hbmysql - вполне работающая библиотека, я ее лет 10 назад начал использовать для некоторых мелочей. По второму - видимо нужно скомпилировать LETO_DB для работы в LINUX .... опять-же - трудности с этим .... А какие именно трудности ? Просто запускаете make_linux.sh, предварительно поставив свои пути Harbour.

alkresin: Andrey пишет: Без точной версии LINUX собрать невозможно. Версия Linux не имеет значения. Главное - правильно указать пути к Harbour, самому компилятору, библиотекам и include.

Softlog86: Если-б кто скинул готовый LITO_DB сервер для указанной системы (FreeBSD).... для пробы пера так сказать .... (пока устанивлю LINUX , пока скачаю нужные компоненты для компиляции ... нет времени ... ведь есть основная работа и она не ждёт ) Пойду тормошить разработчика сайта чтоб сказал что делать для запуска LETO на WEB_сервере .....

alkresin: Softlog86 пишет: Если-б кто скинул готовый LITO_DB сервер для указанной системы (FreeBSD) У меня нету. Пойду тормошить разработчика сайта чтоб сказал что делать для запуска LETO на WEB_сервере Для однократного запуска - просто запустить ./letodb. Где прописать, чтобы LETO сам запускался при включении сервера - это вопрос к тем, кто знаком с FreeBSD.

SergKis: Softlog86 пишет: для пробы пера так сказать... для пробы (отработки методик) достаточно и localhost в win, в сети потом даже быстрее фурычит

Softlog86: Локальное лето в WINDOWS уже работает ( в других приложениях) .... Проба заключается в работе именно с хранилищем в Интернете на нашем Сайте ....

SergKis: Softlog86 пишет:с хранилищем в Интернете на нашем Сайте .... если ваш сайт cms (типа joomla) с mysql, то доступ к letodb в основмном через cgi. у нас именно такой вариант был, мы с него ушли (все работало, но при разрастании все становилось не удобным, громоздким). развите требовало загружать mysql+php, но не хотелось уходить с hb. Перешли к варианту joomla (для сайта клиента - доомоуправление, жск ... со своей инф. ) + http сервер на hb (на базе http://www.dbtopas.lt/hrb/uhttpd-0.3.zip) + letodb (Share_Tables = 1). задача квартплата работает с letodb, заполнение счетчитчиков по воде жильцами возможна с сайта и отчеты по ней на сайте. такая схема работает уже полгода в нескольких домоуправлениях. все очень стабильно, быстро. Для развития сайта (возможно даже замена какихто режимов на MiniGui) смотрим в сторону http://w2ui.com

Softlog86: Ой как сложно ... Задача простая : У клиента установлена программа на Харборе . Работаем с DBF-файлами . Обмен (обновление локальных данных и отправка своих : заказов идёт через FTP на сайт в определенные папки ) Пользователей всего-то около трёх сотен . Работает одновременно - максимум 20-30 . И то - скачивают новые прайсы / остатки и т д .... опять-же - это по FTP . Хотелось-бы чтоб коннектились к таблицам на сайте и тащили только новую информацию а не все таблицы ....

SergKis: Softlog86 Вы так и не ответили на чем Ваш сайт. Статические страницы (на ftp закидываются) или apache+mysql+php. не могу понять доступ через Chrome\Explorer к страницам вашей информации, если есть ввод на страницах - как попадает в базу ?

SergKis: Softlog86 пишет: Обмен (обновление локальных данных и отправка своих : заказов идёт через FTP на сайт в определенные папки ) это задача не сайт, такой вариант у меня тоже есть: Clipper+localdbf+mysql+ftp, при переводе на hb, получилось local dbf+letodb, т.е. задача (отчеты, справочники, операт. информация - local инф.) letodb - производная база от local, hb console+MiniGui работают с letodb (могут и с local по устан.) изменения с letodb попадают на local по запросам (timer), так проще было переводить с clipper и + требования клиента о живучести (оперативная работа склад, торговые точки, ...) если летит сервер - проблем не должно быть, клиент у кассы ждать не будет.

Softlog86: Уточнение : У клиентов - EXE-модуль на HARBOUR+MINIGUI . Локальные файлы - .DBF : Это различные таблицы - список товаров , кросс-коды , и т д . На FTP-сервере в Интернет (физически на нашем информационном сайте ) в различных папках , к которым есть доступ по паролю находятся ZIP(внутри - таблицы DBF). Клиент выбирает пункт "ОБНОВИТЬ БАЗЫ ДАННЫХ" . Прога лезет на FTP и скачивает к себе что нужно : Раскрывает архивы , извлекает .DBF и из них переписываетв в свои локальные базы нужную информацию . Разумеется - это всё статические данные , которые НА FTP мы забрасываем по мере необходимости . Задача - при ОБНОВЛЕНИИ ( клиентом) - идёт подключение (через MySQL или LETO_DB ) к соответствующим таблицам в Интернете и считываем нужные данные , одновременно записывая в локальные базы (обновление или добавление ) . При этом клиент записывает и на сервер какую-то информацию (лог работы , собранные собственные данные : заявки/заказы/отчеты и т д) Разница в том , что при таком способе нет необходимости гнать файлы ( до 2-5 Мбайт x 2-50 шт)

SergKis: Softlog86 пишет:У клиентов - EXE-модуль на HARBOUR+MINIGUI . я уже понял, что у Вас "толстый" клиент на hb и файловый сервер на ftp. т.е. та же технология, что у меня было на Clipper ...(см. пост выше) и Вам требуется перейти на letodb или mysql вместо ftp. Если у Вас hb+MiniGui локально решают все вопросы, а ftp - хранилище zip данных, то, на мой взгляд, letodb лучше - проще. 1. Разделите dbf файлы на рабочие (local) и серверные. 2. Сделайте модуль загрузки инф. на сервер 3. Задайте пути на сервер для серверных файлов (надо учесть разницу файловых функций leto_file и file, ...) и практически вперед ... (конечно нюансов Вашей задачи я не знаю) пока нет версии под линукс, делайте все на win версии - чтобы время не терять

Softlog86: Да , но нужно чтоб сервер LETO работал на нашем виртуальном сервере (LINUX FreeBSD :наш сайт крутится там - и соответственно базы лежат которые LETO и будет обрабатывать ) По-любому нужно 1) LETO_DB Сервер для LINUX 2) в настройках сервера сделать его запуск

SergKis: Softlog86 пишет:Да , но нужно чтоб сервер LETO работал на нашем виртуальном сервере Так я не возражаю, только какя польза будет, если сервер УЖЕ крутится, а задача об этом ничего не знает. Главное, что бы задача умела работать с сервером, а где он запущен - вторично. И времени на это может уйти больше.

SergKis: PS. Задачу с letodb, делаю, отлаживаю в local 127.0.0.1:2812, по мере готовности проверяю в локальной сети, с letodb в инет на удаленном сервере и + через мобильньный модем соединение.

Softlog86: Ребята , в локальной сети LETO уже работает и все нужные мне действия производит . Нужно разместить Лето-сервер на LINUX-машине (Виртуальный сервер ) ... и пробовать 'достучаться' к нему по Интернету (IP): Прилагаю скриншоты : БАЗЫ ДАННЫХ САЙТА ФАЙЛОВАЯ СИСТЕМА ИНФОРМАЦИЯ О САЙТЕ

alkresin: Softlog86 пишет: Нужно разместить Лето-сервер на LINUX-машине (Виртуальный сервер ) ... и пробовать 'достучаться' к нему по Интернету (IP): 1) Скопируйте туда исходники Harbour 2) Откомпилируйте 3) Скопируйте исходники LetoDb 4) Откомпилируйте Если у вас есть доступ к нему по ssh, это делается достаточно просто и быстро.

Softlog86: Это виртуальный сервер от VDS . Я из браузера туда захожу через какую-то консоль ..... думаю проще будет установить Линукс на свой комп и пробовать создать Лето ...:) Что куда потом прописывать чтоб сервер стартовал на той виртуальной машине в сети (у хостера) ...- вот тут нужна помощь тех кто уже делал такое ...

alkresin: Softlog86 пишет: думаю проще будет установить Линукс на свой комп в смысле, FreeBSD ( это не Linux, вообще-то ). Что куда потом прописывать чтоб сервер стартовал на той виртуальной машине в сети (у хостера) Т.е., сервер, все-таки, не ваш, имеется еще хостер А он согласится установить у себя LetoDb ? Обычно хостеры крайне неохотно идут на установку неизвестных им лично программ. Вот хостеры моего сайта не захотели даже fossil устанавливать - именно по той причине, что это, по их мнению, неизвестно что :) - я, правда, и не настаивал.

Softlog86: Я думал что если мы купили хостинг на их машине - значит можем там делать всё что захотим ,,,,, а тут вот значит какая загогулина есть ещё и подводные камни с установщиками .... Значит нужно пробовать работать с MySQL . К этим базам мы можем подключиться из HARBOUR ? Что посоветуете попробовать ? Пока буду играться с примерами из комплекта MiniGUI ....

alkresin: Softlog86 пишет: Я думал что если мы купили хостинг на их машине - значит можем там делать всё что захотим Если вы купили виртуальную машину, изолированную от физического сервера, то, наверное, вы можете устанавливать все, что угодно, т.к. падение этой виртуальной машины вызовет проблемы только у вас. В любом случае, свяжитесь с хостером и выясните у него все. Значит нужно пробовать работать с MySQL . К этим базам мы можем подключиться из HARBOUR ? Что посоветуете попробовать ? harbour/contrib/hbmysql - этого будет достаточно.

finder: Есть ли возможность биндить сервер к одному конкретному адресу, если нет, возможно ли добавить? Возможно ли добавить в Leto DB функцию эквивалентную FCREATE? Отличается ли работа Leto_FileWrite от FWRITE?

alkresin: finder пишет: Есть ли возможность биндить сервер к одному конкретному адресу Поясните, что именно вы имеете ввиду. Возможно ли добавить в Leto DB функцию эквивалентную FCREATE? Leto_FileWrite() создает новый файл с указанным именем, если он не существует и поэтому может служить заменой FCreate(). Отличается ли работа Leto_FileWrite от FWRITE? И да, и нет. FWrite(), как вы знаете, записывает буфер в предварительно открытый файл, начиная с текущей позиции. Leto_FileWrite() открывает файл ( или создает, если его нет ), переходит на указанную позицию (fseek), записывает буфер и закрывает файл.

finder: alkresin пишет: Есть ли возможность биндить сервер к одному конкретному адресу Поясните, что именно вы имеете ввиду. Сейчас сервер стартует без указания IP адреса, т.е. использует все доступные IP адреса с указанным портом. Хотелось бы иметь возможность, чтобы сервер слушал запросы только на ОДНОМ IP адресе, например 127.0.0.1 или любой другой ОДИН адрес который можно было бы указать. Думаю это было бы более разумно для различных условий использования Leto DB. alkresin пишет: Возможно ли добавить в Leto DB функцию эквивалентную FCREATE? Leto_FileWrite() создает новый файл с указанным именем, если он не существует и поэтому может служить заменой FCreate(). Отличается ли работа Leto_FileWrite от FWRITE? И да, и нет. FWrite(), как вы знаете, записывает буфер в предварительно открытый файл, начиная с текущей позиции. Leto_FileWrite() открывает файл ( или создает, если его нет ), переходит на указанную позицию (fseek), записывает буфер и закрывает файл. Теперь хоть ясно, а то было непонятно почему отсутствовала функция создания файла при наличии функции записи. Пара уточнений: 1. Как поведет себя Leto_FileWrite без указания позиции начала записи? запишет сначала? 2. Как обрезать файл до размера соответствующего объему записываемых данных? В случае fcreate + fwrite независимо от наличия файла создается новый файл с нужными правами доступа и в него записывается нужная порция информации. В случае летних функций я так понимаю это должно выглядеть Leto_Ferase Leto_FileWrite ? А в случае когда есть необходимость дописать в конец файла надо использовать Leto_FileSize чтобы узнать в какой позиции находится конец файла, ввиду отсутствия функции fseek? Несколько непривычно получается, но теперь по крайней мере механизм понятен. Еще вопрос, в пользовательских функциях есть возможность задать стартовую функцию типа RunOnStart которая будет автоматически запускаться разово после загрузки letoudf.hrb ? Ну и может быть заодно RunOnStop при выгрузке/перезагрузке letoudf.hrb. P.S. Уточню - меня больше интересует работа под *nix системами, так вот. Только что проверил работу Leto_FileWrite, файл создался с правами чтение/запись для всех. В случае использования стандартных файловых функций при создании устанавливаются такие атрибуты. /* File create flags */ FC_NORMAL - чтение/запись для всех FC_READONLY - только чтение для всех FC_HIDDEN - чтение/запись только для владельца FC_SYSTEM - чтение/исполнение для всех + запись для владельца P.P.S. Описание не совсем корректное? Leto_FileWrite( cFileName, nStart, cBuf ) --> lSuccess Записывает переменную <cBuf> в файл на сервере со смещения <nStart> размером <nLen> Кто такой <nLen> ? Насколько корректен возврат lSuccess при условиях не записалось все или не записалось часть, подозреваю в обоих будет .F., а правильнее было бы наверное <nLen>.

alkresin: finder пишет: Хотелось бы иметь возможность, чтобы сервер слушал запросы только на ОДНОМ IP Я посмотрю, что можно сделать. 1. Как поведет себя Leto_FileWrite без указания позиции начала записи? запишет сначала? Да. Но лучше указать 0 ( сейчас в LETO_FILEWRITE() стоит hb_parnl(2) без проверки типа передаваемого значения ). 2. Как обрезать файл до размера соответствующего объему записываемых данных? Вы сами и ответили на этот вопрос. Несколько непривычно получается, но теперь по крайней мере механизм понятен. LetoDb создавался, в общем-то, для лругих целей. Эти функции были добавлены позже по запросам пользователей и были сделаны с учетом уже сложившейся реализации программы. Еще вопрос, в пользовательских функциях есть возможность задать стартовую функцию... Это к Павлу, я сам эту часть кода еще не смотрел. В случае использования стандартных файловых функций при создании устанавливаются такие атрибуты. Соответствующая функция LetoDb не устанавливает права - просто вызывается стандартная ф-я Harbour hb_fsOpen(). Я вижу, 2-го апреля Павел добавил ф-ю leto_FileAttr() - сее поощью, наверное, можно установить нужные атрибуты.

Pasha: Если в модуле letoudf присутствует функция с именем udf_init, она будет запущена после загрузки модуля.

alkresin: alkresin пишет: цитата: Хотелось бы иметь возможность, чтобы сервер слушал запросы только на ОДНОМ IP Я посмотрю, что можно сделать. Добавил новый параметр в ini-файл: ip, где можно указать этот единственный ip.

finder: Pasha пишет: Если в модуле letoudf присутствует функция с именем udf_init, она будет запущена после загрузки модуля. ТОЧНО ) Прошу прощения - провтыкал... alkresin пишет: цитата: Хотелось бы иметь возможность, чтобы сервер слушал запросы только на ОДНОМ IP Я посмотрю, что можно сделать. Добавил новый параметр в ini-файл: ip, где можно указать этот единственный ip. Проверил, вроде работает ) Спасибо. Имя параметра в letodb.ini окончательное, меняться не будет?

finder: Какие ограничения есть на имена пользовательских групп и переменных? Длина, набор символов, количество, etc...? Доступна ли работа с ними из пользовательских функций? Возможно ли удалить группу? В этих переменных можно хранить только CNL типы?

alkresin: finder пишет: Имя параметра в letodb.ini окончательное, меняться не будет? Окончательное. Какие ограничения есть на имена пользовательских групп и переменных? Длина, набор символов, количество, etc...? Нет ограничений. Доступна ли работа с ними из пользовательских функций? leto_var...(), или вы о чем-то другом ? Возможно ли удалить группу? Попробуйте leto_vardel( cGroupName, "" ) В этих переменных можно хранить только CNL типы? Да.

finder: alkresin пишет: Возможно ли удалить группу? Попробуйте leto_vardel( cGroupName, "" ) С пустой строкой в имени переменной помогло, до этого пробовал указывать только имя группы alkresin пишет: Доступна ли работа с ними из пользовательских функций? leto_var...(), или вы о чем-то другом ? letoudf.prg #include "rddleto.ch" Function UDF_Init LETO_VARSET( 'GroupNameTest', 'VarNameTest', 'VarContent', LETO_VCREAT ) Return NIL hbmk2 letoudf.prg -gh letodb stop letodb start letodb.log 04/07/15 10:20:25: Leto DB Server has been started. Leto DB Server v.2.15 ! INIT: DataPath=/path/data, ShareTables=0, MaxUsers=500, MaxTables=5000, CacheRecords=10 04/07/15 10:20:25: Error BASE/6101 Unknown or unregistered symbol: LETO_VARSET ERROR! SETHRBERROR - pUStru not found!!!!!!!!!!!!!!!!!!!! Возможно я делаю что-то не так? С пользовательскими переменными можно работать только с клиента?

SergKis: finder readme_rus.txt в конце [pre2] Функции letoUseArea, letoOrdListAdd, letoOrdCreate, letoCloseArea, leto_RecLock, leto_RecLock предназначены для использования в udf-функциях вместо rdd функций: dbUseArea, OrdListAdd, OrdCreate, dbCloseArea, RLock, dbUnlock LETO_VARSET( nUserStru, cGroupName, cVarName, xValue[, nFlags ) --> lSuccess LETO_VARGET( nUserStru, cGroupName, cVarName ) --> xValue LETO_VARINCR( nUserStru, cGroupName, cVarName ) --> nValue LETO_VARDECR( nUserStru, cGroupName, cVarName ) --> nValue LETO_VARDEL( nUserStru, cGroupName, cVarName ) --> lSuccess LETO_VARGETLIST( nUserStru, [cGroupName, [lValue]] ) --> aList [/pre2]

SergKis: PS. в пред.версии letodb (двухпоточной): leto_varSet( NIL, cGru, cNam, cVal, LETO_VCREAT ) ... cVal := leto_varGet( NIL, cGru, cNam ) в этой версии еще не пробовал

SergKis: finder пишет:04/07/15 10:20:25: Error BASE/6101 Unknown or unregistered symbol: LETO_VARSET добавьте: #include "rddleto.ch"

alkresin: finder пишет: С пользовательскими переменными можно работать только с клиента? Leto_var... функции определены и в серверной части. Я сейчас добавил в server.prg REQUEST для них, теперь не должен ругаться. Правда, при вызове из udf_init() выскакивает ошибка - возможно, на этот момент что-то недоинициализировано, надо проверить.

SergKis: SergKis пишет:добавьте: #include "rddleto.ch" правильнее будет для работы с leto_var...: #define LETO_VCREAT 1 #define LETO_VOWN 2 #define LETO_VDENYWR 4 #define LETO_VDENYRD 8 #define LETO_VPREVIOUS 1 т.к. #include "rddleto.ch" содержит: #define LETO_NTX 1 #define LETO_CDX 2 что повторяется с server.prg (line 64) или убрать в server.prg (line 64, 65) и использовать #include "rddleto.ch" что лучше - это к alkresin и Pasha

alkresin: или убрать в server.prg (line 64, 65) и использовать #include "rddleto.ch" Убрал, добавил. alkresin пишет: Правда, при вызове из udf_init() выскакивает ошибка - возможно, на этот момент что-то недоинициализировано, надо проверить. Просмотрел код. Функции leto_..., вызываемые из udf, должны в качестве первого параметра передавать nUserStru - параметр, который получает udf ф-я, это идентификатор клиента, который выполняет udf ф-ю. Поскольку udf_init() выполняется автоматически при старте и ни одного пользователя к этому моменту не определено, то leto_... функции не могут вызываться из нее.

finder: alkresin пишет: Просмотрел код. Функции leto_..., вызываемые из udf, должны в качестве первого параметра передавать nUserStru - параметр, который получает udf ф-я, это идентификатор клиента, который выполняет udf ф-ю. Поскольку udf_init() выполняется автоматически при старте и ни одного пользователя к этому моменту не определено, то leto_... функции не могут вызываться из нее. Спасибо, понял, буду использовать внешний инициализатор. Может стоит в readme что-то сделать с этим описанием, а то получается что суть <nLen> не раскрыта? Возможно стоит добавить так же, что при отсутствии файла он создается. Leto_FileWrite( cFileName, nStart, cBuf ) --> lSuccess Write <cBuf> character string to a file at the server from <nStart> offset and <nLen> length

SergKis: alkresin пишет: ни одного пользователя к этому моменту не определено, то leto_... функции не могут вызываться из нее. в пред.версии letodb (двухпоточной) Pasha специально делал для функций leto_var..., с nUserStru := NIL - работа с общими переменными: leto_varSet( NIL, cGru, cNam, cVal, LETO_VCREAT ) cVal := leto_varGet( NIL, cGru, cNam )

finder: SergKis пишет: в пред.версии letodb (двухпоточной) Pasha специально делал для функций leto_var..., с nUserStru := NIL - работа с общими переменными: leto_varSet( NIL, cGru, cNam, cVal, LETO_VCREAT ) cVal := leto_varGet( NIL, cGru, cNam ) Я проверил после обновления, на имя функции ругаться перестало, но валится если их вызывать из udf_init() Кстати это первый раз когда у меня получилось уронить letodb letodb_crash.logBreakdown at: 2015.04.08 10:46:06 Unrecoverable error 6005: Exception %s at address %s SIGSEGV 0x17 ------------------------------------------------------------------------ User: 127.0.0.1 (null) (null) Command: udf_rel Код такой letoudf.prg#include "rddleto.ch" Function UDF_Init LETO_VARSET( NIL, 'GroupNameTest', 'VarNameTest', 'VarContent', LETO_VCREAT ) Return NIL

SergKis: finder пишет:но валится если их вызывать из udf_init() буду знать. я ф-ии использовал в триггере, поэтому было все ok.

alkresin: finder пишет: Может стоит в readme что-то сделать с этим описанием, а то получается что суть <nLen> не раскрыта? Да, никакого nLen нет в этой функции, используется длина cBuf. Исправлю.

nbatocanin: Есть ли где описание команды в дебуг режиме? close;16; unlock;14;02; unlock;15;02; goto;15;1695;par_naz;A; rcou;15; skip;15;-1;1695;par_naz;A; rcou;15; rcou;15; rcou;15; skip;15;1;1695;par_naz;A; rcou;15; rcou;15; rcou;15;

alkresin: nbatocanin пишет: Есть ли где описание команды в дебуг режиме? Нет. Посмотреть можно только по исходникам - source/client/letocl.c

alkresin: Я немного изменил систему нумерации версий LetoDb - добавил туда номер сборки ( build ), чтобы можно было, не меняя все время основной номер версии, выкладывать на Sourceforge обновленные пакеты. Выложен letodb-2.15-b2.src.zip

Dima: alkresin Раздел создавать по LetoDB Server ? Название такое и будет LetoDB Server ?

alkresin: Я бы назвал "LetoDB, HbNetio и пр." "пр." - на всякий случай :) И в разделе GUI подзаголовок, наверное, надо переименовать "GUI в [x]Harbour"

finder: Пользовательские переменные в пользовательских функциях не работают. Попытка создать переменную приводит к падению сервера. При этом без разницы указан nUserStru или просто NIL. letoudf.prg #include "rddleto.ch" Function VarTest( nUserStru ) LETO_VARSET( nUserStru, 'TestGroupName', 'TestVarName', 'TestVarContent', LETO_VCREAT ) //LETO_VARSET( NIL, 'TestGroupName', 'TestVarName', 'TestVarContent', LETO_VCREAT ) Return .T. testvars.prg #include "rddleto.ch" #define LETOSERVER "//127.0.0.1:2812/" Procedure Main(a) local aa REQUEST LETO RDDSETDEFAULT("LETO") leto_Connect( LETOSERVER ) ? "aa:=LETO_UDF( LETOSERVER+'VarTest' )", aa:=LETO_UDF( LETOSERVER+'VarTest' ) ? 'valtype( aa )', valtype( aa ) return ? 'hb_valtoexp( aa )', hb_valtoexp( aa ) return ? 'hb_valtoexp(LETO_VARGETLIST())', hb_valtoexp(LETO_VARGETLIST()) return ? aa:=leto_vargetlist() return ? hb_valtoexp(leto_vargetlist()) return Возможно это как-то победить?

alkresin: finder пишет: Возможно это как-то победить? Победил.

finder: УРААА!!! Заработало! И похоже работает даже из UDF_Init Буду тестировать в расширенном варианте. Огромное Вам, Александр, человеческое СПАСИБО! Небольшое уточнение, это уже будет окончательно без откатов и насовсем?

alkresin: finder пишет: Небольшое уточнение, это уже будет окончательно без откатов Конечно. Там были реальные ошибки, зачем откатывать. и насовсем? До тех пор, пока новых ошибок не наплодим

finder: Эта команда leto_vardel( 'GroupNone', '' ) - удаляет группу со всеми переменными? Мусор оставлять за собой такое удаление не будет? При попытке удалить несуществующую группу переменных - сервер падает, значит ли это, что надо проверять ее наличие со стороны клиента перед удалением? При удалении отсутствующих переменных внутри группы такого не замечено.

alkresin: finder пишет: Эта команда leto_vardel( 'GroupNone', '' ) - удаляет группу со всеми переменными? Да. При попытке удалить несуществующую группу переменных - сервер падает Пример на стол. Мне не удалось воспроизвести падение сервера при удалении несуществующей группы.

alkresin: Впрочем, я сейчас исправил возможный источник проблемы, но у меня и так почему-то работало.

SergKis: alkresin подключение триггера в letodb не работает (в 2-х поточной версии все Ok): letodb.ini : ... Trigger = my_Trigger ... [pre2] FUNCTION my_Trigger( nEvent, nArea, nPos, xTrigVal ) dbInfo(DBI_TRIGGER, .F.) WrLog( Procname()+" "+ hb_valtoexp({ nEvent, nArea, nPos, xTrigVal }) ) dbInfo(DBI_TRIGGER, .T.) RETURN .T. [/pre2] включение этой функции в letodb.hrb или letodb.prg не срабатывает ни разу при операциях над таблицей это можно побороть ?

Dima: SergKis А каков функционал у dbInfo(DBI_TRIGGER...... , для чего она ?

finder: alkresin пишет: Пример на стол. Мне не удалось воспроизвести падение сервера при удалении несуществующей группы. #include "rddleto.ch" #define LETOSERVER "//127.0.0.1:2812/" Procedure Main(a) local cTmp:='', aa REQUEST LETO RDDSETDEFAULT("LETO") leto_Connect( LETOSERVER ) ? leto_vardel( 'GroupNone', '' ) ? leto_vardel( 'GroupNone', '' ) return сервер запускал без letoudf.hrb для чистоты эксперимента результат выполнения Breakdown at: 2015.04.15 11:11:46 Unrecoverable error 6005: Exception %s at address %s SIGSEGV (nil) ------------------------------------------------------------------------ User: 127.0.0.1 localhost testvars Command: var P.S. Только что пересобрал сервер. Теперь при тесте он не падает, но тестовое приложение зависает ничего не выводя т.е. как я понимаю где-то внутри функции удаления группы.

alkresin: finder пишет: Только что пересобрал сервер. Теперь при тесте он не падает, но тестовое приложение зависает ничего не выводя т.е. как я понимаю где-то внутри функции удаления группы. Исправил

finder: alkresin пишет: Исправил Спасибо, сейчас отрабатывает.

SergKis: Dima пишет:А каков функционал у dbInfo(DBI_TRIGGER...... , для чего она ? Сейчас триггер заполняет поля : IDNNN (N10) - идентификатор от поля + (клиент 2-х поточной версии не понимает новые поля) IDDATEADD(C17) - дата добавления Timestamp -> в строку IDDATEUPD (C17) - дата модификации Timestamp -> в строку IDDATEDEL (C17) - дата удаления Timestamp -> в строку эти поля обязательны по закондательству и планировал на новой версии перенести с клиента ведение логов по изменению таблиц.

alkresin: SergKis пишет: включение этой функции в letodb.hrb или letodb.prg не срабатывает ни разу при операциях над таблицей это можно побороть ? Можно, конечно. Только надо сначала разобраться - я не смотрел еще в ту сторону.

alkresin: По-видимому, дело в том, что новые потоки не наследуют RDDI_... установки, их надо переустанавливать для каждого вновь создаваемого потока.

SergKis: alkresin пишет:По-видимому, дело в том, что новые потоки не наследуют RDDI_... установки, наверное, правильно, устанавливать "свой" триггер только для нужной области (с клиента), но общий, в некоторых, ситуациях лучше и лежать триггеру лучше в letodb.hrb - для клиента свой hrb и триггеры

SergKis: alkresin, Pasha извините, что достаю ..., но есть предложение добавить в letodb.ini режим AutoMakeDir = [0] \ 1 - автомат. создание директорий при создании таблицы. такой штукой пользуемся ~5 лет - очень упрощет код на клиенте [pre2] FUNCTION hs_createtable( nUserStru, cCommand ) ... IF Lower(cName) = "/mem:" cDataPath := "" cName := Substr(cName, 2) ELSE cDataPath := leto_GetAppOptions( 1 ) ENDIF // IF ! empty(cDataPath) // cFileName := cDataPath + cName // ENDIF // _MakeDir_(cFileName) // // BEGIN SEQUENCE WITH { |e|break( e ) } ... STATIC FUNCTION _MakeDir_( cDBF ) LOCAL i, cCt, aCt := {} i := RAt(DEF_SEP, cDBF) cCt := Left(cDBF, i-1) DO WHILE ! hb_DirExists( cCt ) i := RAt(DEF_SEP, 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 += (DEF_SEP + aCt[i--]) MakeDir( cCt ) ENDDO RETURN .T. [/pre2] возвращаюсь к наличию в letodb аналогов функций hb_fSetDateTime, hb_fGetDateTime. потестировал: [pre2] FUNCTION UDF_fGetDateTime( nUserStru, cFile ) LOCAL dDate, cTime, lFile, cPath := leto_GetAppOptions(1) IF left(cFile, 1) == DEF_CH_SEP cFile := subs(cFile, 3) cFile := subs(cFile, At(DEF_CH_SEP, cFile)) cFile := StrTran(cFile, DEF_CH_SEP, DEF_SEP) cFile := subs(cFile, len(cPath)+1) ENDIF cPath += DEF_SEP lFile := file(cPath+cFile) IF lFile; hb_fGetDateTime(cPath+cFile, @dDate, @cTime) ENDIF RETURN { dDate, cTime } FUNCTION UDF_fSetDateTime( nUserStru, cFile, dDate, cTime ) LOCAL lFile, cPath := leto_GetAppOptions(1) IF empty(dDate); dDate := Date() ENDIF IF empty(cTime); cTime := Time() ENDIF IF ! '.' $ cTime; cTime += '.001' ENDIF IF left(cFile, 1) == DEF_CH_SEP cFile := subs(cFile, 3) cFile := subs(cFile, At(DEF_CH_SEP, cFile)) cFile := StrTran(cFile, DEF_CH_SEP, DEF_SEP) cFile := subs(cFile, len(cPath)+1) ENDIF cPath += DEF_SEP lFile := file(cPath+cFile) IF lFile; hb_fSetDateTime(cPath+cFile, @dDate, @cTime) ENDIF RETURN lFile [/pre2] работает хорошо, но как мне думается, наличие такого механизма в файловой части letodb (режим EnableFileFunc = 1) более правильное решение, которое позволит организовывать зеркальный letodb, получение изменений на localhost, в mysql, FTP, ... без открытия таблиц (по тэгу модификации dbgobottom, получение данного и закрытие таблицы), что упростит код на клиенте конечно вместо 2-х функций можно соорудить одну: leto_fDateTime(cFileName \ aFileName [, dDate \ .T. [, cTime ]]) leto_fDateTime(cFileName \ aFileName) - возвращает {dDate, cTime} или {{dDate, cTime}, ...} leto_fDateTime(cFileName \ aFileName, .T.) - ставит файлу\файлам дату, время сервера leto_fDateTime(cFileName \ aFileName, dDate, cTime) - - ставит файлу\файлам дату, время параметров наличие такого механизма позволит, попробовать использовать skipbuffer(LastRec()) с прочитанным целиком справочником и отключенной очисткой skipbuffer (вместо чтения в массив или memio) сейчас, в 2-х поточной версии letodb, работает механизм с открытием, ..., закрытием таблиц и набралось ~200 таблиц (только опрос - время) и приходится по клиенту размазывать (урезать) список, перед вых. формами весь, перед документом - связанное с этим докум., и .т.д.

alkresin: Вроде работают теперь триггеры, но, учтите, располагаться сами функции должны в letoudf.hrb. Мне не понятно, почему вы все время говорите о letodb.hrb - файл с таким именем нигде в коде сервера не упоминается. SergKis пишет: наверное, правильно, устанавливать "свой" триггер только для нужной области (с клиента) В смысле - для нужной таблицы ? Я тоже так думаю. Установка общего триггера довольно накладна - эта процедура вызывается при всех операциях со всеми таблицами. А вот насчет "с клиента" - не соглашусь. Триггер должен быть определен только на сервере, в этом весь его смысл - чтобы он работал независимо от того, что написано в клиентской программе.

SergKis: alkresin letodb.hrb - это описка, конечно letoudf.hrb А вот насчет "с клиента" - не соглашусь. Триггер должен быть определен только на сервере Здесь, мы друг друга не допоняли. Триггер(ы) определен(ы) ТОЛЬКО на сервере в letoudf.hrb, но активировать (нужный) триггер для нужной таблицы - с клиента, я это имел ввиду говоря "с клиента" Общий триггер, тоже полезная штука - сейчас (в 2-х поточной версии) работает общий и для всех таблиц заполняет поля обязательные (пост был выше) - нет мороки ставить\снимать для таблиц Если выбирать, какой предпочтительней, то по моей ситуации на сегодня лучше общий - переход на новую версию безболезненный Как разграничить алгоритмы ... ? Если в ini задан Trigger - то общий, иначе с клиента, что то типа leto_SetTrigger(...)

SergKis: alkresin пишет:Вроде работают теперь триггеры туплю в SIXNSX было:[pre2] /* * USE command with support for TRIGGER and PASSWORD clauses */ #command USE <(db)> [VIA <rdd>] [ALIAS <a>] [<nw: NEW>] ; [<ex: EXCLUSIVE>] [<sh: SHARED>] [<ro: READONLY>] ; [CODEPAGE <cp>] [INDEX <(index1)> [, <(indexN)>]] ; [TRIGGER <trig>] [PASSWORD <pass>] => ; [Sx_SetTrigger( TRIGGER_PENDING, <trig>, <rdd> ); ] <-trig-> ; [Sx_SetPass( <pass>, 1, <rdd> ); ] <-pass-> ; dbUseArea( <.nw.>, <rdd>, <(db)>, <(a)>, ; if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.> [, <cp>] ) ; [; dbSetIndex( <(index1)> )] ; [; dbSetIndex( <(indexN)> )] [/pre2] как ставить ? sele 0 HB_RddInfo( RDDI_PENDINGTRIGGER, 'my_Trigger', 'LETO' ) или HB_RddInfo( RDDI_PENDINGTRIGGER, 'my_Trigger', 'DBFCDX' ) dbUseArea(.F., 'LETO', ...) разъясните, пожалуйста и в чем разница RDDI_PENDINGTRIGGER и RDDI_TRIGGER ?

alkresin: SergKis пишет: Триггер(ы) определен(ы) ТОЛЬКО на сервере в letoudf.hrb, но активировать (нужный) триггер для нужной таблицы - с клиента, я это имел ввиду говоря "с клиента" Насколько я понимаю предназначение триггеров, они должны работать всегда, независимо от того, активирует их или нет клиентская программа. Если вы ставите, например, триггер на добавление записи в table1 - чтобы при этом и в table2 что-то добавлялось, а в table3, например, увеличивался счетчик - то важно, чтобы это работало всегда, иначе пострадает целостность базы данных. Обеспечение целостности данных, целостности связей между таблицами, как я понимаю, одна из важнейших задач триггеров. как ставить ? sele 0 HB_RddInfo( RDDI_PENDINGTRIGGER, 'my_Trigger', 'LETO' ) или HB_RddInfo( RDDI_PENDINGTRIGGER, 'my_Trigger', 'DBFCDX' ) dbUseArea(.F., 'LETO', ...) О чем это вы ? Имя процедуры ведь на сервере в letodb.ini указывается. и в чем разница RDDI_PENDINGTRIGGER и RDDI_TRIGGER ? Честно говоря, понятия не имею.

SergKis: alkresin пишет:О чем это вы ? Имя процедуры ведь на сервере в letodb.ini указывается. Не увидел в текстах, где установка, потому и непонятка возникла, если как было через ini, то пошел пробовать. Спасибо.

alkresin: По поводу RDDI_PENDINGTRIGGER. Он используется в dbf1.c следующим образом: [pre2] if( SELF_RDDINFO( SELF_RDDNODE( &pArea->area ), RDDI_PENDINGTRIGGER, pOpenInfo->ulConnection, pItem ) == HB_SUCCESS ) { if( HB_IS_STRING( pItem ) ) hb_dbfTriggerSet( pArea, pItem ); } if( ! pArea->fTrigger ) { if( SELF_RDDINFO( SELF_RDDNODE( &pArea->area ), RDDI_TRIGGER, pOpenInfo->ulConnection, pItem ) == HB_SUCCESS ) { if( HB_IS_STRING( pItem ) ) hb_dbfTriggerSet( pArea, pItem ); } } [/pre2] Т.е., при открытии таблицы сначала устанавливается он, а затем, если его не удалось установить (а это может произойти, если соответствующая функция не найдена), RDDI_TRIGGER. Мне не очень понятно, зачем это может понадобиться.

SergKis: alkresin Спасибо

finder: Возникла пара вопросов после крайнего обновления. Увидел что добавилась функция Udf_Exit() Если я правильно понимаю: Udf_Init() - вызывается как при запуске сервера так и при загрузке letoudf.hrb Udf_Exit() - вызывается только при остановке сервера, но не при выгрузке letoudf.hrb Есть ли возможность добавить, что-то типа Udf_Unload() - которая будет вызываться при выгрузке letoudf.hrb когда идет команда reload.

nbatocanin: Я тестирую Leto_*Transaction: USE (cPath + "Artikli1") ALIAS Artikli1 SHARED NEW VIA "LETO" USE (cPath + "Artikli2") ALIAS Artikli2 SHARED NEW VIA "LETO" FLock () SELECT Artikli1 Leto_BeginTransaction () GO TOP WHILE !Eof() Artikli2->(DBAppend()) Artikli2->a_naziv := Upper(a_naziv) Artikli2->a_naziv2 := Lower(a_naziv2) Artikli2->a_por := a_por + "ABC" ... SKIP END DO Leto_CommitTransaction () Эта программа работает 73 секунд. Без Begin/EndTransaction работает 15 секунд. Почему это так, и может ли это быть ускорено? Спасибо, Ненад

Dima: nbatocanin Давно я работал с LETO но попробуйте Leto_CommitTransaction () поставить до SKIP а Leto_BeginTransaction () перед Artikli2->(DBAppend())

nbatocanin: Dima пишет: Давно я работал с LETO но попробуйте Leto_CommitTransaction () поставить до SKIP а Leto_BeginTransaction () перед Artikli2->(DBAppend()) Я пробовал, когда это сделать получается 790 секунд :(

Andrey: nbatocanin пишет: Я пробовал, когда это сделать получается 790 секунд :( Попробуйте тесты, которые я сделал и проверял. - https://cloud.mail.ru/public/Lr52/WR9soGyFn TEST_DBF.hbp - терминалка сделанная SergKis. Закачивает базу на сервер супер быстро. Сборка под МиниГуи для терминалки. DbftoServer.hbp - загрузка dbf на сервер. Сборка под МиниГуи. Задание вручную параметров размера буфера транзакций.

Pasha: nbatocanin пишет: Эта программа работает 73 секунд. Без Begin/EndTransaction работает 15 секунд. Почему это так, и может ли это быть ускорено? Спасибо, Ненад Если транзакция большая, то желательно задать параметр для Leto_BeginTransaction([ nBlockLen ]) Это размер памяти в байтах для выделения и перевыделения памяти. Попробуйте задать этот параметр равным 16k, или больше Можно разбить большую транзакцию на несколько маленьких, по количеству добавляемых записей.

digikv: Почему leto_directory бы не вернуться имена каталога на сервере LetoDB? У меня есть 3 каталоги на сервере LetoDB но пример вернуться только один файл (test2.txt) #include "rddleto.ch" Function Main( cPath ) Local lRes, cBuf, arr, i REQUEST LETO RDDSETDEFAULT( "LETO" ) IF Empty( cPath ) cPath := "//127.0.0.1:2812/" ELSE cPath := "//" + cPath + Iif( Right(cPath,1) $ "/\", "", "/" ) ENDIF ? "Connect to " + cPath + " - " IF ( leto_Connect( cPath ) ) == -1 nRes := leto_Connect_Err() IF nRes == LETO_ERR_LOGIN ?? "Login failed" ELSEIF nRes == LETO_ERR_RECV ?? "Recv Error" ELSEIF nRes == LETO_ERR_SEND ?? "Send Error" ELSE ?? "No connection" ENDIF Return Nil ELSE ?? "Ok" ENDIF ? ? 'leto_file( "test1.txt" ) - ' ?? Iif( leto_file( cPath + "test1.txt" ), "Ok", "No" ) ? 'leto_memowrite( "test1.txt", "A test N1" ) - ' ?? Iif( leto_memowrite( cPath + "test1.txt", "A test N1" ), "Ok", "Failure" ) ? 'leto_file( "test1.txt" ) - ' ?? Iif( leto_file( cPath + "test1.txt" ), "Ok", "No" ) ? 'leto_memoread( "test1.txt" ) - ' ?? leto_memoread( cPath + "test1.txt" ) ? 'leto_frename( "test1.txt","test2.txt" ) - ' ?? Iif( leto_frename( cPath + "test1.txt","test2.txt" ) == 0, "Ok", "Failure" ) ? 'leto_file( "test1.txt" ) - ' ?? Iif( leto_file( cPath + "test1.txt" ), "Ok", "No" ) ? 'leto_file( "test2.txt" ) - ' ?? Iif( leto_file( cPath + "test2.txt" ), "Ok", "No" ) ? 'leto_fileread( "test2.txt", 7, 2 ) - ' ?? Iif( leto_fileread( cPath + "test2.txt", 7, 2, @cBuf ) > 0, cBuf, "Failure" ) ? 'leto_filewrite( "test2.txt", 7, "N2" ) - ' ?? Iif( leto_filewrite( cPath + "test2.txt", 7, "N2" ), "Ok", "Failure" ) ? 'leto_memoread( "test2.txt" ) - ' ?? leto_memoread( cPath + "test2.txt" ) ? 'leto_filesize( "test2.txt" ) - ' ?? leto_filesize( cPath + "test2.txt" ) arr := leto_directory( cPath ) ? 'leto_directory(): (' + Ltrim(Str(Len(arr))) + ")" ? "Press any key to continue..." Inkey(0) FOR i := 1 TO Len( arr ) ? arr[i,1] NEXT ? "----------" ? 'leto_ferase( "test2.txt" ) - ' ?? Iif( leto_fErase( cPath + "test2.txt" ) == 0, "Ok", "Failure" ) ? ? "Press any key to finish..." Inkey(0) Return Nil

Pasha: Добавьте при вызове функции 2-й параметр: arr := leto_directory( cPath, "D" ) и массив arr будет включать и имена каталогов.

digikv: спасибо! но опять некоторое время возвращает пустую строку, когда вы запустите программу снова это хорошо

Pasha: Дайте пожалуйста пример

nbatocanin: Pasha пишет: Pasha пишет: Если транзакция большая, то желательно задать параметр для Leto_BeginTransaction([ nBlockLen ]) Это размер памяти в байтах для выделения и перевыделения памяти. Попробуйте задать этот параметр равным 16k, или больше Можно разбить большую транзакцию на несколько маленьких, по количеству добавляемых записей. Извините за задержку. Я пытался изменить этот параметр, и получил небольшое улучшение (69 секунд). Менся здесь действительно не нужно транзакции, я просто хочу, чтобы ускорить группа REPLACE команды. Я думал, что транзакции это сделать.

nbatocanin: Andrey пишет: Попробуйте тесты, которые я сделал и проверял. - https://cloud.mail.ru/public/Lr52/WR9soGyFn TEST_DBF.hbp - терминалка сделанная SergKis. Закачивает базу на сервер супер быстро. Сборка под МиниГуи для терминалки. DbftoServer.hbp - загрузка dbf на сервер. Сборка под МиниГуи. Задание вручную параметров размера буфера транзакций. Очень интересные и полезные примеры! Спасибо!

nbatocanin: У меня есть проблемы с одной программе (Win 2003 Server, XP станций). 4-5 раза в день распространенная ошибка: Application Internal Error - G:\Firma\App.exe Terminated at: 2015.05.12 12:41:40 Unrecoverable error 6005: Exception error: Exception Code:C0000005 Exception Address:00417CEB EAX:00000001 EBX:01D21768 ECX:01440407 EDX:00000068 ESI:0022ED7C EDI:00000000 EBP:00000001 CS:EIP:001B:00417CEB SS:ESP:0023:0022ED40 DS:0023 ES:0023 FS:003B GS:0000 Flags:00010246 CS:EIP: 8B 5F 04 89 34 24 89 5C 24 04 E8 AE 23 34 00 85 SS:ESP: 01440468 0022ED54 00000000 4020063C 00001FFD 01D30CE8 00000000 00000000 01443848 00000000 0022EE1C 004A1A5C 0089B98D 00762F80 0024BC70 00000068 C stack: EIP: EBP: Frame: OldEBP, RetAddr, Params... Modules: 0x00400000 0x00A96000 G:\Firma\App.exe 0x7C900000 0x000B2000 C:\WINDOWS\system32\ntdll.dll 0x7C800000 0x000F6000 C:\WINDOWS\system32\kernel32.dll 0x77DD0000 0x0009B000 C:\WINDOWS\system32\ADVAPI32.DLL 0x77E70000 0x00093000 C:\WINDOWS\system32\RPCRT4.dll 0x77FE0000 0x00011000 C:\WINDOWS\system32\Secur32.dll 0x763B0000 0x00049000 C:\WINDOWS\system32\COMDLG32.DLL 0x5D090000 0x0009A000 C:\WINDOWS\system32\COMCTL32.dll 0x77F10000 0x00049000 C:\WINDOWS\system32\GDI32.dll 0x7E410000 0x00091000 C:\WINDOWS\system32\USER32.dll 0x7C9C0000 0x00818000 C:\WINDOWS\system32\SHELL32.dll 0x77C10000 0x00058000 C:\WINDOWS\system32\msvcrt.dll 0x77F60000 0x00077000 C:\WINDOWS\system32\SHLWAPI.dll 0x774E0000 0x0013E000 C:\WINDOWS\system32\OLE32.dll 0x77120000 0x0008B000 C:\WINDOWS\system32\OLEAUT32.DLL 0x77C00000 0x00008000 C:\WINDOWS\system32\VERSION.dll 0x73000000 0x00026000 C:\WINDOWS\system32\WINSPOOL.DRV 0x71AB0000 0x00017000 C:\WINDOWS\system32\WS2_32.dll 0x71AA0000 0x00008000 C:\WINDOWS\system32\WS2HELP.dll 0x76390000 0x0001D000 C:\WINDOWS\system32\IMM32.DLL 0x773D0000 0x00103000 C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.6028_x-ww_61e65202\comctl32.dll 0x71A50000 0x0003F000 C:\WINDOWS\system32\mswsock.dll 0x662B0000 0x00058000 C:\WINDOWS\system32\hnetcfg.dll 0x71A90000 0x00008000 C:\WINDOWS\System32\wshtcpip.dll 0x5AD70000 0x00038000 C:\WINDOWS\system32\uxtheme.dll 0x74720000 0x0004C000 C:\WINDOWS\system32\MSCTF.dll 0x755C0000 0x0002E000 C:\WINDOWS\system32\msctfime.ime 0x01870000 0x002C5000 C:\WINDOWS\system32\xpsp2res.dll 0x76360000 0x00010000 C:\WINDOWS\system32\WINSTA.dll 0x5B860000 0x00055000 C:\WINDOWS\system32\NETAPI32.dll Called from DBSEEK(0) Called from KARZAT(0) in KAR.PRG Called from MAIN(0) in app.prg Ошибка не всегда то же самое, но это всегда связано с такими командами, как DbSeek, Skip.... Идентичные программа работает нормально, когда не используется Letodb.

alkresin: nbatocanin пишет: У меня есть проблемы с одной программе А другие программы, использующие LetoDB, работают нормально ? Может, что-то не так в сборке программы ( rddleto, например, собранная другой версией С компилятора ). У меня много разных программ работают с LetoDb, но такого не припомню. Сервер, бывает, слетает иногда, а клиент по internel error - нет.

nbatocanin: Только что проверил: это происходит в других программах (нет на одном сервере!), но не так часто (раз в десять дней). Я использую HB 3.2 и minGW компилятор. Программа очень большая (12.5MB). Я заметил, что в варианты Share_Tables = 1 есть некоторые проблемы, которые не появляются, если использует Share_Tables = 0. Теперь я использую Share_Tables = 0, программа работает хорошо, но, возможно, потому происходят 6005 ошибки. Рассмотрим это в деталях. Спасибо, Ненад

Dima: nbatocanin Это все ГУГЛ Переводчик переводил ?

nbatocanin: Dima пишет: Это все ГУГЛ Переводчик переводил ? Нет :) Я использую Google, но исправляю перевод, когда вижу что он не хорошый. Я надеюсь что вы понимаете меня?

Andrey: Всем привет. Не собирается новая версия сервера под linux. Не хватает библиотек. Вот мне сделали правку Makefile.linux - поменяйте его в исходниках. https://cloud.mail.ru/public/8Qkf/XWfgwimZJ И еще дали отдельный файл сборки для LetoUdf.prg под linux https://cloud.mail.ru/public/4VDz/zfDHwPDnC Протестировал свой тест (приводил ранее https://cloud.mail.ru/public/9Cjp/YmqHq2msj ) под linux - CentOS release 6.5 (Final), работает великолепно !!!

Pasha: В makefile.linux добавлена библиотека hbct. Для сборки сервера она не нужна. Она нужна при использовании функций вроде lton, ну так это уже неформат. Мало ли какие нестандартные библиотеки используются. В стандартный скрипт ее добавлять незачем. Еще зачем-то добавлена библиотека hbpcre. Вообще сервер лучше собирать с помощью hbmk2. makefile.linux это архаизм, сохранился с тех времен, когда letodb.hbp еще не было. Что касается letoudf.linux, то добавлять его, чтобы продемонстрировать опцию -gh, которая для сборки hrb подразумевается сама собой, тоже вроде бы незачем.

Andrey: Pasha пишет: В стандартный скрипт ее добавлять незачем Понятно...

Pasha: CVS не пашет ? 2-й день хочу загрузить кое-какие обновления, и... облом

SergKis: У меня тоже.

Pasha: На сайте sf глухо, поиск не дает результатов. Может кто знает, кому жаловаться ? Писать в спортлото ?

Pasha: Судя этой по статистике: http://sourceforge.net/projects/letodb/files/stats/timeline загрузки с CVS есть, и сегодня, и во вторник-среду. А у меня CVS не работает, ни через :ext:myname, ни через :pserver:anonymous. Пробовал с разных компьютеров. Так есть доступ к CVS или нет ? Кто может подтвердить ?

PSP: Pasha пишет: Так есть доступ к CVS или нет ? Кто может подтвердить ? Если я использовал правильную команду, то нет:

Pasha: https://www.youtube.com/watch?v=4SCrZ6bEqAc

nbatocanin: Я нашел серьезную ошибку в версии 2.16.b1: USE Test INDEX test NEW SET ORDER TO GO TOP ? IndexOrd() // 1 !!!!

SergKis: nbatocanin LetoUdf.prg [pre2] FUNCTION UDF_Init /* * This function called immediately after loading letoudf.hrb, if exist */ SET AUTORDER TO 1 RETURN Nil ... [/pre2]

Pasha: Я нашел серьезную ошибку в версии 2.16.b1: USE Test INDEX test NEW SET ORDER TO GO TOP ? IndexOrd() // 1 !!!! Я не могу воспроизвести эту ошибку. В моем тесте выдается результат 0, как и должно быть

nbatocanin: Это тест программа: REQUEST LETO PROC Main RddSetDefault ("LETO") cPath := "//192.168.99.10:2807/Test/" Leto_Connect (cPath) ? LETO_GETSERVERVERSION() USE (cPath + "ProTip") NEW SET INDEX To (cPath + "ProTip") GO TOP ? "ORDER", IndexOrd() SET ORDER TO GO TOP ? "SET ORDER TO", IndexOrd() RETURN При использовании v2.15: Leto DB Server v.2.15 ORDER 1 SET ORDER TO 0 А при использовании версии 2.16b1 Leto DB Server v.2.16b1 ORDER 1 SET ORDER TO 1

nbatocanin: Пожалуйста, попробуйте этот тест программ. Версия 2.16 не работает правильно. Я использую DBFNTX индексов. https://drive.google.com/file/d/0BwEGIJ1QfjrKN0FOTXJ0MHFpSUE/view?usp=sharing Server: Leto DB Server v.2.15b2 Client: 2.15b2 ORDER: 1 SET ORDER TO 1: 1 SET ORDER TO : 0 SET ORDER TO 0: 0 Server: Leto DB Server v.2.16b1 Client: 2.16b1 ORDER: 1 SET ORDER TO 1: 1 SET ORDER TO : 1 SET ORDER TO 0: 1 Спасибо, Ненад

nbatocanin: Приложение: при изменении клиента, все работает правильно. Кажется чтобы быть ошибка в клиенте 2.16: Server: Leto DB Server v.2.16b1 Client: 2.15b2 ORDER: 1 SET ORDER TO 1: 1 SET ORDER TO : 0 SET ORDER TO 0: 0

Pasha: После последнего обновления команда set order to работает правильно ? Версия клиента 2.17

nbatocanin: Работает, спасибо большое!!

nbatocanin: Тестирование Leto_Zip. Файлы находятся в base\data\101. Когда я создаю Arhiva.zip, каждый файл в каталоге base\data\101. Есть ли можно сделать Arhiva.zip только с файлами? Ненад

nbatocanin: Я не хорошо объясняется. Я хотел сказать, что каждый файл формата: base/data/101/f001.dbf base/data/101/f002.dbf base/data/101/f003.dbf ... и я хочу, чтобы быть: f001.dbf f002.dbf f003.dbf ...

nbatocanin: Я думаю, что есть ошибка в Leto_FileRead. При запуске этой программы: nLen := Leto_FileSize (cFile) cBuf := Space(nLen) n := Leto_FileRead (cFile, 0, nLen, @cBuf) получает сообщение об ошибке: Unrecoverable error 6005: Exception error: Это происходит только на некоторых файлов! Например, попробуйте этот файл: https://drive.google.com/file/d/0BwEGIJ1QfjrKYk1aQk9SVXZlYWs/view?usp=sharing Если он читает меньше, чем nLen, все работает как надо: nLen := Leto_FileSize (cFile) cBuf := Space(nLen) n := Leto_FileRead (cFile, 0, nLen-1, @cBuf)

nbatocanin: Может кто-нибудь проверить это? В настоящее время это не возможно, чтобы скопировать файлы с сервера к клиенту. Я пытался использовать Leto_MemoRead, но это не будет работать, если большой файл. спасибо, Ненад

Andrey: nbatocanin пишет: Я пытался использовать Leto_MemoRead, но это не будет работать, если большой файл. Делай частями. Размер части (буфер обмена) опредили методом проб и ошибок: 32Кб, 64КбБ 1.2Мб и так далее. Как программа начнёт вылетать, так и используй буфер до вылета. Сам еще не пробовал.

nbatocanin: Если вы думаете о функции Leto_FileRead(), я уже пробовал это. Независимо от параметров Leto_FileRead не работает всегда правильно. В некоторых случаях работает, но, очевидно, есть ошибка.

PSP: nbatocanin пишет: Может кто-нибудь проверить это? Да, у меня так же.

Pasha: Попробуйте после сегодняшнего обновления

nbatocanin: Первоначальные тесты - работает.



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