summaryrefslogtreecommitdiff
authorzecke <zecke>2002-10-10 17:08:58 (UTC)
committer zecke <zecke>2002-10-10 17:08:58 (UTC)
commit1dcc1b1fc9fd35d959255452c8b5be1269ca4f44 (patch) (unidiff)
tree469d239dec74f5751f3aced43c4bae1f0f3a42e3
parentaa38f642a07810515dcc18ea38bf520e26d7f88e (diff)
downloadopie-1dcc1b1fc9fd35d959255452c8b5be1269ca4f44.zip
opie-1dcc1b1fc9fd35d959255452c8b5be1269ca4f44.tar.gz
opie-1dcc1b1fc9fd35d959255452c8b5be1269ca4f44.tar.bz2
The Cache is finally in place
I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;) The read ahead functionality does not make sense for XMLs backends because most of the stuff is already in memory. While using readahead on SQL makes things a lot faster.... I still have to fully implement read ahead This change is bic but sc
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/obackendfactory.h20
-rw-r--r--libopie/pim/opimaccessbackend.h40
-rw-r--r--libopie/pim/opimaccesstemplate.h57
-rw-r--r--libopie/pim/opimcache.h117
-rw-r--r--libopie/pim/orecordlist.h20
-rw-r--r--libopie/pim/otemplatebase.h11
-rw-r--r--libopie2/opiepim/backend/obackendfactory.h20
-rw-r--r--libopie2/opiepim/backend/opimaccessbackend.h40
-rw-r--r--libopie2/opiepim/core/opimaccesstemplate.h57
-rw-r--r--libopie2/opiepim/core/opimcache.h117
-rw-r--r--libopie2/opiepim/core/otemplatebase.h11
-rw-r--r--libopie2/opiepim/orecordlist.h20
12 files changed, 496 insertions, 34 deletions
diff --git a/libopie/pim/obackendfactory.h b/libopie/pim/obackendfactory.h
index f11f029..89b8c58 100644
--- a/libopie/pim/obackendfactory.h
+++ b/libopie/pim/obackendfactory.h
@@ -7,49 +7,57 @@
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; 9 * License as published by the Free Software Foundation;
10 * either version 2 of the License, or (at your option) any later 10 * either version 2 of the License, or (at your option) any later
11 * version. 11 * version.
12 * ===================================================================== 12 * =====================================================================
13 * ToDo: Use plugins 13 * ToDo: Use plugins
14 * ===================================================================== 14 * =====================================================================
15 * Version: $Id$ 15 * Version: $Id$
16 * ===================================================================== 16 * =====================================================================
17 * History: 17 * History:
18 * $Log$ 18 * $Log$
19 * Revision 1.3 2002/10/10 17:08:58 zecke
20 * The Cache is finally in place
21 * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;)
22 * The read ahead functionality does not make sense for XMLs backends because most of the stuff is already in memory. While using readahead on SQL makes things a lot faster....
23 * I still have to fully implement read ahead
24 * This change is bic but sc
25 *
19 * Revision 1.2 2002/10/08 09:27:36 eilers 26 * Revision 1.2 2002/10/08 09:27:36 eilers
20 * Fixed libopie.pro to include the new pim-API. 27 * Fixed libopie.pro to include the new pim-API.
21 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to 28 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to
22 * compile itself would need to install libsqlite, libopiesql... 29 * compile itself would need to install libsqlite, libopiesql...
23 * Therefore, the backend currently uses XML only.. 30 * Therefore, the backend currently uses XML only..
24 * 31 *
25 * Revision 1.1 2002/10/07 17:35:01 eilers 32 * Revision 1.1 2002/10/07 17:35:01 eilers
26 * added OBackendFactory for advanced backend access 33 * added OBackendFactory for advanced backend access
27 * 34 *
28 * 35 *
29 * ===================================================================== 36 * =====================================================================
30 */ 37 */
31#ifndef __OPIE_BACKENDFACTORY_H_ 38#ifndef OPIE_BACKENDFACTORY_H_
32#define __OPIE_BACKENDFACTORY_H_ 39#define OPIE_BACKENDFACTORY_H_
33 40
34#include <qstring.h> 41#include <qstring.h>
35#include <qasciidict.h> 42#include <qasciidict.h>
36#include <qpe/config.h> 43#include <qpe/config.h>
37 44
38#include "otodoaccessxml.h" 45#include "otodoaccessxml.h"
39#include "ocontactaccessbackend_xml.h" 46#include "ocontactaccessbackend_xml.h"
40 47
41#ifdef __USE_SQL 48/*#ifdef __USE_SQL
42#include "otodoaccesssql.h" 49#include "otodoaccesssql.h"
43#endif 50#endif
51*/
44 52
45template<class T> 53template<class T>
46class OBackendFactory 54class OBackendFactory
47{ 55{
48 public: 56 public:
49 OBackendFactory() {}; 57 OBackendFactory() {};
50 58
51 enum BACKENDS { 59 enum BACKENDS {
52 TODO, 60 TODO,
53 CONTACT, 61 CONTACT,
54 DATE 62 DATE
55 }; 63 };
@@ -63,31 +71,31 @@ class OBackendFactory
63 71
64 QAsciiDict<int> dict ( 3 ); 72 QAsciiDict<int> dict ( 3 );
65 dict.setAutoDelete ( TRUE ); 73 dict.setAutoDelete ( TRUE );
66 74
67 dict.insert( "todo", new int (TODO) ); 75 dict.insert( "todo", new int (TODO) );
68 dict.insert( "contact", new int (CONTACT) ); 76 dict.insert( "contact", new int (CONTACT) );
69 77
70 qWarning ("TODO is: %d", TODO); 78 qWarning ("TODO is: %d", TODO);
71 qWarning ("CONTACT is: %d", CONTACT); 79 qWarning ("CONTACT is: %d", CONTACT);
72 80
73 switch ( *dict.take( backendName ) ){ 81 switch ( *dict.take( backendName ) ){
74 case TODO: 82 case TODO:
75#ifdef __USE_SQL 83/*#ifdef __USE_SQL
76 if ( backend == "sql" ) 84 if ( backend == "sql" )
77 return (T*) new OTodoAccessBackendSQL(""); 85 return (T*) new OTodoAccessBackendSQL("");
78#else 86#else*/
79 if ( backend == "sql" ) 87 if ( backend == "sql" )
80 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); 88 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!");
81#endif 89//#endif
82 90
83 return (T*) new OTodoAccessXML( appName ); 91 return (T*) new OTodoAccessXML( appName );
84 case CONTACT: 92 case CONTACT:
85 if ( backend == "sql" ) 93 if ( backend == "sql" )
86 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); 94 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!");
87 95
88 return (T*) new OContactAccessBackend_XML( appName ); 96 return (T*) new OContactAccessBackend_XML( appName );
89 case DATE: 97 case DATE:
90 qWarning ("OBackendFactory:: DATE-Backend not implemented!"); 98 qWarning ("OBackendFactory:: DATE-Backend not implemented!");
91 return NULL; 99 return NULL;
92 default: 100 default:
93 return NULL; 101 return NULL;
diff --git a/libopie/pim/opimaccessbackend.h b/libopie/pim/opimaccessbackend.h
index c27acbb..27d3cb8 100644
--- a/libopie/pim/opimaccessbackend.h
+++ b/libopie/pim/opimaccessbackend.h
@@ -1,31 +1,33 @@
1#ifndef OPIE_PIM_ACCESS_BACKEND 1#ifndef OPIE_PIM_ACCESS_BACKEND
2#define OPIE_PIM_ACCESS_BACKEND 2#define OPIE_PIM_ACCESS_BACKEND
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/otemplatebase.h>
6#include <opie/opimrecord.h> 7#include <opie/opimrecord.h>
7 8
8 9
9/** 10/**
10 * OPimAccessBackend is the base class 11 * OPimAccessBackend is the base class
11 * for all private backends 12 * for all private backends
12 * it operates on OPimRecord as the base class 13 * it operates on OPimRecord as the base class
13 * and it's responsible for fast manipulating 14 * and it's responsible for fast manipulating
14 * the resource the implementation takes care 15 * the resource the implementation takes care
15 * of 16 * of
16 */ 17 */
17template <class T = OPimRecord> 18template <class T = OPimRecord>
18class OPimAccessBackend { 19class OPimAccessBackend {
19public: 20public:
21 typedef OTemplateBase<T> Frontend;
20 OPimAccessBackend(); 22 OPimAccessBackend();
21 virtual ~OPimAccessBackend(); 23 virtual ~OPimAccessBackend();
22 24
23 /** 25 /**
24 * load the resource 26 * load the resource
25 */ 27 */
26 virtual bool load() = 0; 28 virtual bool load() = 0;
27 29
28 /** 30 /**
29 * reload the resource 31 * reload the resource
30 */ 32 */
31 virtual bool reload() = 0; 33 virtual bool reload() = 0;
@@ -45,45 +47,81 @@ public:
45 /** 47 /**
46 * queryByExample for T with the SortOrder 48 * queryByExample for T with the SortOrder
47 * sort 49 * sort
48 */ 50 */
49 virtual QArray<int> queryByExample( const T& t, int sort ) = 0; 51 virtual QArray<int> queryByExample( const T& t, int sort ) = 0;
50 52
51 /** 53 /**
52 * find the OPimRecord with uid @param uid 54 * find the OPimRecord with uid @param uid
53 * returns T and T.isEmpty() if nothing was found 55 * returns T and T.isEmpty() if nothing was found
54 */ 56 */
55 virtual T find(int uid )const = 0; 57 virtual T find(int uid )const = 0;
56 58
59 virtual T find(int uid, const QArray<int>& items,
60 uint current, Frontend::CacheDirection )const ;
57 /** 61 /**
58 * clear the back end 62 * clear the back end
59 */ 63 */
60 virtual void clear() = 0; 64 virtual void clear() = 0;
61 65
62 /** 66 /**
63 * add T 67 * add T
64 */ 68 */
65 virtual bool add( const T& t ) = 0; 69 virtual bool add( const T& t ) = 0;
66 70
67 /** 71 /**
68 * remove 72 * remove
69 */ 73 */
70 virtual bool remove( int uid ) = 0; 74 virtual bool remove( int uid ) = 0;
71 75
72 /** 76 /**
73 * replace a record with T.uid() 77 * replace a record with T.uid()
74 */ 78 */
75 virtual bool replace( const T& t ) = 0; 79 virtual bool replace( const T& t ) = 0;
76 80
81 /*
82 * setTheFrontEnd!!!
83 */
84 void setFrontend( Frontend* front );
85
86protected:
87 void cache( const T& t )const;
88
89 /**
90 * use a prime number here!
91 */
92 void setSaneCacheSize( int );
93
94private:
95 Frontend* m_front;
77 96
78}; 97};
79 98
80template <class T> 99template <class T>
81OPimAccessBackend<T>::OPimAccessBackend() { 100OPimAccessBackend<T>::OPimAccessBackend() {
82 101 m_front = 0l;
83} 102}
84template <class T> 103template <class T>
85OPimAccessBackend<T>::~OPimAccessBackend() { 104OPimAccessBackend<T>::~OPimAccessBackend() {
86 105
87} 106}
107template <class T>
108void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
109 m_front = fr;
110}
111template <class T>
112void OPimAccessBackend<T>::cache( const T& t )const {
113 if (m_front )
114 m_front->cache( t );
115}
116template <class T>
117void OPimAccessBackend<T>::setSaneCacheSize( int size) {
118 if (m_front )
119 m_front->setSaneCacheSize( size );
120}
121template <class T>
122T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
123 uint, Frontend::CacheDirection )const {
124 return find( uid );
125}
88 126
89#endif 127#endif
diff --git a/libopie/pim/opimaccesstemplate.h b/libopie/pim/opimaccesstemplate.h
index 31ab516..92d7192 100644
--- a/libopie/pim/opimaccesstemplate.h
+++ b/libopie/pim/opimaccesstemplate.h
@@ -1,37 +1,39 @@
1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H 1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
2#define OPIE_PIM_ACCESS_TEMPLATE_H 2#define OPIE_PIM_ACCESS_TEMPLATE_H
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/opimrecord.h> 6#include <opie/opimrecord.h>
7#include <opie/opimaccessbackend.h> 7#include <opie/opimaccessbackend.h>
8#include <opie/orecordlist.h> 8#include <opie/orecordlist.h>
9 9
10#include "opimcache.h"
10#include "otemplatebase.h" 11#include "otemplatebase.h"
11 12
12/** 13/**
13 * Thats the frontend to our OPIE PIM 14 * Thats the frontend to our OPIE PIM
14 * Library. Either you want to use it's 15 * Library. Either you want to use it's
15 * interface or you want to implement 16 * interface or you want to implement
16 * your own Access lib 17 * your own Access lib
17 * Just create a OPimRecord and inherit from 18 * Just create a OPimRecord and inherit from
18 * the plugins 19 * the plugins
19 */ 20 */
20 21
21template <class T = OPimRecord > 22template <class T = OPimRecord >
22class OPimAccessTemplate : public OTemplateBase<T> { 23class OPimAccessTemplate : public OTemplateBase<T> {
23public: 24public:
24 typedef ORecordList<T> List; 25 typedef ORecordList<T> List;
25 typedef OPimAccessBackend<T> BackEnd; 26 typedef OPimAccessBackend<T> BackEnd;
27 typedef OPimCache<T> Cache;
26 28
27 /** 29 /**
28 * our sort order 30 * our sort order
29 * should be safe explaining 31 * should be safe explaining
30 */ 32 */
31 enum SortOrder { WildCards = 0, IgnoreCase = 1, 33 enum SortOrder { WildCards = 0, IgnoreCase = 1,
32 RegExp = 2, ExactMatch = 4 }; 34 RegExp = 2, ExactMatch = 4 };
33 35
34 /** 36 /**
35 * c'tor BackEnd 37 * c'tor BackEnd
36 */ 38 */
37 OPimAccessTemplate( BackEnd* end); 39 OPimAccessTemplate( BackEnd* end);
@@ -64,24 +66,30 @@ public:
64 virtual List allRecords()const; 66 virtual List allRecords()const;
65 67
66 /** 68 /**
67 * queryByExample 69 * queryByExample
68 */ 70 */
69 virtual List queryByExample( const T& t, int sortOrder ); 71 virtual List queryByExample( const T& t, int sortOrder );
70 72
71 /** 73 /**
72 * find the OPimRecord uid 74 * find the OPimRecord uid
73 */ 75 */
74 virtual T find( int uid )const; 76 virtual T find( int uid )const;
75 77
78 /**
79 * read ahead cache find method ;)
80 */
81 virtual T find( int uid, const QArray<int>&,
82 uint current, CacheDirection dir = Forward )const;
83
76 /* invalidate cache here */ 84 /* invalidate cache here */
77 /** 85 /**
78 * clears the backend and invalidates the backend 86 * clears the backend and invalidates the backend
79 */ 87 */
80 virtual void clear() ; 88 virtual void clear() ;
81 89
82 /** 90 /**
83 * add T to the backend 91 * add T to the backend
84 */ 92 */
85 virtual bool add( const T& t ) ; 93 virtual bool add( const T& t ) ;
86 94
87 /* only the uid matters */ 95 /* only the uid matters */
@@ -90,52 +98,61 @@ public:
90 */ 98 */
91 virtual bool remove( const T& t ); 99 virtual bool remove( const T& t );
92 100
93 /** 101 /**
94 * remove the OPimRecord with uid 102 * remove the OPimRecord with uid
95 */ 103 */
96 virtual bool remove( int uid ); 104 virtual bool remove( int uid );
97 105
98 /** 106 /**
99 * replace T from backend 107 * replace T from backend
100 */ 108 */
101 virtual bool replace( const T& t) ; 109 virtual bool replace( const T& t) ;
110
111 /**
112 * @internal
113 */
114 void cache( const T& )const;
115 void setSaneCacheSize( int );
102protected: 116protected:
103 /** 117 /**
104 * invalidate the cache 118 * invalidate the cache
105 */ 119 */
106 void invalidateCache(); 120 void invalidateCache();
107 121
108 void setBackEnd( BackEnd* end ); 122 void setBackEnd( BackEnd* end );
109 /** 123 /**
110 * returns the backend 124 * returns the backend
111 */ 125 */
112 BackEnd* backEnd(); 126 BackEnd* backEnd();
113 BackEnd* m_backEnd; 127 BackEnd* m_backEnd;
128 Cache m_cache;
114 129
115}; 130};
116 131
117template <class T> 132template <class T>
118OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) 133OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
119 : OTemplateBase<T>(), m_backEnd( end ) 134 : OTemplateBase<T>(), m_backEnd( end )
120{ 135{
121 136 if (end )
137 end->setFrontend( this );
122} 138}
123template <class T> 139template <class T>
124OPimAccessTemplate<T>::~OPimAccessTemplate() { 140OPimAccessTemplate<T>::~OPimAccessTemplate() {
125 qWarning("~OPimAccessTemplate<T>"); 141 qWarning("~OPimAccessTemplate<T>");
126 delete m_backEnd; 142 delete m_backEnd;
127} 143}
128template <class T> 144template <class T>
129bool OPimAccessTemplate<T>::load() { 145bool OPimAccessTemplate<T>::load() {
146 invalidateCache();
130 return m_backEnd->load(); 147 return m_backEnd->load();
131} 148}
132template <class T> 149template <class T>
133bool OPimAccessTemplate<T>::reload() { 150bool OPimAccessTemplate<T>::reload() {
134 return m_backEnd->reload(); 151 return m_backEnd->reload();
135} 152}
136template <class T> 153template <class T>
137bool OPimAccessTemplate<T>::save() { 154bool OPimAccessTemplate<T>::save() {
138 return m_backEnd->save(); 155 return m_backEnd->save();
139} 156}
140template <class T> 157template <class T>
141OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { 158OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
@@ -145,52 +162,86 @@ OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
145} 162}
146template <class T> 163template <class T>
147OPimAccessTemplate<T>::List 164OPimAccessTemplate<T>::List
148OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { 165OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) {
149 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); 166 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder );
150 167
151 List lis(ints, this ); 168 List lis(ints, this );
152 return lis; 169 return lis;
153} 170}
154template <class T> 171template <class T>
155T OPimAccessTemplate<T>::find( int uid ) const{ 172T OPimAccessTemplate<T>::find( int uid ) const{
156 T t = m_backEnd->find( uid ); 173 T t = m_backEnd->find( uid );
174 cache( t );
175 return t;
176}
177template <class T>
178T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
179 uint current, CacheDirection dir )const {
180 /*
181 * better do T.isEmpty()
182 * after a find this way we would
183 * avoid two finds in QCache...
184 */
185 // qWarning("find it now %d", uid );
186 if (m_cache.contains( uid ) ) {
187 qWarning("m cache contains %d", uid);
188 return m_cache.find( uid );
189 }
190
191 T t = m_backEnd->find( uid, ar, current, dir );
192 qWarning("found it and cache it now %d", uid);
193 cache( t );
157 return t; 194 return t;
158} 195}
159template <class T> 196template <class T>
160void OPimAccessTemplate<T>::clear() { 197void OPimAccessTemplate<T>::clear() {
161 invalidateCache(); 198 invalidateCache();
162 m_backEnd->clear(); 199 m_backEnd->clear();
163} 200}
164template <class T> 201template <class T>
165bool OPimAccessTemplate<T>::add( const T& t ) { 202bool OPimAccessTemplate<T>::add( const T& t ) {
203 cache( t );
166 return m_backEnd->add( t ); 204 return m_backEnd->add( t );
167} 205}
168template <class T> 206template <class T>
169bool OPimAccessTemplate<T>::remove( const T& t ) { 207bool OPimAccessTemplate<T>::remove( const T& t ) {
170 return m_backEnd->remove( t.uid() ); 208 return remove( t.uid() );
171} 209}
172template <class T> 210template <class T>
173bool OPimAccessTemplate<T>::remove( int uid ) { 211bool OPimAccessTemplate<T>::remove( int uid ) {
212 m_cache.remove( uid );
174 return m_backEnd->remove( uid ); 213 return m_backEnd->remove( uid );
175} 214}
176template <class T> 215template <class T>
177bool OPimAccessTemplate<T>::replace( const T& t ) { 216bool OPimAccessTemplate<T>::replace( const T& t ) {
217 m_cache.replace( t );
178 return m_backEnd->replace( t ); 218 return m_backEnd->replace( t );
179} 219}
180template <class T> 220template <class T>
181void OPimAccessTemplate<T>::invalidateCache() { 221void OPimAccessTemplate<T>::invalidateCache() {
182 222 m_cache.invalidate();
183} 223}
184template <class T> 224template <class T>
185OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() { 225OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
186 return m_backEnd; 226 return m_backEnd;
187} 227}
188template <class T> 228template <class T>
189bool OPimAccessTemplate<T>::wasChangedExternally()const { 229bool OPimAccessTemplate<T>::wasChangedExternally()const {
190 return false; 230 return false;
191} 231}
192template <class T> 232template <class T>
193void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) { 233void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) {
194 m_backEnd = end; 234 m_backEnd = end;
235 if (m_backEnd )
236 m_backEnd->setFrontend( this );
237}
238template <class T>
239void OPimAccessTemplate<T>::cache( const T& t ) const{
240 /* hacky we need to work around the const*/
241 ((OPimAccessTemplate<T>*)this)->m_cache.add( t );
242}
243template <class T>
244void OPimAccessTemplate<T>::setSaneCacheSize( int size ) {
245 m_cache.setSize( size );
195} 246}
196#endif 247#endif
diff --git a/libopie/pim/opimcache.h b/libopie/pim/opimcache.h
new file mode 100644
index 0000000..067f6e7
--- a/dev/null
+++ b/libopie/pim/opimcache.h
@@ -0,0 +1,117 @@
1#ifndef OPIE_PIM_CACHE_H
2#define OPIE_PIM_CACHE_H
3
4#include <qintcache.h>
5
6#include "opimrecord.h"
7
8template <class T = OPimRecord>
9class OPimCacheItem {
10public:
11 OPimCacheItem( const T& t = T() );
12 ~OPimCacheItem();
13
14 T record()const;
15 void setRecord( const T& );
16private:
17 T m_t;
18};
19
20/**
21 * OPimCache for caching the items
22 * We support adding, removing
23 * and finding
24 */
25template <class T = OPimRecord>
26class OPimCache {
27public:
28 typedef OPimCacheItem<T> Item;
29 OPimCache();
30 ~OPimCache();
31
32 bool contains(int uid)const;
33 void invalidate();
34 void setSize( int size );
35
36 T find(int uid )const;
37 void add( const T& );
38 void remove( int uid );
39 void replace( const T& );
40
41private:
42 QIntCache<Item> m_cache;
43};
44
45// Implementation
46template <class T>
47OPimCacheItem<T>::OPimCacheItem( const T& t )
48 : m_t(t) {
49}
50template <class T>
51OPimCacheItem<T>::~OPimCacheItem() {
52
53}
54template <class T>
55T OPimCacheItem<T>::record()const {
56 return m_t;
57}
58template <class T>
59void OPimCacheItem<T>::setRecord( const T& t ) {
60 m_t = t;
61}
62// Cache
63template <class T>
64OPimCache<T>::OPimCache() {
65 m_cache.setAutoDelete( TRUE );
66}
67template <class T>
68OPimCache<T>::~OPimCache() {
69
70}
71template <class T>
72bool OPimCache<T>::contains(int uid )const {
73 Item* it = m_cache.find( uid, FALSE );
74 if (!it)
75 return false;
76 return true;
77}
78template <class T>
79void OPimCache<T>::invalidate() {
80 m_cache.clear();
81}
82template <class T>
83void OPimCache<T>::setSize( int size ) {
84 m_cache.setMaxCost( size );
85}
86template <class T>
87T OPimCache<T>::find(int uid )const {
88 Item *it = m_cache.find( uid );
89 if (it)
90 return it->record();
91 return T();
92}
93template <class T>
94void OPimCache<T>::add( const T& t ) {
95 Item* it = 0l;
96 it = m_cache.find(t.uid(), FALSE );
97
98 if (it )
99 it->setRecord( t );
100
101 it = new Item( t );
102 if (!m_cache.insert( t.uid(), it ) )
103 delete it;
104}
105template <class T>
106void OPimCache<T>::remove( int uid ) {
107 m_cache.remove( uid );
108}
109template <class T>
110void OPimCache<T>::replace( const T& t) {
111 Item *it = m_cache.find( t.uid() );
112 if ( it ) {
113 it->setRecord( t );
114 }
115}
116
117#endif
diff --git a/libopie/pim/orecordlist.h b/libopie/pim/orecordlist.h
index b6fa7fa..08f5c85 100644
--- a/libopie/pim/orecordlist.h
+++ b/libopie/pim/orecordlist.h
@@ -59,24 +59,25 @@ public:
59 59
60 /** 60 /**
61 * sets the current item 61 * sets the current item
62 */ 62 */
63 void setCurrent( uint cur ); 63 void setCurrent( uint cur );
64 64
65private: 65private:
66 QArray<int> m_uids; 66 QArray<int> m_uids;
67 uint m_current; 67 uint m_current;
68 const Base* m_temp; 68 const Base* m_temp;
69 bool m_end : 1; 69 bool m_end : 1;
70 T m_record; 70 T m_record;
71 bool m_direction :1;
71 72
72 /* d pointer for future versions */ 73 /* d pointer for future versions */
73 class IteratorPrivate; 74 class IteratorPrivate;
74 IteratorPrivate *d; 75 IteratorPrivate *d;
75}; 76};
76/** 77/**
77 * The recordlist used as a return type 78 * The recordlist used as a return type
78 * from OPimAccessTemplate 79 * from OPimAccessTemplate
79 */ 80 */
80template <class T = OPimRecord > 81template <class T = OPimRecord >
81class ORecordList { 82class ORecordList {
82public: 83public:
@@ -116,78 +117,81 @@ public:
116private: 117private:
117 QArray<int> m_ids; 118 QArray<int> m_ids;
118 const Base* m_acc; 119 const Base* m_acc;
119}; 120};
120 121
121/* ok now implement it */ 122/* ok now implement it */
122template <class T> 123template <class T>
123ORecordListIterator<T>::ORecordListIterator() { 124ORecordListIterator<T>::ORecordListIterator() {
124 m_current = 0; 125 m_current = 0;
125 m_temp = 0l; 126 m_temp = 0l;
126 m_end = true; 127 m_end = true;
127 m_record = T(); 128 m_record = T();
129 /* forward */
130 m_direction = TRUE;
128} 131}
129template <class T> 132template <class T>
130ORecordListIterator<T>::~ORecordListIterator() { 133ORecordListIterator<T>::~ORecordListIterator() {
131/* nothing to delete */ 134/* nothing to delete */
132} 135}
133 136
134template <class T> 137template <class T>
135ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) { 138ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) {
136// qWarning("ORecordListIterator copy c'tor"); 139// qWarning("ORecordListIterator copy c'tor");
137 m_uids = it.m_uids; 140 m_uids = it.m_uids;
138 m_current = it.m_current; 141 m_current = it.m_current;
139 m_temp = it.m_temp; 142 m_temp = it.m_temp;
140 m_end = it.m_end; 143 m_end = it.m_end;
141 m_record = it.m_record; 144 m_record = it.m_record;
145 m_direction = it.m_direction;
142} 146}
143 147
144template <class T> 148template <class T>
145ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) { 149ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) {
146 m_uids = it.m_uids; 150 m_uids = it.m_uids;
147 m_current = it.m_current; 151 m_current = it.m_current;
148 m_temp = it.m_temp; 152 m_temp = it.m_temp;
149 m_end = it.m_end; 153 m_end = it.m_end;
150 m_record = it.m_record; 154 m_record = it.m_record;
151 155
152 return *this; 156 return *this;
153} 157}
154 158
155template <class T> 159template <class T>
156T ORecordListIterator<T>::operator*() { 160T ORecordListIterator<T>::operator*() {
157 qWarning("operator* %d %d", m_current, m_uids[m_current] ); 161 qWarning("operator* %d %d", m_current, m_uids[m_current] );
158 if (!m_end ) 162 if (!m_end )
159 /* FIXME 163 m_record = m_temp->find( m_uids[m_current], m_uids, m_current,
160 * until the cache is in place 164 m_direction ? Base::Forward :
161 * we do the uid match uid check 165 Base::Reverse );
162 */
163 m_record = m_temp->find( m_uids[m_current] );
164 else 166 else
165 m_record = T(); 167 m_record = T();
166 168
167 return m_record; 169 return m_record;
168} 170}
169 171
170template <class T> 172template <class T>
171ORecordListIterator<T> &ORecordListIterator<T>::operator++() { 173ORecordListIterator<T> &ORecordListIterator<T>::operator++() {
174 m_direction = true;
172 if (m_current < m_uids.count() ) { 175 if (m_current < m_uids.count() ) {
173 m_end = false; 176 m_end = false;
174 ++m_current; 177 ++m_current;
175 }else 178 }else
176 m_end = true; 179 m_end = true;
177 180
178 return *this; 181 return *this;
179} 182}
180template <class T> 183template <class T>
181ORecordListIterator<T> &ORecordListIterator<T>::operator--() { 184ORecordListIterator<T> &ORecordListIterator<T>::operator--() {
185 m_direction = false;
182 if ( m_current > 0 ) { 186 if ( m_current > 0 ) {
183 --m_current; 187 --m_current;
184 m_end = false; 188 m_end = false;
185 } else 189 } else
186 m_end = true; 190 m_end = true;
187 191
188 return *this; 192 return *this;
189} 193}
190 194
191template <class T> 195template <class T>
192bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) { 196bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) {
193 197
@@ -198,25 +202,26 @@ bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) {
198 if ( m_current != it.m_current ) return false; 202 if ( m_current != it.m_current ) return false;
199 if ( m_temp != it.m_temp ) return false; 203 if ( m_temp != it.m_temp ) return false;
200 204
201 return true; 205 return true;
202} 206}
203template <class T> 207template <class T>
204bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) { 208bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) {
205 return !(*this == it ); 209 return !(*this == it );
206} 210}
207template <class T> 211template <class T>
208ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids, 212ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids,
209 const Base* t ) 213 const Base* t )
210 : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ) 214 : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ),
215 m_direction( false )
211{ 216{
212} 217}
213template <class T> 218template <class T>
214uint ORecordListIterator<T>::current()const { 219uint ORecordListIterator<T>::current()const {
215 return m_current; 220 return m_current;
216} 221}
217template <class T> 222template <class T>
218void ORecordListIterator<T>::setCurrent( uint cur ) { 223void ORecordListIterator<T>::setCurrent( uint cur ) {
219 if( cur < m_uids.count() ) { 224 if( cur < m_uids.count() ) {
220 m_end = false; 225 m_end = false;
221 m_current= cur; 226 m_current= cur;
222 } 227 }
@@ -245,15 +250,16 @@ ORecordList<T>::Iterator ORecordList<T>::end() {
245 Iterator it( m_ids, m_acc ); 250 Iterator it( m_ids, m_acc );
246 it.m_end = true; 251 it.m_end = true;
247 it.m_current = m_ids.count(); 252 it.m_current = m_ids.count();
248 253
249 return it; 254 return it;
250} 255}
251template <class T> 256template <class T>
252uint ORecordList<T>::count()const { 257uint ORecordList<T>::count()const {
253return m_ids.count(); 258return m_ids.count();
254} 259}
255template <class T> 260template <class T>
256T ORecordList<T>::operator[]( uint i ) { 261T ORecordList<T>::operator[]( uint i ) {
257 return m_acc->find( m_ids[i] ); 262 /* forward */
263 return m_acc->find( m_ids[i], m_ids, i );
258} 264}
259#endif 265#endif
diff --git a/libopie/pim/otemplatebase.h b/libopie/pim/otemplatebase.h
index f71417b..b855919 100644
--- a/libopie/pim/otemplatebase.h
+++ b/libopie/pim/otemplatebase.h
@@ -1,21 +1,32 @@
1#ifndef OPIE_TEMPLATE_BASE_H 1#ifndef OPIE_TEMPLATE_BASE_H
2#define OPIE_TEMPLATE_BASE_H 2#define OPIE_TEMPLATE_BASE_H
3 3
4#include <qarray.h>
5
4#include "opimrecord.h" 6#include "opimrecord.h"
5 7
6/** 8/**
7 * internal template base 9 * internal template base
8 */ 10 */
9template <class T = OPimRecord> 11template <class T = OPimRecord>
10class OTemplateBase { 12class OTemplateBase {
11public: 13public:
14 enum CacheDirection { Forward=0, Reverse };
12 OTemplateBase() { 15 OTemplateBase() {
13 }; 16 };
14 virtual ~OTemplateBase() { 17 virtual ~OTemplateBase() {
15 } 18 }
16 virtual T find( int uid )const = 0; 19 virtual T find( int uid )const = 0;
17 20
21 /**
22 * read ahead find
23 */
24 virtual T find( int uid, const QArray<int>& items,
25 uint current, CacheDirection dir = Forward )const = 0;
26 virtual void cache( const T& )const = 0;
27 virtual void setSaneCacheSize( int ) = 0;
28
18}; 29};
19 30
20 31
21#endif 32#endif
diff --git a/libopie2/opiepim/backend/obackendfactory.h b/libopie2/opiepim/backend/obackendfactory.h
index f11f029..89b8c58 100644
--- a/libopie2/opiepim/backend/obackendfactory.h
+++ b/libopie2/opiepim/backend/obackendfactory.h
@@ -7,49 +7,57 @@
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; 9 * License as published by the Free Software Foundation;
10 * either version 2 of the License, or (at your option) any later 10 * either version 2 of the License, or (at your option) any later
11 * version. 11 * version.
12 * ===================================================================== 12 * =====================================================================
13 * ToDo: Use plugins 13 * ToDo: Use plugins
14 * ===================================================================== 14 * =====================================================================
15 * Version: $Id$ 15 * Version: $Id$
16 * ===================================================================== 16 * =====================================================================
17 * History: 17 * History:
18 * $Log$ 18 * $Log$
19 * Revision 1.3 2002/10/10 17:08:58 zecke
20 * The Cache is finally in place
21 * I tested it with my todolist and it 'works' for 10.000 todos the hits are awesome ;)
22 * The read ahead functionality does not make sense for XMLs backends because most of the stuff is already in memory. While using readahead on SQL makes things a lot faster....
23 * I still have to fully implement read ahead
24 * This change is bic but sc
25 *
19 * Revision 1.2 2002/10/08 09:27:36 eilers 26 * Revision 1.2 2002/10/08 09:27:36 eilers
20 * Fixed libopie.pro to include the new pim-API. 27 * Fixed libopie.pro to include the new pim-API.
21 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to 28 * The SQL-Stuff is currently deactivated. Otherwise everyone who wants to
22 * compile itself would need to install libsqlite, libopiesql... 29 * compile itself would need to install libsqlite, libopiesql...
23 * Therefore, the backend currently uses XML only.. 30 * Therefore, the backend currently uses XML only..
24 * 31 *
25 * Revision 1.1 2002/10/07 17:35:01 eilers 32 * Revision 1.1 2002/10/07 17:35:01 eilers
26 * added OBackendFactory for advanced backend access 33 * added OBackendFactory for advanced backend access
27 * 34 *
28 * 35 *
29 * ===================================================================== 36 * =====================================================================
30 */ 37 */
31#ifndef __OPIE_BACKENDFACTORY_H_ 38#ifndef OPIE_BACKENDFACTORY_H_
32#define __OPIE_BACKENDFACTORY_H_ 39#define OPIE_BACKENDFACTORY_H_
33 40
34#include <qstring.h> 41#include <qstring.h>
35#include <qasciidict.h> 42#include <qasciidict.h>
36#include <qpe/config.h> 43#include <qpe/config.h>
37 44
38#include "otodoaccessxml.h" 45#include "otodoaccessxml.h"
39#include "ocontactaccessbackend_xml.h" 46#include "ocontactaccessbackend_xml.h"
40 47
41#ifdef __USE_SQL 48/*#ifdef __USE_SQL
42#include "otodoaccesssql.h" 49#include "otodoaccesssql.h"
43#endif 50#endif
51*/
44 52
45template<class T> 53template<class T>
46class OBackendFactory 54class OBackendFactory
47{ 55{
48 public: 56 public:
49 OBackendFactory() {}; 57 OBackendFactory() {};
50 58
51 enum BACKENDS { 59 enum BACKENDS {
52 TODO, 60 TODO,
53 CONTACT, 61 CONTACT,
54 DATE 62 DATE
55 }; 63 };
@@ -63,31 +71,31 @@ class OBackendFactory
63 71
64 QAsciiDict<int> dict ( 3 ); 72 QAsciiDict<int> dict ( 3 );
65 dict.setAutoDelete ( TRUE ); 73 dict.setAutoDelete ( TRUE );
66 74
67 dict.insert( "todo", new int (TODO) ); 75 dict.insert( "todo", new int (TODO) );
68 dict.insert( "contact", new int (CONTACT) ); 76 dict.insert( "contact", new int (CONTACT) );
69 77
70 qWarning ("TODO is: %d", TODO); 78 qWarning ("TODO is: %d", TODO);
71 qWarning ("CONTACT is: %d", CONTACT); 79 qWarning ("CONTACT is: %d", CONTACT);
72 80
73 switch ( *dict.take( backendName ) ){ 81 switch ( *dict.take( backendName ) ){
74 case TODO: 82 case TODO:
75#ifdef __USE_SQL 83/*#ifdef __USE_SQL
76 if ( backend == "sql" ) 84 if ( backend == "sql" )
77 return (T*) new OTodoAccessBackendSQL(""); 85 return (T*) new OTodoAccessBackendSQL("");
78#else 86#else*/
79 if ( backend == "sql" ) 87 if ( backend == "sql" )
80 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); 88 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!");
81#endif 89//#endif
82 90
83 return (T*) new OTodoAccessXML( appName ); 91 return (T*) new OTodoAccessXML( appName );
84 case CONTACT: 92 case CONTACT:
85 if ( backend == "sql" ) 93 if ( backend == "sql" )
86 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!"); 94 qWarning ("OBackendFactory:: sql Backend not implemented! Using XML instead!");
87 95
88 return (T*) new OContactAccessBackend_XML( appName ); 96 return (T*) new OContactAccessBackend_XML( appName );
89 case DATE: 97 case DATE:
90 qWarning ("OBackendFactory:: DATE-Backend not implemented!"); 98 qWarning ("OBackendFactory:: DATE-Backend not implemented!");
91 return NULL; 99 return NULL;
92 default: 100 default:
93 return NULL; 101 return NULL;
diff --git a/libopie2/opiepim/backend/opimaccessbackend.h b/libopie2/opiepim/backend/opimaccessbackend.h
index c27acbb..27d3cb8 100644
--- a/libopie2/opiepim/backend/opimaccessbackend.h
+++ b/libopie2/opiepim/backend/opimaccessbackend.h
@@ -1,31 +1,33 @@
1#ifndef OPIE_PIM_ACCESS_BACKEND 1#ifndef OPIE_PIM_ACCESS_BACKEND
2#define OPIE_PIM_ACCESS_BACKEND 2#define OPIE_PIM_ACCESS_BACKEND
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/otemplatebase.h>
6#include <opie/opimrecord.h> 7#include <opie/opimrecord.h>
7 8
8 9
9/** 10/**
10 * OPimAccessBackend is the base class 11 * OPimAccessBackend is the base class
11 * for all private backends 12 * for all private backends
12 * it operates on OPimRecord as the base class 13 * it operates on OPimRecord as the base class
13 * and it's responsible for fast manipulating 14 * and it's responsible for fast manipulating
14 * the resource the implementation takes care 15 * the resource the implementation takes care
15 * of 16 * of
16 */ 17 */
17template <class T = OPimRecord> 18template <class T = OPimRecord>
18class OPimAccessBackend { 19class OPimAccessBackend {
19public: 20public:
21 typedef OTemplateBase<T> Frontend;
20 OPimAccessBackend(); 22 OPimAccessBackend();
21 virtual ~OPimAccessBackend(); 23 virtual ~OPimAccessBackend();
22 24
23 /** 25 /**
24 * load the resource 26 * load the resource
25 */ 27 */
26 virtual bool load() = 0; 28 virtual bool load() = 0;
27 29
28 /** 30 /**
29 * reload the resource 31 * reload the resource
30 */ 32 */
31 virtual bool reload() = 0; 33 virtual bool reload() = 0;
@@ -45,45 +47,81 @@ public:
45 /** 47 /**
46 * queryByExample for T with the SortOrder 48 * queryByExample for T with the SortOrder
47 * sort 49 * sort
48 */ 50 */
49 virtual QArray<int> queryByExample( const T& t, int sort ) = 0; 51 virtual QArray<int> queryByExample( const T& t, int sort ) = 0;
50 52
51 /** 53 /**
52 * find the OPimRecord with uid @param uid 54 * find the OPimRecord with uid @param uid
53 * returns T and T.isEmpty() if nothing was found 55 * returns T and T.isEmpty() if nothing was found
54 */ 56 */
55 virtual T find(int uid )const = 0; 57 virtual T find(int uid )const = 0;
56 58
59 virtual T find(int uid, const QArray<int>& items,
60 uint current, Frontend::CacheDirection )const ;
57 /** 61 /**
58 * clear the back end 62 * clear the back end
59 */ 63 */
60 virtual void clear() = 0; 64 virtual void clear() = 0;
61 65
62 /** 66 /**
63 * add T 67 * add T
64 */ 68 */
65 virtual bool add( const T& t ) = 0; 69 virtual bool add( const T& t ) = 0;
66 70
67 /** 71 /**
68 * remove 72 * remove
69 */ 73 */
70 virtual bool remove( int uid ) = 0; 74 virtual bool remove( int uid ) = 0;
71 75
72 /** 76 /**
73 * replace a record with T.uid() 77 * replace a record with T.uid()
74 */ 78 */
75 virtual bool replace( const T& t ) = 0; 79 virtual bool replace( const T& t ) = 0;
76 80
81 /*
82 * setTheFrontEnd!!!
83 */
84 void setFrontend( Frontend* front );
85
86protected:
87 void cache( const T& t )const;
88
89 /**
90 * use a prime number here!
91 */
92 void setSaneCacheSize( int );
93
94private:
95 Frontend* m_front;
77 96
78}; 97};
79 98
80template <class T> 99template <class T>
81OPimAccessBackend<T>::OPimAccessBackend() { 100OPimAccessBackend<T>::OPimAccessBackend() {
82 101 m_front = 0l;
83} 102}
84template <class T> 103template <class T>
85OPimAccessBackend<T>::~OPimAccessBackend() { 104OPimAccessBackend<T>::~OPimAccessBackend() {
86 105
87} 106}
107template <class T>
108void OPimAccessBackend<T>::setFrontend( Frontend* fr ) {
109 m_front = fr;
110}
111template <class T>
112void OPimAccessBackend<T>::cache( const T& t )const {
113 if (m_front )
114 m_front->cache( t );
115}
116template <class T>
117void OPimAccessBackend<T>::setSaneCacheSize( int size) {
118 if (m_front )
119 m_front->setSaneCacheSize( size );
120}
121template <class T>
122T OPimAccessBackend<T>::find( int uid, const QArray<int>&,
123 uint, Frontend::CacheDirection )const {
124 return find( uid );
125}
88 126
89#endif 127#endif
diff --git a/libopie2/opiepim/core/opimaccesstemplate.h b/libopie2/opiepim/core/opimaccesstemplate.h
index 31ab516..92d7192 100644
--- a/libopie2/opiepim/core/opimaccesstemplate.h
+++ b/libopie2/opiepim/core/opimaccesstemplate.h
@@ -1,37 +1,39 @@
1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H 1#ifndef OPIE_PIM_ACCESS_TEMPLATE_H
2#define OPIE_PIM_ACCESS_TEMPLATE_H 2#define OPIE_PIM_ACCESS_TEMPLATE_H
3 3
4#include <qarray.h> 4#include <qarray.h>
5 5
6#include <opie/opimrecord.h> 6#include <opie/opimrecord.h>
7#include <opie/opimaccessbackend.h> 7#include <opie/opimaccessbackend.h>
8#include <opie/orecordlist.h> 8#include <opie/orecordlist.h>
9 9
10#include "opimcache.h"
10#include "otemplatebase.h" 11#include "otemplatebase.h"
11 12
12/** 13/**
13 * Thats the frontend to our OPIE PIM 14 * Thats the frontend to our OPIE PIM
14 * Library. Either you want to use it's 15 * Library. Either you want to use it's
15 * interface or you want to implement 16 * interface or you want to implement
16 * your own Access lib 17 * your own Access lib
17 * Just create a OPimRecord and inherit from 18 * Just create a OPimRecord and inherit from
18 * the plugins 19 * the plugins
19 */ 20 */
20 21
21template <class T = OPimRecord > 22template <class T = OPimRecord >
22class OPimAccessTemplate : public OTemplateBase<T> { 23class OPimAccessTemplate : public OTemplateBase<T> {
23public: 24public:
24 typedef ORecordList<T> List; 25 typedef ORecordList<T> List;
25 typedef OPimAccessBackend<T> BackEnd; 26 typedef OPimAccessBackend<T> BackEnd;
27 typedef OPimCache<T> Cache;
26 28
27 /** 29 /**
28 * our sort order 30 * our sort order
29 * should be safe explaining 31 * should be safe explaining
30 */ 32 */
31 enum SortOrder { WildCards = 0, IgnoreCase = 1, 33 enum SortOrder { WildCards = 0, IgnoreCase = 1,
32 RegExp = 2, ExactMatch = 4 }; 34 RegExp = 2, ExactMatch = 4 };
33 35
34 /** 36 /**
35 * c'tor BackEnd 37 * c'tor BackEnd
36 */ 38 */
37 OPimAccessTemplate( BackEnd* end); 39 OPimAccessTemplate( BackEnd* end);
@@ -64,24 +66,30 @@ public:
64 virtual List allRecords()const; 66 virtual List allRecords()const;
65 67
66 /** 68 /**
67 * queryByExample 69 * queryByExample
68 */ 70 */
69 virtual List queryByExample( const T& t, int sortOrder ); 71 virtual List queryByExample( const T& t, int sortOrder );
70 72
71 /** 73 /**
72 * find the OPimRecord uid 74 * find the OPimRecord uid
73 */ 75 */
74 virtual T find( int uid )const; 76 virtual T find( int uid )const;
75 77
78 /**
79 * read ahead cache find method ;)
80 */
81 virtual T find( int uid, const QArray<int>&,
82 uint current, CacheDirection dir = Forward )const;
83
76 /* invalidate cache here */ 84 /* invalidate cache here */
77 /** 85 /**
78 * clears the backend and invalidates the backend 86 * clears the backend and invalidates the backend
79 */ 87 */
80 virtual void clear() ; 88 virtual void clear() ;
81 89
82 /** 90 /**
83 * add T to the backend 91 * add T to the backend
84 */ 92 */
85 virtual bool add( const T& t ) ; 93 virtual bool add( const T& t ) ;
86 94
87 /* only the uid matters */ 95 /* only the uid matters */
@@ -90,52 +98,61 @@ public:
90 */ 98 */
91 virtual bool remove( const T& t ); 99 virtual bool remove( const T& t );
92 100
93 /** 101 /**
94 * remove the OPimRecord with uid 102 * remove the OPimRecord with uid
95 */ 103 */
96 virtual bool remove( int uid ); 104 virtual bool remove( int uid );
97 105
98 /** 106 /**
99 * replace T from backend 107 * replace T from backend
100 */ 108 */
101 virtual bool replace( const T& t) ; 109 virtual bool replace( const T& t) ;
110
111 /**
112 * @internal
113 */
114 void cache( const T& )const;
115 void setSaneCacheSize( int );
102protected: 116protected:
103 /** 117 /**
104 * invalidate the cache 118 * invalidate the cache
105 */ 119 */
106 void invalidateCache(); 120 void invalidateCache();
107 121
108 void setBackEnd( BackEnd* end ); 122 void setBackEnd( BackEnd* end );
109 /** 123 /**
110 * returns the backend 124 * returns the backend
111 */ 125 */
112 BackEnd* backEnd(); 126 BackEnd* backEnd();
113 BackEnd* m_backEnd; 127 BackEnd* m_backEnd;
128 Cache m_cache;
114 129
115}; 130};
116 131
117template <class T> 132template <class T>
118OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end ) 133OPimAccessTemplate<T>::OPimAccessTemplate( BackEnd* end )
119 : OTemplateBase<T>(), m_backEnd( end ) 134 : OTemplateBase<T>(), m_backEnd( end )
120{ 135{
121 136 if (end )
137 end->setFrontend( this );
122} 138}
123template <class T> 139template <class T>
124OPimAccessTemplate<T>::~OPimAccessTemplate() { 140OPimAccessTemplate<T>::~OPimAccessTemplate() {
125 qWarning("~OPimAccessTemplate<T>"); 141 qWarning("~OPimAccessTemplate<T>");
126 delete m_backEnd; 142 delete m_backEnd;
127} 143}
128template <class T> 144template <class T>
129bool OPimAccessTemplate<T>::load() { 145bool OPimAccessTemplate<T>::load() {
146 invalidateCache();
130 return m_backEnd->load(); 147 return m_backEnd->load();
131} 148}
132template <class T> 149template <class T>
133bool OPimAccessTemplate<T>::reload() { 150bool OPimAccessTemplate<T>::reload() {
134 return m_backEnd->reload(); 151 return m_backEnd->reload();
135} 152}
136template <class T> 153template <class T>
137bool OPimAccessTemplate<T>::save() { 154bool OPimAccessTemplate<T>::save() {
138 return m_backEnd->save(); 155 return m_backEnd->save();
139} 156}
140template <class T> 157template <class T>
141OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const { 158OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
@@ -145,52 +162,86 @@ OPimAccessTemplate<T>::List OPimAccessTemplate<T>::allRecords()const {
145} 162}
146template <class T> 163template <class T>
147OPimAccessTemplate<T>::List 164OPimAccessTemplate<T>::List
148OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) { 165OPimAccessTemplate<T>::queryByExample( const T& t, int sortOrder ) {
149 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder ); 166 QArray<int> ints = m_backEnd->queryByExample( t, sortOrder );
150 167
151 List lis(ints, this ); 168 List lis(ints, this );
152 return lis; 169 return lis;
153} 170}
154template <class T> 171template <class T>
155T OPimAccessTemplate<T>::find( int uid ) const{ 172T OPimAccessTemplate<T>::find( int uid ) const{
156 T t = m_backEnd->find( uid ); 173 T t = m_backEnd->find( uid );
174 cache( t );
175 return t;
176}
177template <class T>
178T OPimAccessTemplate<T>::find( int uid, const QArray<int>& ar,
179 uint current, CacheDirection dir )const {
180 /*
181 * better do T.isEmpty()
182 * after a find this way we would
183 * avoid two finds in QCache...
184 */
185 // qWarning("find it now %d", uid );
186 if (m_cache.contains( uid ) ) {
187 qWarning("m cache contains %d", uid);
188 return m_cache.find( uid );
189 }
190
191 T t = m_backEnd->find( uid, ar, current, dir );
192 qWarning("found it and cache it now %d", uid);
193 cache( t );
157 return t; 194 return t;
158} 195}
159template <class T> 196template <class T>
160void OPimAccessTemplate<T>::clear() { 197void OPimAccessTemplate<T>::clear() {
161 invalidateCache(); 198 invalidateCache();
162 m_backEnd->clear(); 199 m_backEnd->clear();
163} 200}
164template <class T> 201template <class T>
165bool OPimAccessTemplate<T>::add( const T& t ) { 202bool OPimAccessTemplate<T>::add( const T& t ) {
203 cache( t );
166 return m_backEnd->add( t ); 204 return m_backEnd->add( t );
167} 205}
168template <class T> 206template <class T>
169bool OPimAccessTemplate<T>::remove( const T& t ) { 207bool OPimAccessTemplate<T>::remove( const T& t ) {
170 return m_backEnd->remove( t.uid() ); 208 return remove( t.uid() );
171} 209}
172template <class T> 210template <class T>
173bool OPimAccessTemplate<T>::remove( int uid ) { 211bool OPimAccessTemplate<T>::remove( int uid ) {
212 m_cache.remove( uid );
174 return m_backEnd->remove( uid ); 213 return m_backEnd->remove( uid );
175} 214}
176template <class T> 215template <class T>
177bool OPimAccessTemplate<T>::replace( const T& t ) { 216bool OPimAccessTemplate<T>::replace( const T& t ) {
217 m_cache.replace( t );
178 return m_backEnd->replace( t ); 218 return m_backEnd->replace( t );
179} 219}
180template <class T> 220template <class T>
181void OPimAccessTemplate<T>::invalidateCache() { 221void OPimAccessTemplate<T>::invalidateCache() {
182 222 m_cache.invalidate();
183} 223}
184template <class T> 224template <class T>
185OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() { 225OPimAccessTemplate<T>::BackEnd* OPimAccessTemplate<T>::backEnd() {
186 return m_backEnd; 226 return m_backEnd;
187} 227}
188template <class T> 228template <class T>
189bool OPimAccessTemplate<T>::wasChangedExternally()const { 229bool OPimAccessTemplate<T>::wasChangedExternally()const {
190 return false; 230 return false;
191} 231}
192template <class T> 232template <class T>
193void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) { 233void OPimAccessTemplate<T>::setBackEnd( BackEnd* end ) {
194 m_backEnd = end; 234 m_backEnd = end;
235 if (m_backEnd )
236 m_backEnd->setFrontend( this );
237}
238template <class T>
239void OPimAccessTemplate<T>::cache( const T& t ) const{
240 /* hacky we need to work around the const*/
241 ((OPimAccessTemplate<T>*)this)->m_cache.add( t );
242}
243template <class T>
244void OPimAccessTemplate<T>::setSaneCacheSize( int size ) {
245 m_cache.setSize( size );
195} 246}
196#endif 247#endif
diff --git a/libopie2/opiepim/core/opimcache.h b/libopie2/opiepim/core/opimcache.h
new file mode 100644
index 0000000..067f6e7
--- a/dev/null
+++ b/libopie2/opiepim/core/opimcache.h
@@ -0,0 +1,117 @@
1#ifndef OPIE_PIM_CACHE_H
2#define OPIE_PIM_CACHE_H
3
4#include <qintcache.h>
5
6#include "opimrecord.h"
7
8template <class T = OPimRecord>
9class OPimCacheItem {
10public:
11 OPimCacheItem( const T& t = T() );
12 ~OPimCacheItem();
13
14 T record()const;
15 void setRecord( const T& );
16private:
17 T m_t;
18};
19
20/**
21 * OPimCache for caching the items
22 * We support adding, removing
23 * and finding
24 */
25template <class T = OPimRecord>
26class OPimCache {
27public:
28 typedef OPimCacheItem<T> Item;
29 OPimCache();
30 ~OPimCache();
31
32 bool contains(int uid)const;
33 void invalidate();
34 void setSize( int size );
35
36 T find(int uid )const;
37 void add( const T& );
38 void remove( int uid );
39 void replace( const T& );
40
41private:
42 QIntCache<Item> m_cache;
43};
44
45// Implementation
46template <class T>
47OPimCacheItem<T>::OPimCacheItem( const T& t )
48 : m_t(t) {
49}
50template <class T>
51OPimCacheItem<T>::~OPimCacheItem() {
52
53}
54template <class T>
55T OPimCacheItem<T>::record()const {
56 return m_t;
57}
58template <class T>
59void OPimCacheItem<T>::setRecord( const T& t ) {
60 m_t = t;
61}
62// Cache
63template <class T>
64OPimCache<T>::OPimCache() {
65 m_cache.setAutoDelete( TRUE );
66}
67template <class T>
68OPimCache<T>::~OPimCache() {
69
70}
71template <class T>
72bool OPimCache<T>::contains(int uid )const {
73 Item* it = m_cache.find( uid, FALSE );
74 if (!it)
75 return false;
76 return true;
77}
78template <class T>
79void OPimCache<T>::invalidate() {
80 m_cache.clear();
81}
82template <class T>
83void OPimCache<T>::setSize( int size ) {
84 m_cache.setMaxCost( size );
85}
86template <class T>
87T OPimCache<T>::find(int uid )const {
88 Item *it = m_cache.find( uid );
89 if (it)
90 return it->record();
91 return T();
92}
93template <class T>
94void OPimCache<T>::add( const T& t ) {
95 Item* it = 0l;
96 it = m_cache.find(t.uid(), FALSE );
97
98 if (it )
99 it->setRecord( t );
100
101 it = new Item( t );
102 if (!m_cache.insert( t.uid(), it ) )
103 delete it;
104}
105template <class T>
106void OPimCache<T>::remove( int uid ) {
107 m_cache.remove( uid );
108}
109template <class T>
110void OPimCache<T>::replace( const T& t) {
111 Item *it = m_cache.find( t.uid() );
112 if ( it ) {
113 it->setRecord( t );
114 }
115}
116
117#endif
diff --git a/libopie2/opiepim/core/otemplatebase.h b/libopie2/opiepim/core/otemplatebase.h
index f71417b..b855919 100644
--- a/libopie2/opiepim/core/otemplatebase.h
+++ b/libopie2/opiepim/core/otemplatebase.h
@@ -1,21 +1,32 @@
1#ifndef OPIE_TEMPLATE_BASE_H 1#ifndef OPIE_TEMPLATE_BASE_H
2#define OPIE_TEMPLATE_BASE_H 2#define OPIE_TEMPLATE_BASE_H
3 3
4#include <qarray.h>
5
4#include "opimrecord.h" 6#include "opimrecord.h"
5 7
6/** 8/**
7 * internal template base 9 * internal template base
8 */ 10 */
9template <class T = OPimRecord> 11template <class T = OPimRecord>
10class OTemplateBase { 12class OTemplateBase {
11public: 13public:
14 enum CacheDirection { Forward=0, Reverse };
12 OTemplateBase() { 15 OTemplateBase() {
13 }; 16 };
14 virtual ~OTemplateBase() { 17 virtual ~OTemplateBase() {
15 } 18 }
16 virtual T find( int uid )const = 0; 19 virtual T find( int uid )const = 0;
17 20
21 /**
22 * read ahead find
23 */
24 virtual T find( int uid, const QArray<int>& items,
25 uint current, CacheDirection dir = Forward )const = 0;
26 virtual void cache( const T& )const = 0;
27 virtual void setSaneCacheSize( int ) = 0;
28
18}; 29};
19 30
20 31
21#endif 32#endif
diff --git a/libopie2/opiepim/orecordlist.h b/libopie2/opiepim/orecordlist.h
index b6fa7fa..08f5c85 100644
--- a/libopie2/opiepim/orecordlist.h
+++ b/libopie2/opiepim/orecordlist.h
@@ -59,24 +59,25 @@ public:
59 59
60 /** 60 /**
61 * sets the current item 61 * sets the current item
62 */ 62 */
63 void setCurrent( uint cur ); 63 void setCurrent( uint cur );
64 64
65private: 65private:
66 QArray<int> m_uids; 66 QArray<int> m_uids;
67 uint m_current; 67 uint m_current;
68 const Base* m_temp; 68 const Base* m_temp;
69 bool m_end : 1; 69 bool m_end : 1;
70 T m_record; 70 T m_record;
71 bool m_direction :1;
71 72
72 /* d pointer for future versions */ 73 /* d pointer for future versions */
73 class IteratorPrivate; 74 class IteratorPrivate;
74 IteratorPrivate *d; 75 IteratorPrivate *d;
75}; 76};
76/** 77/**
77 * The recordlist used as a return type 78 * The recordlist used as a return type
78 * from OPimAccessTemplate 79 * from OPimAccessTemplate
79 */ 80 */
80template <class T = OPimRecord > 81template <class T = OPimRecord >
81class ORecordList { 82class ORecordList {
82public: 83public:
@@ -116,78 +117,81 @@ public:
116private: 117private:
117 QArray<int> m_ids; 118 QArray<int> m_ids;
118 const Base* m_acc; 119 const Base* m_acc;
119}; 120};
120 121
121/* ok now implement it */ 122/* ok now implement it */
122template <class T> 123template <class T>
123ORecordListIterator<T>::ORecordListIterator() { 124ORecordListIterator<T>::ORecordListIterator() {
124 m_current = 0; 125 m_current = 0;
125 m_temp = 0l; 126 m_temp = 0l;
126 m_end = true; 127 m_end = true;
127 m_record = T(); 128 m_record = T();
129 /* forward */
130 m_direction = TRUE;
128} 131}
129template <class T> 132template <class T>
130ORecordListIterator<T>::~ORecordListIterator() { 133ORecordListIterator<T>::~ORecordListIterator() {
131/* nothing to delete */ 134/* nothing to delete */
132} 135}
133 136
134template <class T> 137template <class T>
135ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) { 138ORecordListIterator<T>::ORecordListIterator( const ORecordListIterator<T>& it) {
136// qWarning("ORecordListIterator copy c'tor"); 139// qWarning("ORecordListIterator copy c'tor");
137 m_uids = it.m_uids; 140 m_uids = it.m_uids;
138 m_current = it.m_current; 141 m_current = it.m_current;
139 m_temp = it.m_temp; 142 m_temp = it.m_temp;
140 m_end = it.m_end; 143 m_end = it.m_end;
141 m_record = it.m_record; 144 m_record = it.m_record;
145 m_direction = it.m_direction;
142} 146}
143 147
144template <class T> 148template <class T>
145ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) { 149ORecordListIterator<T> &ORecordListIterator<T>::operator=( const ORecordListIterator<T>& it) {
146 m_uids = it.m_uids; 150 m_uids = it.m_uids;
147 m_current = it.m_current; 151 m_current = it.m_current;
148 m_temp = it.m_temp; 152 m_temp = it.m_temp;
149 m_end = it.m_end; 153 m_end = it.m_end;
150 m_record = it.m_record; 154 m_record = it.m_record;
151 155
152 return *this; 156 return *this;
153} 157}
154 158
155template <class T> 159template <class T>
156T ORecordListIterator<T>::operator*() { 160T ORecordListIterator<T>::operator*() {
157 qWarning("operator* %d %d", m_current, m_uids[m_current] ); 161 qWarning("operator* %d %d", m_current, m_uids[m_current] );
158 if (!m_end ) 162 if (!m_end )
159 /* FIXME 163 m_record = m_temp->find( m_uids[m_current], m_uids, m_current,
160 * until the cache is in place 164 m_direction ? Base::Forward :
161 * we do the uid match uid check 165 Base::Reverse );
162 */
163 m_record = m_temp->find( m_uids[m_current] );
164 else 166 else
165 m_record = T(); 167 m_record = T();
166 168
167 return m_record; 169 return m_record;
168} 170}
169 171
170template <class T> 172template <class T>
171ORecordListIterator<T> &ORecordListIterator<T>::operator++() { 173ORecordListIterator<T> &ORecordListIterator<T>::operator++() {
174 m_direction = true;
172 if (m_current < m_uids.count() ) { 175 if (m_current < m_uids.count() ) {
173 m_end = false; 176 m_end = false;
174 ++m_current; 177 ++m_current;
175 }else 178 }else
176 m_end = true; 179 m_end = true;
177 180
178 return *this; 181 return *this;
179} 182}
180template <class T> 183template <class T>
181ORecordListIterator<T> &ORecordListIterator<T>::operator--() { 184ORecordListIterator<T> &ORecordListIterator<T>::operator--() {
185 m_direction = false;
182 if ( m_current > 0 ) { 186 if ( m_current > 0 ) {
183 --m_current; 187 --m_current;
184 m_end = false; 188 m_end = false;
185 } else 189 } else
186 m_end = true; 190 m_end = true;
187 191
188 return *this; 192 return *this;
189} 193}
190 194
191template <class T> 195template <class T>
192bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) { 196bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) {
193 197
@@ -198,25 +202,26 @@ bool ORecordListIterator<T>::operator==( const ORecordListIterator<T>& it ) {
198 if ( m_current != it.m_current ) return false; 202 if ( m_current != it.m_current ) return false;
199 if ( m_temp != it.m_temp ) return false; 203 if ( m_temp != it.m_temp ) return false;
200 204
201 return true; 205 return true;
202} 206}
203template <class T> 207template <class T>
204bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) { 208bool ORecordListIterator<T>::operator!=( const ORecordListIterator<T>& it ) {
205 return !(*this == it ); 209 return !(*this == it );
206} 210}
207template <class T> 211template <class T>
208ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids, 212ORecordListIterator<T>::ORecordListIterator( const QArray<int> uids,
209 const Base* t ) 213 const Base* t )
210 : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ) 214 : m_uids( uids ), m_current( 0 ), m_temp( t ), m_end( false ),
215 m_direction( false )
211{ 216{
212} 217}
213template <class T> 218template <class T>
214uint ORecordListIterator<T>::current()const { 219uint ORecordListIterator<T>::current()const {
215 return m_current; 220 return m_current;
216} 221}
217template <class T> 222template <class T>
218void ORecordListIterator<T>::setCurrent( uint cur ) { 223void ORecordListIterator<T>::setCurrent( uint cur ) {
219 if( cur < m_uids.count() ) { 224 if( cur < m_uids.count() ) {
220 m_end = false; 225 m_end = false;
221 m_current= cur; 226 m_current= cur;
222 } 227 }
@@ -245,15 +250,16 @@ ORecordList<T>::Iterator ORecordList<T>::end() {
245 Iterator it( m_ids, m_acc ); 250 Iterator it( m_ids, m_acc );
246 it.m_end = true; 251 it.m_end = true;
247 it.m_current = m_ids.count(); 252 it.m_current = m_ids.count();
248 253
249 return it; 254 return it;
250} 255}
251template <class T> 256template <class T>
252uint ORecordList<T>::count()const { 257uint ORecordList<T>::count()const {
253return m_ids.count(); 258return m_ids.count();
254} 259}
255template <class T> 260template <class T>
256T ORecordList<T>::operator[]( uint i ) { 261T ORecordList<T>::operator[]( uint i ) {
257 return m_acc->find( m_ids[i] ); 262 /* forward */
263 return m_acc->find( m_ids[i], m_ids, i );
258} 264}
259#endif 265#endif