SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 01.02.12 20:48
Оценка:
Начал использовать SQLite++ (http://sqlitepp.berlios.de/) в своем проекте, возникло несколько вопросов и предложений по развитию проекта.
1 — Проект еще жив? Последний коммит был в 2007 году.
2 — Можно ли использовать один объект sqlitepp::session из нескольких потоков? Если да, то какие ограничения на такое использование?
3 — Кровь из носу нужна возможность вызывать сишные sqlite функции для объекта sqlitepp::session, например никак невозможно обойтись без sqlite3_busy_timeout, иначе запросы к базе обламываются при параллельном доступе из другого объекта sqlitepp::session.
4 — Нужна возможность указывать флаги при открытии базы, например нужен флаг SQLITE_OPEN_SHAREDCACHE, он ускоряет одновременную работу нескольких сессий БД.

Можно ли все это сделать? И вопрос к автору: если я сам это сделаю, примет ли он патч?
Re: SQLite++ в многопоточном приложении
От: PM  
Дата: 02.02.12 07:00
Оценка:
Здравствуйте, Gorilla, Вы писали:

Отвечал на личное сообещние, может не дошло

G>Начал использовать SQLite++ (http://sqlitepp.berlios.de/) в своем проекте, возникло несколько вопросов и предложений по развитию проекта.

G>1 — Проект еще жив? Последний коммит был в 2007 году.

Эээ, проект есть. Последний коммит в trunk был 6 апреля 2011 г.

G>2 — Можно ли использовать один объект sqlitepp::session из нескольких потоков? Если да, то какие ограничения на такое использование?


Можно, если обеспечить синхронизацию доступа к экземпляру sqlitepp::session, т.к. класс session не потокобезопасен.

G>3 — Кровь из носу нужна возможность вызывать сишные sqlite функции для объекта sqlitepp::session, например никак невозможно обойтись без sqlite3_busy_timeout, иначе запросы к базе обламываются при параллельном доступе из другого объекта sqlitepp::session.


Можно добавить нужные функции в класс sqlitepp::session, или сделать доступным sqlite3* хранящийся в session. Мне кажется первый путь чуть безопаснее и функции session::last_changes(), session::total_changes() были так и добавлены.

G>4 — Нужна возможность указывать флаги при открытии базы, например нужен флаг SQLITE_OPEN_SHAREDCACHE, он ускоряет одновременную работу нескольких сессий БД.


Без проблем — можно добавить параметр для флагов в session::open()

G>Можно ли все это сделать? И вопрос к автору: если я сам это сделаю, примет ли он патч?


Патч приму
Re[2]: SQLite++ в многопоточном приложении
От: cppnick  
Дата: 02.02.12 07:49
Оценка:
Здравствуйте, PM, Вы писали:

PM>Можно добавить нужные функции в класс sqlitepp::session, или сделать доступным sqlite3* хранящийся в session. Мне кажется первый путь чуть безопаснее и функции session::last_changes(), session::total_changes() были так и добавлены.

При нужде не очень хочется менять библиотечные заголовочные файлы, ведь они могут быть перезаписаны при обновлении. Наверное, для таких случаев лучше предоставить явный доступ к экземпляру sqlite3.
Re: SQLite++ в многопоточном приложении
От: nen777w  
Дата: 02.02.12 08:15
Оценка:
Даже не знал про такую штуку.
В свое время написал свою обёртку с datasource, datarow, всякими перегруженными операторами преобразования к интегральным типам и std::s/w string, с поддержкой prepared statment-ов, с поддержкой сессий, и возможностью инжектить самописные extensions (т.е. расширять набор функций SQL). Вот уже год как юзаем, никто пока не жаловался
Re[2]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 02.02.12 08:50
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здравствуйте, Gorilla, Вы писали:


PM>Эээ, проект есть. Последний коммит в trunk был 6 апреля 2011 г.

Cорри, смотрел по дате на главной странице сайта. Раз проект жив, то не помешало бы обновить версию sqlite до 3.7.10 и в солюшене для VC10 прописать x64 конфигурацию.

PM>Можно, если обеспечить синхронизацию доступа к экземпляру sqlitepp::session, т.к. класс session не потокобезопасен.

Тогда сужаю вопрос: конструкция
unsigned long count;
database << "SELECT COUNT(*) FROM table", sqlitepp::into(count);

потокобезопасна? В коде много таких конструкций, очень не хочется здесь городить синхронизацию. Пока без нее все работает.

PM>Можно добавить нужные функции в класс sqlitepp::session, или сделать доступным sqlite3* хранящийся в session. Мне кажется первый путь чуть безопаснее и функции session::last_changes(), session::total_changes() были так и добавлены.

Хорошо бы тогда добавить нужные функции плюс функцию get_impl() для прямого доступа к sqlite3*. Все возможности sqlite сразу не перекроешь, желательно оставлять пользователям библиотеки обходной вариант на свой страх и риск, чтобы не пришлось делать #define private public перед хедером.

PM>Без проблем — можно добавить параметр для флагов в session::open()

Флаги уже не нужны, почитав документацию я нашел функцию sqlite3_enable_shared_cache включающую разделяемый кэш глобально. Мне этого достаточно.

PM>Патч приму

Отлично, в ближайшее время будет.
Re[3]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 02.02.12 09:49
Оценка:
Хотя нет, все-таки флаги оказались нужны.
Re[2]: SQLite++ в многопоточном приложении
От: PM  
Дата: 02.02.12 12:22
Оценка:
Здравствуйте, nen777w, Вы писали:

N>Даже не знал про такую штуку.

N>В свое время написал свою обёртку с datasource, datarow, всякими перегруженными операторами преобразования к интегральным типам и std::s/w string, с поддержкой prepared statment-ов, с поддержкой сессий, и возможностью инжектить самописные extensions (т.е. расширять набор функций SQL). Вот уже год как юзаем, никто пока не жаловался



Я делал эту обертку на идеях из SOCI, которая тогда поддерживала только Oracle. Есть еще одна похожая библиотека, CppDB, использовал ее в одном проекте для работы с MySQL.
Re[3]: SQLite++ в многопоточном приложении
От: PM  
Дата: 02.02.12 12:27
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>Здравствуйте, PM, Вы писали:


PM>>Здравствуйте, Gorilla, Вы писали:


PM>>Эээ, проект есть. Последний коммит в trunk был 6 апреля 2011 г.

G>Cорри, смотрел по дате на главной странице сайта. Раз проект жив, то не помешало бы обновить версию sqlite до 3.7.10 и в солюшене для VC10 прописать x64 конфигурацию.

Это может быть когда-нибудь SQLite можно обновлять по необходимости — достаточно распаковывать файлы из SQLite amalagamation в каталог sqlite и пересобирать библиотеку. В плане поддержки обратной совместимости D. Richard Hipp делает все что можно.

PM>>Можно, если обеспечить синхронизацию доступа к экземпляру sqlitepp::session, т.к. класс session не потокобезопасен.

G>Тогда сужаю вопрос: конструкция
G>
G>unsigned long count;
G>database << "SELECT COUNT(*) FROM table", sqlitepp::into(count);
G>

G>потокобезопасна? В коде много таких конструкций, очень не хочется здесь городить синхронизацию. Пока без нее все работает.

Везет В экземпляре session хранятся 2 вспомогательны переменных — указатель на активную транзакцию и результат последнего вызова sqlite3_step(). Я думаю, если не обращаться к session::active_txn() и всем функциям session::last_*() то все будет в порядке (при условии что экземпляр session живет дольше любого из созданных в нем statement).

PM>>Можно добавить нужные функции в класс sqlitepp::session, или сделать доступным sqlite3* хранящийся в session. Мне кажется первый путь чуть безопаснее и функции session::last_changes(), session::total_changes() были так и добавлены.

G>Хорошо бы тогда добавить нужные функции плюс функцию get_impl() для прямого доступа к sqlite3*. Все возможности sqlite сразу не перекроешь, желательно оставлять пользователям библиотеки обходной вариант на свой страх и риск, чтобы не пришлось делать #define private public перед хедером.

Ок, не вижу проблем добавить пару функций sqlite3* session::impl() const и sqlite3_stmt* statement::impl() const;
Re: SQLite++ в многопоточном приложении
От: PM  
Дата: 02.02.12 12:53
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>3 — Кровь из носу нужна возможность вызывать сишные sqlite функции для объекта sqlitepp::session, например никак невозможно обойтись без sqlite3_busy_timeout, иначе запросы к базе обламываются при параллельном доступе из другого объекта sqlitepp::session.


Закоммитил в trunk:

Revision: 87
Changed SQLite path to the version 3.7.10

Revision: 85
Added session::impl() and statement::impl() functions for SQLite implementation

Re[2]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 02.02.12 20:25
Оценка: 6 (1)
Я еще добавил вот такой патч:


Index: session.cpp
===================================================================
--- session.cpp    (revision 9)
+++ session.cpp    (working copy)
@@ -54,6 +54,14 @@
 {
     open(file_name);
 }
+
+session::session(utf8_string const& file_name, int flags)
+    : impl_(0)
+    , active_txn_(0)
+    , last_exec_(false)
+{
+    open(file_name, flags);
+}
 //----------------------------------------------------------------------------
 
 session::~session()
@@ -82,6 +90,21 @@
         throw exception(err, msg);
     }
 }
+
+void session::open(utf8_string const& file_name, int flags)
+{
+    // close previouse session
+    close();
+
+    int const r = sqlite3_open_v2(file_name.c_str(), &impl_, flags, NULL);
+    if ( r != SQLITE_OK )
+    {
+        string_t const msg( last_error_msg(impl_) );
+        int const err = ::sqlite3_errcode(impl_);
+        close(); // session should be closed anyway
+        throw exception(err, msg);
+    }
+}
 //----------------------------------------------------------------------------
 
 void session::close()
Index: session.hpp
===================================================================
--- session.hpp    (revision 9)
+++ session.hpp    (working copy)
@@ -33,12 +33,14 @@
     
     // Create and open session.
     explicit session(string_t const& file_name);
+    explicit session(utf8_string const& file_name, int flags);
     
     // Close session on destroy.
     ~session();
 
     // Open database session. Previous one will be closed.
     void open(string_t const& file_name);
+    void open(utf8_string const& file_name, int flags);
     
     // Close database session.
     void close();
@@ -92,6 +94,11 @@
         std::swap(lhs.impl_, rhs.impl_);
         std::swap(lhs.active_txn_, rhs.active_txn_);
     }
+
+    sqlite3* get_impl() const
+    {
+        return impl_;
+    }
 private:
     // Noncopyable.
     session(session const&);
Re[3]: SQLite++ в многопоточном приложении
От: PM  
Дата: 03.02.12 13:11
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>Я еще добавил вот такой патч:


[здесь был патч]

спасибо, применю. Только я думаю не добавлять третий конструктор session, а добавить к нему второму параметр:

explicit session(string_t const& filename, int flags = 0);
Re[4]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 03.02.12 13:14
Оценка:
Здравствуйте, PM, Вы писали:

PM>Здравствуйте, Gorilla, Вы писали:


G>>Я еще добавил вот такой патч:


PM>[здесь был патч]


PM>спасибо, применю. Только я думаю не добавлять третий конструктор session, а добавить к нему второму параметр:


PM>
PM>explicit session(string_t const& filename, int flags = 0);
PM>

Функция open_v2 есть только в utf8 варианте, это может стать проблемой.
Re[5]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 03.02.12 13:31
Оценка:
И еще: flags = 0 будет неправильно, дефолтовые флаги другие и могут поменяться в следующей версии sqlite
Re[5]: SQLite++ в многопоточном приложении
От: PM  
Дата: 03.02.12 13:32
Оценка:
Здравствуйте, Gorilla, Вы писали:


PM>>
PM>>explicit session(string_t const& filename, int flags = 0);
PM>>

G>Функция open_v2 есть только в utf8 варианте, это может стать проблемой.

Это не проблема В sqlitepp/string.hpp есть функция utf8() для конверсии строк в UTF-8

Закоммитил в trunk.

Вчера внезапно нашлось время для обновления SQLite до версии 3.7.10 Заодно добавил функции session::impl() и statement::impl() для прямого доступа к структурам SQLite. Также обновил Solution для Visual Studio 2010 — добавил конфигурацию для x64, переименовал targets сборки чтобы не было конфликтов при сборке Win32 или x64. Правда batch build не проходит. Но по отдельности все цели собираются и тесты проходят.
Re[6]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 03.02.12 14:57
Оценка:
Еще небольшой список изменений которых не хватает для полного счасться:

Вот мои правки последней версии проекта, с ними он красивее компилируется и включена вся нужная в релизе оптимизация.
Еще наткнулся на баг студии с созданием пусорной директории "Debug", но не знаю как его обойти. Может быть стоит компилить исходники sqlite внутри проекта sqlitepp, а не в отдельном проекте?

патч
Re[7]: SQLite++ в многопоточном приложении
От: PM  
Дата: 03.02.12 20:38
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>Еще небольшой список изменений которых не хватает для полного счасться:


G>Вот мои правки последней версии проекта, с ними он красивее компилируется и включена вся нужная в релизе оптимизация.

G>Еще наткнулся на баг студии с созданием пусорной директории "Debug", но не знаю как его обойти. Может быть стоит компилить исходники sqlite внутри проекта sqlitepp, а не в отдельном проекте?

Применил, спасибо. Также подчистил немного код и настройки тестового проекта чтобы избавиться от предупреждений компилятора.

Насчет исходников SQLite внутри SQLite++ не уверен — я собираю sqltepp.so в Linux, и там почти всегда уже есть какая-то из более-менее свежих версий SQLite. Я думаю зависимости от SQLite на уровне библиотек вполне достаточно.
Re[8]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 03.02.12 20:16
Оценка:
Здравствуйте, PM, Вы писали:

PM>Применил, спасибо. Также подчистил немного код и настройки тестового проекта чтобы избавиться от предупреждений компилятора.

А зачем удалил "<Filter Include="Source Files">..." из файлов .filters? Ведь именно в этом фича фильтров, чтобы показывало хедеры и сорсы отдельно.
Re[9]: SQLite++ в многопоточном приложении
От: PM  
Дата: 03.02.12 20:55
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>А зачем удалил "<Filter Include="Source Files">..." из файлов .filters? Ведь именно в этом фича фильтров, чтобы показывало хедеры и сорсы отдельно.


Никогда не понимал искусственное деление на Source/Header. Предпочитаю в своих проектах группировать файлы по подсистемам. На мой взгляд так удобнее и логичнее, когда заголовочный и исходный файлы отображаются рядом в Solution Explorer. И так быстрее между ними переключаться. В идеале, иерархия файлов в Solution Explorer и их размещение в файловой системе совпадают.
Re[10]: SQLite++ в многопоточном приложении
От: Gorilla  
Дата: 04.02.12 12:18
Оценка:
А можно добавить use биндеры для char* и wchar_t* ?
Re[11]: SQLite++ в многопоточном приложении
От: PM  
Дата: 04.02.12 21:44
Оценка:
Здравствуйте, Gorilla, Вы писали:

G>А можно добавить use биндеры для char* и wchar_t* ?


Добавил пару перегруженных функций:
use(utf8_char const* str)
use(utf16_char const* str)


Под капотом вызывается sqlite3_bind_text(impl_, pos, str, -1, SQLITE_STATIC) или sqlite3_bind_text16 для utf16_char, т.е. преборазований в string_t и лишних копирований не происходит.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.