📄 khtml_pagecache.cpp
字号:
/* This file is part of the KDE project * * Copyright (C) 2000 Waldo Bastian <bastian@kde.org> * * 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 <kstaticdeleter.h>#include <ktempfile.h>#include <kstandarddirs.h>#include <qintdict.h>#include <qtimer.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#endiftemplate class QPtrList<KHTMLPageCacheDelivery>;class KHTMLPageCacheEntry{ friend class KHTMLPageCache;public: KHTMLPageCacheEntry(long id); ~KHTMLPageCacheEntry(); void addData(const QByteArray &data); void endData(); bool isComplete() { return m_complete; } KHTMLPageCacheDelivery *fetchData(QObject *recvObj, const char *recvSlot);private: long m_id; bool m_complete; QValueList<QByteArray> m_data; KTempFile *m_file;};class KHTMLPageCachePrivate{public: long newId; QIntDict<KHTMLPageCacheEntry> dict; QPtrList<KHTMLPageCacheDelivery> delivery; QPtrList<KHTMLPageCacheEntry> expireQueue; bool deliveryActive;};KHTMLPageCacheEntry::KHTMLPageCacheEntry(long id) : m_id(id), m_complete(false){ QString path = locateLocal("tmp", "khtmlcache"); m_file = new KTempFile(path); m_file->unlink();}KHTMLPageCacheEntry::~KHTMLPageCacheEntry(){ delete m_file;}voidKHTMLPageCacheEntry::addData(const QByteArray &data){ if (m_file->status() == 0) m_file->dataStream()->writeRawBytes(data.data(), data.size());}voidKHTMLPageCacheEntry::endData(){ m_complete = true; if ( m_file->status() == 0) { m_file->dataStream()->device()->flush(); m_file->dataStream()->device()->at(0); }}KHTMLPageCacheDelivery *KHTMLPageCacheEntry::fetchData(QObject *recvObj, const char *recvSlot){ // Duplicate fd so that entry can be safely deleted while delivering the data. int fd = dup(m_file->handle()); lseek(fd, 0, SEEK_SET); KHTMLPageCacheDelivery *delivery = new KHTMLPageCacheDelivery(fd); recvObj->connect(delivery, SIGNAL(emitData(const QByteArray&)), recvSlot); delivery->recvObj = recvObj; return delivery;}static KStaticDeleter<KHTMLPageCache> pageCacheDeleter;KHTMLPageCache *KHTMLPageCache::_self = 0;KHTMLPageCache *KHTMLPageCache::self(){ if (!_self) _self = pageCacheDeleter.setObject(_self, new KHTMLPageCache); return _self;}KHTMLPageCache::KHTMLPageCache(){ d = new KHTMLPageCachePrivate; d->newId = 1; d->deliveryActive = false;}KHTMLPageCache::~KHTMLPageCache(){ d->delivery.setAutoDelete(true); d->dict.setAutoDelete(true); delete d;}longKHTMLPageCache::createCacheEntry(){ KHTMLPageCacheEntry *entry = new KHTMLPageCacheEntry(d->newId); d->dict.insert(d->newId, entry); d->expireQueue.append(entry); if (d->expireQueue.count() > KHTML_PAGE_CACHE_SIZE) { KHTMLPageCacheEntry *entry = d->expireQueue.take(0); d->dict.remove(entry->m_id); delete entry; } return (d->newId++);}voidKHTMLPageCache::addData(long id, const QByteArray &data){ KHTMLPageCacheEntry *entry = d->dict.find(id); if (entry) entry->addData(data);}voidKHTMLPageCache::endData(long id){ KHTMLPageCacheEntry *entry = d->dict.find(id); if (entry) entry->endData();}voidKHTMLPageCache::cancelEntry(long id){ KHTMLPageCacheEntry *entry = d->dict.take(id); if (entry) { d->expireQueue.removeRef(entry); delete entry; }}boolKHTMLPageCache::isValid(long id){ return (d->dict.find(id) != 0);}boolKHTMLPageCache::isComplete(long id){ KHTMLPageCacheEntry *entry = d->dict.find(id); if (entry) return entry->isComplete(); return false;}voidKHTMLPageCache::fetchData(long id, QObject *recvObj, const char *recvSlot){ KHTMLPageCacheEntry *entry = d->dict.find(id); if (!entry || !entry->isComplete()) return; // Make this entry the most recent entry. d->expireQueue.removeRef(entry); d->expireQueue.append(entry); d->delivery.append( entry->fetchData(recvObj, recvSlot) ); if (!d->deliveryActive) { d->deliveryActive = true; QTimer::singleShot(20, this, SLOT(sendData())); }}voidKHTMLPageCache::cancelFetch(QObject *recvObj){ KHTMLPageCacheDelivery *next; for(KHTMLPageCacheDelivery* delivery = d->delivery.first(); delivery; delivery = next) { next = d->delivery.next(); if (delivery->recvObj == recvObj) { d->delivery.removeRef(delivery); delete delivery; } }}voidKHTMLPageCache::sendData(){ if (d->delivery.isEmpty()) { d->deliveryActive = false; return; } KHTMLPageCacheDelivery *delivery = d->delivery.take(0); assert(delivery); char buf[8192]; QByteArray byteArray; int n = read(delivery->fd, buf, 8192); if ((n < 0) && (errno == EINTR)) { // try again later d->delivery.append( delivery ); } else if (n <= 0) { // done. delivery->emitData(byteArray); // Empty array delete delivery; } else { byteArray.setRawData(buf, n); delivery->emitData(byteArray); byteArray.resetRawData(buf, n); d->delivery.append( delivery ); } QTimer::singleShot(0, this, SLOT(sendData()));}voidKHTMLPageCache::saveData(long id, QDataStream *str){ KHTMLPageCacheEntry *entry = d->dict.find(id); assert(entry); int fd = entry->m_file->handle(); if ( fd < 0 ) return; off_t pos = lseek(fd, 0, SEEK_CUR); lseek(fd, 0, SEEK_SET); char buf[8192]; while(true) { int n = read(fd, buf, 8192); if ((n < 0) && (errno == EINTR)) { // try again continue; } else if (n <= 0) { // done. break; } else { str->writeRawBytes(buf, n); } } if (pos != (off_t)-1) lseek(fd, pos, SEEK_SET);}KHTMLPageCacheDelivery::~KHTMLPageCacheDelivery(){ close(fd);}#include "khtml_pagecache.moc"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -