Форум » LetoDB, HbNetio. » Вопрос по реализации сервера » Ответить

Вопрос по реализации сервера

alkresin: Павел, не могли бы вы дать некоторые пояснения по текущей реализации сервера, чтобы мне не выкапывать все подряд из исходников? На каждого пользователя теперь открывается свой поток, так ? А что с таблицами: они, как и прежде, открываются в exclusive mode и используются всеми, или теперь у каждого пользователя свои открытые таблицы ?

Ответов - 15

Pasha: Да, для каждого пользователя создается отдельный поток. Что касается таблиц - то все осталось по-прежнему: они открываются в exclusive-режиме, один раз для всех потоков, при обработке запроса в потоке выполняется request area, затем detach area. Режим Share_Tables также поддерживается.

alkresin: Pasha пишет: Режим Share_Tables также поддерживается Насколько я помню, этот режим отличается от основного только тем, что таблицы открываются в том режиме (shared или exclusive), который запрошен пользователем. А вот No_Save_WA вы не пробовали ? Я его всерьез так и не тестировал. Спрашиваю вот почему. Мне на днях написали, что на большой таблице с большим числом записей в scope очень медленно работает OrdKeyNo() - по сравнению с обычным DBFCDX с файлом, открытым по сети. Думаю, тут дело в том, что нам каждый раз приходится вызывать leto_SetAreaEnv() с последующим leto_ClearAreaEnv() - при этом все внутренние буферы теряются, scope ставятся по новой и по новой пересчитывается положение текущей записи в этом scope. Теоретически мог бы помочь как раз режим No_Save_WA, но для этого, по идее, надо прописать в leto_SetAreaEnv() и leto_ClearAreaEnv() условие, чтобы они выполнялись только при !bNoSaveWA.

Pasha: Мне тоже про это писали, наверное, тот же товарищ. Но я специально для такого случая делал режим буферизации этих команд, который задается настройкой с клиента: RddInfo( RDDI_BUFKEYCOUNT, <lSet>,, [nConnection] ) и RddInfo( RDDI_BUFKEYNO, <lSet>,, [nConnection] ) При этом запросы на сервер не передаются вообще, а значение берется из предыдущей команды. Для всяческих бровсов это должно резко уменьшить число запросов к серверу, и, по факту, если анализировать лог, действительно уменьшает. Но он ответил, что не помогло.


Pasha: Режим No_Save_WA используется только при открытии файла, и при выполнении блокировок. Можно, конечно, еще для него в функциях leto_SetAreaEnv() и leto_ClearAreaEnv() сделать проверку, и, если он используется, вообще ничего не делать. Но я никогда не тестировал этот режим.

alkresin: Pasha пишет: Можно, конечно, еще для него в функциях leto_SetAreaEnv() и leto_ClearAreaEnv() сделать проверку, Там еще кое-что сделать надо - начальную установку фильтра и scope для этого режима. Я сделаю, посмотрим что выйдет.

alkresin: Сделал несколько очевидных поправок, но этот режим (No_Save_WA) пока не работает нормально: при закрытии файла время от времени сервер вылетает напрочь, даже без единого слова. Надо еще смотреть.

Pasha: В функции leto_SetAreaEnv надо вызывать hb_setSetDeleted( bDeleted ) и для режима No_Save_WA. В функции leto_CloseArea надо в любом случае закрывать рабочую область. Но мне кажется, что от этого режима будет мало толку. Узкое место здесь не небольшая разница в скорости обработки запросов на сервере, а сами эти запросы. Да и к тому же в этом режиме приходится открывать файлы в режиме shared, что само по себе плохо влияет на скорость.

alkresin: Pasha пишет: Но мне кажется, что от этого режима будет мало толку. Может быть. Но будет интересно попробовать. Помню, что еще Przemek возмущался тем, как жестко мы обращаемся с workarea - имеется ввиду постоянный сброс ее текущего состояния при передаче в пользование очередному соединению.

alkresin: Сделал еще несколько правок, в первом приближении на простых тестах работает нормально. Хорошо было бы теперь протестировать. Есть у нас готовые тесты ? Возможная польза от этого режима может ощущаться на больших файлах. APPEND BLANK, REPLACE, думаю, в любом случае будут медленнее.

alkresin: Тот товарищ, что жаловался на замедление ordkeyno() и, соответственно, отображения browse, пишет что с No_Save_WA = 1 все стало нормально. Так что подействовало! Там у него обнаружился еще странный эффект. Он пишет, что когда в browse начальные записи выбранного диапазона, все работает быстро, а к концу - заметное замедление. Он убрал кэширование записей - поставил Cache_Records = 1 - и замедление пропало. Наверное, какие-то особенности реализации browse.

alkresin: И еще по поводу No_Save_WA. В основном режиме при любой операции с таблицей осуществляется временный ее захват соответствующим потоком, что эквивалентно блокировке таблицы - т.е., фактически, таблица блокируется при каждой операции с ней, чтения, записи или перемещения ( я ведь правильно понимаю, Павел ? ). При No_Save_WA = 1 этого не происходит, это еще один источник прироста производительности в этом режиме работы в высококонкурентных применениях (т.е. когда много пользователей активно используют одни и те же таблицы).

SergKis: Нет файлов (обработка ошибок): [pre2] DBFCDX 1. нет файла BEGIN SEQUENCE WITH { |e|break( e ) } USE ( "test_new" ) VIA "DBFCDX" New RECOVER USING oError ? oError:genCode,oError:osCode,oError:subCode // 21, 2, 1001 END SEQUENCE 2. в подкаталоге (каталога нет) BEGIN SEQUENCE WITH { |e|break( e ) } USE ( ".\dir\test_new" ) New RECOVER USING oError ? oError:genCode,oError:osCode,oError:subCode // 21, 3, 1001 END SEQUENCE LETO 1. нет файла BEGIN SEQUENCE WITH { |e|break( e ) } USE ( cPath + "test_new" ) New RECOVER USING oError ? oError:genCode,oError:osCode,oError:subCode // 33, 0, 1021 END SEQUENCE 2. в подкаталоге (каталога нет) BEGIN SEQUENCE WITH { |e|break( e ) } USE ( cPath + "dir/test_new" ) New RECOVER USING oError ? oError:genCode,oError:osCode,oError:subCode // 33, 0, 1021 END SEQUENCE [/pre2] Почему такая разница ?

SergKis: alkresin, Pasha SergKis пишет Почему такая разница ? Костыль, на предыдущий пост, в сервере я сделал:[pre2] FUNCTION UDF_TableError ( nUserStru ) AAdd(oAppObj:aError, nUserStru) RETURN oAppObj:aError STATIC FUNCTION oErr2oApp( oErr, cFile, cTag ) LOCAL cDataPath := leto_GetAppOptions(1) If !Empty(oErr) cFile := subs(cFile, len(cDataPath)+1) If ! empty(cTag); cFile += "("+cTag+")" EndIf oAppObj:aError := { oErr:genCode, ; oErr:osCode, ; oErr:subCode, ; iif(Empty(oErr:subSystem ), "", oErr:subSystem ), ; iif(Empty(oErr:description), "", oErr:description), ; cFile, ; ProcName(1) ; } EndIf RETURN Nil [/pre2] сделав вызовы oErr2oApp() в ситуациях If ! lres ... функций hs_opentable, hs_ ... Можно ли получить версию сервера. что бы убрать костыль ? readme_rus.txt LETO_USERADD( "admin", "secret:)", "YYY" ) где "YYY" это строка, которая дает права администрирования, управления и права на запись. Вы можете также использовать программу utils/manager/console.prg, чтобы установить или изменить данные авторизации. Для соединения с сервером с данными авторизации ( именем пользователя и паролем) необходимо вызвать функцию LETO_CONNECT(). Можно ли добавить к YYY значения EnableFileFunc, EnableUDF для соединения ? LETO_USERADD( "admin", "secret:)", "YYY12" ) LETO_USERADD( "direktor", "12345", "YYY00" ) LETO_USERADD( "other", "55555", "YYY01" ) т.е что бы записать и получить для соединения ограничения исполнения серверных функций.

SergKis: PS Использование в UDF функций letoUseArea(...), letoOrdCreate(...), ..., и ситуация RECOVER oError (oError недоступен) в них, не позволяет понять, что происходит в реале. Т.е., получив, nAreaID := letoUseArea(...) равным 0, не ясна причина

SergKis: PS Если сделать возможность обработывать ошибки открытия, то можно добавить:[pre2] STATIC FUNCTION ErrorStr(cSign, oError, cFileName) LOCAL nFlags := 0 IF oError:canDefault nFlags += EF_CANDEFAULT ENDIF IF oError:canRetry nFlags += EF_CANRETRY ENDIF IF oError:canSubstitute nFlags += EF_CANSUBSTITUTE ENDIF If ! ( oError:genCode==EG_OPEN .and. ( oError:osCode==32 .or. ; oError:osCode==3 .or. ; oError:osCode==2 ) ) WrLog( Leto_ErrorMessage( oError ) ) EndIf RETURN cSign ; ... [/pre2] что бы не получать лишних сообщений в log.



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