• Skip to content
  • Skip to link menu
KDE 4.7 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     typedef FetchScope_ FetchScope;
00083     explicit EntityCache( int maxCapacity, Session *session = 0, QObject *parent = 0 ) :
00084       EntityCacheBase( session, parent ),
00085       mCapacity( maxCapacity )
00086     {}
00087 
00088     ~EntityCache()
00089     {
00090       qDeleteAll( mCache );
00091     }
00092 
00094     bool isCached( typename T::Id id ) const
00095     {
00096       EntityCacheNode<T>* node = cacheNodeForId( id );
00097       return node && !node->pending;
00098     }
00099 
00101     bool isRequested( typename T::Id id ) const
00102     {
00103       return cacheNodeForId( id );
00104     }
00105 
00107     virtual T retrieve( typename T::Id id ) const
00108     {
00109       EntityCacheNode<T>* node = cacheNodeForId( id );
00110       if ( node && !node->pending && !node->invalid )
00111         return node->entity;
00112       return T();
00113     }
00114 
00116     void invalidate( typename T::Id id )
00117     {
00118       EntityCacheNode<T>* node = cacheNodeForId( id );
00119       if ( node )
00120         node->invalid = true;
00121     }
00122 
00124     void update( typename T::Id id, const FetchScope &scope )
00125     {
00126       EntityCacheNode<T>* node = cacheNodeForId( id );
00127       if ( node ) {
00128         mCache.removeAll( node );
00129         if ( node->pending )
00130           request( id, scope );
00131         delete node;
00132       }
00133     }
00134 
00136     virtual bool ensureCached( typename T::Id id, const FetchScope &scope )
00137     {
00138       EntityCacheNode<T>* node = cacheNodeForId( id );
00139       if ( !node ) {
00140         request( id, scope );
00141         return false;
00142       }
00143       return !node->pending;
00144     }
00145 
00151     virtual void request( typename T::Id id, const FetchScope &scope )
00152     {
00153       Q_ASSERT( !isRequested( id ) );
00154       shrinkCache();
00155       EntityCacheNode<T> *node = new EntityCacheNode<T>( id );
00156       FetchJob* job = createFetchJob( id );
00157       job->setFetchScope( scope );
00158       job->setProperty( "EntityCacheNode", QVariant::fromValue<typename T::Id>( id ) );
00159       connect( job, SIGNAL( result( KJob* ) ), SLOT( fetchResult( KJob* ) ) );
00160       mCache.enqueue( node );
00161     }
00162 
00163   private:
00164     EntityCacheNode<T>* cacheNodeForId( typename T::Id id ) const
00165     {
00166       for ( typename QQueue<EntityCacheNode<T>*>::const_iterator it = mCache.constBegin(), endIt = mCache.constEnd();
00167             it != endIt; ++it )
00168       {
00169         if ( (*it)->entity.id() == id )
00170           return *it;
00171       }
00172       return 0;
00173     }
00174 
00175     void fetchResult( KJob* job )
00176     {
00177       typename T::Id id = job->property( "EntityCacheNode" ).template value<typename T::Id>();
00178       EntityCacheNode<T> *node = cacheNodeForId( id );
00179       if ( !node )
00180         return; // got replaced in the meantime
00181 
00182       node->pending = false;
00183       extractResult( node, job );
00184       // make sure we find this node again if something went wrong here,
00185       // most likely the object got deleted from the server in the meantime
00186       if ( node->entity.id() != id ) {
00187         node->entity.setId( id );
00188         node->invalid = true;
00189       }
00190       emit dataAvailable();
00191     }
00192 
00193     void extractResult( EntityCacheNode<T>* node, KJob* job ) const;
00194 
00195     inline FetchJob* createFetchJob( typename T::Id id )
00196     {
00197       return new FetchJob( T( id ), session );
00198     }
00199 
00201     void shrinkCache()
00202     {
00203       while ( mCache.size() >= mCapacity && !mCache.first()->pending )
00204         delete mCache.dequeue();
00205     }
00206 
00207   private:
00208     QQueue<EntityCacheNode<T>*> mCache;
00209     int mCapacity;
00210 };
00211 
00212 template<> inline void EntityCache<Collection, CollectionFetchJob, CollectionFetchScope>::extractResult( EntityCacheNode<Collection>* node, KJob *job ) const
00213 {
00214   CollectionFetchJob* fetch = qobject_cast<CollectionFetchJob*>( job );
00215   Q_ASSERT( fetch );
00216   if ( fetch->collections().isEmpty() )
00217     node->entity = Collection();
00218   else
00219     node->entity = fetch->collections().first();
00220 }
00221 
00222 template<> inline void EntityCache<Item, ItemFetchJob, ItemFetchScope>::extractResult( EntityCacheNode<Item>* node, KJob *job ) const
00223 {
00224   ItemFetchJob* fetch = qobject_cast<ItemFetchJob*>( job );
00225   Q_ASSERT( fetch );
00226   if ( fetch->items().isEmpty() )
00227     node->entity = Item();
00228   else
00229     node->entity = fetch->items().first();
00230 }
00231 
00232 template<> inline CollectionFetchJob* EntityCache<Collection, CollectionFetchJob, CollectionFetchScope>::createFetchJob( Collection::Id id )
00233 {
00234   return new CollectionFetchJob( Collection( id ), CollectionFetchJob::Base, session );
00235 }
00236 
00237 typedef EntityCache<Collection, CollectionFetchJob, CollectionFetchScope> CollectionCache;
00238 typedef EntityCache<Item, ItemFetchJob, ItemFetchScope> ItemCache;
00239 
00240 }
00241 
00242 #endif

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • 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.5
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