Commit 6df37d30 authored by Ronan's avatar Ronan

feat(EventsDb): provide interface

parent 0399162c
......@@ -34,8 +34,8 @@ bool AbstractDb::connect (Backend backend, const string &parameters) {
L_D(AbstractDb);
d->dbSession = DbSessionProvider::getInstance()->getSession(
(backend == Mysql ? "mysql://" : "sqlite3://") + parameters
);
(backend == Mysql ? "mysql://" : "sqlite3://") + parameters
);
if (d->dbSession)
init();
......
......@@ -16,17 +16,21 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SOCI_ENABLED
#include <soci/soci.h>
#endif // ifdef SOCI_ENABLED
#include "abstract/abstract-db-p.h"
#include "event/call-event.h"
#include "event/event.h"
#include "event/message-event.h"
#include "events-db.h"
// TODO: Remove me.
#ifdef SOCI_ENABLED
#undef SOCI_ENABLED
#endif
// =============================================================================
using namespace std;
LINPHONE_BEGIN_NAMESPACE
class EventsDbPrivate : public AbstractDbPrivate {};
......@@ -37,34 +41,34 @@ EventsDb::EventsDb () : AbstractDb(*new EventsDbPrivate) {}
void EventsDb::init () {
#ifdef SOCI_ENABLED
L_D(EventsDb);
soci::session *session = d->dbSession.getBackendSession<soci::session>();
d->session <<
*session <<
"CREATE TABLE IF NOT EXISTS sip_address ("
" id" + primaryKeyAutoIncrementStr() + ","
" value VARCHAR(255) NOT NULL"
")";
d->session <<
*session <<
"CREATE TABLE IF NOT EXISTS event ("
" id" + primaryKeyAutoIncrementStr() + ","
" timestamp TIMESTAMP NOT NULL"
")";
d->session <<
*session <<
"CREATE TABLE IF NOT EXISTS message_status ("
" id" + primaryKeyAutoIncrementStr() + ","
" status VARCHAR(255) NOT NULL"
")";
d->session <<
*session <<
"CREATE TABLE IF NOT EXISTS message_direction ("
" id" + primaryKeyAutoIncrementStr() + ","
" direction VARCHAR(255) NOT NULL"
")";
d->session <<
*session <<
"CREATE TABLE IF NOT EXISTS dialog ("
" local_sip_address_id BIGINT UNSIGNED NOT NULL," // Sip address used to communicate.
" remote_sip_address_id BIGINT UNSIGNED NOT NULL," // Server (for conference) or user sip address.
......@@ -78,7 +82,7 @@ void EventsDb::init () {
" ON DELETE CASCADE"
")";
d->session <<
*session <<
"CREATE TABLE IF NOT EXISTS message_event ("
" id" + primaryKeyAutoIncrementStr() + ","
" dialog_id BIGINT UNSIGNED NOT NULL,"
......@@ -99,7 +103,74 @@ void EventsDb::init () {
" ON DELETE CASCADE"
")";
#endif // ifndef SOCI_ENABLED
#endif // ifdef SOCI_ENABLED
}
// -----------------------------------------------------------------------------
bool EventsDb::addEvent (const Event &event) {
// TODO.
switch (event.getType()) {
case Event::None:
return false;
case Event::MessageEvent:
case Event::CallStartEvent:
case Event::CallEndEvent:
break;
}
return true;
}
bool EventsDb::deleteEvent (const Event &event) {
// TODO.
(void)event;
return true;
}
void EventsDb::cleanEvents (FilterMask mask) {
// TODO.
(void)mask;
}
int EventsDb::getEventsCount (FilterMask mask) {
// TODO.
(void)mask;
return 0;
}
int EventsDb::getMessagesCount (const string &remoteAddress) {
// TODO.
(void)remoteAddress;
return 0;
}
int EventsDb::getUnreadMessagesCount (const string &remoteAddress) {
// TODO.
(void)remoteAddress;
return 0;
}
list<Event> EventsDb::getHistory (const string &remoteAddress, int nLast, FilterMask mask) {
// TODO.
(void)remoteAddress;
(void)nLast;
(void)mask;
return list<Event>();
}
list<Event> EventsDb::getHistory (const string &remoteAddress, int begin, int end, FilterMask mask) {
// TODO.
(void)remoteAddress;
(void)begin;
(void)end;
(void)mask;
return list<Event>();
}
void EventsDb::cleanHistory (const string &remoteAddress) {
// TODO.
(void)remoteAddress;
}
LINPHONE_END_NAMESPACE
......@@ -19,6 +19,8 @@
#ifndef _EVENTS_DB_H_
#define _EVENTS_DB_H_
#include <list>
#include "abstract/abstract-db.h"
// =============================================================================
......@@ -30,9 +32,29 @@ class EventsDbPrivate;
class LINPHONE_PUBLIC EventsDb : public AbstractDb {
public:
enum Filter {
NoFilter = 0x0,
MessageFilter = 0x1,
CallFilter = 0x2,
ConferenceFilter = 0x4
};
typedef int FilterMask;
EventsDb ();
bool writeEvent (const Event &event);
// Generic.
bool addEvent (const Event &event);
bool deleteEvent (const Event &event);
void cleanEvents (FilterMask mask = NoFilter);
int getEventsCount (FilterMask mask = NoFilter);
// Messages, calls and conferences.
int getMessagesCount (const std::string &remoteAddress);
int getUnreadMessagesCount (const std::string &remoteAddress);
std::list<Event> getHistory (const std::string &remoteAddress, int nLast, FilterMask mask = NoFilter);
std::list<Event> getHistory (const std::string &remoteAddress, int begin, int end, FilterMask mask = NoFilter);
void cleanHistory (const std::string &remoteAddress);
protected:
void init () override;
......
......@@ -19,32 +19,25 @@
#ifndef _DB_SESSION_P_H_
#define _DB_SESSION_P_H_
#ifdef SOCI_ENABLED
#include <memory>
#endif // ifdef SOCI_ENABLED
#include <memory>
#include "db-session.h"
#include "object/clonable-object-p.h"
// =============================================================================
#ifdef SOCI_ENABLED
namespace soci {
class session;
}
#endif // ifdef SOCI_ENABLED
LINPHONE_BEGIN_NAMESPACE
// -----------------------------------------------------------------------------
class DbSessionPrivate : public ClonableObjectPrivate {
friend class DbSessionProvider;
private:
bool isValid = false;
#ifdef SOCI_ENABLED
std::shared_ptr<soci::session> session;
#endif // ifndef SOCI_ENABLED
DbSession::Type type = DbSession::None;
std::shared_ptr<void> backendSession;
L_DECLARE_PUBLIC(DbSession);
};
......
......@@ -16,9 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef SOCI_ENABLED
#include <unordered_map>
#include <unordered_map>
#ifdef SOCI_ENABLED
#include <soci/soci.h>
#endif // ifdef SOCI_ENABLED
......@@ -37,45 +37,45 @@ LINPHONE_BEGIN_NAMESPACE
class DbSessionProviderPrivate : public ObjectPrivate {
public:
#ifdef SOCI_ENABLED
typedef pair<weak_ptr<soci::session>, DbSessionPrivate *> InternalSession;
unordered_map<string, InternalSession> sessions;
#endif // ifdef SOCI_ENABLED
typedef pair<weak_ptr<void>, DbSessionPrivate *> InternalSession;
unordered_map<string, InternalSession> sessions;
int cleanCounter = 0;
};
DbSessionProvider::DbSessionProvider () : Singleton(*new DbSessionProviderPrivate) {}
DbSession DbSessionProvider::getSession (const string &uri) {
DbSession session;
L_D(DbSessionProvider);
#ifdef SOCI_ENABLED
L_D(DbSessionProvider);
DbSession session(DbSession::Soci);
try {
shared_ptr<soci::session> sociSession = d->sessions[uri].first.lock();
if (!sociSession) { // Create new session.
sociSession = make_shared<soci::session>(uri);
shared_ptr<void> backendSession = d->sessions[uri].first.lock();
++d->cleanCounter;
if (!backendSession) { // Create new session.
backendSession = make_shared<soci::session>(uri);
DbSessionPrivate *p = session.getPrivate();
p->session = sociSession;
p->backendSession = backendSession;
p->isValid = true;
d->sessions[uri] = make_pair(sociSession, p);
d->sessions[uri] = make_pair(backendSession, p);
} else // Share session.
session.setRef(*d->sessions[uri].second);
} catch (const exception &) {}
#else
DbSession session(DbSession::None);
#endif // ifdef SOCI_ENABLED
// Remove invalid weak ptrs.
if (++d->cleanCounter >= CLEAN_COUNTER_MAX) {
d->cleanCounter = 0;
// Remove invalid weak ptrs.
if (d->cleanCounter >= CLEAN_COUNTER_MAX) {
d->cleanCounter = 0;
for (auto it = d->sessions.begin(), itEnd = d->sessions.end(); it != itEnd;) {
if (it->second.first.expired())
it = d->sessions.erase(it);
else
++it;
}
for (auto it = d->sessions.begin(), itEnd = d->sessions.end(); it != itEnd;) {
if (it->second.first.expired())
it = d->sessions.erase(it);
else
++it;
}
#endif // ifndef SOCI_ENABLED
}
return session;
}
......
......@@ -26,6 +26,11 @@ using namespace std;
LINPHONE_BEGIN_NAMESPACE
DbSession::DbSession (Type type) : ClonableObject(*new DbSessionPrivate) {
L_D(DbSession);
d->type = type;
}
L_USE_DEFAULT_SHARE_IMPL(DbSession, ClonableObject);
DbSession::operator bool () const {
......@@ -33,4 +38,14 @@ DbSession::operator bool () const {
return d->isValid;
}
DbSession::Type DbSession::getBackendType () const {
L_D(const DbSession);
return d->type;
}
void *DbSession::getBackendSession () const {
L_D(const DbSession);
return d->backendSession.get();
}
LINPHONE_END_NAMESPACE
......@@ -25,6 +25,12 @@
// =============================================================================
#ifdef SOCI_ENABLED
namespace soci {
class session;
}
#endif // ifdef SOCI_ENABLED
LINPHONE_BEGIN_NAMESPACE
class DbSessionPrivate;
......@@ -33,17 +39,54 @@ class DbSession : public ClonableObject {
friend class DbSessionProvider;
public:
DbSession ();
enum Type {
None,
Soci
};
DbSession (Type type = None);
DbSession (const DbSession &src);
DbSession &operator= (const DbSession &src);
operator bool () const;
Type getBackendType () const;
template<typename T>
T *getBackendSession () const;
private:
void *getBackendSession () const;
L_DECLARE_PRIVATE(DbSession);
};
// -----------------------------------------------------------------------------
template<typename T>
struct TypeOfDbSession {
static const DbSession::Type type = DbSession::None;
};
#ifdef SOCI_ENABLED
template<>
struct TypeOfDbSession<::soci::session> {
static const DbSession::Type type = DbSession::Soci;
};
#endif // ifdef SOCI_ENABLED
template<typename T>
T *DbSession::getBackendSession () const {
typedef TypeOfDbSession<T> Type;
static_assert(Type::type != DbSession::None, "Unable to get backend session, invalid type.");
if (getBackendType() != Type::type)
return nullptr;
return static_cast<T *>(getBackendSession());
}
LINPHONE_END_NAMESPACE
#endif // ifndef _DB_SESSION_H_
......@@ -110,8 +110,7 @@ inline const Object *getPublicHelper (const T *object, const ObjectPrivate *) {
#define L_Q(CLASS) CLASS * const q = getPublic();
#define L_USE_DEFAULT_SHARE_IMPL(CLASS, PARENT_CLASS) \
CLASS::CLASS () : PARENT_CLASS(*new CLASS ## Private) {} \
CLASS::CLASS (const CLASS &src) : ClonableObject(*src.getPrivate()) {} \
CLASS::CLASS (const CLASS &src) : PARENT_CLASS(*src.getPrivate()) {} \
CLASS &CLASS::operator= (const CLASS &src) { \
if (this != &src) \
setRef(*src.getPrivate()); \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment