Source: kio_cache.h


Annotated List
Files
Globals
Hierarchy
Index
#ifndef __kio_cache_h__
#define __kio_cache_h__

#include "kio_job.h"   

#include <qstrlist.h>
#include <qdict.h>
#include <qlist.h>
#include <qstring.h>
#include <qdatetime.h>
#include <qtimer.h>
#include <qbuffer.h>

#include <kconfig.h> 

#define MAX_JOBS 4

class KIOCache;

/**
 * @short A cache entry.
 *
 * KIOCacheEntry encapsulates all data associated with one entry
 * in KIOCache. It is mainly used for communication between @see
 * #KIOCache and @see #KIOCachedJob.
 */
class KIOCacheEntry
{
public:
    /**
     * Constructs a new empty KIOCacheEntry.
     */
    KIOCacheEntry() {}

    /**
     * Constructs a new KIOCacheEntry referencing the same document as
     * 'ref'.
     */
    KIOCacheEntry (const KIOCacheEntry &ref);

    /**
     * Constructs a new KIOCacheEntry referencing _url
     */
    KIOCacheEntry (const QString& _url);

    /**
     * @return TRUE if this cache entry is empty, FALSE if it actually
     * references a document.
     */
    bool isEmpty() const
	{ return docURL.isEmpty(); }

    /**
     * Returns the URL of the document.
     */
    QString url() const
	{ return docURL; }

    /**
     * Returns the local file name for the document, without path.
     */
    QString localFile() const
	{ return localName; }

    QString localKey() const
	{ return localName; }
    /**
     * Sets the local file key, that is the name of the file used to
     * store the documents content. Don't set a complete path, only
     * the filename relativ to the cache path.
     */
    void setLocalKey(QString key)
       { localName = key; }
    
    /**
     * Returns the mime type of the document
     */
    QString mimeType() const
	{ return docMimeType; }
    /**
     * Sets the mime type of the document
     */
     void setMimeType(QString mimeType)
	{ docMimeType = mimeType; }

    /**
     * Returns the redirection, this means the real address of the document.
     */
    QString redirection() const
	{ return redirectionURL; }
    /**
     * Sets the redirection URL.
     */
    void setRedirection( const char* _redirection )
	{ redirectionURL = _redirection; }

    /**
     * Returns the document content or a NULL QByteArray in case something
     * went wrong.
     *
     * Caveat: content() returns a shallow copy of the data only, if
     * you want to modify the data, you need to detach it first!
     */
    QByteArray content() const;

    /**
     * Appends to the document content. Should not be used outside of @see
     * KIOCache and @see KIOCachedJob
     */
    void addData(const QByteArray &_data);
    void addData( const char *_data, int _len );

    /**
     * Returns date and time when this document expires. If an invalid
     * date is returned, this document will never expire.
     */
    QDateTime expiresAt() const 
	{ return expires; }
    /**
     * Set date and time when this document expires. You can pass a
     + null QDateTime to indicate that this document should never expire.
     */
    QDateTime setExpiresAt(const QDateTime &time) 
	{ return expires = time; }

    /**
     * Returns the creation date and time of this document. An invalid
     * QDateTime indicates there is no cretion date available for this
     * document.
     */
    QDateTime createdAt() const
	{ return created; }
    /**
     * Sets the creation date and time of this document. This function
     * should not be used by anything besides @see KIOCache and @see
     * CacheKIOJob.
     */
    QDateTime setCreatedAt(const QDateTime &time) 
	{ return created = time; }

    /**
     * Returns the last date and time this cache entry has been
     * read. Beware: This has nothing to do with the cached documents'
     * last access time, it should be used within KIOCache only.
     * (e.g. for an LRU algorithm to discard cached documents in order
     * to limit on-disk cache size).
     */
    QDateTime lastAccessedAt() const 
	{ return lastAccess; }

    /**
     * Sets the date and time returned as last access time for this
     * cache entry. Shouldn't be used outside of @see KIOCache.
     */
    QDateTime setLastAccessedAt(const QDateTime &time)
	{ return lastAccess = time; }

    /**
     * Returns the date and time this document has been last modified. An
     * invalid QDateTime indicates there is no modification date
     * available for this document.
     */
    QDateTime lastModifiedAt() const
	{ return lastModified; }
    /**
     * Sets the modification date and timefor this document.
     */
    QDateTime setLastModifiedAt(const QDateTime &time)
	{ return lastModified = time; }

    /**
     * Write the content of @ref data to a file and erase data. The
     * filename is KIOCache::cachePath() + localKey(). This function
     * is intended for use by KIOCache only.
     *
     * @return TRUE on success, FALSE on failure.
     */
    bool storeData();

private:
    QDateTime expires;
    QDateTime created;
    QDateTime lastAccess;
    QDateTime lastModified;
    QBuffer data;
    QString docURL;
    QString localName;
    QString docMimeType;
    QString redirectionURL;
};


/**
 * @short Basic functionality for an on-disk cache.
 *
 * KIOCache provides basic functionality to maintain a local on-disk
 * cache for remote documents. KIOCache provides methods to check if a
 * document is in cache and valid (i.e. not yet expired), if a certain
 * URL can be cached at all, to retrieve documents and additional data
 * (such as mime type or expiration date) from cache, to insert
 * documents into the cache and finally to save the cache to and load
 * it from disk and to clear the cache.  Some additional methods cover
 * cache settings like which documents should be cached, how to handle
 * documents without explicit expiration date and so on.
 *
 * Right now, only documents retrieved by the HTTP protocol can be
 * cached, but don't depend on this, this may (and most probably will)
 * change in future.
 *
 * KIOCache should not be used directly to perform cached IO, the
 * recommended way to access documents from the cache is by using @ref
 * KIOCachedJob. This class provides transparent access to cached
 * documents and handles all the tedious details such as checking if a
 * document is in cache and valid (and retrieving it from the source
 * if not) for you.
 */

class KIOCache
{
public:
    KIOCache();
    ~KIOCache();
    
    static void Check_KIOCache_Initialized();

    static void initStatic();
  
    /**
     * Enables or disables the cache.
     */
    static void enableCache( bool enable )
	{ cacheEnabled = enable; }

    /**
     * Enables or disables saving the cache.
     */
    static void enableSaveCache( bool enable )
	{ saveCacheEnabled = enable; }
	
    /**
     * Check enable status
     */
    static bool isEnabled()
	{ return cacheEnabled; }
    static bool isSaveEnabled()
	{ return saveCacheEnabled; }

    /**
     * Reads the cache configuration from config. Cache config entries
     * are expected in section [Cache].
     */
    static void readConfig(KConfig &config);

    /**
     * Stores the cache configuration in config. Cache config entries
     * are written to section [Cache]. The modified KConfig object is
     * returned.
     */
    static KConfig &storeConfig(KConfig &config);
  
    /**
     * Reads the stored cache content from disk. Actually, only the
     * info on which documents are in cache and where they are stored
     * on disk is read, the actual document content is not read until it
     * is needed.
     *
     * Cache info is stored as a KDE config file.  Every cache entry
     * has its own section [Cacheentry #], where # is the number of
     * the entry, starting with 1. Note that these numbers are only
     * used to create unique section names when writing the cache,
     * they have nothing to do with local file names for the cached
     * document's content. Cache entry numbers must be consecutive for
     * readCache() to work correctly. If there are numbers missing,
     * only entries up to the first missing number will be read back.
     * 
     * return TRUE on success, FALSE if nothing can be read back.  */
    static bool readCache();
    /**
     * Writes the cache content to disk in a form that is understood
     * by @ref #readCache and creates an index.html file in the cache
     * directory reflecting the current cache content.
     *
     * Note that some part of the cache content (namely the cached
     * documents) will be written immediately when a document is
     * entered into cache, but other associated data will be kept in
     * memory. After a successful storeCache() however the complete
     * cache content at the time of calling is guaranteed to be on
     * disk.
     *
     * @return TRUE on success, FALSE if the cache content cannot be
     * stored. 
     */
    static bool storeCache();

    /**
     * @return the full path of the written index file or an empty string
     *         in case of an error.
     */
    static QString storeIndex();
  
    /**
     * Clears the cache.
     */
    static bool clear();

    /**
     * Returns a QString containing an HTML document which describes the
     * current cache contents. Useful for presenting in an HTML widget
     * or for storing as index.html file in the cache directory.
     */
    static QString htmlIndex();

    /**
     * Check if the document referenced by url is in cache and the
     * cached copy is valid, i.e. not yet expired. Use @ref isCached
     * if you want to check for cached documents that may already have
     * expired.
     */
    static bool isValid(const QString &url);

    /**
     * Check if the document referenced by url is in cache. This
     * returns true even if the document is no longer valid. Use 
     * @see isValid if you want to check document validity.
     */
    static bool isCached(const QString &url);

    /**
     * Get the document referenced by url from the cache. If there is
     * no matching document in cache, an empty @ref KIOCacheEntry is
     * returned. Note that a returned document may no longer be valid,
     * use @ref isValid to check for validity.
     */
    static const KIOCacheEntry& lookup(const QString &url);

    /**
     * Put a document into the cache. At least the url field (see 
     * @ref KIOCacheEntry) of entry must be set to a (syntactically)
     * correct url. The document will be stored in cache if its URL is
     * cacheable (see @ref #isCacheable) and if the document has not
     * yet expired (as indicated by entry->expiresAt()).
     *
     * Note: entry must point to a KIOCacheEntry allocated with new
     * and may not be deleted or modified by the caller if insert()
     * returns TRUE. KIOCache stores this pointer in its internal
     * dictionary in this case. If insert() returns FALSE however, the
     * caller is responsible for deleting entry.
     *
     * @returns TRUE if entry is stored in cache, FALSE if not.  */
    static bool insert(KIOCacheEntry *entry);
    
    /**
     * Indicates if the document referenced by url may be stored in
     * cache at all. The test is based on the URL only, document
     * content, expiration date or other information is not
     * used. Hence, a document may be rejected by @ref #insert even if
     * isCacheable returned TRUE, e.g. because it has already expired
     * at the time insert is called for this document.
     *
     * Currently, isCacheable returns TRUE if the protocol part of url
     * is listed in @ref cacheProtocols and the hostname part is not
     * listed in @ref excludeHosts. These settings are user
     * configurable.
     *
     * In future, isCacheable probably will be extended to check other
     * criteria as well.
     *
     * @returns FALSE if the document referenced by URL may not be
     * stored in cache, TRUE otherwise.
     */
    static bool isCacheable(const QString &_url);

    /**
     * Returns the name of the directory where all the cached files
     * reside.
     */
    static const QString& cacheRoot()
	{ return *cachePath; }


    /**
     * Trim url, that is remove all parts of url that should not be
     * used in the cache key. Right now, only the reference part is
     * removed, so 'http://www.somewhere.org/something#index_1' and
     * 'http://www.somewhere.org/something#index_2' will both be cached
     * as 'http://www.somewhere.org/something'.
     *
     * @returns the trimmed URL
     */
    static QString trimURL(const QString &url);

protected:
    /**
     * Calculate a default expiration date time for entry based on user
     * settings and the date fields that are set in entry.
     *
     * @returns A default expiration date and time.
     * @see KIOCacheEntry
     */
    static QDateTime defaultExpire(const KIOCacheEntry *entry);
    /**
     * Calculate a local file name for the document in entry. This
     * local file name consists of the prefix 'entry-', the current
     * date and time, a '.', a sequence number, another '.' and the
     * filename part of the documents URL.
     */
    static QString localKey(const KIOCacheEntry *entry);
private:
    /**
     * This dictionary is used to store information about every
     * document currently in cache. 
     */
    static QDict<KIOCacheEntry> *cacheDict;

    /**
     * A list of protocols that should be handled by the cache.
     * User configurable through the entry 'Protocols' in the 'Cache'
     * section of the applications config file. Defaults to 'http' and
     * 'cgi' if not set.
     */
    static QStrList *cacheProtocols;

    /**
     * A list of host/domain names that should be excluded from
     * caching. The names may contain wildcards, see the KIO proxy
     * exclude list for an example.
     * User configurable through the entry 'ExcludeHosts' in the 'Cache'
     * section of the applications config file. Empty by default.
     */
    static QStrList *excludeHosts;

    /**
     * The path where KIOCache stores the cached documents and related
     * information.
     */
    static QString *cachePath;

    /**
     * This flag tells wheter the cache is enabled or not. If
     * cacheEnabled is FALSE, @ref #isCacheable and @ref #isValid will
     * always return FALSE. Note however that it still is possible to
     * enter documents with @ref #insert and that @ref #isCached will
     * still return TRUE if a document is cached.
     *
     * This flag defaults to FALSE before the first call to
     * @ref #loadConfig. After that, it has the value given by the
     * 'UseCache' entry in the [Cache] config section, TRUE if no such
     * entry is given.
     */
    static bool cacheEnabled;

    /**
     * This flag tells wheter the cache will save itself to disk.     
     */
    static bool saveCacheEnabled;

    /**
     * Maximum length of URL's to display in full in @ref #index. Any
     * URL in cache which is longer than maxURLLenght will be
     * abbreviated for display.
     */
    static unsigned int maxURLLength;
};

/**
 * @short Transparent access to cached data.
 *
 * KIOCachedJob provides a means to transparently access data that may
 * reside in a local on-disk cache. Transparent means you don't need
 * to worry about the details, just use KIOCachedJob like you would
 * use KIOJob. KIOCachedJob will fetch the requested documents from the
 * cache if appropriate and get them from their original source if not
 * (see @ref #KIOCache for details like caching strategy and the
 * like).
 *
 * KIOCachedJob provides the same interface as KIOJob with one
 * addition: @ref #forceReload can be used to force reloading of a
 * document even if it is in cache and valid.
 *
 * Right now, data is only cached (and searched in cache) when it is
 * requested by calling get(), all other request methods ignore the cache.
 * Do not depend on this however, this can and most probably will
 * change in future.
 */

class KIOCachedJob : public KIOJob
{
    Q_OBJECT
public:
    enum Step 
    {
      STEP_NONE, STEP_REDIRECTION, STEP_DATE, STEP_MIME, STEP_DATA, STEP_FINISHED
    };
  
    /**
     * Constructs a new job. Overloaded from @ref KIOJob
     */
    KIOCachedJob();
    ~KIOCachedJob();
  
    /**
      * Calling forceReload(TRUE) (or forceReload() for convenience)
      * forces KIOCachedJob to retrieve all documents requested before a
      * subsequent call to forceReload(FALSE) directly from the original
      * source, even if they are in cache and valid. It doesn't turn off
      * caching of these documents however, use KIOCache::enable(FALSE)
      * to turn off caching altogether or use KIOJob instead of
      * CachedIOJob to bypass the cache for certain documents.
      */
    void forceReload(bool _force_reload = TRUE) 
	{ m_bLookInCache = !_force_reload; }
    
    /**
      * Retrieve _url, get it from cache if possible and if _reload is
      * FALSE. Data is delivered by sending appropriate signals (see
      * @ref KIOJob for details).
      */
    void get( const char *_url, bool _reload = false );
    
protected slots:
    ////////////////
    // Slots used internally for handling cached data.
    ////////////////

    /**
     * This slot is connected to the see #finished signal of the same
     * KIOCachedJob when a document is retrieved and should be stored
     * in cache. The document is written to the cache in this function.
     */
    virtual void slotFinished();
    
    /**
     * This slot is connected to the @see #data signal of this object
     * while a document is retrieved that should be stored in cache.
     * It simply adds all data received to @see dataBuffer which is
     * used later to store all of the data in cache (and maybe to pass
     * the data already available to KIOCachedJobs in repeater mode).
     */
    virtual void slotData( void *_data, int _len);

    virtual void slotRedirection( const char *_url );
    virtual void slotMimeType( const char *_mime );
    virtual void slotError( int, const char* );
  
    /**
     * This slot is connected to the @see #date signal of this object 
     * while a document is retrieved that should be stored in
     * cache. It stores the appropriate dates (most notably EXPIRES)
     * in order to commit them to cache later when @see #commitToCache
     * is called.
     */
    // void storeDate();

    /////////////////////////
    // Slots used if we got a cache hit.
    ////////////////////////

    void slotTimeout();
  
protected:
    /**
      * If TRUE, get documents from cache if possible. If false,
      * always retrieve documents from the original source. See also
      * @ref #forceReload. By default, look_in_cache is TRUE.
      */
    bool m_bLookInCache;

    /**
      * A pointer to the new cache entry for the current document. 
      */
    KIOCacheEntry *m_pCurrentDoc;  

    QTimer m_timer;
    Step m_step;
};

#endif

Generated by: root@tantive.terraplex.com on Sun Feb 27 17:39:31 2000, using kdoc 2.0a33.