• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

khtml_pagecache.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002  *
00003  * Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
00004  * Copyright (C) 2007 Nick Shaforostoff <shafff@ukr.net>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public License
00017  * along with this library; see the file COPYING.LIB.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  */
00021 
00022 #include "khtml_pagecache.h"
00023 
00024 #include <kfilterdev.h>
00025 #include <QTemporaryFile>
00026 #include <kstandarddirs.h>
00027 
00028 #include <QQueue>
00029 #include <QHash>
00030 #include <QList>
00031 #include <QtCore/QTimer>
00032 #include <QtCore/QFile>
00033 #include <errno.h>
00034 #include <sys/types.h>
00035 #include <unistd.h>
00036 #include <assert.h>
00037 
00038 // We keep 12 pages in memory.
00039 #ifndef KHTML_PAGE_CACHE_SIZE
00040 #define KHTML_PAGE_CACHE_SIZE 12
00041 #endif
00042 
00043 template class QList<KHTMLPageCacheDelivery*>;
00044 class KHTMLPageCacheEntry
00045 {
00046   friend class KHTMLPageCache;
00047 public:
00048   KHTMLPageCacheEntry(long id);
00049 
00050   ~KHTMLPageCacheEntry();
00051 
00052   void addData(const QByteArray &data);
00053   void endData();
00054 
00055   bool isComplete() const {return m_complete;}
00056   QString fileName() const {return m_fileName;}
00057 
00058   KHTMLPageCacheDelivery *fetchData(QObject *recvObj, const char *recvSlot);
00059 private:
00060   long m_id;
00061   bool m_complete;
00062   QByteArray m_buffer;
00063   QIODevice* m_file;
00064   QString m_fileName;
00065 };
00066 
00067 class KHTMLPageCachePrivate
00068 {
00069 public:
00070   long newId;
00071   bool deliveryActive;
00072   QHash<int, KHTMLPageCacheEntry*> dict;
00073   QList<KHTMLPageCacheDelivery*> delivery;
00074   QQueue<long> expireQueue;
00075 };
00076 
00077 KHTMLPageCacheEntry::KHTMLPageCacheEntry(long id)
00078     : m_id(id)
00079     , m_complete(false)
00080 {
00081   //get tmp file name
00082   QTemporaryFile* f=new QTemporaryFile(KStandardDirs::locateLocal("tmp", "")+"khtmlcacheXXXXXX.tmp");
00083   f->open();
00084   m_fileName=f->fileName();
00085   f->setAutoRemove(false);
00086   delete f;
00087 
00088   m_file = KFilterDev::deviceForFile(m_fileName, "application/x-gzip"/*,false*/);
00089   m_file->open(QIODevice::WriteOnly);
00090 }
00091 
00092 KHTMLPageCacheEntry::~KHTMLPageCacheEntry()
00093 {
00094   delete m_file;
00095   QFile::remove(m_fileName);
00096 }
00097 
00098 
00099 void
00100 KHTMLPageCacheEntry::addData(const QByteArray &data)
00101 {
00102     m_buffer+=data;
00103 }
00104 
00105 void
00106 KHTMLPageCacheEntry::endData()
00107 {
00108   m_complete = true;
00109  m_file->write(m_buffer);
00110  m_buffer.clear();
00111  m_file->close();
00112 }
00113 
00114 
00115 KHTMLPageCacheDelivery *
00116 KHTMLPageCacheEntry::fetchData(QObject *recvObj, const char *recvSlot)
00117 {
00118   // Duplicate fd so that entry can be safely deleted while delivering the data.
00119   KHTMLPageCacheDelivery *delivery=new KHTMLPageCacheDelivery(
00120                                                               KFilterDev::deviceForFile (m_fileName, "application/x-gzip")
00121                                                              );
00122   delivery->file->open(QIODevice::ReadOnly);
00123 
00124   recvObj->connect(delivery, SIGNAL(emitData(const QByteArray&)), recvSlot);
00125   delivery->recvObj = recvObj;
00126   return delivery;
00127 }
00128 
00129 KHTMLPageCache *
00130 KHTMLPageCache::self()
00131 {
00132   K_GLOBAL_STATIC(KHTMLPageCache, _self)
00133   return _self;
00134 }
00135 
00136 KHTMLPageCache::KHTMLPageCache()
00137     :d( new KHTMLPageCachePrivate)
00138 {
00139   d->newId = 1;
00140   d->deliveryActive = false;
00141 }
00142 
00143 KHTMLPageCache::~KHTMLPageCache()
00144 {
00145   qDeleteAll(d->dict);
00146   qDeleteAll(d->delivery);
00147   delete d;
00148 }
00149 
00150 long
00151 KHTMLPageCache::createCacheEntry()
00152 {
00153 
00154   KHTMLPageCacheEntry *entry = new KHTMLPageCacheEntry(d->newId);
00155   d->dict.insert(d->newId, entry);
00156   d->expireQueue.append(d->newId);
00157   if (d->expireQueue.count() > KHTML_PAGE_CACHE_SIZE)
00158      delete d->dict.take(d->expireQueue.dequeue());
00159   return (d->newId++);
00160 }
00161 
00162 void
00163 KHTMLPageCache::addData(long id, const QByteArray &data)
00164 {
00165 
00166   KHTMLPageCacheEntry *entry = d->dict.value( id );
00167   if (entry)
00168      entry->addData(data);
00169 }
00170 
00171 void
00172 KHTMLPageCache::endData(long id)
00173 {
00174   KHTMLPageCacheEntry *entry = d->dict.value( id );
00175   if (entry)
00176      entry->endData();
00177 }
00178 
00179 void
00180 KHTMLPageCache::cancelEntry(long id)
00181 {
00182   KHTMLPageCacheEntry *entry = d->dict.take( id );
00183   if (entry)
00184   {
00185      d->expireQueue.removeAll(entry->m_id);
00186      delete entry;
00187   }
00188 }
00189 
00190 bool
00191 KHTMLPageCache::isValid(long id)
00192 {
00193   return d->dict.contains(id);
00194 }
00195 
00196 bool
00197 KHTMLPageCache::isComplete(long id)
00198 {
00199   KHTMLPageCacheEntry *entry = d->dict.value( id );
00200   if (entry)
00201      return entry->isComplete();
00202   return false;
00203 }
00204 
00205 void
00206 KHTMLPageCache::fetchData(long id, QObject *recvObj, const char *recvSlot)
00207 {
00208   KHTMLPageCacheEntry *entry = d->dict.value( id );
00209   if (!entry || !entry->isComplete()) return;
00210 
00211   // Make this entry the most recent entry.
00212   d->expireQueue.removeAll(entry->m_id);
00213   d->expireQueue.enqueue(entry->m_id);
00214 
00215   d->delivery.append( entry->fetchData(recvObj, recvSlot) );
00216   if (!d->deliveryActive)
00217   {
00218      d->deliveryActive = true;
00219      QTimer::singleShot(20, this, SLOT(sendData()));
00220   }
00221 }
00222 
00223 void
00224 KHTMLPageCache::cancelFetch(QObject *recvObj)
00225 {
00226   QMutableListIterator<KHTMLPageCacheDelivery*> it( d->delivery );
00227   while (it.hasNext()) {
00228       KHTMLPageCacheDelivery* delivery = it.next();
00229       if (delivery->recvObj == recvObj)
00230       {
00231          delete delivery;
00232          it.remove();
00233       }
00234   }
00235 }
00236 
00237 void
00238 KHTMLPageCache::sendData()
00239 {
00240   if (d->delivery.isEmpty())
00241   {
00242      d->deliveryActive = false;
00243      return;
00244   }
00245 
00246   KHTMLPageCacheDelivery *delivery = d->delivery.takeFirst();
00247   assert(delivery);
00248 
00249   QByteArray byteArray(delivery->file->read(64*1024));
00250   delivery->emitData(byteArray);
00251 
00252   //put back in queue
00253   if (delivery->file->atEnd())
00254   {
00255     // done.
00256     delivery->file->close();
00257     delivery->emitData(QByteArray()); // Empty array
00258     delete delivery;
00259   }
00260   else
00261     d->delivery.append( delivery );
00262 
00263   QTimer::singleShot(0, this, SLOT(sendData()));
00264 }
00265 
00266 void
00267 KHTMLPageCache::saveData(long id, QDataStream *str)
00268 {
00269   assert(d->dict.contains( id ));
00270   KHTMLPageCacheEntry *entry = d->dict.value( id );
00271 
00272   if (!entry->isComplete())
00273   {
00274       QTimer::singleShot(20, this, SLOT(saveData()));
00275       return;
00276   }
00277 
00278   QIODevice* file = KFilterDev::deviceForFile (entry->fileName(), "application/x-gzip");
00279   if (!file->open(QIODevice::ReadOnly))
00280     return;
00281 
00282   QByteArray byteArray(file->readAll());
00283   file->close();
00284 
00285   str->writeRawData(byteArray.constData(), byteArray.length());
00286 
00287 }
00288 
00289 KHTMLPageCacheDelivery::~KHTMLPageCacheDelivery()
00290 {
00291   file->close();
00292   delete file;
00293 }
00294 
00295 #include "khtml_pagecache.moc"

KHTML

Skip menu "KHTML"
  • Main Page
  • 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
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
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