khtml Library API Documentation

khtml_pagecache.cpp

00001 /* This file is part of the KDE project 00002 * 00003 * Copyright (C) 2000 Waldo Bastian <bastian@kde.org> 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., 59 Temple Place - Suite 330, 00018 * Boston, MA 02111-1307, USA. 00019 */ 00020 00021 #include "khtml_pagecache.h" 00022 00023 #include <kstaticdeleter.h> 00024 #include <ktempfile.h> 00025 #include <kstandarddirs.h> 00026 00027 #include <qintdict.h> 00028 #include <qtimer.h> 00029 00030 #include <sys/types.h> 00031 #include <unistd.h> 00032 #include <assert.h> 00033 00034 // We keep 12 pages in memory. 00035 #ifndef KHTML_PAGE_CACHE_SIZE 00036 #define KHTML_PAGE_CACHE_SIZE 12 00037 #endif 00038 00039 template class QPtrList<KHTMLPageCacheDelivery>; 00040 class KHTMLPageCacheEntry 00041 { 00042 friend class KHTMLPageCache; 00043 public: 00044 KHTMLPageCacheEntry(long id); 00045 00046 ~KHTMLPageCacheEntry(); 00047 00048 void addData(const QByteArray &data); 00049 00050 void endData(); 00051 00052 bool isComplete() 00053 { return m_complete; } 00054 00055 KHTMLPageCacheDelivery *fetchData(QObject *recvObj, const char *recvSlot); 00056 private: 00057 long m_id; 00058 bool m_complete; 00059 QValueList<QByteArray> m_data; 00060 KTempFile *m_file; 00061 }; 00062 00063 class KHTMLPageCachePrivate 00064 { 00065 public: 00066 long newId; 00067 QIntDict<KHTMLPageCacheEntry> dict; 00068 QPtrList<KHTMLPageCacheDelivery> delivery; 00069 QPtrList<KHTMLPageCacheEntry> expireQueue; 00070 bool deliveryActive; 00071 }; 00072 00073 KHTMLPageCacheEntry::KHTMLPageCacheEntry(long id) : m_id(id), m_complete(false) 00074 { 00075 QString path = locateLocal("tmp", "khtmlcache"); 00076 m_file = new KTempFile(path); 00077 m_file->unlink(); 00078 } 00079 00080 KHTMLPageCacheEntry::~KHTMLPageCacheEntry() 00081 { 00082 delete m_file; 00083 } 00084 00085 00086 void 00087 KHTMLPageCacheEntry::addData(const QByteArray &data) 00088 { 00089 if (m_file->status() == 0) 00090 m_file->dataStream()->writeRawBytes(data.data(), data.size()); 00091 } 00092 00093 void 00094 KHTMLPageCacheEntry::endData() 00095 { 00096 m_complete = true; 00097 if ( m_file->status() == 0) { 00098 m_file->dataStream()->device()->flush(); 00099 m_file->dataStream()->device()->at(0); 00100 } 00101 } 00102 00103 00104 KHTMLPageCacheDelivery * 00105 KHTMLPageCacheEntry::fetchData(QObject *recvObj, const char *recvSlot) 00106 { 00107 // Duplicate fd so that entry can be safely deleted while delivering the data. 00108 int fd = dup(m_file->handle()); 00109 lseek(fd, 0, SEEK_SET); 00110 KHTMLPageCacheDelivery *delivery = new KHTMLPageCacheDelivery(fd); 00111 recvObj->connect(delivery, SIGNAL(emitData(const QByteArray&)), recvSlot); 00112 delivery->recvObj = recvObj; 00113 return delivery; 00114 } 00115 00116 static KStaticDeleter<KHTMLPageCache> pageCacheDeleter; 00117 00118 KHTMLPageCache *KHTMLPageCache::_self = 0; 00119 00120 KHTMLPageCache * 00121 KHTMLPageCache::self() 00122 { 00123 if (!_self) 00124 _self = pageCacheDeleter.setObject(_self, new KHTMLPageCache); 00125 return _self; 00126 } 00127 00128 KHTMLPageCache::KHTMLPageCache() 00129 { 00130 d = new KHTMLPageCachePrivate; 00131 d->newId = 1; 00132 d->deliveryActive = false; 00133 } 00134 00135 KHTMLPageCache::~KHTMLPageCache() 00136 { 00137 d->delivery.setAutoDelete(true); 00138 d->dict.setAutoDelete(true); 00139 delete d; 00140 } 00141 00142 long 00143 KHTMLPageCache::createCacheEntry() 00144 { 00145 KHTMLPageCacheEntry *entry = new KHTMLPageCacheEntry(d->newId); 00146 d->dict.insert(d->newId, entry); 00147 d->expireQueue.append(entry); 00148 if (d->expireQueue.count() > KHTML_PAGE_CACHE_SIZE) 00149 { 00150 KHTMLPageCacheEntry *entry = d->expireQueue.take(0); 00151 d->dict.remove(entry->m_id); 00152 delete entry; 00153 } 00154 return (d->newId++); 00155 } 00156 00157 void 00158 KHTMLPageCache::addData(long id, const QByteArray &data) 00159 { 00160 KHTMLPageCacheEntry *entry = d->dict.find(id); 00161 if (entry) 00162 entry->addData(data); 00163 } 00164 00165 void 00166 KHTMLPageCache::endData(long id) 00167 { 00168 KHTMLPageCacheEntry *entry = d->dict.find(id); 00169 if (entry) 00170 entry->endData(); 00171 } 00172 00173 void 00174 KHTMLPageCache::cancelEntry(long id) 00175 { 00176 KHTMLPageCacheEntry *entry = d->dict.take(id); 00177 if (entry) 00178 { 00179 d->expireQueue.removeRef(entry); 00180 delete entry; 00181 } 00182 } 00183 00184 bool 00185 KHTMLPageCache::isValid(long id) 00186 { 00187 return (d->dict.find(id) != 0); 00188 } 00189 00190 bool 00191 KHTMLPageCache::isComplete(long id) 00192 { 00193 KHTMLPageCacheEntry *entry = d->dict.find(id); 00194 if (entry) 00195 return entry->isComplete(); 00196 return false; 00197 } 00198 00199 void 00200 KHTMLPageCache::fetchData(long id, QObject *recvObj, const char *recvSlot) 00201 { 00202 KHTMLPageCacheEntry *entry = d->dict.find(id); 00203 if (!entry || !entry->isComplete()) return; 00204 00205 // Make this entry the most recent entry. 00206 d->expireQueue.removeRef(entry); 00207 d->expireQueue.append(entry); 00208 00209 d->delivery.append( entry->fetchData(recvObj, recvSlot) ); 00210 if (!d->deliveryActive) 00211 { 00212 d->deliveryActive = true; 00213 QTimer::singleShot(20, this, SLOT(sendData())); 00214 } 00215 } 00216 00217 void 00218 KHTMLPageCache::cancelFetch(QObject *recvObj) 00219 { 00220 KHTMLPageCacheDelivery *next; 00221 for(KHTMLPageCacheDelivery* delivery = d->delivery.first(); 00222 delivery; 00223 delivery = next) 00224 { 00225 next = d->delivery.next(); 00226 if (delivery->recvObj == recvObj) 00227 { 00228 d->delivery.removeRef(delivery); 00229 delete delivery; 00230 } 00231 } 00232 } 00233 00234 void 00235 KHTMLPageCache::sendData() 00236 { 00237 if (d->delivery.isEmpty()) 00238 { 00239 d->deliveryActive = false; 00240 return; 00241 } 00242 KHTMLPageCacheDelivery *delivery = d->delivery.take(0); 00243 assert(delivery); 00244 00245 char buf[8192]; 00246 QByteArray byteArray; 00247 00248 int n = read(delivery->fd, buf, 8192); 00249 00250 if ((n < 0) && (errno == EINTR)) 00251 { 00252 // try again later 00253 d->delivery.append( delivery ); 00254 } 00255 else if (n <= 0) 00256 { 00257 // done. 00258 delivery->emitData(byteArray); // Empty array 00259 delete delivery; 00260 } 00261 else 00262 { 00263 byteArray.setRawData(buf, n); 00264 delivery->emitData(byteArray); 00265 byteArray.resetRawData(buf, n); 00266 d->delivery.append( delivery ); 00267 } 00268 QTimer::singleShot(0, this, SLOT(sendData())); 00269 } 00270 00271 void 00272 KHTMLPageCache::saveData(long id, QDataStream *str) 00273 { 00274 KHTMLPageCacheEntry *entry = d->dict.find(id); 00275 assert(entry); 00276 00277 int fd = entry->m_file->handle(); 00278 if ( fd < 0 ) return; 00279 00280 off_t pos = lseek(fd, 0, SEEK_CUR); 00281 lseek(fd, 0, SEEK_SET); 00282 00283 char buf[8192]; 00284 00285 while(true) 00286 { 00287 int n = read(fd, buf, 8192); 00288 if ((n < 0) && (errno == EINTR)) 00289 { 00290 // try again 00291 continue; 00292 } 00293 else if (n <= 0) 00294 { 00295 // done. 00296 break; 00297 } 00298 else 00299 { 00300 str->writeRawBytes(buf, n); 00301 } 00302 } 00303 00304 if (pos != (off_t)-1) 00305 lseek(fd, pos, SEEK_SET); 00306 } 00307 00308 KHTMLPageCacheDelivery::~KHTMLPageCacheDelivery() 00309 { 00310 close(fd); 00311 } 00312 00313 #include "khtml_pagecache.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:31:26 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003