Форум » 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

AlexMyr: Все собралось нормально, спасибо. Собрал manage и вот что получилось (поле номера порта)

Pasha: Что-то изменилось в hwgui Какой hwgui используется при сборке ?

AlexMyr: hwgui * $Id: Changelog 1623 2011-04-02 07:34:40Z druzus $


SergejKis: Продолжу тему, чего еще не хватает в letodb, на мой взгляд (после опыта перевода одной задачи с sql): 1.Если рассматривать cGroupName, как таблицы в памяти, то требуется еще наличие функции на клиенте (возможно и на сервере) LETO_VARGETGROUP() --> aList Функция на клиенте LETO_VARGETLIST( [cGroupName [, nMaxLen]] ), наверно, тоже должна иметь вид: LETO_VARGETLIST( [cGroupName [, nMaxLen][, lValue]] ). 2.Оператора INSERTUPDATE. В рамках существующей транзакции это могло бы выглядеть так: leto_BeginTransaction() sele AAA dbAppend() Replace ... sele BBB leto_Insert(cKeyValueSeek1) Replace .... sele CCC leto_Insert(cKeyValueSeek2) Replace .... leto_CommitTransaction() т.е. leto_Insert(...) должна в буфер транзакции записать инструкцию на выполнение типа: IF dbSeek(...) DoRlock(...) ELSE dbAppend() ENDIF По хорошему, ключ поиска, можно было бы не задавать (IndexKey(0) серверу и так известен), но это не принципиально ... Так как транзакции на сервере выполняются последовательно (если я правильно понимаю), то проблем с конфликтом dbRLock() не должно быть. 3.Функции leto_LockTable({cT1, cT2, ...}[, nCountTimeout]) и leto_UnLockTable([{cT1, cT2, ...}]), выполняющиеся сервером. nCountTimeout - кол-во циклов ожидания как в DoRLock( n ) Возможно я много хочу ..., но я совершенно отвык писать с использованием dbRLock(), dbUnLock() и считайте что я стал фанатом транзакций.

Pasha: SergejKis пишет: 1.Если рассматривать cGroupName, как таблицы в памяти, то требуется еще наличие функции на клиенте (возможно и на сервере) LETO_VARGETGROUP() --> aList Функция на клиенте LETO_VARGETLIST( [cGroupName [, nMaxLen]] ), наверно, тоже должна иметь вид: LETO_VARGETLIST( [cGroupName [, nMaxLen][, lValue]] ). LETO_VARGETLIST так и работает. Если название группы опущено, то возвращается список групп. Если задано - список переменных этой группы. По поводу таблиц в памяти. Харбор поддерживает нативные таблицы в памяти - см. contrib/hbmemio. Тогда уж лучше поднять их поддержку в letodb, чтобы не использовать суррогатное решение с переменными памяти.

AlexMyr: По поводу хотелок, хотелось бы вести лог подключений к серверу, можно опционально через letodb.ini log_connect = 0, типа: login ip (name) date time logout ip (name) date time ... Вот

SergejKis: Это МЕЧТА !!! Но действительность заставляет крутится. Я же с sql на letodb ... LETO_VARGETLIST() действительно возвращает список групп, я же проверял - это меня занесло ... А что по поводу на клиенте LETO_VARGETLIST( [cGroupName [, nMaxLen][, lValue]] ) - возвращать на группу (как на сервере) массив переменных со значениями при lValue = .T. ?

SergejKis: По поводу, суррогатного решения с переменными памяти, попробую обяснить. В sql были триггера, которые вели общую таблицу со списком прикладных таблиц и значением TimeStamp модификации, т.е. любое изменение в прикладной таблице вызывало изменение TimeStamp в общей таблице. Клиент сначала делает запрос к общей таблице и получает список изменившихся таблиц и только потом приступает к запросам на изменения из нужных таблиц. Так как алгоритм клиента задачи (при переходе к letodb, т.е. sql клиент остался и может работать) не меняется, то использование переменных letodb для этих целей, я так думаю, не есть криминал. Так же как в sql переменные (таблицы) можно сгруппировать по задачам и общие. Вот как-то так ...

Pasha: Добавил функцию LETO_MAKEDIR Что касается поддержки hb_memio, то сделать это достаточно просто. Надо при создании/открытии таблиц/индексов проверять имя на mem: и в случае успеха не приклеивать к нему префикс cDataPath. Ну и собирать сервер letodb с библиотекой hbmemio Может быть, сделать отдельный флаг при сборке

Pasha: По поводу времени модификации, жаль, что заголовок dbf содержит только дату создания. Иначе можно было бы обойтись запросом dbInfo( DBI_LASTUPDATE )

Pasha: SergejKis пишет: А что по поводу на клиенте LETO_VARGETLIST( [cGroupName [, nMaxLen][, lValue]] ) - возвращать на группу (как на сервере) массив переменных со значениями при lValue = .T. ? Так эта функция изначально так и работает, если задать параметр nMaxLen: LETO_VARGETLIST( cGroupName , 100 ) вернет двумерный массив со значениями переменных. А nMaxLen Александр наверное ввел, чтобы ограничить обьем передаваемых данных.

SergejKis: Паша, большое спасибо за разъяснения - не понял правильно идею второго параметра в leto_VarGetList, а потому и не попробовал. С dbInfo( DBI_LASTUPDATE ) - это очень давно жаль ... А почему бы в letodb не сделать механизм как в MySql, первое поле типа TimeStamp заполнять временем модификации при всех операциях с записью таблицы. Понимая, что такое поле уже может быть использовано в dbf (у пользователей letodb), предлагаю добавить свое имя поля, что-то вроде __LETO_UPD типа C/T. Также можно добавить поле __LETO_ID и после dbAppend() заполнять RecNo(). Т.е. если в структуре такие поля есть их заполнять. Включать такой режим через letodb.ini. hbmemio хотел заняться после перевода задач на letodb (уж очень достало администрирование на чужих PC с чужими администраторами). Но пока со сборкой своего сервера заклинило ... . Похоже на пару-тройку недель с letodb придется все отложить - возникла срочная работа - а жаль ... Паша, я правильно понял, это Max длина имени переменной (letovars.c): #define VARS_ALLOC 10 Если да, то по нынешним временам маловато будет ?!

Pasha: SergejKis пишет: Паша, я правильно понял, это Max длина имени переменной (letovars.c): #define VARS_ALLOC 10 Если да, то по нынешним временам маловато будет ?! VARS_ALLOC предназначен для выделения памяти в группе под LETO_VAR - память выделяется не под одну переменную, а сразу под 10, для оптимизации выделения. Это вообще не ограничение. А nMaxLen задает ограничение для длины строки с именами и значениями переменных группы, которую сервер вернет клиенту. Я б такой, чтобы это ограничение убрать вообще.

SergejKis: Паша, большое спасибо за разъяснения. Хотел еще спросить (посмотрел, что есть по Rdd и не увидел или не нашел похожих функций) есть ли механизм работы с буфером записи в HB ? В VO есть на уровне Rdd: VoDbRecordGet() и VoDbRecordPut(cBuff) читает и пишет всю запись, включая признак удаления. Скорость, при применении, сумасшедшая.

Pasha: В харборе таких функций нет, да и в них нет необходимости. Просто работа с записью изначально так и сделана: Запись считывается при позиционировании на нее в буфер, чтение поля - это просто выборка из буфера, запись поля - это запись в буфер А сам буфер сбрасывается в файл по dbCommit или другим операциям. Оптимизировать можно что-то неоптимальное, а здесь и так все оптимально. Я что-то сомневаюсь, что в VO по-другому. Разве что обращение к полям сделано неоптимально, но этот вряд ли. Ведь VO делался на основе клиппера. А написать такие функции я могу что называется "с колес", прямо сейчас: #include "hbapi.h" #include "hbapirdd.h" HB_FUNC( DBRECORDGET ) { AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); USHORT uiRecLen; PHB_ITEM pItem = hb_itemPutNI( pItem, 0 ); char *pRec; if( pArea && (SELF_INFO( pArea, DBI_GETRECSIZE, pItem ) == SUCCESS) && ( SELF_GETREC( pArea, &pRec ) == SUCCESS ) ) { hb_retclen( pRec, hb_itemGetNI(pItem) ); } hb_itemRelease( pItem ); } HB_FUNC( DBRECORDPUT ) { AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); PHB_ITEM pItem = hb_itemPutNI( pItem, 0 ); if( pArea && ISCHAR(1) && (SELF_INFO( pArea, DBI_GETRECSIZE, pItem ) == SUCCESS) && hb_parclen(1) >= hb_itemGetNI(pItem) ) { SELF_PUTREC( pArea, hb_parc(1) ); } hb_itemRelease( pItem ); } Извини, не проверял (с) к/ф Брат Но я сомневаюсь, что скорость при их использовании существенно увеличится. Оптимизируется только преобразование части строки в ITEM, а это некритичная операция

Pasha: Я наверное добавлю в letodb установку серверных триггеров с клиента, т.е. поддержку dbInfo( DBI_TRIGGER, <cProcName> )

leo: Заканчиваю переводить первое приложение на Letodb. Большое спасибо Паше за то, что прояснил многие вещи. Два вопроса к тем, кто уже давно работает с Letodb. 1) Не получилось показать процесс индексации файлов так как это было раньше. У кого-то это получается? Если да подскажите как вы это сделали. 2) Кто-то реализовал работу с семафорами в Letodb И если да нельзя ли поделиться результатами работы. Очень не хочется быть в очередной раз изобретателем велосипеда.

Pasha: leo пишет: 1) Не получилось показать процесс индексации файлов так как это было раньше. У кого-то это получается? Если да подскажите как вы это сделали. Сейчас это невозможно. Индексация происходит так: клиент посылает запрос серверу на создание индекса, и ждет ответа. Как только индекс создан, приходит ответ. Опции EVAL, EVERY в команде INDEX не поддерживаются. Чтобы это сделать, необходимо, чтобы сервер в процессе индексации посылал клиенту каждые EVERY записей сообщение, и (наверное) ждал от клиента квитанции о его получении. На мой взгляд, это излишне. Я не говорю, что это невозможно, и не буду возражать, если кто-то это сделает, но сам делать не буду.

SergejKis: leo пишет: 2) Кто-то реализовал работу с семафорами в Letodb И если да нельзя ли поделиться результатами работы. Очень не хочется быть в очередной раз изобретателем велосипеда. От семафоров сам очень давно отказаля, а для реализации в letodb используйте механизмы работы с переменными leto_var.... По поводу индексации (это мое мнение), если длительная (по времени) делайте в фоне, захватывая таблицу(ы) Exclusive. Для коротких, если очень надо, используйте функции hb_idleadd(...), hb_idledel(...). Подробнее в примерах каталога test.

SergejKis: Паша пишет: Я наверное добавлю в letodb установку серверных триггеров с клиента, т.е. поддержку dbInfo( DBI_TRIGGER, <cProcName> ) Это здорово и очень важно и нужно !!! Но ... Что делать, если на одну таблицу разные кленты будут делать: dbInfo( DBI_TRIGGER, "ProcName_1" ) dbInfo( DBI_TRIGGER, "ProcName_2" ) ... Ведь триггер (мое мнение) это свойство таблицы, не зависящее от клиента. Если бы, в letodb был файл описания таблицы (как sixnsx), то можно было бы в нем: [MAIN] Driver = CDX Trigger = MyTable1 ... [FIELDS] ; структура ... [INDEX] ; индексы/тэги ... А так, наверное, надо устанавливать первый и отшивать остальные по ошибке, возлагая все на разработчика



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