author | eilers <eilers> | 2004-08-29 12:50:18 (UTC) |
---|---|---|
committer | eilers <eilers> | 2004-08-29 12:50:18 (UTC) |
commit | 679d9fef2673eea18fe5d9c85df2b10b09a8a250 (patch) (side-by-side diff) | |
tree | 8b3d6dbef45568be6f5daac31094d6e599fdefdf /libopie2 | |
parent | 45327ef3c0f093fc227682f79158632afc09e6d1 (diff) | |
download | opie-679d9fef2673eea18fe5d9c85df2b10b09a8a250.zip opie-679d9fef2673eea18fe5d9c85df2b10b09a8a250.tar.gz opie-679d9fef2673eea18fe5d9c85df2b10b09a8a250.tar.bz2 |
Added lookahead caching for addressbook (SQL-only) for speed improvement.
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp | 154 | ||||
-rw-r--r-- | libopie2/opiepim/backend/ocontactaccessbackend_sql.h | 5 | ||||
-rw-r--r-- | libopie2/opiepim/backend/opimaccessbackend.h | 28 | ||||
-rw-r--r-- | libopie2/opiepim/core/opimaccesstemplate.h | 40 | ||||
-rw-r--r-- | libopie2/opiepim/core/opimtemplatebase.h | 16 |
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 @@ -299,30 +299,31 @@ 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; } FindCustomQuery::FindCustomQuery(int uid) @@ -472,9 +473,9 @@ 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(); OPimContact retContact( requestNonCustom( uid ) ); @@ -483,8 +484,49 @@ OPimContact OPimContactAccessBackend_SQL::find ( int uid ) const odebug << "OPimContactAccessBackend_SQL::find() needed: " << t.elapsed() << " ms" << oendl; 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 ) { @@ -767,10 +809,8 @@ 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; t2.start(); @@ -779,19 +819,78 @@ QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) co t2needed = t2.elapsed(); 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(); for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ // Get data for the selected column and store it with the // 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; switch( id ){ @@ -815,19 +914,14 @@ QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) co nonCustomMap.insert( id, value ); } } - // 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; t.start(); 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 @@ -72,10 +72,9 @@ 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 ); @@ -97,8 +96,10 @@ class OPimContactAccessBackend_SQL : public OPimContactAccessBackend { private: 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: bool m_changed; 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 @@ -95,9 +95,9 @@ 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 */ virtual void clear() = 0; @@ -127,10 +127,18 @@ 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! */ void setSaneCacheSize( int ); @@ -160,19 +168,31 @@ void OPimAccessBackend<T>::setFrontend( Frontend* fr ) { m_front = 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> void OPimAccessBackend<T>::setReadAhead( uint count ) { 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 @@ -34,9 +34,8 @@ #include <opie2/opimrecord.h> #include <opie2/opimaccessbackend.h> #include <opie2/opimrecordlist.h> -#include <opie2/opimcache.h> #include <opie2/opimtemplatebase.h> #include <opie2/odebug.h> /* QT */ @@ -127,8 +126,9 @@ 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 */ @@ -138,15 +138,17 @@ public: * add T to the backend * @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* ); /* only the uid matters */ @@ -175,8 +177,9 @@ public: void setReadAhead( uint count ); /** * @internal */ + virtual T cacheFind( int uid )const; void cache( const T& )const; void setSaneCacheSize( int ); QArray<int> records()const; @@ -191,8 +194,9 @@ protected: * returns the backend */ BackEnd* backEnd(); BackEnd* m_backEnd; + Cache m_cache; private: OPimAccessTemplatePrivate *d; @@ -217,9 +221,9 @@ bool OPimAccessTemplate<T>::load() { return m_backEnd->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> bool OPimAccessTemplate<T>::save() { @@ -250,12 +254,24 @@ OPimAccessTemplate<T>::queryByExample( const T& t, int settings, const QDateTime return lis; } 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 { /* @@ -263,9 +279,9 @@ T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar, * after a find this way we would * 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 ); } T t = m_backEnd->find( uid, ar, current, dir ); @@ -283,14 +299,16 @@ bool OPimAccessTemplate<T>::add( const T& t ) { return m_backEnd->add( 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; } @@ -300,8 +318,10 @@ bool OPimAccessTemplate<T>::add( const OPimRecord* rec) { 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; } 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 @@ -30,8 +30,9 @@ #define OTEMPLATEBASE_H /* OPIE */ #include <opie2/opimrecord.h> +#include <opie2/opimcache.h> /* QT */ #include <qarray.h> @@ -69,15 +70,17 @@ 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() { } @@ -87,14 +90,25 @@ public: * read ahead find */ 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; }; |