summaryrefslogtreecommitdiff
authorzecke <zecke>2005-02-06 21:39:24 (UTC)
committer zecke <zecke>2005-02-06 21:39:24 (UTC)
commitec33239c6edd9927fe2f82953fa48dec47d19567 (patch) (unidiff)
treed546238a10bf19641198f6f4eea32ac942a7116c
parentf1a89d7deff682ea52f34a7d160eaa69886aa340 (diff)
downloadopie-ec33239c6edd9927fe2f82953fa48dec47d19567.zip
opie-ec33239c6edd9927fe2f82953fa48dec47d19567.tar.gz
opie-ec33239c6edd9927fe2f82953fa48dec47d19567.tar.bz2
Rewrite Trolltechs Cache implementation.
-Update the used timestamp on access -Do not play silly games with ConfigPrivate pointers copying them is enough In write save the old config group and restore it after writing it
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--library/config.cpp238
1 files changed, 109 insertions, 129 deletions
diff --git a/library/config.cpp b/library/config.cpp
index f68c336..e9cae4c 100644
--- a/library/config.cpp
+++ b/library/config.cpp
@@ -69,172 +69,152 @@ public:
69#ifndef Q_OS_WIN32 69#ifndef Q_OS_WIN32
70 70
71//#define DEBUG_CONFIG_CACHE 71//#define DEBUG_CONFIG_CACHE
72
73const int CONFIG_CACHE_SIZE = 8192;
74const int CONFIG_CACHE_TIMEOUT = 1000;
75
76class ConfigData 72class ConfigData
77{ 73{
78public: 74public:
79 ConfigData(const ConfigData& o) : 75 ConfigData() {}
80 cfg(o.cfg), 76 ConfigData( const ConfigGroupMap& cf, const ConfigPrivate& pri,
81 priv(o.priv ? new ConfigPrivate(*o.priv) : 0), 77 struct stat sbuf )
82 mtime(o.mtime), 78 : cfg( cf ), priv( pri ), mtime( sbuf.st_mtime ),
83 size(o.size), 79 size( sbuf.st_size )
84 used(o.used)
85 { }
86
87 ConfigData& operator=(const ConfigData& o)
88 { 80 {
89 cfg = o.cfg; 81 gettimeofday(&used, 0 );
90 delete priv;
91 priv = o.priv ? new ConfigPrivate(*o.priv) : 0;
92 mtime = o.mtime;
93 size = o.size;
94 used = o.used;
95 return *this;
96 } 82 }
97 83
98 ConfigData() : priv(0) {}
99 ~ConfigData() { delete priv; }
100
101 ConfigGroupMap cfg; 84 ConfigGroupMap cfg;
102 ConfigPrivate *priv; // Owned by this object 85 ConfigPrivate priv; // Owned by this object
103 time_t mtime; 86 time_t mtime;
104 unsigned int size; 87 unsigned int size;
105 struct timeval used; 88 struct timeval used;
106}; 89};
107 90
108class ConfigCache : public QObject
109{
110public:
111 ConfigCache();
112 91
113 void insert(const QString &filename, const ConfigGroupMap &cfg, const ConfigPrivate* priv); 92class ConfigCache : public QObject {
114 bool find(const QString &filename, ConfigGroupMap &cfg, ConfigPrivate*& priv); 93public:
115 void remove(const QString &filename); 94 static ConfigCache* instance();
116 95
96 void insert( const QString& fileName, const ConfigGroupMap& cfg,
97 const ConfigPrivate *priv );
98 bool find(const QString& fileName, ConfigGroupMap& cfg,
99 ConfigPrivate** priv );
117protected: 100protected:
118 void timerEvent(QTimerEvent *); 101 void timerEvent(QTimerEvent *);
119 102
120private: 103private:
104 ConfigCache();
105 void remove( const QString& fileName );
121 void removeLru(); 106 void removeLru();
122 107
123 QMap<QString, ConfigData> configData; 108private:
124 unsigned int totalsize; 109 QMap<QString, ConfigData> m_cached;
125 int tid; 110 unsigned int m_totalSize;
111 int m_tid;
112private:
113 static ConfigCache* m_inst;
114 static const unsigned int CONFIG_CACHE_SIZE = 8192;
115 static const unsigned int CONFIG_CACHE_TIMEOUT = 1000;
126}; 116};
127 117
128ConfigCache::ConfigCache() : QObject(), totalsize(0), tid(0) 118ConfigCache* ConfigCache::m_inst = 0;
129{ 119/*
120 * get destroyed when qApp gets destroyed
121 */
122ConfigCache::ConfigCache() : QObject( qApp ), m_totalSize( 0 ), m_tid( 0 ) {}
123ConfigCache* ConfigCache::instance() {
124 if ( !m_inst )
125 m_inst = new ConfigCache();
126
127 return m_inst;
130} 128}
131 129
132void ConfigCache::insert(const QString &filename, const ConfigGroupMap &cfg, const ConfigPrivate* priv) 130void ConfigCache::remove( const QString& fileName ) {
133{ 131 QMap<QString, ConfigData>::Iterator it = m_cached.find( fileName );
134 // use stat() rather than QFileInfo for speed.
135 struct stat sbuf;
136 stat(filename.local8Bit().data(), &sbuf);
137
138 if (sbuf.st_size < CONFIG_CACHE_SIZE/2) {
139 ConfigData data;
140 data.cfg = cfg;
141 data.priv = priv ? new ConfigPrivate(*priv) : 0;
142 data.mtime = sbuf.st_mtime;
143 data.size = sbuf.st_size;
144 gettimeofday(&data.used, 0);
145 132
146 remove(filename); 133 if ( it == m_cached.end() )
147 configData.insert(filename, data); 134 return;
148 135
149 totalsize += data.size; 136 m_totalSize -= (*it).size;
150#ifdef DEBUG_CONFIG_CACHE 137 m_cached.remove( it );
151 qDebug("++++++ insert %s", filename.latin1());
152#endif
153 } 138 }
154 139
155 if (totalsize > (uint)CONFIG_CACHE_SIZE) { 140void ConfigCache::removeLru() {
156 // We'll delay deleting anything until later. 141 QMap<QString, ConfigData>::Iterator it = m_cached.begin();
157 // This lets us grow quite large during some operations, 142 QMap<QString, ConfigData>::Iterator lru = it;
158 // but we'll be reduced to a decent size later. 143 ++it;
159 // This works well with the main use case - app startup. 144 for (; it != m_cached.end(); ++it)
160 if (!tid) 145 if ((*it).used.tv_sec < (*lru).used.tv_sec ||
161 tid = startTimer(CONFIG_CACHE_TIMEOUT); 146 ((*it).used.tv_sec == (*lru).used.tv_sec &&
162 } 147 (*it).used.tv_usec < (*lru).used.tv_usec))
148 lru = it;
149
150 qWarning( "Removing item" );
151 m_totalSize -= (*lru).size;
152 m_cached.remove(lru);
163} 153}
164 154
165bool ConfigCache::find(const QString &filename, ConfigGroupMap &cfg, ConfigPrivate*& priv) 155void ConfigCache::timerEvent( QTimerEvent* ) {
166{ 156 while ( m_totalSize > CONFIG_CACHE_SIZE )
167 QMap<QString, ConfigData>::Iterator it = configData.find(filename); 157 removeLru();
168 if (it != configData.end()) {
169 ConfigData data = *it;
170 // use stat() rather than QFileInfo for speed.
171 struct stat sbuf;
172 stat(filename.local8Bit().data(), &sbuf);
173 158
174 if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) { 159 killTimer(m_tid);
175 cfg = data.cfg; 160 m_tid = 0;
176 delete priv;
177 priv = data.priv ? new ConfigPrivate(*data.priv) : 0;
178 gettimeofday(&data.used, 0);
179#ifdef DEBUG_CONFIG_CACHE
180 qDebug("******* Cache hit: %s", filename.latin1());
181#endif
182 return TRUE;
183 }
184 } 161 }
185 162
186#ifdef DEBUG_CONFIG_CACHE 163void ConfigCache::insert( const QString& fileName, const ConfigGroupMap& cfg,
187 qDebug("------- Cache miss: %s", filename.latin1()); 164 const ConfigPrivate* _priv ) {
188#endif
189 165
190 return FALSE;
191}
192 166
193void ConfigCache::remove(const QString &filename) 167 struct stat sbuf;
194{ 168 ::stat( QFile::encodeName(fileName), &sbuf );
195 QMap<QString, ConfigData>::Iterator it = configData.find(filename); 169 if ( static_cast<unsigned int>(sbuf.st_size) >= CONFIG_CACHE_SIZE>>1)
196 if (it != configData.end()) { 170 return;
197 totalsize -= (*it).size;
198 configData.remove(it);
199 }
200}
201 171
202void ConfigCache::timerEvent(QTimerEvent *) 172 /*
203{ 173 * remove the old version and use the new one
204#ifdef DEBUG_CONFIG_CACHE 174 */
205 qDebug( "cache size: %d", totalsize); 175 ConfigPrivate priv = _priv ? *_priv : ConfigPrivate();
206#endif 176 ConfigData data( cfg, priv, sbuf );
207 while (totalsize > (uint)CONFIG_CACHE_SIZE) 177 m_totalSize += data.size;
208 removeLru();
209 killTimer(tid);
210 tid = 0;
211}
212 178
213void ConfigCache::removeLru() 179 remove( fileName );
214{ 180 m_cached.insert( fileName, data );
215 QMap<QString, ConfigData>::Iterator it = configData.begin();
216 QMap<QString, ConfigData>::Iterator lru = it;
217 ++it;
218 for (; it != configData.end(); ++it) {
219 if ((*it).used.tv_sec < (*lru).used.tv_sec ||
220 ((*it).used.tv_sec == (*lru).used.tv_sec &&
221 (*it).used.tv_usec < (*lru).used.tv_usec))
222 lru = it;
223 }
224 181
225#ifdef DEBUG_CONFIG_CACHE 182 /*
226 qDebug("Cache full, removing: %s", lru.key().latin1()); 183 * we've overcommited allocation, let us clean up
227#endif 184 * soon
228 totalsize -= (*lru).size; 185 */
229 configData.remove(lru); 186 if ( m_totalSize >= CONFIG_CACHE_SIZE )
187 if ( !m_tid )
188 m_tid = startTimer(CONFIG_CACHE_TIMEOUT);
230} 189}
231 190
232static ConfigCache *qpe_configCache = 0; 191bool ConfigCache::find( const QString& fileName, ConfigGroupMap& cfg,
192 ConfigPrivate **ppriv ) {
193 QMap<QString, ConfigData>::Iterator it = m_cached.find(fileName);
194 if (it != m_cached.end()) {
195 ConfigData &data = *it;
196 struct stat sbuf;
197 ::stat(QFile::encodeName( fileName ), &sbuf);
233 198
234#endif /* Q_OS_WIN32 */ 199 if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) {
200 cfg = data.cfg;
235 201
202 /*
203 * null pointer
204 */
205 if ( *ppriv == 0 )
206 *ppriv = new ConfigPrivate( data.priv );
207 **ppriv = data.priv;
208 gettimeofday(&data.used, 0);
236 209
237// ========================================================================== 210 return true;
211 }
212 }
213
214 return false;
215}
216
217#endif
238 218
239 219
240/*! 220/*!
@@ -695,6 +675,8 @@ void Config::clearGroup()
695*/ 675*/
696void Config::write( const QString &fn ) 676void Config::write( const QString &fn )
697{ 677{
678 QString oldGroup = git.key();
679
698 QString strNewFile; 680 QString strNewFile;
699 if ( !fn.isEmpty() ) 681 if ( !fn.isEmpty() )
700 filename = fn; 682 filename = fn;
@@ -739,8 +721,8 @@ void Config::write( const QString &fn )
739 } 721 }
740 722
741#ifndef Q_OS_WIN32 723#ifndef Q_OS_WIN32
742 if (qpe_configCache) 724 ConfigCache::instance()->insert( filename, groups, d );
743 qpe_configCache->insert(filename, groups, d); 725 setGroup( oldGroup );
744#endif 726#endif
745 changed = FALSE; 727 changed = FALSE;
746} 728}
@@ -781,10 +763,8 @@ void Config::read()
781 } 763 }
782 764
783#ifndef Q_OS_WIN32 765#ifndef Q_OS_WIN32
784 if (!qpe_configCache)
785 qpe_configCache = new ConfigCache;
786 766
787 if (qpe_configCache->find(readFilename, groups, d)) { 767 if (ConfigCache::instance()->find(readFilename, groups, &d)) {
788 if ( d && d->multilang ) { 768 if ( d && d->multilang ) {
789 QStringList l = Global::languageList(); 769 QStringList l = Global::languageList();
790 lang = l[0]; 770 lang = l[0];
@@ -812,7 +792,7 @@ void Config::read()
812 f.close(); 792 f.close();
813 793
814#ifndef Q_OS_WIN32 794#ifndef Q_OS_WIN32
815 qpe_configCache->insert(readFilename, groups, d); 795 ConfigCache::instance()->insert(readFilename, groups, d);
816#endif 796#endif
817} 797}
818 798