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

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

alkresin: Только что открыл на Sourceforge новый проект - Leto DB Server - https://sourceforge.net/projects/letodb Это мультиплатформенный ( Windows, Unix/Linux ) сервер баз данных, предоставляющий клиентским программам доступ к dbf/cdx файлам, находящимся на удаленном сервере ( можно и на локальном компьютере запускать - в отладочных целях ). В общем, как ADS :). Проект - на стадии разработки, не все даже базовые функции еще реализованы, до оптимизации дело еще не дошло. Но работает :). Крутится у меня на сервере несколько дней, подключал до 15 клиентов, пока не падает. Мои программы работают с ним нормально. Преимущества по сравнению с обычным файл-сервером: 1) Безопасность - базы могут быть в каталоге, недоступном для клиентских компьютеров - никто их случайно не удалит и не повредит. 2) Поскольку базы открываются серверной программой, а не клиентской, ее целостности ничего не грозит при случайном отключении клиентского компьютера. 3) значительное уменьшение сетевого траффика. 4) Должен быть, по идее, выигрыш в скорости. 5) Возможность контроля за пользователями с помощью утилиты manage ( можно придумать и другие формы контроля ). 6) Можно будет сделать транзакции, stored procedures на Харборе, ... и вообще все в наших руках :). Кто хочет участвовать в разработке, тестировании - пишите.

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

Pasha: Пример udf-функции, которая вызывается с клиента, добавляет запись на сервере, заполняет ключевое поле по индексу cOrder, и возвращает полученную запись: Function Leto_AppKey(nUserStru, cAlias, cOrder) Local cRealAlias := Leto_Alias(nUserStru, cAlias) Local cField, cKey := "", nKey if ! Empty(cRealAlias) dbSelectArea(cRealAlias) OrdSetFocus(cOrder) cField := IndexKey() dbGoBottom() cKey := FieldGet(FieldPos(cField)) nKey := Val(cKey) dbAppend() FieldPut(FieldPos(cField), StrZero(nKey+1, len(cKey)) ) dbCommit() // Еще не реализовано: кроме возврата результата функции, на клиенте еще будет получена текущая запись в рабочей области cAlias //leto_udfrec(nUserStru, cRealAlias) endif Return cKey Какие будут мнения, сомнения, предложения, замечания ?

alkresin: будут ли эти операторы компилироваться старым Harbour ? Какие именно операторы ? Ф-я hb_HrbLoad(() в старом Harbour есть. А вот hbhrb.ch - нет, поэтому у меня оно не компилируется.

alkresin: Обнаружил один неприятный момент - dbusearea() перестала возвращать neterr(), когда это надо, а вместо этого выдает стандартный error. Раньше в letoOpen() ( leto1.c ) стояла проверка кода возврата от сервера, и если это -004, то предпринимались соответствующие действия. Теперь этот код закомментирован и вместо него используется ф-я leto_checkerror(), где эта проверка не производится. Если нет возражений, я сделаю как было.


Pasha: А у функции hb_hrbLoad 2 параметра, nOption и имя файла ? Уберите hbhrb.ch , и поставьте #define HB_HRB_BIND_DEFAULT 0x0

Pasha: alkresin пишет: Если нет возражений, я сделаю как было. Конечно делайте Еще надо заменить hb_retcAdopt на hb_retc_buffer в letofunc.c Этой функции сейчас в Harbour нет

alkresin: Pasha пишет: А у функции hb_hrbLoad 2 параметра, nOption и имя файла ? Нет, только имя файла

Pasha: alkresin пишет: Pasha пишет: цитата: А у функции hb_hrbLoad 2 параметра, nOption и имя файла ? Нет, только имя файла Плохо. У этой функции в разных версиях получаются разные правила вызова. В старом Harbour есть еще функция __hrbLoad, которой нет в новом Можно ли проверить, есть ли символ __hrbLoad, и, если есть, вызывать вместо функции hb_hrbLoad функцию __hrbLoad, но не напрямую, а через макроподстановку ? Вроде: #ifndef __XHARBOUR__ if SYMEXIST("__HRBLOAD") // как проверить ? &("__HrbLoad(0,'letoudf.grb')") else hb_HrbLoad(0, "letoudf.grb") endif #else ...

alkresin: Изначально проблема состоит в том, что в xHarbour и в Harbour 1.0 препроцессор работает не вполне корректно, так ведь ? Тогда можно перенести вызов hb_HrbLoad() на С уровень.

Pasha: Остался вопрос по корректному закрытию сервера при выключении компьютера. Как можно под windows, терминал gtgui, перехватить событие WM_ENDSESSION ? Ведь окно программы не создается. Кстати, при перезагрузке/выключении компьютера функция exit function не вызывается

PSP: А если запускать LetoDB как системную службу?

AlexMyr: PSP пишет: А если запускать LetoDB как системную службу? на 98 винде где она эта служба?

PSP: AlexMyr пишет: на 98 винде где она эта служба? Ну да... Просто я уже забыл про нее... :)

Pasha: Дело не в версии win, а в том, что letodb не служба, и средствами harbour ее сделать как служба сейчас не получится Так что вопрос, где ловить событие, остается

alkresin: Остался вопрос по корректному закрытию сервера при выключении компьютера. Как можно под windows, терминал gtgui, перехватить событие WM_ENDSESSION ? Ведь окно программы не создается. Варианты такие: 1) создать окно для сервера и обрабатывать сообщения, реализовав все это на С уровне без использования харборовских GUI библиотек. В принципе, это очень просто, вопрос в том, как это скажется на производительности - это можно проверить экспериментальным путем. 2) По примеру ранее обсуждавшейся утилиты написать маленькую утилитку с окном, которое будет ловить WM_ENDSESSION и корректно закрывать сервер. Правда, это может и не сработать - а вдруг Windows убьет letodb раньше, чем пошлет сообщение для этой утилиты. 3) Выяснить, есть ли в Windows средства поймать и обработать момент закрытия процесса, не имеющего окна. 1-й представляется наиболее универсальным ( для всех версий Windows ) и простым.

alkresin: To Pasha: По поводу последних изменений: было бы хорошо перенести эти новые элементы, возвращаемые при открытии таблицы в конец - так можно было бы избежать проблем с версиями клиента и сервера.

alkresin: И еще по поводу последних изменений - там закралась какая-то ошибка. Мне прислали вот такой тест: FUNCTION Main REQUEST LETO #include 'inkey.ch' LOCAL cPath := '//127.0.0.1:2812/' rddSetDefault( "LETO" ) CriaDB( cPath ) dbUseArea( .T. , 'LETO', cPath + 'test', 'pa', .F. , .F. , ) dbAppend() REPLACE mercadoria WITH 'teste 1' dbAppend() REPLACE mercadoria WITH 'teste 2' dbAppend() REPLACE mercadoria WITH 'teste 3' dbgotop() obro := tbrowsedb( 05, 1, MaxRow() - 7, MaxCol() - 1 ) ocol01 := tbcolumnnew( "Produto" , { ||pa -> mercadoria } ) obro:addcolumn( ocol01 ) WHILE .T. WHILE ( !obro:stabilize() ) ; ENDDO // msginfo( str(recno())) tecla := Inkey( 0 ) TestaTecla( tecla, obro ) IF tecla = K_ESC EXIT ENDIF ENDDO RETURN Nil FUNCTION CriaDB( cPath ) IF PCount() = 0 dbCreate( "test.dbf", { { "mercadoria","C",30,0 } }, 'DBFCDX' ) ELSE dbCreate( cPath + "test.dbf", { { "mercadoria","C",30,0 } }, 'LETO' ) ENDIF //***************************** FUNCTION TestaTecla( tecla, obj ) //***************************** DO CASE CASE tecla = K_UP ; obj:up() CASE tecla = K_DOWN ; obj:down() CASE tecla = K_LEFT ; obj:Left() CASE tecla = K_CTRL_LEFT ; obj:panleft() CASE tecla = K_RIGHT ; obj:Right() CASE tecla = K_CTRL_RIGHT ; obj:panright() CASE tecla = K_PGUP ; obj:pageup() CASE tecla = K_CTRL_PGUP ; obj:gotop() CASE tecla = K_PGDN ; obj:pagedown() CASE tecla = K_CTRL_PGDN ; obj:gobottom() CASE tecla = K_HOME ; obj:home() CASE tecla = K_CTRL_HOME ; obj:panhome() CASE tecla = K_END ; obj:end() CASE tecla = K_CTRL_END ; obj:panend() CASE tecla = K_MWFORWARD ; obj:up() CASE tecla = K_MWBACKWARD ; obj:down() ENDCASE RETURN nil При прохождении вверх/вниз в browse появляются лишние строки - что-то не то с eof()

Pasha: Я тоже пытался добиться от Itamar M. Lins Jr. Lins пример, но мне это не удалось. Наконец он его дал Баг связан с буферизацией в skip при смене направления перемещения. Поскольку класс tbrowse в harbour и xharbour разный, в первом баг проявляется, а во втором - нет. Вот как он проявляется, если в примере добавлять не 3 записи, а 2: dbUseArea( .T. , 'LETO', cPath + 'test', 'pa', .F. , .F. , ) dbAppend() REPLACE mercadoria WITH 'teste 1' dbAppend() REPLACE mercadoria WITH 'teste 2' dbgotop() Skip 1 // стабилизация tbrowse - идем вниз ? "skip 1", RecNo(), bof(), eof() Skip 1 // стабилизация tbrowse - идем вниз ? "skip 1", RecNo(), bof(), eof() Skip -1 // стабилизация tbrowse - уперлись в eof, возвращаемся ? "skip -1", RecNo(), bof(), eof() Skip -1 // стабилизация tbrowse - уперлись в eof, возвращаемся ? "skip -1", RecNo(), bof(), eof() skip -1 // пользователь нажал K_UP ? "skip -1", RecNo(), bof(), eof() Skip 1 // пользователь нажал K_DOWN ? "skip 1", RecNo(), bof(), eof() // здесь баг: после skip должна быть запись № 2, а остается запись № 1 Skip 1 ? "skip 1", RecNo(), bof(), eof() // дальше - последствия этого бага wait как исправить баг, я пока не увидел.

alx_on: многопоточность Примечание: Для использования таблиц в exclusive режиме приходится использовать hb_rddDetachArea и hb_rddRequestArea (при этом замедление работы одного соединения (в худшем варианте), примерно, 15%) Но (я надеюсь, пока не пробовал) в целом отзывчивость системы на множестве соединений должна быть лучше, чем раньше 0 - главный поток а) как и ранее отрабатывает новые соединения б) часть команд в) для (уже установленных) соединений принимает команды в буфер если есть свободный поток - вызывает ThreadCondUnlock для него 1 - вторичный поток а) только открывает и закрывает таблицы (дабы не городить огород, например, при одновременном открытии в двух потоках одной и той же таблицы) после открытия таблицы hb_rddDetachArea перед закрытием таблицы hb_rddRequestArea б) если есть новая команда (открытия закрытия) - снова отрабатывает если нет - ThreadCondWait 2 и далее (по ядрам или настраиваемо в ini) а) собственно отработка команд (кроме команд для потока 1) перед работой с таблицой hb_rddRequestArea после hb_rddDetachArea (один момент - ожидание другого потока, если таблица уже в работе) б) если есть новая команда - снова отрабатывает если нет - ThreadCondWait Какие замечания к схеме?

Pasha: letodb работал на сервере win2k. Внезапно он перестал запускаться. Причем, до сбоя компьютер не перегружался более месяца, и letodb также работал без останова (видно по логу) больше месяца. Теперь по логу видно, что letodb стартует и сразу же останавливается. Раскопки показали, что завершение происходит на вызове: if( ( hSocketMain = hb_ipServer( iServerPort, NULL, 10 ) ) == ( HB_SOCKET_T ) -1 ) return; Перед return я поставил вызов hb_iperrorcode(), он возвращает код ошибки 0x2736. Где можно глянуть, что это за ошибка ? Почему не выполняется hb_ipServer - совершенно непонятно. Пришлось перенести letodb на другой компьютер с winxp. Но бывший сервер не коннектится с новым сервером, т.е. не работает и как клиент. Это еще не все. В этой же сети есть станция с win98, которая полтора месяца назад вдруг ни с того ни с сего перестала коннектиться с letodb. Я писал об этом. Тогда на ней пришлось переустановить win98. Так вот, теперь эта станция не коннектится с letodb на новом сервере. Повторять переустановку ОС я не стал, пришлось настроить запуск letodb в режиме Share_Tables=1, и с этой станции работать с БД через dbfcdx. Такие вот пироги с котятами. Самое неприятное, что такие сбои происходят неожиданно, после продолжительного периода стабильной работы без единого сбоя Особенность этой сети то, что у сетевушек настроено два ip адреса, вторая подсеть - для доступа в инет. Но изначально letodb работал, работать он прекращает внезапно и навсегда, по неизвестной причине.

Pasha: Ошибку я нашел: #define WSAENOTSOCK (WSABASEERR+38) Вот пишут: http://www.wasm.ru/forum/viewtopic.php?id=18803 Мегажесть :) - оказывается стек, не выровненный на 4 байта при вызове socket вызывает такую лажу Я на такую лажу натыкался c файлами работал)))) Стек приходится по всей программе выравнивать, иначе любая функция винды тожет глюкнуть. Притом происходить это будет через раз, один раз откопмилил не сработала, второй раз откомпилил, пашет. Т.е. ты можешь даже не заметить проблему...



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