• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

KDECore

kmemfile.cpp

Go to the documentation of this file.
00001 /*
00002    This file is part of the KDE libraries
00003    Copyright (C) 2008 Christian Ehrlicher <ch.ehrlicher@gmx.de>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kmemfile.h"
00022 
00023 #ifndef QT_NO_SHAREDMEMORY
00024 
00025 #include <QtCore/QSharedMemory>
00026 #include <QtCore/QCryptographicHash>
00027 #include <QtCore/QFile>
00028 #include <QtCore/QDir>
00029 
00030 #include "klocalizedstring.h"
00031 
00032 class KMemFile::Private
00033 {
00034 public:
00035   struct sharedInfoData {
00036     int  shmCounter;
00037     qint64 shmDataSize;
00038 
00039     sharedInfoData() {
00040       memset ( this, 0, sizeof ( this ) );
00041     }
00042   };
00043   Private ( KMemFile *_parent ) : readWritePos ( 0 ), shmDataSize ( 0 ), parent ( _parent ) {}
00044 
00045   QString getShmKey ( int iCounter = -1 );
00046   static QString getShmKey ( const QString &filename, int iCounter = -1 );
00047   bool loadContentsFromFile();
00048   void close();
00049 
00050   QString filename;
00051   QSharedMemory shmInfo;
00052   QSharedMemory shmData;
00053   qint64 readWritePos;
00054   qint64 shmDataSize;
00055 
00056   KMemFile *parent;
00057 };
00058 
00059 QString KMemFile::Private::getShmKey ( int iCounter )
00060 {
00061   return getShmKey ( filename, iCounter );
00062 }
00063 
00064 QString KMemFile::Private::getShmKey ( const QString &filename, int iCounter )
00065 {
00066   QByteArray tmp = QString ( QDir ( filename ).canonicalPath() + QString::number ( iCounter ) ).toUtf8();
00067   return QString::fromAscii ( QCryptographicHash::hash ( tmp, QCryptographicHash::Sha1 ) );
00068 }
00069 
00070 bool KMemFile::Private::loadContentsFromFile()
00071 {
00072   QFile f ( filename );
00073   if ( !f.exists() ) {
00074     close();
00075     parent->setErrorString ( i18n ( "File %1 does not exist" , filename ) );
00076     return false;
00077   }
00078   if ( !f.open ( QIODevice::ReadOnly ) ) {
00079     close();
00080     parent->setErrorString ( i18n ( "Cannot open %1 for reading" , filename ) );
00081     return false;
00082   }
00083 
00084   sharedInfoData *infoPtr = static_cast<sharedInfoData*> ( shmInfo.data() );
00085 
00086   infoPtr->shmDataSize = f.size();
00087   shmData.setKey ( getShmKey ( infoPtr->shmCounter ) );
00088   if ( !shmData.create ( infoPtr->shmDataSize ) ) {
00089     close();
00090     parent->setErrorString ( i18n ( "Cannot create memory segment for file %1" , filename ) );
00091     return false;
00092   }
00093   shmData.lock();
00094   qint64 size = 0;
00095   qint64 bytesRead;
00096   char *data = static_cast<char*> ( shmData.data() );
00097   bytesRead = f.read ( data, infoPtr->shmDataSize );
00098   if ( bytesRead != infoPtr->shmDataSize ) {
00099     close();
00100     parent->setErrorString ( i18n ( "Could not read data from %1 into shm" , filename ) );
00101     return false;
00102   }
00103   shmDataSize = size;
00104   shmData.unlock();
00105   return true;
00106 }
00107 
00108 void KMemFile::Private::close()
00109 {
00110   shmData.unlock();
00111   shmData.detach();
00112   shmInfo.unlock();
00113   shmInfo.detach();
00114   readWritePos = 0;
00115   shmDataSize = 0;
00116 }
00117 
00118 KMemFile::KMemFile ( const QString &filename, QObject *parent )
00119     : QIODevice ( parent ), d ( new Private ( this ) )
00120 {
00121   d->filename = filename;
00122 }
00123 
00124 KMemFile::~KMemFile()
00125 {
00126   close();
00127   delete d;
00128 }
00129 
00130 void KMemFile::close ()
00131 {
00132   QIODevice::close();
00133   if ( !isOpen() )
00134     return;
00135   d->close();
00136 }
00137 
00138 bool KMemFile::isSequential () const
00139 {
00140   return false;
00141 }
00142 
00143 bool KMemFile::open ( OpenMode mode )
00144 {
00145   if ( isOpen() ) {
00146     QIODevice::open ( mode );
00147     return false;
00148   }
00149 
00150   if ( mode != QIODevice::ReadOnly ) {
00151     setErrorString ( i18n ( "Only 'ReadOnly' allowed" ) );
00152     return false;
00153   }
00154 
00155   if ( !QFile::exists ( d->filename ) ) {
00156     setErrorString ( i18n ( "File %1 does not exist" , d->filename ) );
00157     return false;
00158   }
00159 
00160   QSharedMemory lock ( QDir ( d->filename ).canonicalPath() );
00161   lock.lock();
00162 
00163   Private::sharedInfoData *infoPtr;
00164   d->shmInfo.setKey ( d->getShmKey() );
00165   // see if it's already in memory
00166   if ( !d->shmInfo.attach ( QSharedMemory::ReadWrite ) ) {
00167     if ( !d->shmInfo.create ( sizeof ( Private::sharedInfoData ) ) ) {
00168       lock.unlock();
00169       setErrorString ( i18n ( "Cannot create memory segment for file %1" , d->filename ) );
00170       return false;
00171     }
00172     d->shmInfo.lock();
00173     // no -> create it
00174     infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
00175     memset ( infoPtr, 0, sizeof ( Private::sharedInfoData ) );
00176     infoPtr->shmCounter = 1;
00177     if ( !d->loadContentsFromFile() ) {
00178       d->shmInfo.unlock();
00179       d->shmInfo.detach();
00180       lock.unlock();
00181       return false;
00182     }
00183   } else {
00184     d->shmInfo.lock();
00185     infoPtr = static_cast<Private::sharedInfoData*> ( d->shmInfo.data() );
00186     d->shmData.setKey ( d->getShmKey ( infoPtr->shmCounter ) );
00187     if ( !d->shmData.attach ( QSharedMemory::ReadOnly ) ) {
00188       if ( !d->loadContentsFromFile() ) {
00189         d->shmInfo.unlock();
00190         d->shmInfo.detach();
00191         lock.unlock();
00192         return false;
00193       }
00194     }
00195   }
00196   d->shmDataSize = infoPtr->shmDataSize;
00197   d->shmInfo.unlock();
00198   lock.unlock();
00199 
00200   setOpenMode ( mode );
00201   return true;
00202 }
00203 
00204 bool KMemFile::seek ( qint64 pos )
00205 {
00206   if ( d->shmDataSize < pos ) {
00207     setErrorString ( i18n ( "Cannot seek past eof" ) );
00208     return false;
00209   }
00210   d->readWritePos = pos;
00211   QIODevice::seek ( pos );
00212   return true;
00213 }
00214 
00215 qint64 KMemFile::size () const
00216 {
00217   return d->shmDataSize;
00218 }
00219 
00220 qint64 KMemFile::readData ( char * data, qint64 maxSize )
00221 {
00222   if ( ( openMode() & QIODevice::ReadOnly ) == 0 )
00223     return -1;
00224 
00225   qint64 maxRead = size() - d->readWritePos;
00226   qint64 bytesToRead = qMin ( maxRead, maxSize );
00227   const char *src = static_cast<const char*> ( d->shmData.data() );
00228   memcpy ( data, &src[d->readWritePos], bytesToRead );
00229   d->readWritePos += bytesToRead;
00230   return bytesToRead;
00231 }
00232 
00233 qint64 KMemFile::writeData ( const char *, qint64 )
00234 {
00235   return -1;
00236 }
00237 
00238 void KMemFile::fileContentsChanged ( const QString &filename )
00239 {
00240   QSharedMemory lock ( QDir ( filename ).canonicalPath() );
00241   lock.lock();
00242 
00243   QSharedMemory shmData ( Private::getShmKey ( filename ) );
00244   if ( !shmData.attach() )
00245     return;
00246   shmData.lock();
00247   Private::sharedInfoData *infoPtr = static_cast<Private::sharedInfoData*> ( shmData.data() );
00248   infoPtr->shmCounter++;
00249   infoPtr->shmDataSize = 0;
00250   shmData.unlock();
00251 }
00252 
00253 #endif //QT_NO_SHAREDMEMORY

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal