mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 02:42:48 +00:00
generic: use file strategy for ksycoca by default
fixes thread-safety issues such as KRunner crashes Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
077f3395a4
commit
ddfc92dc1e
8 changed files with 2 additions and 386 deletions
|
@ -231,7 +231,6 @@ set(kdecore_LIB_SRCS
|
|||
sycoca/ksycocafactory.cpp
|
||||
sycoca/kprotocolinfo.cpp
|
||||
sycoca/kprotocolinfofactory.cpp
|
||||
sycoca/kmemfile.cpp
|
||||
text/kstringhandler.cpp
|
||||
util/kautostart.cpp
|
||||
util/kdedmodule.cpp
|
||||
|
|
|
@ -139,7 +139,6 @@ sonnet/
|
|||
spellerplugin.cpp
|
||||
|
||||
sycoca/
|
||||
kmemfile.cpp
|
||||
kprotocolinfo.cpp David Faure <faure@kde.org>
|
||||
kprotocolinfofactory.cpp David Faure <faure@kde.org>
|
||||
ksycoca.cpp David Faure <faure@kde.org>
|
||||
|
|
|
@ -1,249 +0,0 @@
|
|||
/*
|
||||
This file is part of the KDE libraries
|
||||
Copyright (C) 2008 Christian Ehrlicher <ch.ehrlicher@gmx.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include "kmemfile.h"
|
||||
|
||||
#ifndef QT_NO_SHAREDMEMORY
|
||||
|
||||
#include <QtCore/QSharedMemory>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDir>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
#include "klocalizedstring.h"
|
||||
|
||||
class KMemFile::Private
|
||||
{
|
||||
public:
|
||||
struct sharedInfoData {
|
||||
int shmCounter;
|
||||
qint64 shmDataSize;
|
||||
};
|
||||
Private ( KMemFile *_parent ) : readWritePos ( 0 ), shmDataSize ( 0 ), parent ( _parent ) {}
|
||||
|
||||
QString getShmKey ( int iCounter = -1 );
|
||||
static QString getShmKey ( const QString &filename, int iCounter = -1 );
|
||||
bool loadContentsFromFile();
|
||||
void close();
|
||||
|
||||
QString filename;
|
||||
QSharedMemory shmInfo;
|
||||
QSharedMemory shmData;
|
||||
qint64 readWritePos;
|
||||
qint64 shmDataSize;
|
||||
|
||||
KMemFile *parent;
|
||||
};
|
||||
|
||||
QString KMemFile::Private::getShmKey ( int iCounter )
|
||||
{
|
||||
return getShmKey ( filename, iCounter );
|
||||
}
|
||||
|
||||
QString KMemFile::Private::getShmKey ( const QString &filename, int iCounter )
|
||||
{
|
||||
QByteArray tmp = QString ( QDir ( filename ).canonicalPath() + QString::number ( iCounter ) ).toUtf8();
|
||||
return QString::fromLatin1 ( QCryptographicHash::hash ( tmp, QCryptographicHash::Sha1 ) );
|
||||
}
|
||||
|
||||
bool KMemFile::Private::loadContentsFromFile()
|
||||
{
|
||||
QFile f ( filename );
|
||||
if ( !f.exists() ) {
|
||||
close();
|
||||
parent->setErrorString ( i18n ( "File %1 does not exist" , filename ) );
|
||||
return false;
|
||||
}
|
||||
if ( !f.open ( QIODevice::ReadOnly ) ) {
|
||||
close();
|
||||
parent->setErrorString ( i18n ( "Cannot open %1 for reading" , filename ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
sharedInfoData *infoPtr = static_cast<sharedInfoData*> ( shmInfo.data() );
|
||||
|
||||
infoPtr->shmDataSize = f.size();
|
||||
shmData.setKey ( getShmKey ( infoPtr->shmCounter ) );
|
||||
if ( !shmData.create ( infoPtr->shmDataSize ) ) {
|
||||
close();
|
||||
parent->setErrorString ( i18n ( "Cannot create memory segment for file %1" , filename ) );
|
||||
return false;
|
||||
}
|
||||
shmData.lock();
|
||||
qint64 size = 0;
|
||||
qint64 bytesRead;
|
||||
char *data = static_cast<char*> ( shmData.data() );
|
||||
bytesRead = f.read ( data, infoPtr->shmDataSize );
|
||||
if ( bytesRead != infoPtr->shmDataSize ) {
|
||||
close();
|
||||
parent->setErrorString ( i18n ( "Could not read data from %1 into shm" , filename ) );
|
||||
return false;
|
||||
}
|
||||
shmDataSize = size;
|
||||
shmData.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
void KMemFile::Private::close()
|
||||
{
|
||||
shmData.unlock();
|
||||
shmData.detach();
|
||||
shmInfo.unlock();
|
||||
shmInfo.detach();
|
||||
readWritePos = 0;
|
||||
shmDataSize = 0;
|
||||
}
|
||||
|
||||
KMemFile::KMemFile ( const QString &filename, QObject *parent )
|
||||
: QIODevice ( parent ), d ( new Private ( this ) )
|
||||
{
|
||||
d->filename = filename;
|
||||
}
|
||||
|
||||
KMemFile::~KMemFile()
|
||||
{
|
||||
close();
|
||||
delete d;
|
||||
}
|
||||
|
||||
void KMemFile::close ()
|
||||
{
|
||||
QIODevice::close();
|
||||
if ( !isOpen() )
|
||||
return;
|
||||
d->close();
|
||||
}
|
||||
|
||||
bool KMemFile::isSequential () const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KMemFile::open ( OpenMode mode )
|
||||
{
|
||||
if ( isOpen() ) {
|
||||
QIODevice::open ( mode );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( mode != QIODevice::ReadOnly ) {
|
||||
setErrorString ( i18n ( "Only 'ReadOnly' allowed" ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !QFile::exists ( d->filename ) ) {
|
||||
setErrorString ( i18n ( "File %1 does not exist" , d->filename ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
QSharedMemory lock ( QDir ( d->filename ).canonicalPath() );
|
||||
lock.lock();
|
||||
|
||||
Private::sharedInfoData *infoPtr;
|
||||
d->shmInfo.setKey ( d->getShmKey() );
|
||||
// see if it's already in memory
|
||||
if ( !d->shmInfo.attach ( QSharedMemory::ReadWrite ) ) {
|
||||
if ( !d->shmInfo.create ( sizeof ( Private::sharedInfoData ) ) ) {
|
||||
lock.unlock();
|
||||
setErrorString ( i18n ( "Cannot create memory segment for file %1" , d->filename ) );
|
||||
return false;
|
||||
}
|
||||
d->shmInfo.lock();
|
||||
// no -> create it
|
||||
infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
|
||||
infoPtr->shmCounter = 1;
|
||||
infoPtr->shmDataSize = 0;
|
||||
if ( !d->loadContentsFromFile() ) {
|
||||
d->shmInfo.unlock();
|
||||
d->shmInfo.detach();
|
||||
lock.unlock();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
d->shmInfo.lock();
|
||||
infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
|
||||
d->shmData.setKey ( d->getShmKey ( infoPtr->shmCounter ) );
|
||||
if ( !d->shmData.attach ( QSharedMemory::ReadOnly ) ) {
|
||||
if ( !d->loadContentsFromFile() ) {
|
||||
d->shmInfo.unlock();
|
||||
d->shmInfo.detach();
|
||||
lock.unlock();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
d->shmDataSize = infoPtr->shmDataSize;
|
||||
d->shmInfo.unlock();
|
||||
lock.unlock();
|
||||
|
||||
setOpenMode ( mode );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool KMemFile::seek ( qint64 pos )
|
||||
{
|
||||
if ( d->shmDataSize < pos ) {
|
||||
setErrorString ( i18n ( "Cannot seek past eof" ) );
|
||||
return false;
|
||||
}
|
||||
d->readWritePos = pos;
|
||||
QIODevice::seek ( pos );
|
||||
return true;
|
||||
}
|
||||
|
||||
qint64 KMemFile::size () const
|
||||
{
|
||||
return d->shmDataSize;
|
||||
}
|
||||
|
||||
qint64 KMemFile::readData ( char * data, qint64 maxSize )
|
||||
{
|
||||
if ( ( openMode() & QIODevice::ReadOnly ) == 0 )
|
||||
return -1;
|
||||
|
||||
qint64 maxRead = size() - d->readWritePos;
|
||||
qint64 bytesToRead = qMin ( maxRead, maxSize );
|
||||
const char *src = static_cast<const char*> ( d->shmData.data() );
|
||||
memcpy ( data, &src[d->readWritePos], bytesToRead );
|
||||
d->readWritePos += bytesToRead;
|
||||
return bytesToRead;
|
||||
}
|
||||
|
||||
qint64 KMemFile::writeData ( const char *, qint64 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void KMemFile::fileContentsChanged ( const QString &filename )
|
||||
{
|
||||
QSharedMemory lock ( QDir ( filename ).canonicalPath() );
|
||||
lock.lock();
|
||||
|
||||
QSharedMemory shmData ( Private::getShmKey ( filename ) );
|
||||
if ( !shmData.attach() )
|
||||
return;
|
||||
shmData.lock();
|
||||
Private::sharedInfoData *infoPtr = static_cast<Private::sharedInfoData*> ( shmData.data() );
|
||||
infoPtr->shmCounter++;
|
||||
infoPtr->shmDataSize = 0;
|
||||
shmData.unlock();
|
||||
}
|
||||
|
||||
#endif //QT_NO_SHAREDMEMORY
|
|
@ -1,100 +0,0 @@
|
|||
/*
|
||||
This file is part of the KDE libraries
|
||||
Copyright (C) 2008 Christian Ehrlicher <ch.ehrlicher@gmx.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this library; see the file COPYING.LIB. If not, write to
|
||||
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef KMEMFILE_H
|
||||
#define KMEMFILE_H
|
||||
|
||||
#ifndef QT_NO_SHAREDMEMORY
|
||||
|
||||
#include <QtCore/QIODevice>
|
||||
#include <kdecore_export.h>
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* Simple QIODevice for QSharedMemory to keep ksycoca cache in memory only once
|
||||
* The first call to open() loads the file into a shm segment. Every
|
||||
* subsequent call only attaches to this segment. When the file content changed,
|
||||
* you have to execute KMemFile::fileContentsChanged() to update the internal
|
||||
* structures. The next call to open() creates a new shm segment. The old one
|
||||
* is automatically destroyed when the last process closed KMemFile.
|
||||
*/
|
||||
|
||||
class KDECORE_EXPORT KMemFile : public QIODevice
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* ctor
|
||||
*
|
||||
* @param filename the file to load into memory
|
||||
* @param parent our parent
|
||||
*/
|
||||
explicit KMemFile ( const QString &filename, QObject *parent = 0 );
|
||||
/**
|
||||
* dtor
|
||||
*/
|
||||
virtual ~KMemFile();
|
||||
/**
|
||||
* closes the KMemFile
|
||||
*
|
||||
* @reimp
|
||||
*/
|
||||
virtual void close ();
|
||||
/**
|
||||
* As KMemFile is a random access device, it returns false
|
||||
*
|
||||
* @reimp
|
||||
*/
|
||||
virtual bool isSequential () const;
|
||||
/**
|
||||
* @reimp
|
||||
* @param mode only QIODevice::ReadOnly is accepted
|
||||
*/
|
||||
virtual bool open ( OpenMode mode );
|
||||
/**
|
||||
* Sets the current read/write position to pos
|
||||
* @reimp
|
||||
* @param pos the new read/write position
|
||||
*/
|
||||
virtual bool seek ( qint64 pos );
|
||||
/**
|
||||
* Returns the size of the file
|
||||
* @reimp
|
||||
*/
|
||||
virtual qint64 size () const;
|
||||
/**
|
||||
* This static function updates the internal information about the file
|
||||
* loaded into shared memory. The next time the file is opened, the file is
|
||||
* reread from the file system.
|
||||
*/
|
||||
static void fileContentsChanged ( const QString &filename );
|
||||
protected:
|
||||
/** @reimp */
|
||||
virtual qint64 readData ( char * data, qint64 maxSize );
|
||||
/** @reimp */
|
||||
virtual qint64 writeData ( const char * data, qint64 maxSize );
|
||||
private:
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private * const d;
|
||||
};
|
||||
|
||||
#endif //QT_NO_SHAREDMEMORY
|
||||
|
||||
#endif // KMEMFILE_H
|
|
@ -29,7 +29,6 @@
|
|||
#include "ksharedconfig.h"
|
||||
#include "kdebug.h"
|
||||
#include "kstandarddirs.h"
|
||||
#include "kmemfile.h"
|
||||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QCoreApplication>
|
||||
|
@ -79,7 +78,7 @@ KSycocaPrivate::KSycocaPrivate()
|
|||
updateSig( 0 ),
|
||||
m_device(0)
|
||||
{
|
||||
m_sycocaStrategy = StrategyMemFile;
|
||||
m_sycocaStrategy = StrategyFile;
|
||||
KConfigGroup config(KGlobal::config(), "KSycoca");
|
||||
setStrategyFromString(config.readEntry("strategy"));
|
||||
}
|
||||
|
@ -87,8 +86,6 @@ KSycocaPrivate::KSycocaPrivate()
|
|||
void KSycocaPrivate::setStrategyFromString(const QString& strategy) {
|
||||
if (strategy == QLatin1String("file"))
|
||||
m_sycocaStrategy = StrategyFile;
|
||||
else if (strategy == QLatin1String("sharedmem"))
|
||||
m_sycocaStrategy = StrategyMemFile;
|
||||
else if (!strategy.isEmpty())
|
||||
kWarning(7011) << "Unknown sycoca strategy:" << strategy;
|
||||
}
|
||||
|
@ -191,14 +188,6 @@ KSycocaAbstractDevice* KSycocaPrivate::device()
|
|||
device = new KSycocaBufferDevice;
|
||||
device->device()->open(QIODevice::ReadOnly); // can't fail
|
||||
} else {
|
||||
#ifndef QT_NO_SHAREDMEMORY
|
||||
if (!device && m_sycocaStrategy == StrategyMemFile) {
|
||||
device = new KSycocaMemFileDevice(m_databasePath);
|
||||
if (!device->device()->open(QIODevice::ReadOnly)) {
|
||||
delete device; device = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!device) {
|
||||
device = new KSycocaFileDevice(m_databasePath);
|
||||
if (!device->device()->open(QIODevice::ReadOnly)) {
|
||||
|
|
|
@ -56,7 +56,7 @@ public:
|
|||
bool readError;
|
||||
|
||||
quint32 timeStamp;
|
||||
enum { StrategyMemFile, StrategyFile, StrategyDummyBuffer } m_sycocaStrategy;
|
||||
enum { StrategyFile, StrategyDummyBuffer } m_sycocaStrategy;
|
||||
QString m_databasePath;
|
||||
QStringList changeList;
|
||||
QString language;
|
||||
|
|
|
@ -63,25 +63,6 @@ private:
|
|||
QFile* m_database;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_SHAREDMEMORY
|
||||
// Reading from a KMemFile
|
||||
class KSycocaMemFileDevice : public KSycocaAbstractDevice
|
||||
{
|
||||
public:
|
||||
KSycocaMemFileDevice(const QString& path) {
|
||||
m_database = new KMemFile(path);
|
||||
}
|
||||
~KSycocaMemFileDevice() {
|
||||
delete m_database;
|
||||
}
|
||||
virtual QIODevice* device() {
|
||||
return m_database;
|
||||
}
|
||||
private:
|
||||
KMemFile* m_database;
|
||||
};
|
||||
#endif
|
||||
|
||||
// Reading from a dummy memory buffer
|
||||
class KSycocaBufferDevice : public KSycocaAbstractDevice
|
||||
{
|
||||
|
|
|
@ -53,7 +53,6 @@
|
|||
#ifndef KBUILDSYCOCA_NO_KCRASH
|
||||
#include <kcrash.h>
|
||||
#endif
|
||||
#include <kmemfile.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
@ -455,8 +454,6 @@ bool KBuildSycoca::recreate()
|
|||
if (g_vfolder)
|
||||
str << g_vfolder->allDirectories(); // Extra resource dirs
|
||||
}
|
||||
if (d->m_sycocaStrategy == KSycocaPrivate::StrategyMemFile)
|
||||
KMemFile::fileContentsChanged(path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue