Форум » 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 на Харборе, ... и вообще все в наших руках :). Кто хочет участвовать в разработке, тестировании - пишите.

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

PSP: Pasha пишет: Транзакции делал Александр. Попробуйте написать ему напрямую Спасибо.

alkresin: Речь о блокировках при работе с транзакциями. Повторю здесь то, что писал Сергею по email. Если при активной транзакции снять блокировку(ки), то она(и) успешно снимаются, не дожидаясь выполнения Leto_CommitTransaction(). При попытке разблокировке записи во время транзакции должна выскочить ошибка "LETO/1031 Syntax Error". По идее-то все действия, производимые с базой после Leto_BeginTransaction(), должны делаться в Leto_CommitTransaction() или я не прав? Не все, а только добавление, удаление, модификация записи. Некоторые операции вообще запрещены во время транзакции, в том числе и снятие блокировки. Кстати, если вызвать Leto_CommitTransaction( .t. ) вот так, с параметром .t., все записи будут по ее окончании разблокированы автоматически. ... Я взял за основу рекомендации из руководства к ADS: File locks and/or record locks must be acquired on data before it can be updated. Once data locks are acquired, they are maintained throughout the entire transaction to ensure that the updates can be made to the database during the commit of the transaction. Record and file locking is best performed before a transaction begins. If an update needs to be made to a record in order to complete the transaction, and the lock operation on that record is attempted during the transaction and is unsuccessful, the corresponding update cannot be performed. The application will most likely need to roll back the transaction. All previous update and insert operations performed prior to the failed data lock will be rolled back due to poor transaction programming. If all explicit data locks are acquired before a transaction begins, unnecessary rollbacks will be prevented. Explicit data locking during a transaction is not recommended, but is supported. Some data locking behavioral differences exist when data locks are performed during a transaction. Review the "Advantage TPS Special Conditions" section if data locking must be done during a transaction. Хотя здесь не запрещается категорически блокировать записи во время транзакции и ничего не говорится про деблокирование, но логика ясна и, мне кажется, разумна: 1. Подготовка транзакции: блокировки, сбор данных для последующей записи; 2. Осуществление транзакции; 3. Деблокировка. Такая последовательность обеспечивает успешное проведение транзакции, практически гарантирует, что она будет вся осуществлена. .... А как вам вот такой вариант ( я давно подумывал о нем, но все руки не доходят, да и практической необходимости не было ): Добавить в Leto_BeginTransaction() параметр, котрый определяет эту транзакцию, как "автоблокировочную" - т.е. все необходимые блокировки делаются сервером при выполнении Leto_CommitTransaction(). Это повышает риск неудачного завершения транзакции, теперь надо обязательно проверять код возврата Leto_CommitTransaction() и повторять ее в случае неудачи, но упрощает подготовку к транзакции и заметно ускоряет ее.

alkresin: Pasha пишет: ... 16-й и 17-й элемент массива будут соответственно дата (Long) и время: целая часть - секунды, дробная часть - миллисекунды после полуночи Если Александр не против, можно это сбросить на CVS Мне кажется, что лучше это сделать отдельной функцией, что-то вроде: HB_FUNC( LETO_MGGETTIME ) { if( pCurrentConn ) { if( leto_DataSendRecv( pCurrentConn, "mgmt;03;\r\n", 0 ) ) { PHB_ITEM temp; PHB_ITEM aInfo; char szData[32]; char * ptr = leto_firstchar(); int i; if( *(ptr-1) == '+' ) { aInfo = hb_itemArrayNew( 2 ); for( i=1; i<=2; i++ ) { if( !leto_getCmdItem( &ptr, szData ) ) { hb_itemReturn( aInfo ); hb_itemRelease( aInfo ); return; } ptr ++; temp = hb_itemPutCL( NULL, szData, strlen(szData) ); hb_itemArrayPut( aInfo, i, temp ); hb_itemRelease( temp ); } hb_itemReturn( aInfo ); hb_itemRelease( aInfo ); } } } } ну и соответственно в letofunc: case '3': { ... Если вы не возражаете, сбросьте на CVS, пожалуйста.


Pasha: Хорошо, сброшу

PSP: alkresin пишет: Я взял за основу рекомендации из руководства к ADS: O'kay, я согласен с этим. Спасибо. :)

PSP: alkresin пишет: А как вам вот такой вариант ( я давно подумывал о нем, но все руки не доходят, да и практической необходимости не было ): Добавить в Leto_BeginTransaction() параметр, котрый определяет эту транзакцию, как "автоблокировочную" - т.е. все необходимые блокировки делаются сервером при выполнении Leto_CommitTransaction(). Это повышает риск неудачного завершения транзакции, теперь надо обязательно проверять код возврата Leto_CommitTransaction() и повторять ее в случае неудачи, но упрощает подготовку к транзакции и заметно ускоряет ее. Ваша идея мне нравится. Единственное, "авторазблокировка" не должна касаться записей, заблокированных до начала транзакции. А повтор транзакции в cлучае неудачи - не проблема, имхо. Проще один раз проверить код возврата Leto_CommitTransaction(), чем проверять при подготовке к транзакции каждый RLock(). Это - мое мнение.

Andrey: Обращаюсь к PSP ! Так как вы разбираетесь с транзакциями, очень прошу (я думаю и другие поддержат) сделать небольшой пример с пояснениями, как нужно правильно делать эти операции... Потратьте чуть-чуть времени для всех нас ...

Dima: Andrey Из NG по ADS Смысл транзакций в Leto DB Server , вероятно тот же , или я вопроса не понял ? :) BEGIN TRANSACTION Определяет начало транзакции ------------------------------------------------------------------------------ Синтаксис BEGIN TRANSACTION Описание Эта команда отмечает начало Advantage TPS-транзакции. Из той точки Вашего приложения, где расположена команда BEGIN TRANSACTION, каждая встреченная команда APPEND или REPLACE, вставленная перед соответс- твующей командой COMMIT TRANSACTION или ROLLBACK TRANSACTION, будет считаться одной транзакцией. Учтите: Текущая рабочая область должна использоваться Advantage RDD для того, чтобы работали Advantage TPS-команды или функции. Если Вы вводите Advantage TPS-команду или функцию не в рабочей области, ис- пользуемой Advantage RDD, Вы получите ошибку 6034 - "Для транзакций требуется рабочая область Advantage" ("Advantage workarea required for transaction"). Как только выполнится команда BEGIN TRANSACTION, любые изменения (REPLACE и APPEND), произведенные с базой данных, будут помещены в журнал транзакций. Другие пользователи, использующие ту же базу дан- ных, не увидят этих изменений до тех пор, пока не завершится транзак- ция. Когда это произойдет, изменения запишутся в базу данных и индек- сы. Например, если Вы в примере, описанном ниже, остановили отладчик на операторе COMMIT TRANSACTION, другие пользователи этих двух баз дан- ных не смогут увидеть результатов команд APPEND и REPLACE пока Вы не пройдете COMMIT TRANSACTION. Для них запись будет содержать первона- чальные значения. Добавление записей не будет видно остальным. В пределах транзакции могут быть произведены изменения только над те- ми таблицами, которые расположены на том же файл-сервере. Пример В этом примере производится блокировка необходимой записи в первой таблице - CUSTOMER.DBF. Если блокировка происходит успешно, начинает- ся транзакция, в пределах которой производятся изменения в двух таб- лицах. После выполнения команд REPLACE, команда COMMIT TRANSACTION физически передает изменения сетевой ОС, которая производит физичес- кую запись данных на жесткий диск. Как упоминалось ранее, код между командами BEGIN TRANSACTION и COMMIT TRANSACTION должен содержать только команды REPLACE и APPEND. В этом случае транзакция точно описана и будет выполнена. Если между коман- дами BEGIN TRANSACTION и COMMIT TRANSACTION присутствует небольшое количество другого кода, то увеличивается вероятность того, что тран- закция завершится с ошибкой и потребуется откат транзакции. // Обеспечим блокировку первой базы данных и добавим необходимые записи SELECT CUSTOMER IF !RLock() Alert( "Невозможно заблокировать запись в CUSTOMER для транзакции" ) RETURN( .F. ) ENDIF // Начало транзакции BEGIN TRANSACTION // Модификация полей в текущей записи из CUSTOMER.DBF SELECT CUSTOMER REPLACE c_lname WITH cLastName REPLACE c_fname WITH cFirstName REPLACE c_add1 WITH cAdd1 REPLACE c_city WITH cCity REPLACE c_state WITH cState REPLACE c_zip WITH cZip // Добавление 2 записей в ORDER.DBF и редактирование // соответствующей информации APPEND BLANK REPLACE o_ordernum WITH cOrderNum REPLACE o_orddate WITH dOrdDate REPLACE o_sales WITH cSalesRep REPLACE o_terms WITH cTerms REPLACE o_amount WITH nAmount REPLACE o_salestax WITH nSalesTac APPEND BLANK REPLACE ol_ordernum WITH cOrderNum REPLACE ol_itemnum WITH cItemNum REPLACE ol_descr WITH cItemDescr REPLACE ol_cost WITH nCost REPLACE ol_numof WITH nNumItems REPLACE ol_subtotal WITH nSubTotal // Завершение транзакции COMMIT TRANSACTION

PSP: В общем-то Dima уже ответил. Добавлю, что для меня возможность использовать транзакции была решающим фактором для использования сервера LetoDB. Транзакция либо выполняется полностью, либо не выполняется вообще. Т.е., если в момент выполнения транзакции (между BeginTransaction и CommitTransaction) с рабочей станцией что-то случилось (вырубилось питание, случилась run-time error и т.п.), сервер не запишет в таблицы ошибочные или неполные данные. Соответственно, таблицы и индексы не повредятся. Это очень удобно в плане целостности данных. Как-то так...

PSP: Pasha пишет: Хорошо, сброшу Еще не сбрасывал?

Pasha: PSP пишет: Еще не сбрасывал? Только что сбросил: 2009-01-30 21:40 UTC+0200 Pavel Tsarenko (tpe2/at/mail.ru) * source/client/letomgmn.c * source/server/letofunc.c * Readme.txt + added LETO_MGGETTIME function. It's return array with server date and time (seconds after midnight): {dDate, nSeconds} Не стал возвращать одну переменную типа DateTime, в харборе функция DateTime() не возвращает миллисеунды, а они, как я понимаю, нужны.

PSP: Pasha пишет: Не стал возвращать одну переменную типа DateTime, в харборе функция DateTime() не возвращает миллисеунды, а они, как я понимаю, нужны. Конечно нужны. Все правильно. Спасибо большое!

Pasha: К слову. Непонятно, почему в харборе(ах) в функции DateTime() обрезаны миллисекунды. Разрядность double позволяел хранить и юлианские дни в целой части, и секунды с миллисекундами в дробной. Вот аналог DateTime() с миллисекундами: #include "hbapi.h" #include "hbdate.h" HB_FUNC( DATETIME2 ) { int iYear, iMonth, iDay, iHour, iMinute; double dSeconds; hb_dateToday( &iYear, &iMonth, &iDay ); dSeconds = hb_dateSeconds( ); iHour = (int) (dSeconds / 3600); iMinute = (int) (dSeconds / 60) - iHour*60; dSeconds -= iHour*3600 + iMinute * 60; hb_retdt( iYear, iMonth, iDay, iHour, iMinute, dSeconds, 0 ); }



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