mirror of
https://bitbucket.org/smil3y/kdelibs.git
synced 2025-02-24 19:02:48 +00:00
296 lines
6.5 KiB
C++
296 lines
6.5 KiB
C++
![]() |
/* This file is part of the KDE project
|
||
|
*
|
||
|
* Copyright (C) 2000 Waldo Bastian <bastian@kde.org>
|
||
|
* Copyright (C) 2007 Nick Shaforostoff <shafff@ukr.net>
|
||
|
*
|
||
|
* 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 "khtml_pagecache.h"
|
||
|
|
||
|
#include <kfilterdev.h>
|
||
|
#include <QTemporaryFile>
|
||
|
#include <kstandarddirs.h>
|
||
|
|
||
|
#include <QQueue>
|
||
|
#include <QHash>
|
||
|
#include <QList>
|
||
|
#include <QtCore/QTimer>
|
||
|
#include <QtCore/QFile>
|
||
|
#include <errno.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <unistd.h>
|
||
|
#include <assert.h>
|
||
|
|
||
|
// We keep 12 pages in memory.
|
||
|
#ifndef KHTML_PAGE_CACHE_SIZE
|
||
|
#define KHTML_PAGE_CACHE_SIZE 12
|
||
|
#endif
|
||
|
|
||
|
template class QList<KHTMLPageCacheDelivery*>;
|
||
|
class KHTMLPageCacheEntry
|
||
|
{
|
||
|
friend class KHTMLPageCache;
|
||
|
public:
|
||
|
KHTMLPageCacheEntry(long id);
|
||
|
|
||
|
~KHTMLPageCacheEntry();
|
||
|
|
||
|
void addData(const QByteArray &data);
|
||
|
void endData();
|
||
|
|
||
|
bool isComplete() const {return m_complete;}
|
||
|
QString fileName() const {return m_fileName;}
|
||
|
|
||
|
KHTMLPageCacheDelivery *fetchData(QObject *recvObj, const char *recvSlot);
|
||
|
private:
|
||
|
long m_id;
|
||
|
bool m_complete;
|
||
|
QByteArray m_buffer;
|
||
|
QIODevice* m_file;
|
||
|
QString m_fileName;
|
||
|
};
|
||
|
|
||
|
class KHTMLPageCachePrivate
|
||
|
{
|
||
|
public:
|
||
|
long newId;
|
||
|
bool deliveryActive;
|
||
|
QHash<int, KHTMLPageCacheEntry*> dict;
|
||
|
QList<KHTMLPageCacheDelivery*> delivery;
|
||
|
QQueue<long> expireQueue;
|
||
|
};
|
||
|
|
||
|
KHTMLPageCacheEntry::KHTMLPageCacheEntry(long id)
|
||
|
: m_id(id)
|
||
|
, m_complete(false)
|
||
|
{
|
||
|
//get tmp file name
|
||
|
QTemporaryFile* f=new QTemporaryFile(KStandardDirs::locateLocal("tmp", "")+"khtmlcacheXXXXXX.tmp");
|
||
|
f->open();
|
||
|
m_fileName=f->fileName();
|
||
|
f->setAutoRemove(false);
|
||
|
delete f;
|
||
|
|
||
|
m_file = KFilterDev::deviceForFile(m_fileName, "application/x-gzip"/*,false*/);
|
||
|
m_file->open(QIODevice::WriteOnly);
|
||
|
}
|
||
|
|
||
|
KHTMLPageCacheEntry::~KHTMLPageCacheEntry()
|
||
|
{
|
||
|
delete m_file;
|
||
|
QFile::remove(m_fileName);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
KHTMLPageCacheEntry::addData(const QByteArray &data)
|
||
|
{
|
||
|
m_buffer+=data;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCacheEntry::endData()
|
||
|
{
|
||
|
m_complete = true;
|
||
|
m_file->write(m_buffer);
|
||
|
m_buffer.clear();
|
||
|
m_file->close();
|
||
|
}
|
||
|
|
||
|
|
||
|
KHTMLPageCacheDelivery *
|
||
|
KHTMLPageCacheEntry::fetchData(QObject *recvObj, const char *recvSlot)
|
||
|
{
|
||
|
// Duplicate fd so that entry can be safely deleted while delivering the data.
|
||
|
KHTMLPageCacheDelivery *delivery=new KHTMLPageCacheDelivery(
|
||
|
KFilterDev::deviceForFile (m_fileName, "application/x-gzip")
|
||
|
);
|
||
|
delivery->file->open(QIODevice::ReadOnly);
|
||
|
|
||
|
recvObj->connect(delivery, SIGNAL(emitData(QByteArray)), recvSlot);
|
||
|
delivery->recvObj = recvObj;
|
||
|
return delivery;
|
||
|
}
|
||
|
|
||
|
KHTMLPageCache *
|
||
|
KHTMLPageCache::self()
|
||
|
{
|
||
|
K_GLOBAL_STATIC(KHTMLPageCache, _self)
|
||
|
return _self;
|
||
|
}
|
||
|
|
||
|
KHTMLPageCache::KHTMLPageCache()
|
||
|
:d( new KHTMLPageCachePrivate)
|
||
|
{
|
||
|
d->newId = 1;
|
||
|
d->deliveryActive = false;
|
||
|
}
|
||
|
|
||
|
KHTMLPageCache::~KHTMLPageCache()
|
||
|
{
|
||
|
qDeleteAll(d->dict);
|
||
|
qDeleteAll(d->delivery);
|
||
|
delete d;
|
||
|
}
|
||
|
|
||
|
long
|
||
|
KHTMLPageCache::createCacheEntry()
|
||
|
{
|
||
|
|
||
|
KHTMLPageCacheEntry *entry = new KHTMLPageCacheEntry(d->newId);
|
||
|
d->dict.insert(d->newId, entry);
|
||
|
d->expireQueue.append(d->newId);
|
||
|
if (d->expireQueue.count() > KHTML_PAGE_CACHE_SIZE)
|
||
|
delete d->dict.take(d->expireQueue.dequeue());
|
||
|
return (d->newId++);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCache::addData(long id, const QByteArray &data)
|
||
|
{
|
||
|
|
||
|
KHTMLPageCacheEntry *entry = d->dict.value( id );
|
||
|
if (entry)
|
||
|
entry->addData(data);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCache::endData(long id)
|
||
|
{
|
||
|
KHTMLPageCacheEntry *entry = d->dict.value( id );
|
||
|
if (entry)
|
||
|
entry->endData();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCache::cancelEntry(long id)
|
||
|
{
|
||
|
KHTMLPageCacheEntry *entry = d->dict.take( id );
|
||
|
if (entry)
|
||
|
{
|
||
|
d->expireQueue.removeAll(entry->m_id);
|
||
|
delete entry;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
KHTMLPageCache::isValid(long id)
|
||
|
{
|
||
|
return d->dict.contains(id);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
KHTMLPageCache::isComplete(long id)
|
||
|
{
|
||
|
KHTMLPageCacheEntry *entry = d->dict.value( id );
|
||
|
if (entry)
|
||
|
return entry->isComplete();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCache::fetchData(long id, QObject *recvObj, const char *recvSlot)
|
||
|
{
|
||
|
KHTMLPageCacheEntry *entry = d->dict.value( id );
|
||
|
if (!entry || !entry->isComplete()) return;
|
||
|
|
||
|
// Make this entry the most recent entry.
|
||
|
d->expireQueue.removeAll(entry->m_id);
|
||
|
d->expireQueue.enqueue(entry->m_id);
|
||
|
|
||
|
d->delivery.append( entry->fetchData(recvObj, recvSlot) );
|
||
|
if (!d->deliveryActive)
|
||
|
{
|
||
|
d->deliveryActive = true;
|
||
|
QTimer::singleShot(20, this, SLOT(sendData()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCache::cancelFetch(QObject *recvObj)
|
||
|
{
|
||
|
QMutableListIterator<KHTMLPageCacheDelivery*> it( d->delivery );
|
||
|
while (it.hasNext()) {
|
||
|
KHTMLPageCacheDelivery* delivery = it.next();
|
||
|
if (delivery->recvObj == recvObj)
|
||
|
{
|
||
|
delete delivery;
|
||
|
it.remove();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCache::sendData()
|
||
|
{
|
||
|
if (d->delivery.isEmpty())
|
||
|
{
|
||
|
d->deliveryActive = false;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
KHTMLPageCacheDelivery *delivery = d->delivery.takeFirst();
|
||
|
assert(delivery);
|
||
|
|
||
|
QByteArray byteArray(delivery->file->read(64*1024));
|
||
|
delivery->emitData(byteArray);
|
||
|
|
||
|
//put back in queue
|
||
|
if (delivery->file->atEnd())
|
||
|
{
|
||
|
// done.
|
||
|
delivery->file->close();
|
||
|
delivery->emitData(QByteArray()); // Empty array
|
||
|
delete delivery;
|
||
|
}
|
||
|
else
|
||
|
d->delivery.append( delivery );
|
||
|
|
||
|
QTimer::singleShot(0, this, SLOT(sendData()));
|
||
|
}
|
||
|
|
||
|
void
|
||
|
KHTMLPageCache::saveData(long id, QDataStream *str)
|
||
|
{
|
||
|
assert(d->dict.contains( id ));
|
||
|
KHTMLPageCacheEntry *entry = d->dict.value( id );
|
||
|
|
||
|
if (!entry->isComplete())
|
||
|
{
|
||
|
QTimer::singleShot(20, this, SLOT(saveData()));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
QIODevice* file = KFilterDev::deviceForFile (entry->fileName(), "application/x-gzip");
|
||
|
if (!file->open(QIODevice::ReadOnly))
|
||
|
return;
|
||
|
|
||
|
QByteArray byteArray(file->readAll());
|
||
|
file->close();
|
||
|
|
||
|
str->writeRawData(byteArray.constData(), byteArray.length());
|
||
|
|
||
|
}
|
||
|
|
||
|
KHTMLPageCacheDelivery::~KHTMLPageCacheDelivery()
|
||
|
{
|
||
|
file->close();
|
||
|
delete file;
|
||
|
}
|
||
|
|
||
|
#include "moc_khtml_pagecache.cpp"
|