summaryrefslogtreecommitdiff
authorzecke <zecke>2005-02-06 21:39:24 (UTC)
committer zecke <zecke>2005-02-06 21:39:24 (UTC)
commitec33239c6edd9927fe2f82953fa48dec47d19567 (patch) (side-by-side diff)
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
@@ -60,190 +60,170 @@ public:
QString trfile;
QCString trcontext;
bool multilang;
};
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
#ifndef Q_OS_WIN32
//#define DEBUG_CONFIG_CACHE
-
-const int CONFIG_CACHE_SIZE = 8192;
-const int CONFIG_CACHE_TIMEOUT = 1000;
-
class ConfigData
{
public:
- ConfigData(const ConfigData& o) :
- cfg(o.cfg),
- priv(o.priv ? new ConfigPrivate(*o.priv) : 0),
- mtime(o.mtime),
- size(o.size),
- used(o.used)
- { }
-
- ConfigData& operator=(const ConfigData& o)
+ ConfigData() {}
+ ConfigData( const ConfigGroupMap& cf, const ConfigPrivate& pri,
+ struct stat sbuf )
+ : cfg( cf ), priv( pri ), mtime( sbuf.st_mtime ),
+ size( sbuf.st_size )
{
- cfg = o.cfg;
- delete priv;
- priv = o.priv ? new ConfigPrivate(*o.priv) : 0;
- mtime = o.mtime;
- size = o.size;
- used = o.used;
- return *this;
+ gettimeofday(&used, 0 );
}
- ConfigData() : priv(0) {}
- ~ConfigData() { delete priv; }
-
ConfigGroupMap cfg;
- ConfigPrivate *priv; // Owned by this object
+ ConfigPrivate priv; // Owned by this object
time_t mtime;
unsigned int size;
struct timeval used;
};
-class ConfigCache : public QObject
-{
-public:
- ConfigCache();
- void insert(const QString &filename, const ConfigGroupMap &cfg, const ConfigPrivate* priv);
- bool find(const QString &filename, ConfigGroupMap &cfg, ConfigPrivate*& priv);
- void remove(const QString &filename);
+class ConfigCache : public QObject {
+public:
+ static ConfigCache* instance();
+ void insert( const QString& fileName, const ConfigGroupMap& cfg,
+ const ConfigPrivate *priv );
+ bool find(const QString& fileName, ConfigGroupMap& cfg,
+ ConfigPrivate** priv );
protected:
void timerEvent(QTimerEvent *);
private:
+ ConfigCache();
+ void remove( const QString& fileName );
void removeLru();
- QMap<QString, ConfigData> configData;
- unsigned int totalsize;
- int tid;
+private:
+ QMap<QString, ConfigData> m_cached;
+ unsigned int m_totalSize;
+ int m_tid;
+private:
+ static ConfigCache* m_inst;
+ static const unsigned int CONFIG_CACHE_SIZE = 8192;
+ static const unsigned int CONFIG_CACHE_TIMEOUT = 1000;
};
-ConfigCache::ConfigCache() : QObject(), totalsize(0), tid(0)
-{
+ConfigCache* ConfigCache::m_inst = 0;
+/*
+ * get destroyed when qApp gets destroyed
+ */
+ConfigCache::ConfigCache() : QObject( qApp ), m_totalSize( 0 ), m_tid( 0 ) {}
+ConfigCache* ConfigCache::instance() {
+ if ( !m_inst )
+ m_inst = new ConfigCache();
+
+ return m_inst;
}
-void ConfigCache::insert(const QString &filename, const ConfigGroupMap &cfg, const ConfigPrivate* priv)
-{
- // use stat() rather than QFileInfo for speed.
- struct stat sbuf;
- stat(filename.local8Bit().data(), &sbuf);
-
- if (sbuf.st_size < CONFIG_CACHE_SIZE/2) {
- ConfigData data;
- data.cfg = cfg;
- data.priv = priv ? new ConfigPrivate(*priv) : 0;
- data.mtime = sbuf.st_mtime;
- data.size = sbuf.st_size;
- gettimeofday(&data.used, 0);
+void ConfigCache::remove( const QString& fileName ) {
+ QMap<QString, ConfigData>::Iterator it = m_cached.find( fileName );
- remove(filename);
- configData.insert(filename, data);
+ if ( it == m_cached.end() )
+ return;
- totalsize += data.size;
-#ifdef DEBUG_CONFIG_CACHE
- qDebug("++++++ insert %s", filename.latin1());
-#endif
+ m_totalSize -= (*it).size;
+ m_cached.remove( it );
}
- if (totalsize > (uint)CONFIG_CACHE_SIZE) {
- // We'll delay deleting anything until later.
- // This lets us grow quite large during some operations,
- // but we'll be reduced to a decent size later.
- // This works well with the main use case - app startup.
- if (!tid)
- tid = startTimer(CONFIG_CACHE_TIMEOUT);
- }
+void ConfigCache::removeLru() {
+ QMap<QString, ConfigData>::Iterator it = m_cached.begin();
+ QMap<QString, ConfigData>::Iterator lru = it;
+ ++it;
+ for (; it != m_cached.end(); ++it)
+ if ((*it).used.tv_sec < (*lru).used.tv_sec ||
+ ((*it).used.tv_sec == (*lru).used.tv_sec &&
+ (*it).used.tv_usec < (*lru).used.tv_usec))
+ lru = it;
+
+ qWarning( "Removing item" );
+ m_totalSize -= (*lru).size;
+ m_cached.remove(lru);
}
-bool ConfigCache::find(const QString &filename, ConfigGroupMap &cfg, ConfigPrivate*& priv)
-{
- QMap<QString, ConfigData>::Iterator it = configData.find(filename);
- if (it != configData.end()) {
- ConfigData data = *it;
- // use stat() rather than QFileInfo for speed.
- struct stat sbuf;
- stat(filename.local8Bit().data(), &sbuf);
+void ConfigCache::timerEvent( QTimerEvent* ) {
+ while ( m_totalSize > CONFIG_CACHE_SIZE )
+ removeLru();
- if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) {
- cfg = data.cfg;
- delete priv;
- priv = data.priv ? new ConfigPrivate(*data.priv) : 0;
- gettimeofday(&data.used, 0);
-#ifdef DEBUG_CONFIG_CACHE
- qDebug("******* Cache hit: %s", filename.latin1());
-#endif
- return TRUE;
- }
+ killTimer(m_tid);
+ m_tid = 0;
}
-#ifdef DEBUG_CONFIG_CACHE
- qDebug("------- Cache miss: %s", filename.latin1());
-#endif
+void ConfigCache::insert( const QString& fileName, const ConfigGroupMap& cfg,
+ const ConfigPrivate* _priv ) {
- return FALSE;
-}
-void ConfigCache::remove(const QString &filename)
-{
- QMap<QString, ConfigData>::Iterator it = configData.find(filename);
- if (it != configData.end()) {
- totalsize -= (*it).size;
- configData.remove(it);
- }
-}
+ struct stat sbuf;
+ ::stat( QFile::encodeName(fileName), &sbuf );
+ if ( static_cast<unsigned int>(sbuf.st_size) >= CONFIG_CACHE_SIZE>>1)
+ return;
-void ConfigCache::timerEvent(QTimerEvent *)
-{
-#ifdef DEBUG_CONFIG_CACHE
- qDebug( "cache size: %d", totalsize);
-#endif
- while (totalsize > (uint)CONFIG_CACHE_SIZE)
- removeLru();
- killTimer(tid);
- tid = 0;
-}
+ /*
+ * remove the old version and use the new one
+ */
+ ConfigPrivate priv = _priv ? *_priv : ConfigPrivate();
+ ConfigData data( cfg, priv, sbuf );
+ m_totalSize += data.size;
-void ConfigCache::removeLru()
-{
- QMap<QString, ConfigData>::Iterator it = configData.begin();
- QMap<QString, ConfigData>::Iterator lru = it;
- ++it;
- for (; it != configData.end(); ++it) {
- if ((*it).used.tv_sec < (*lru).used.tv_sec ||
- ((*it).used.tv_sec == (*lru).used.tv_sec &&
- (*it).used.tv_usec < (*lru).used.tv_usec))
- lru = it;
- }
+ remove( fileName );
+ m_cached.insert( fileName, data );
-#ifdef DEBUG_CONFIG_CACHE
- qDebug("Cache full, removing: %s", lru.key().latin1());
-#endif
- totalsize -= (*lru).size;
- configData.remove(lru);
+ /*
+ * we've overcommited allocation, let us clean up
+ * soon
+ */
+ if ( m_totalSize >= CONFIG_CACHE_SIZE )
+ if ( !m_tid )
+ m_tid = startTimer(CONFIG_CACHE_TIMEOUT);
}
-static ConfigCache *qpe_configCache = 0;
+bool ConfigCache::find( const QString& fileName, ConfigGroupMap& cfg,
+ ConfigPrivate **ppriv ) {
+ QMap<QString, ConfigData>::Iterator it = m_cached.find(fileName);
+ if (it != m_cached.end()) {
+ ConfigData &data = *it;
+ struct stat sbuf;
+ ::stat(QFile::encodeName( fileName ), &sbuf);
-#endif /* Q_OS_WIN32 */
+ if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) {
+ cfg = data.cfg;
+ /*
+ * null pointer
+ */
+ if ( *ppriv == 0 )
+ *ppriv = new ConfigPrivate( data.priv );
+ **ppriv = data.priv;
+ gettimeofday(&data.used, 0);
-// ==========================================================================
+ return true;
+ }
+ }
+
+ return false;
+}
+
+#endif
/*!
\internal
*/
QString Config::configFilename(const QString& name, Domain d)
{
switch (d) {
case File:
return name;
case User: {
QDir dir = (QString(getenv("HOME")) + "/Settings");
@@ -686,24 +666,26 @@ void Config::clearGroup()
}
if ( !(*git).isEmpty() ) {
( *git ).clear();
changed = TRUE;
}
}
/*!
\internal
*/
void Config::write( const QString &fn )
{
+ QString oldGroup = git.key();
+
QString strNewFile;
if ( !fn.isEmpty() )
filename = fn;
strNewFile = filename + ".new";
QFile f( strNewFile );
if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
qWarning( "could not open for writing `%s'", strNewFile.latin1() );
git = groups.end();
return;
}
@@ -730,26 +712,26 @@ void Config::write( const QString &fn )
}
f.close();
// now rename the file...
if ( rename( strNewFile, filename ) < 0 ) {
qWarning( "problem renaming the file %s to %s", strNewFile.latin1(),
filename.latin1() );
QFile::remove( strNewFile );
return;
}
#ifndef Q_OS_WIN32
- if (qpe_configCache)
- qpe_configCache->insert(filename, groups, d);
+ ConfigCache::instance()->insert( filename, groups, d );
+ setGroup( oldGroup );
#endif
changed = FALSE;
}
/*!
Returns whether the Config is in a valid state.
*/
bool Config::isValid() const
{
return groups.end() != git;
}
@@ -772,28 +754,26 @@ void Config::read()
if (QFile::exists(dftlFile)) {
readFilename = dftlFile;
failed = FALSE;
}
}
if (failed) {
git = groups.end();
return;
}
}
#ifndef Q_OS_WIN32
- if (!qpe_configCache)
- qpe_configCache = new ConfigCache;
- if (qpe_configCache->find(readFilename, groups, d)) {
+ if (ConfigCache::instance()->find(readFilename, groups, &d)) {
if ( d && d->multilang ) {
QStringList l = Global::languageList();
lang = l[0];
glang = l[1];
}
git = groups.begin();
return;
}
#endif
QFile f( readFilename );
if ( !f.open( IO_ReadOnly ) ) {
@@ -803,25 +783,25 @@ void Config::read()
if (f.getch()!='[') {
git = groups.end();
return;
}
f.ungetch('[');
QTextStream s( &f );
read( s );
f.close();
#ifndef Q_OS_WIN32
- qpe_configCache->insert(readFilename, groups, d);
+ ConfigCache::instance()->insert(readFilename, groups, d);
#endif
}
/*!
\internal
*/
bool Config::parse( const QString &l )
{
QString line = l.stripWhiteSpace();
if ( line[ 0 ] == QChar( '[' ) ) {
QString gname = line;
gname = gname.remove( 0, 1 );