summaryrefslogtreecommitdiff
path: root/libopie2
authoreilers <eilers>2004-08-29 12:50:18 (UTC)
committer eilers <eilers>2004-08-29 12:50:18 (UTC)
commit679d9fef2673eea18fe5d9c85df2b10b09a8a250 (patch) (side-by-side diff)
tree8b3d6dbef45568be6f5daac31094d6e599fdefdf /libopie2
parent45327ef3c0f093fc227682f79158632afc09e6d1 (diff)
downloadopie-679d9fef2673eea18fe5d9c85df2b10b09a8a250.zip
opie-679d9fef2673eea18fe5d9c85df2b10b09a8a250.tar.gz
opie-679d9fef2673eea18fe5d9c85df2b10b09a8a250.tar.bz2
Added lookahead caching for addressbook (SQL-only) for speed improvement.
Diffstat (limited to 'libopie2') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp154
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.h5
-rw-r--r--libopie2/opiepim/backend/opimaccessbackend.h28
-rw-r--r--libopie2/opiepim/core/opimaccesstemplate.h40
-rw-r--r--libopie2/opiepim/core/opimtemplatebase.h16
5 files changed, 196 insertions, 47 deletions
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
index dda23cc..abfd944 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
@@ -300,28 +300,29 @@ namespace {
FindQuery::~FindQuery() {
}
QString FindQuery::query()const{
-// if ( m_uids.count() == 0 )
- return single();
+ if ( m_uids.count() == 0 )
+ return single();
+ else
+ return multi();
}
- /*
- else
- return multi();
- }
- QString FindQuery::multi()const {
- QString qu = "select uid, type, value from addressbook where";
- for (uint i = 0; i < m_uids.count(); i++ ) {
- qu += " UID = " + QString::number( m_uids[i] ) + " OR";
- }
- qu.remove( qu.length()-2, 2 ); // Hmmmm..
- return qu;
+
+ QString FindQuery::multi()const {
+ QString qu = "select * from addressbook where";
+ for (uint i = 0; i < m_uids.count(); i++ ) {
+ qu += " uid = " + QString::number( m_uids[i] ) + " OR";
+ }
+ qu.remove( qu.length()-2, 2 ); // Hmmmm..
+
+ odebug << "find query: " << qu << "" << oendl;
+ return qu;
}
- */
- QString FindQuery::single()const{
- QString qu = "select *";
- qu += " from addressbook where uid = " + QString::number(m_uid);
- // owarn << "find query: " << qu << "" << oendl;
- return qu;
+ QString FindQuery::single()const{
+ QString qu = "select *";
+ qu += " from addressbook where uid = " + QString::number(m_uid);
+
+ // owarn << "find query: " << qu << "" << oendl;
+ return qu;
}
@@ -473,7 +474,7 @@ bool OPimContactAccessBackend_SQL::replace ( const OPimContact &contact )
OPimContact OPimContactAccessBackend_SQL::find ( int uid ) const
{
- odebug << "OPimContactAccessBackend_SQL::find()" << oendl;
+ odebug << "OPimContactAccessBackend_SQL::find(" << uid << ")" << oendl;
QTime t;
t.start();
@@ -484,6 +485,47 @@ OPimContact OPimContactAccessBackend_SQL::find ( int uid ) const
return retContact;
}
+OPimContact OPimContactAccessBackend_SQL::find( int uid, const QArray<int>& queryUids, uint current, Frontend::CacheDirection direction ) const
+{
+ odebug << "OPimContactAccessBackend_SQL::find( ..multi.. )" << oendl;
+ odebug << "searching for " << uid << "" << oendl;
+
+ QTime t;
+ t.start();
+
+ uint numReadAhead = readAhead();
+ QArray<int> searchList( numReadAhead );
+
+ uint size =0;
+
+ // Build an array with all elements which should be requested and cached
+ // We will just request "numReadAhead" elements, starting from "current" position in
+ // the list of many uids !
+ switch( direction ) {
+ /* forward */
+ case Frontend::Forward:
+ for ( uint i = current; i < queryUids.count() && size < numReadAhead; i++ ) {
+ searchList[size] = queryUids[i];
+ size++;
+ }
+ break;
+ /* reverse */
+ case Frontend::Reverse:
+ for ( uint i = current; i != 0 && size < numReadAhead; i-- ) {
+ searchList[size] = queryUids[i];
+ size++;
+ }
+ break;
+ }
+
+ //Shrink to real size..
+ searchList.resize( size );
+
+ OPimContact retContact( requestContactsAndCache( uid, searchList ) );
+
+ odebug << "OPimContactAccessBackend_SQL::find( ..multi.. ) needed: " << t.elapsed() << " ms" << oendl;
+ return retContact;
+}
QArray<int> OPimContactAccessBackend_SQL::queryByExample ( const OPimContact &query, int settings, const QDateTime& qd )
@@ -768,8 +810,6 @@ QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) co
QTime t;
t.start();
- QMap<int, QString> nonCustomMap;
-
int t2needed = 0;
int t3needed = 0;
QTime t2;
@@ -780,8 +820,67 @@ QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) co
OSQLResultItem resItem = res_noncustom.first();
+ QMap<int, QString> nonCustomMap;
QTime t3;
t3.start();
+ nonCustomMap = fillNonCustomMap( resItem );
+ t3needed = t3.elapsed();
+
+
+ // odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl;
+ odebug << "RequestNonCustom needed: insg.:" << t.elapsed() << " ms, query: " << t2needed
+ << " ms, mapping: " << t3needed << " ms" << oendl;
+
+ return nonCustomMap;
+}
+
+/* Returns contact requested by uid and fills cache with contacts requested by uids in the cachelist */
+OPimContact OPimContactAccessBackend_SQL::requestContactsAndCache( int uid, const QArray<int>& uidlist )const
+{
+ // We want to get all contacts with one query.
+ // We don't have to add the given uid to the uidlist, it is expected to be there already (see opimrecordlist.h).
+ // All contacts will be stored in the cache, afterwards the contact with the user id "uid" will be returned
+ // by using the cache..
+ QArray<int> cachelist = uidlist;
+
+ odebug << "Reqest and cache" << cachelist.size() << "elements !" << oendl;
+
+ QTime t;
+ t.start();
+
+ int t2needed = 0;
+ int t3needed = 0;
+ QTime t2;
+ t2.start();
+ FindQuery query( cachelist );
+ OSQLResult res_noncustom = m_driver->query( &query );
+ t2needed = t2.elapsed();
+
+ QMap<int, QString> nonCustomMap;
+ QTime t3;
+ t3.start();
+ OSQLResultItem resItem = res_noncustom.first();
+ do {
+ OPimContact contact( fillNonCustomMap( resItem ) );
+ contact.setExtraMap( requestCustom( contact.uid() ) );
+ odebug << "Caching uid: " << contact.uid() << oendl;
+ cache( contact );
+ resItem = res_noncustom.next();
+ } while ( ! res_noncustom.atEnd() ); //atEnd() is true if we are past(!) the list !!
+ t3needed = t3.elapsed();
+
+
+ // odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl;
+ odebug << "RequestContactsAndCache needed: insg.:" << t.elapsed() << " ms, query: " << t2needed
+ << " ms, mapping: " << t3needed << " ms" << oendl;
+
+ return cacheFind( uid );
+}
+
+QMap<int, QString> OPimContactAccessBackend_SQL::fillNonCustomMap( const OSQLResultItem& resultItem ) const
+{
+ QMap<int, QString> nonCustomMap;
+
// Now loop through all columns
QStringList fieldList = OPimContactFields::untrfields( false );
QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
@@ -790,7 +889,7 @@ QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) co
// corresponding id into the map..
int id = translate[*it];
- QString value = resItem.data( (*it) );
+ QString value = resultItem.data( (*it) );
// odebug << "Reading " << (*it) << "... found: " << value << "" << oendl;
@@ -816,17 +915,12 @@ QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) co
}
}
- // First insert uid
- nonCustomMap.insert( Qtopia::AddressUid, resItem.data( "uid" ) );
- t3needed = t3.elapsed();
-
- // odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl;
- odebug << "RequestNonCustom needed: insg.:" << t.elapsed() << " ms, query: " << t2needed
- << " ms, mapping: " << t3needed << " ms" << oendl;
+ nonCustomMap.insert( Qtopia::AddressUid, resultItem.data( "uid" ) );
return nonCustomMap;
}
+
QMap<QString, QString> OPimContactAccessBackend_SQL::requestCustom( int uid ) const
{
QTime t;
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
index ba122ec..4f81735 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
@@ -73,8 +73,7 @@ class OPimContactAccessBackend_SQL : public OPimContactAccessBackend {
QArray<int> allRecords() const;
OPimContact find ( int uid ) const;
- // FIXME: Add lookahead-cache support !
- //OPimContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
+ OPimContact find( int uid, const QArray<int>&, uint cur, Frontend::CacheDirection ) const;
QArray<int> queryByExample ( const OPimContact &query, int settings,
const QDateTime& d );
@@ -98,6 +97,8 @@ class OPimContactAccessBackend_SQL : public OPimContactAccessBackend {
QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
QMap<int, QString> requestNonCustom( int uid ) const;
QMap<QString, QString> requestCustom( int uid ) const;
+ QMap<int, QString> fillNonCustomMap( const Opie::DB::OSQLResultItem& resultItem ) const;
+ OPimContact requestContactsAndCache( int uid, const QArray<int>& cachelist ) const;
void update();
protected:
diff --git a/libopie2/opiepim/backend/opimaccessbackend.h b/libopie2/opiepim/backend/opimaccessbackend.h
index 0682063..15a7b7f 100644
--- a/libopie2/opiepim/backend/opimaccessbackend.h
+++ b/libopie2/opiepim/backend/opimaccessbackend.h
@@ -96,7 +96,7 @@ public:
virtual T find(int uid )const = 0;
virtual T find(int uid, const QArray<int>& items,
- uint current, typename Frontend::CacheDirection )const ;
+ uint current, typename Frontend::CacheDirection ) const;
/**
* clear the back end
*/
@@ -128,8 +128,16 @@ public:
void setReadAhead( uint count );
protected:
int access()const;
+
void cache( const T& t )const;
+ /**
+ * Returns the element with given uid out of the cache.
+ * Returns empty element if nothing was found.
+ * <b>Attention:</b> This just works if we have a frontend which contains the cache !
+ */
+ T cacheFind( int uid ) const;
+
/**
* use a prime number here!
*/
@@ -161,17 +169,29 @@ void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
}
template <class T>
void OPimAccessBackend<T>::cache( const T& t )const {
- if (m_front )
+ if ( m_front )
m_front->cache( t );
}
+
+template <class T>
+T OPimAccessBackend<T>::cacheFind( int uid )const {
+ if ( ! m_front ){
+ qWarning ( "No frontend assigned ! Therefore we cannot access the cache to return the right element!" );
+ return T();
+ }
+
+ return m_front->cacheFind( uid );
+}
+
template <class T>
void OPimAccessBackend<T>::setSaneCacheSize( int size) {
- if (m_front )
+ if ( m_front )
m_front->setSaneCacheSize( size );
}
template <class T>
T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
- uint, typename Frontend::CacheDirection )const {
+ uint, typename Frontend::CacheDirection ) const{
+ qDebug( "*** Lookahead feature not supported. Fallback to default find!" );
return find( uid );
}
template <class T>
diff --git a/libopie2/opiepim/core/opimaccesstemplate.h b/libopie2/opiepim/core/opimaccesstemplate.h
index 55d600a..6f01b46 100644
--- a/libopie2/opiepim/core/opimaccesstemplate.h
+++ b/libopie2/opiepim/core/opimaccesstemplate.h
@@ -35,7 +35,6 @@
#include <opie2/opimaccessbackend.h>
#include <opie2/opimrecordlist.h>
-#include <opie2/opimcache.h>
#include <opie2/opimtemplatebase.h>
#include <opie2/odebug.h>
@@ -128,6 +127,7 @@ public:
virtual T find( int uid, const QArray<int>&,
uint current, typename OTemplateBase<T>::CacheDirection dir = OTemplateBase<T>::Forward )const;
+
/* invalidate cache here */
/**
* clears the backend and invalidates the backend
@@ -139,13 +139,15 @@ public:
* @param t The item to add.
* @return <i>true</i> if added successfully.
*/
- virtual bool add( const T& t ) ;
+ virtual bool add( const T& t ) ;
+
bool add( const OPimRecord& );
- // Needed for real generic access (eilers)
- // Info: Take this if you are working with OPimRecord, which is a generic base class, and
- // you need to add it into any database, you cannot generate a reference to
- // it and casting may be not approriate, too.
- // But take care that the accessing database is compatible to the real type of OPimRecord !!
+ /**
+ * Add an Opie PimRecord.
+ * Info: Take this if you are working with OPimRecords and you need to add it into any database.
+ * But take care that the accessing database is compatible to the real type of OPimRecord !!
+ * Otherwise this access will be rejected !
+ */
bool add( const OPimRecord* );
@@ -176,6 +178,7 @@ public:
/**
* @internal
*/
+ virtual T cacheFind( int uid )const;
void cache( const T& )const;
void setSaneCacheSize( int );
@@ -192,6 +195,7 @@ protected:
*/
BackEnd* backEnd();
BackEnd* m_backEnd;
+
Cache m_cache;
private:
@@ -218,7 +222,7 @@ bool OPimAccessTemplate<T>::load() {
}
template <class T>
bool OPimAccessTemplate<T>::reload() {
- invalidateCache(); // zecke: I think this should be added (se)
+ invalidateCache();
return m_backEnd->reload();
}
template <class T>
@@ -251,10 +255,22 @@ OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime
}
template <class T>
T OPimAccessTemplate<T>::find( int uid ) const{
+ // First search in cache..
+ if ( m_cache.contains( uid ) )
+ return m_cache.find( uid );
+
T t = m_backEnd->find( uid );
cache( t );
+
return t;
}
+
+template <class T>
+T OPimAccessTemplate<T>::cacheFind( int uid ) const
+{
+ return m_cache.find( uid );
+}
+
template <class T>
T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
uint current, typename OTemplateBase<T>::CacheDirection dir )const {
@@ -264,7 +280,7 @@ T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
* avoid two finds in QCache...
*/
// owarn << "find it now " << uid << oendl;
- if (m_cache.contains( uid ) ) {
+ if ( m_cache.contains( uid ) ) {
return m_cache.find( uid );
}
@@ -284,12 +300,14 @@ bool OPimAccessTemplate<T>::add( const T& t ) {
}
template <class T>
-bool OPimAccessTemplate<T>::add( const OPimRecord& rec) {
+bool OPimAccessTemplate<T>::add( const OPimRecord& rec ) {
/* same type */
T tempInstance;
if ( rec.rtti() == tempInstance.rtti() ) {
const T& t = static_cast<const T&>(rec);
return add(t);
+ } else {
+ owarn << "Adding not possible: Objecttype mismatch" << oendl;
}
return false;
}
@@ -301,6 +319,8 @@ bool OPimAccessTemplate<T>::add( const OPimRecord* rec) {
if ( rec -> rtti() == tempInstance.rtti() ) {
const T* t = static_cast<const T*>(rec);
return add( *t );
+ } else {
+ owarn << "Adding not possible: Objecttype mismatch" << oendl;
}
return false;
}
diff --git a/libopie2/opiepim/core/opimtemplatebase.h b/libopie2/opiepim/core/opimtemplatebase.h
index b48dfed..ec9a94e 100644
--- a/libopie2/opiepim/core/opimtemplatebase.h
+++ b/libopie2/opiepim/core/opimtemplatebase.h
@@ -31,6 +31,7 @@
/* OPIE */
#include <opie2/opimrecord.h>
+#include <opie2/opimcache.h>
/* QT */
#include <qarray.h>
@@ -70,13 +71,15 @@ private:
};
/**
* internal template base
- * T needs to implement the copy c'tor!!!
+ * Attention: T needs to implement the copy c'tor!!!
*/
class OTemplateBasePrivate;
template <class T = OPimRecord>
class OTemplateBase : public OPimBase {
public:
+ /** Look ahead direction of cache */
enum CacheDirection { Forward=0, Reverse };
+
OTemplateBase() {
};
virtual ~OTemplateBase() {
@@ -88,12 +91,23 @@ public:
*/
virtual T find( int uid, const QArray<int>& items,
uint current, CacheDirection dir = Forward )const = 0;
+
+ /**
+ * Find in Cache..
+ * Returns empty object if nothing found.
+ */
+ virtual T cacheFind( int uid )const = 0;
+
+ /**
+ * Put element into Cache
+ */
virtual void cache( const T& )const = 0;
virtual void setSaneCacheSize( int ) = 0;
OPimRecord* record()const;
OPimRecord* record(int uid )const;
static T* rec();
+
private:
OTemplateBasePrivate *d;