Форум » [x]Harbour » Перехожу с Clipper 5.2e на Harbour, список вопросов от "новичка" » Ответить

Перехожу с Clipper 5.2e на Harbour, список вопросов от "новичка"

Sergy: Добрый день, уважаемые коллеги. Большое спасибо за море справочной информации по переходу, но нужно ещё пнуть меня в нужном направлении. Итак, установил Harbour 3.0 + BCC 5.5.1 ==>> 3.2.0 +minGW скомпилировал и запустил традиционный "Hello, world!" Дело перешло к проекту, из-за которого собственно и речь. Компилируется что через hbmk2, что самим харбором - без ошибок, всего с парой предупреждений, что меня немало удивило. Возникли ошибки на этапе линковки: [more]Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: Unresolved external '_HB_FUN_ENVPARAM' referenced from D:\HB\TRADE100.OBJ Error: Unresolved external '_HB_FUN_INKEYTRAP' referenced from D:\HB\TRADE226.OBJ Error: Unresolved external '_HB_FUN_DISKFREE' referenced from D:\HB\TRADE222.OBJ Error: Unresolved external '_HB_FUN_DISKTOTAL' referenced from D:\HB\TRADE222.OBJ Error: Unresolved external '_HB_FUN_BIOSDATE' referenced from D:\HB\TRADE.OBJ Error: Unresolved external '_HB_FUN_FT_ONTICK' referenced from D:\HB\TRADE.OBJ Error: Unresolved external '_HB_FUN_FT_ONIDLE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_FT_IAMIDLE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_TRAPANYKEY' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_KEYSEND' referenced from D:\HB\TRADE200.OBJ 1) Так понимаю, это ошибки из-за того, что не находятся некоторые функции из активно используемых CT3/Nanforum Toolkit ? Что делать с ними ? Отказываться ? Или есть заменители ? Error: Unresolved external '_HB_FUN_STACKFREE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLILOCUSE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLILOCAVL' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLILOCTOT' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLISTCUSE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLISTCAVL' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLISTCTOT' referenced from D:\HB\TRADE200.OBJ 2) Это - ошибки из-за вызовов встроенных в Blinker функций, без них легко обойтись в принципе... Error: Unresolved external '_HB_FUN_STRNUM2ARRAY' referenced from D:\HB\TRADE208.OBJ Error: Unresolved external '_HB_FUN_CMJS_EXTRACTPARAMS' referenced from D:\HB\TRADE206.OBJ Error: Unresolved external '_HB_FUN_SELECTSTOCKS' referenced from D:\HB\TRADE220.OBJ Error: Unresolved external '_HB_FUN_APPLYSERTCHAGES' referenced from D:\HB\TRADE221.OBJ Error: Unresolved external '_HB_FUN_APPLYCARGOCHAGES' referenced from D:\HB\TRADE221.OBJ Error: Unresolved external '_HB_FUN_APPLYPRICECHAGES' referenced from D:\HB\TRADE221.OBJ 3) А вот это - самое странное - это мои функции, причем некоторые из них вызываются многократно из других модулей. Например ApplyCargoChanges является STATIC в самом модуле TRADE221 - почему линковщик ее не видит, наряду с парой Apply... других ? SelectStocks активно используется в других модулях - но там линкер почему-то ошибок не видит... [/more] Help, please - что делать и куды бечь ?

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

Sergy: http://www.hmgforum.com/viewtopic.php?f=5&t=2169 Походу существует какая-то фигня, из-за которой Harbour не ждет и не пытается повторить несколько раз (как Clipper ?) попытку открыть таблицу и индекс... Т.е. попытался один раз - сразу ставим юзера в известность... каким только вот образом ?

Pasha: Sergy пишет: Возникает ошибка: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Вызов из ORDLISTADD(0) Вызов из DBSETINDEX(0) Вызов из OPENMAIL(81) ... Судя по ошибке, dbf открылся, а ntx - нет. Поясняю второй раз. Ошибка возникла при открытии индекса, вызов из dbSetIndex/OrdListAdd. Код ошибки 2001 - это EDBCMD_NOTABLE, т.е вызов из неоткрытой рабочей области. Это означает, что предыдущая команда use была неудачной. Чтобы было понятнее, вот исходник OrdListAdd из сырцов харбора: HB_FUNC( ORDLISTADD ) { AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); // текущая рабочая область if( pArea ) // Проверка, открыта ли рабочая область { // Открытие индекса ... } else // не открыта, возникает ошибка 2001, здесь и только здесь hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, HB_ERR_FUNCNAME ); } Вы меня совсем уж за придурка не держите плиз. больше 15 лет разработки и поддержания именно этой задачи. В сети сидят одновременно 20-30 юзеров работали на Clipper задаче. Но медленно. В EXCLUSIVE открывается локальный файл со справочником, который редко меняется (имена, цены, контрагенты). Целиком берется и целиком сливается. Дальше строится локальный индекс и открывается в ESXCLUSIVE. Первый пример (с mail.dbf) - способ открытия по умолчанию, т.е. SHARED (тк в самом начале программы установка SET EXCLUSIVE OFF). Второй - аналогичная ситуация, но файл - локальный и открывается монопольно. И не может быть открыт никаким другим процессом. Это временная таблица, которая будет стерта при выходе. Поэтому вопрос пока открыт: почему с переходом на Harbour стали возникать ошибки такого рода: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Что мешает вам вставить проверку на neterr после выполнения use ? Сразу все станет на свои места. По вашему коду не видно, в каком режиме открывается mail.dbf. Если не устанавливалось никакого нестандартного обработчика ошибок, то что клиппер, что харбор не будет генерировать исключение только в том случае, когда файл не открыт из-за ошибки доступа к нему. Насчет второго примера, когда открывается локальный файл в режиме exclusive. Возможно, на этом компьютере была запущена вторая копия программы, которая попытается открыть этот файл также монопольно, и возникнет та же ошибка. Я же ваш код не вижу, могу только сказать по логу ошибки, по какой причине она возникла. Третий раз повторять надо или ограничимся ? В теме по ссылке на hmgforum ясно видно, что файл открывается монопольно. И что непонятно ? Что хотели, то и получили. Файл уже открыт другой задачей, и не может быть открыт монопольно. А что это за фантазии насчет того, что клиппер пытается несколько раз открывать файл ?

petr707: Цитата: И не может быть открыт никаким другим процессом Этого (знать наверняка и) утверждать никак невозможно. Есть , например, Google Desktop, который при своей работе может занимать монопольно файлы DBF, NTX и прочие и легко может завалить задачу. Да и зависшие блокировки от операционки бывают да мало ли чего. В терминальном режиме можно потерять сеанс задачи, который будет жить на таблицах самостоятельно.


Sergy: Pasha пишет: Что мешает вам вставить проверку на neterr после выполнения use ? Вот лог ошибки: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Вызов из ORDLISTADD(0) Вызов из DBSETINDEX(0) Вызов из IP_LOAD(734) Вызов из PRINTPRLIST(3715) ... Open Tables: 1. BUYPRICE 2. PRICE 3. RESERV 4. AMOUNT 5. AMIMAGE 6. IPRICEV Вот код, который работает в данном случае: [pre2] area:=SELECT() IF !FileExist(local_dir+"ipricev.dbf") // нет образа локально - загружаем CheckNLoad("ipricev") // копируем с сервера в локальную папку и строим индекс CLOSE ipricev ENDI USE (local_dir+"ipricev") INDEX (local_dir+"ipricev") EXCLUSIVE NEW /// <<< строка 734 IF NETERR() /// сюда уже не попадает, программа завершила работу [/pre2] Получается, что в рабочей области N6 уже открыт dbf, но не открыт индекс... // не открыта, возникает ошибка 2001, здесь и только здесь Мда... нужно будет всерьез задуматься... Тогда каковы причины не открытия *.dbf ? Ведь он окрывается в 9 случаях из 10 нормально. И юзеры рядом работают...

Sergy: Pasha пишет: Возможно, на этом компьютере была запущена вторая копия программы, Это тоже полностью исключено. Открывается в монопольном режиме mem файл с сохраненными переменными. Вторая копия за 15 лет ни разу еще не смогла начать работать в таком режиме. Выдается сообщение пользователю и привет. А что это за фантазии насчет того, что клиппер пытается несколько раз открывать файл ? Х.е. знает - посмотрел по тому примеру, дядька советует вьетнамцу попытаться несколько сек. подождать. Clipper ведь ни разу на этом месте не спотыкался. Вот и подумал...

Dima: Sergy пишет: USE (local_dir+"ipricev") INDEX (local_dir+"ipricev") EXCLUSIVE NEW После того как поюзал эту базу локально , ты ее закрываешь ?

Pasha: В этом фрагменте кода ошибки нет. Но неизвестно, что в остальном коде. Возможно, файл ipricev уже был открыт в момент выдачи команды use в строке 734 Сделайте тест: use ipricev EXCLUSIVE NEW ? Alias(), NetErr() use ipricev EXCLUSIVE NEW ? Alias(), NetErr() Результат будет ожидаем: IPRICEV .T. .F. Если к команде use добавить еще опцию index, то как раз получим желаемый результат: попытка открытия индекса в неоткрытой р.о, и ошибка 2001

Sergy: Dima пишет: После того как поюзал эту базу локально , ты ее закрываешь ? Разумеется. На выходе из каждой процедуры формирования отчета идет CloseAll(), по сути обертка для CLOSE ALL и нескольких внутренних обработок.

Sergy: Pasha пишет: В этом фрагменте кода ошибки нет. Но неизвестно, что в остальном коде. Возможно, файл ipricev уже был открыт в момент выдачи команды use в строке 734 Сделайте тест: use ipricev EXCLUSIVE NEW ? Alias(), NetErr() use ipricev EXCLUSIVE NEW ? Alias(), NetErr() Результат будет ожидаем: IPRICEV .T. .F. Если к команде use добавить еще опцию index, то как раз получим желаемый результат: попытка открытия индекса в неоткрытой р.о, и ошибка 2001 Проблема в том, что на компе с Harbour (где база локальна) я вообще ни разу не смог получить подобные ошибки. Они возникают только в сети после перехода на Harbour. И то через раз - то есть, то нет...

Pasha: Sergy пишет: Тогда каковы причины не открытия *.dbf ? Ведь он окрывается в 9 случаях из 10 нормально. И юзеры рядом работают... Наиболее вероятную причину я назвал. Из текста errorsys видно: // Set NetErr() of there was a database open error IF oError:genCode == EG_OPEN .AND. ; oError:osCode == 32 .AND. ; oError:canDefault NetErr( .T. ) RETURN .F. ENDIF что NetErr( .T. ) устанавливается при ошибке открытия по команде use, когда oError:osCode == 32 32 - это Sharing violation Что такое Sharing violation думаю обьяснять не надо

SergKis: Sergy Еще с Clipper делаю примерно так: [pre2] bOldError := ErrorBlock( { |e|break( e ) } ) BEGIN SEQUENCE dbUseArea( .F., cRdd, cDbf, cAls, lSha ) IF ! Used() DO WHILE s-- >= 0 dbUseArea( .F., cRdd, cDbf, cAls, lSha ) IF Used(); EXIT ENDIF hb_IdleSleep(0.1) ENDDO ENDIF RECOVER USING oError lRet := .F. END SEQUENCE ErrorBlock( bOldError ) [/pre2] практика использования clipper, hb показала, даже на локальной базе, при больших расчетах, простое use не открывает файл handle нет - на это может влиять антивирус (особенно Касперский - это наш опыт). use в цикле - решение проблеммы

PSP: Да, кстати, антивирус - реальная причина.

Dima: SergKis пишет: особенно Касперский - это наш опыт а у меня (вернее у моего клиента) тоже делал NOD32 , сканировал и лочил DBF базы

Pasha: В конце концов, поведение совеременных ОС при открытии файла в ntvdm b в реальном режиме действительно может быть различным. Я встречался с случаями, когда серверные ОС ведут себя неадекватно: файл вроде бы уже создан, а открыть его нельзя. Могут гадить и аетивирусы. И харбор тут ни при чем, и средствами харбора этот вопрос не решить. А решить его можно простыми приемами: Если используется локально временный файл, то создавать его именно как временный, и тогда его можно открывать монопольно. Во всех остальных случаях открывать файл как shared, особенно если он располагается на сетевых ресурсах Ну и вместо последовательности: use ... index ... new использовать use ... if ! neterr() set index to ...

SergKis: Pasha +1 то что use м set index надо разделить во времени - однозначно

Sergy: Pasha пишет: Если используется локально временный файл, то создавать его именно как временный, и тогда его можно открывать монопольно Именно так и сделано. Локальные - монопольно, удаленные - shared. В остальном - мысли разумные и дали пищу для размышлений, спасибо. Поковырялся у себя в errorsys.ch, вот что обнаружил: [pre2] IF (e:genCode == EG_ZERODIV) // По умолчанию деление на ноль дает ноль RETURN (0) ENDI IF (e:SubSystem == 'DBFNTX') .AND. ; // специфика dbfntx & Win2K based servers (e:SubCode == 1035) .AND. ; (e:tries < 25) RETURN (.T.) ENDI IF (e:genCode == EG_LOCK) .AND. e:canDefault // обработка специфич.ошибки ntx в 5.2e RETURN (.F.) ENDI IF (e:genCode == EG_OPEN) .AND. (e:osCode == 32) .AND. e:canDefault // Для ошибки открытия файла в сетевом окружении..установка NETERR() // и значения SUBSYSTEM по умолчанию NetErr(.T.) RETURN (.F.) // NOTE ENDI IF (e:genCode == EG_APPENDLOCK) .AND. e:canDefault // Для ошибки блокировки во время APPEND BLANK..установка NETERR() // и значения SUBSYSTEM по умолчанию NetErr(.T.) RETURN (.F.) // NOTE END [/pre2] Откуда это могло у меня взяться - ума не приложу. То-ли это что-то из базовой поставки Clipper еще с 5.01, то-ли где-то нарыл, возможно с этого форума. У меня просто дописано сохранение сообщений, стека вызовов, открытых алиасов в report.log с последуюущим скидыванием его на сервер, чтобы можно было понять, что происходит у клиентов. Поэтому этот файл еще жив. Вопрос: что из этого лишнее и чего (возможно) не хватает ? там есть некий e:tries - может быть использовать его ?

Andrey: Sergy пишет: Вопрос: что из этого лишнее и чего (возможно) не хватает ? Выкинуть его нафиг и взять из поставки Харбора. Я писал вам, да и все тоже это скажут: Харбор более требователен к синтаксису ! Что есть очень хорошо. Харбор не отвечает за старые ошибки Клипера, он более СТАБИЛЬНЕЙ по работе в сети и локально. НЕ ТАЩИТЕ весь функционал который был на клипере, переделывайте узкие места: открытие/закрытие/блокировки баз !!! Я тоже сначала натыкался на это и злился... После переделок, со временем все становиться прозрачно и понятно !

Pasha: Sergy пишет: IF (e:SubSystem == 'DBFNTX') .AND. ; // специфика dbfntx & Win2K based servers (e:SubCode == 1035) .AND. ; (e:tries < 25) RETURN (.T.) ENDI могу только сказать, что 1035 - это LOCKTIMEOUT

Sergy: Сделал вот так: [pre2] #command USE <(db)> ; [VIA <rdd>] ; [ALIAS <a>] ; [<new: NEW>] ; [<ex: EXCLUSIVE>] ; [<sh: SHARED>] ; [<ro: READONLY>] ; [INDEX <(index1)> [, <(indexn)>]] ; ; => NetUse( ; <.new.>, <rdd>, <(db)>, <(a)>, ; if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.> ; ) ; ; [; IIF(USED(),NetSetIndex( <(index1)> ),NIL)] ; [; IIF(USED(),NetSetIndex( <(indexn)> ),NIL)] // далее: * ----------------------------------------------- * FUNC NetUse(lNew,cRdd,cDb,cAlias,lShared,lReadonly) LOCAL start_time,res,cnt cnt := 0 start_time := SECONDS() REPEAT DBUSEAREA(lNew,cRdd,cDb,cAlias,lShared,lReadonly) res:=USED() IF res EXIT ENDIF cnt++ hb_IdleSleep(0.1) UNTIL (ABS(SECONDS() - start_time) > 1) // не более 1 сек с уч.полуночи IF (cnt > 0) OutReportLog("NetUse("+cDb+") tried to open "+NTRIM(cnt)+" times and "+IIF(res,"OK","FAIL")) ENDIF RETURN res * ------------------- * FUNC NetSetIndex(cName) LOCAL start_time,res,cnt cnt := 0 start_time := SECONDS() REPEAT res:=DBSETINDEX(cName) IF res; EXIT; ENDIF hb_IdleSleep(0.1) cnt++ UNTIL (ABS(SECONDS()-start_time) > 1) // не более 1 сек c уч.перехода полуночи IF (cnt > 0) OutReportLog("NetSetIndex("+cName+") tried to open "+NTRIM(cnt)+" times and "+IIF(res,"OK","FAIL")) ENDIF RETURN res [/pre2] Получил одно вот такое сообщение: 27.08.2013 09:45:46 NetUse(caroute) tried to open 1 times and OK и несколько вот таких: Ошибка DBFNTX/1201 Файл не индексирован Вызов из DBSEEK(0) Вызов из GETNOMINALPRICE(322) Вызов из LOADDATA(148) ... Ошибка DBFNTX/1201 Файл не индексирован Вызов из DBSEEK(0) Вызов из DBVIEW(4752) Вызов из CARMANAGER(515) ... Совершенно точно вчера/позавчера и под Clipper этот код работал. В NetSetIndex() поставил проверку успешности открытия индекса ( res:=DBSETINDEX() ), но почему-то она не сработала ?

Vlad04: Из моего опыта перехода с Clipper на Харбор (это было уже давно- несколько лет назад). Пришлось в местах сохранения данных дописать везде Commit. Clipper и так нормально сохранял .А Харбор без этой команды, по- видимому используя буфер Windows, сбрасывал мусор в базы.



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