• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • KDE Home
  • Contact Us
 

akonadi

entitycache_p.h

00001 /*
00002     Copyright (c) 2009 Volker Krause <vkrause@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #ifndef AKONADI_ENTITYCACHE_P_H
00021 #define AKONADI_ENTITYCACHE_P_H
00022 
00023 #include <akonadi/item.h>
00024 #include <akonadi/itemfetchjob.h>
00025 #include <akonadi/itemfetchscope.h>
00026 #include <akonadi/collection.h>
00027 #include <akonadi/collectionfetchjob.h>
00028 #include <akonadi/collectionfetchscope.h>
00029 #include <akonadi/session.h>
00030 
00031 #include "akonadiprivate_export.h"
00032 
00033 #include <qobject.h>
00034 #include <QQueue>
00035 #include <QVariant>
00036 #include <QtCore/QQueue>
00037 
00038 class KJob;
00039 
00040 namespace Akonadi {
00041 
00046 class AKONADI_TESTS_EXPORT EntityCacheBase : public QObject
00047 {
00048   Q_OBJECT
00049   public:
00050     explicit EntityCacheBase ( Session *session, QObject * parent = 0 );
00051 
00052     void setSession(Session *session);
00053 
00054   protected:
00055     Session *session;
00056 
00057   signals:
00058     void dataAvailable();
00059 
00060   private slots:
00061     virtual void fetchResult( KJob* job ) = 0;
00062 };
00063 
00064 template <typename T>
00065 struct EntityCacheNode
00066 {
00067   EntityCacheNode() : pending( false ), invalid( false ) {}
00068   EntityCacheNode( typename T::Id id ) : entity( T( id ) ), pending( true ), invalid( false ) {}
00069   T entity;
00070   bool pending;
00071   bool invalid;
00072 };
00073 
00078 template<typename T, typename FetchJob, typename FetchScope>
00079 class EntityCache : public EntityCacheBase
00080 {
00081   public:
00082     explicit EntityCache( int maxCapacity, Session *session = 0, QObject *parent = 0 ) :
00083       EntityCacheBase( session, parent ),
00084       mCapacity( maxCapacity )
00085     {}
00086 
00087     ~EntityCache()
00088     {
00089       qDeleteAll( mCache );
00090     }
00091 
00093     bool isCached( typename T::Id id ) const
00094     {
00095       EntityCacheNode<T>* node = cacheNodeForId( id );
00096       return node && !node->pending;
00097     }
00098 
00100     bool isRequested( typename T::Id id ) const
00101     {
00102       return cacheNodeForId( id );
00103     }
00104 
00106     T retrieve( typename T::Id id ) const
00107     {
00108       EntityCacheNode<T>* node = cacheNodeForId( id );
00109       if ( node && !node->pending && !node->invalid )
00110         return node->entity;
00111       return T();
00112     }
00113 
00115     void invalidate( typename T::Id id )
00116     {
00117       EntityCacheNode<T>* node = cacheNodeForId( id );
00118       if ( node )
00119         node->invalid = true;
00120     }
00121 
00123     void update( typename T::Id id, const FetchScope &scope )
00124     {
00125       EntityCacheNode<T>* node = cacheNodeForId( id );
00126       if ( node ) {
00127         mCache.removeAll( node );
00128         if ( node->pending )
00129           request( id, scope );
00130         delete node;
00131       }
00132     }
00133 
00135     bool ensureCached( typename T::Id id, const FetchScope &scope )
00136     {
00137       EntityCacheNode<T>* node = cacheNodeForId( id );
00138       if ( !node ) {
00139         request( id, scope );
00140         return false;
00141       }
00142       return !node->pending;
00143     }
00144 
00150     void request( typename T::Id id, const FetchScope &scope )
00151     {
00152       Q_ASSERT( !isRequested( id ) );
00153       shrinkCache();
00154       EntityCacheNode<T> *node = new EntityCacheNode<T>( id );
00155       FetchJob* job = createFetchJob( id );
00156       job->setFetchScope( scope );
00157       job->setProperty( "EntityCacheNode", QVariant::fromValue<typename T::Id>( id ) );
00158       connect( job, SIGNAL( result( KJob* ) ), SLOT( fetchResult( KJob* ) ) );
00159       mCache.enqueue( node );
00160     }
00161 
00162   private:
00163     EntityCacheNode<T>* cacheNodeForId( typename T::Id id ) const
00164     {
00165       for ( typename QQueue<EntityCacheNode<T>*>::const_iterator it = mCache.constBegin(), endIt = mCache.constEnd();
00166             it != endIt; ++it )
00167       {
00168         if ( (*it)->entity.id() == id )
00169           return *it;
00170       }
00171       return 0;
00172     }
00173 
00174     void fetchResult( KJob* job )
00175     {
00176       typename T::Id id = job->property( "EntityCacheNode" ).template value<typename T::Id>();
00177       EntityCacheNode<T> *node = cacheNodeForId( id );
00178       if ( !node )
00179         return; // got replaced in the meantime
00180 
00181       node->pending = false;
00182       extractResult( node, job );
00183       // make sure we find this node again if something went wrong here,
00184       // most likely the object got deleted from the server in the meantime
00185       if ( node->entity.id() != id ) {
00186         node->entity.setId( id );
00187         node->invalid = true;
00188       }
00189       emit dataAvailable();
00190     }
00191 
00192     void extractResult( EntityCacheNode<T>* node, KJob* job ) const;
00193 
00194     inline FetchJob* createFetchJob( typename T::Id id )
00195     {
00196       return new FetchJob( T( id ), session );
00197     }
00198 
00200     void shrinkCache()
00201     {
00202       while ( mCache.size() >= mCapacity && !mCache.first()->pending )
00203         delete mCache.dequeue();
00204     }
00205 
00206   private:
00207     QQueue<EntityCacheNode<T>*> mCache;
00208     int mCapacity;
00209 };
00210 
00211 template<> inline void EntityCache<Collection, CollectionFetchJob, CollectionFetchScope>::extractResult( EntityCacheNode<Collection>* node, KJob *job ) const
00212 {
00213   CollectionFetchJob* fetch = qobject_cast<CollectionFetchJob*>( job );
00214   Q_ASSERT( fetch );
00215   if ( fetch->collections().isEmpty() )
00216     node->entity = Collection();
00217   else
00218     node->entity = fetch->collections().first();
00219 }
00220 
00221 template<> inline void EntityCache<Item, ItemFetchJob, ItemFetchScope>::extractResult( EntityCacheNode<Item>* node, KJob *job ) const
00222 {
00223   ItemFetchJob* fetch = qobject_cast<ItemFetchJob*>( job );
00224   Q_ASSERT( fetch );
00225   if ( fetch->items().isEmpty() )
00226     node->entity = Item();
00227   else
00228     node->entity = fetch->items().first();
00229 }
00230 
00231 template<> inline CollectionFetchJob* EntityCache<Collection, CollectionFetchJob, CollectionFetchScope>::createFetchJob( Collection::Id id )
00232 {
00233   return new CollectionFetchJob( Collection( id ), CollectionFetchJob::Base, session );
00234 }
00235 
00236 typedef EntityCache<Collection, CollectionFetchJob, CollectionFetchScope> CollectionCache;
00237 typedef EntityCache<Item, ItemFetchJob, ItemFetchScope> ItemCache;
00238 
00239 }
00240 
00241 #endif

akonadi

Skip menu "akonadi"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal