⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cache.c

📁 浏览器的源代码,可移植到嵌入式设备.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * File: cache.c * * Copyright 2000, 2001, 2002, 2003, 2004 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *//* * Dillo's cache module */#include <ctype.h>              /* for tolower */#include <sys/types.h>#include <sys/stat.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include "msg.h"#include "list.h"#include "IO/Url.h"#include "IO/IO.h"#include "web.h"#include "dicache.h"#include "interface.h"#include "nav.h"#include "cookies.h"#include "misc.h"#define NULLKey 0#define DEBUG_LEVEL 5#include "debug.h"/* *  Local data types */typedef struct {   const DilloUrl *Url;      /* Cached Url. Url is used as a primary Key */   const char *Type;         /* MIME type string */   GString *Header;          /* HTTP header */   const DilloUrl *Location; /* New URI for redirects */   void *Data;               /* Pointer to raw data */   size_t ValidSize,         /* Actually size of valid range */          TotalSize,         /* Goal size of the whole data (0 if unknown) */          BuffSize;          /* Buffer Size for unknown length transfers */   guint Flags;              /* Look Flag Defines in cache.h */   IOData_t *io;             /* Pointer to IO data */   ChainLink *CCCQuery;      /* CCC link for querying branch */   ChainLink *CCCAnswer;     /* CCC link for answering branch */} CacheData_t;/* *  Local data *//* A hash for cached data. Holds pointers to CacheData_t structs */static GHashTable *CacheHash = NULL;/* A list for cache clients. * Although implemented as a list, we'll call it ClientQueue  --Jcid */static GSList *ClientQueue = NULL;/* A list for delayed clients (it holds weak pointers to cache entries, * which are used to make deferred calls to Cache_process_queue) */static GSList *DelayedQueue = NULL;static guint DelayedQueueIdleId = 0;/* *  Forward declarations */static void Cache_process_queue(CacheData_t *entry);static void Cache_delayed_process_queue(CacheData_t *entry);static void Cache_stop_client(gint Key, gint force);/* * Determine if two hash entries are equal (used by GHashTable) */static gint Cache_hash_entry_equal(gconstpointer v1, gconstpointer v2){   return (!a_Url_cmp((DilloUrl *)v1, (DilloUrl *)v2));}/* * Determine the hash value given the key (used by GHashTable) */static guint Cache_url_hash(gconstpointer key){   const char *p = URL_STR((DilloUrl *)key);   guint h = *p;   if (h)      for (p += 1; *p != '\0' && *p != '#'; p++)         h = (h << 5) - h + *p;   return h;}/* * Initialize dicache data */void a_Cache_init(void){   CacheHash = g_hash_table_new(Cache_url_hash, Cache_hash_entry_equal);}/* Client operations ------------------------------------------------------ *//* * Make a unique primary-key for cache clients */static gint Cache_client_make_key(void){   static gint ClientKey = 0; /* Provide a primary key for each client */   if ( ++ClientKey < 0 ) ClientKey = 1;   return ClientKey;}/* * Add a client to ClientQueue. *  - Every client-camp is just a reference (except 'Web'). *  - Return a unique number for identifying the client. */static gint Cache_client_enqueue(const DilloUrl *Url, DilloWeb *Web,                                 CA_Callback_t Callback, void *CbData){   gint ClientKey;   CacheClient_t *NewClient;   NewClient = g_new(CacheClient_t, 1);   ClientKey = Cache_client_make_key();   NewClient->Key = ClientKey;   NewClient->Url = Url;   NewClient->Buf = NULL;   NewClient->Callback = Callback;   NewClient->CbData = CbData;   NewClient->Web    = Web;   ClientQueue = g_slist_append(ClientQueue, NewClient);   return ClientKey;}/* * Compare function for searching a Client by its key */static gint Cache_client_key_cmp(gconstpointer client, gconstpointer key){   return ( GPOINTER_TO_INT(key) != ((CacheClient_t *)client)->Key );}/* * Compare function for searching a Client by its URL */static gint Cache_client_url_cmp(gconstpointer client, gconstpointer url){   return a_Url_cmp((DilloUrl *)url, ((CacheClient_t *)client)->Url);}/* * Compare function for searching a Client by hostname */static gint Cache_client_host_cmp(gconstpointer client, gconstpointer hostname){   return g_strcasecmp(URL_HOST(((CacheClient_t *)client)->Url),                       (gchar *)hostname );}/* * Remove a client from the queue */static void Cache_client_dequeue(CacheClient_t *Client, gint Key){   GSList *List;   if (!Client &&       (List = g_slist_find_custom(ClientQueue, GINT_TO_POINTER(Key),                                   Cache_client_key_cmp)))      Client = List->data;   if ( Client ) {      ClientQueue = g_slist_remove(ClientQueue, Client);      a_Web_free(Client->Web);      g_free(Client);   }}/* Entry operations ------------------------------------------------------- *//* * Set safe values for a new cache entry */static void Cache_entry_init(CacheData_t *NewEntry, const DilloUrl *Url){   NewEntry->Url = a_Url_dup(Url);   NewEntry->Type = NULL;   NewEntry->Header = g_string_new("");   NewEntry->Location = NULL;   NewEntry->Data = NULL;   NewEntry->ValidSize = 0;   NewEntry->TotalSize = 0;   NewEntry->BuffSize = 4096;   NewEntry->Flags = 0;   NewEntry->io = NULL;   NewEntry->CCCQuery = a_Chain_new();   NewEntry->CCCAnswer = NULL;}/* * Get the data structure for a cached URL (using 'Url' as the search key) * If 'Url' isn't cached, return NULL */static CacheData_t *Cache_entry_search(const DilloUrl *Url){   return g_hash_table_lookup(CacheHash, Url);}/* * Allocate and set a new entry in the cache list */static CacheData_t *Cache_entry_add(const DilloUrl *Url){   CacheData_t *new_entry = g_new(CacheData_t, 1);   if (Cache_entry_search(Url))      DEBUG_MSG(5, "WARNING: Cache_entry_add, leaking an entry.\n");   Cache_entry_init(new_entry, Url);  /* Set safe values */   g_hash_table_insert(CacheHash, (gpointer)new_entry->Url, new_entry);   return new_entry;}/* *  Free the components of a CacheData_t struct. */static void Cache_entry_free(CacheData_t *entry){   a_Url_free((DilloUrl *)entry->Url);   g_free((gchar *)entry->Type);   g_string_free(entry->Header, TRUE);   a_Url_free((DilloUrl *)entry->Location);   g_free(entry->Data);   g_free(entry);   /* CCCQuery and CCCAnswer are just references */}/* * Remove an entry from the CacheList (no CCC-function is called) */static gint Cache_entry_remove_raw(CacheData_t *entry, DilloUrl *url){   if (!entry && !(entry = Cache_entry_search(url)))      return 0;   /* There MUST NOT be any clients */   g_return_val_if_fail(      !g_slist_find_custom(ClientQueue, url, Cache_client_url_cmp), 0);   /* remove from DelayedQueue */   DelayedQueue = g_slist_remove(DelayedQueue, entry);   /* remove from dicache */   a_Dicache_invalidate_entry(url);   /* remove from cache */   g_hash_table_remove(CacheHash, entry->Url);   Cache_entry_free(entry);   return 1;}/* * Remove an entry, using the CCC if necessary. * (entry SHOULD NOT have clients) */static void Cache_entry_remove(CacheData_t *entry, DilloUrl *url){   ChainLink *InfoQuery, *InfoAnswer;   if (!entry && !(entry = Cache_entry_search(url)))      return;   InfoQuery  = entry->CCCQuery;   InfoAnswer = entry->CCCAnswer;   if (InfoQuery) {      DEBUG_MSG(2, "## Aborting CCCQuery\n");      a_Cache_ccc(OpAbort, 1, BCK, InfoQuery, NULL, NULL);   } else if (InfoAnswer) {      DEBUG_MSG(2, "## Aborting CCCAnswer\n");      a_Cache_ccc(OpAbort, 2, BCK, InfoAnswer, NULL, NULL);   } else {      DEBUG_MSG(2, "## Aborting raw2\n");      Cache_entry_remove_raw(entry, url);   }}/* Misc. operations ------------------------------------------------------- *//* * Given an entry (url), remove all its clients (by url or host). */static void Cache_stop_clients(DilloUrl *url, gint ByHost){   gint i;   CacheClient_t *Client;   for (i = 0; (Client = g_slist_nth_data(ClientQueue, i)); ++i) {      if ( (ByHost && Cache_client_host_cmp(Client, URL_HOST(url)) == 0) ||           (!ByHost && Cache_client_url_cmp(Client, url) == 0) ) {         Cache_stop_client(Client->Key, 0);         --i;      }   }}/* * Prepare a reload by stopping clients and removing the entry *  Return value: 1 if on success, 0 otherwise */static gint Cache_prepare_reload(DilloUrl *url){   CacheClient_t *Client;   DilloWeb *ClientWeb;   gint i;   for (i = 0; (Client = g_slist_nth_data(ClientQueue, i)); ++i){      if (Cache_client_url_cmp(Client, url) == 0 &&          (ClientWeb = Client->Web) && !(ClientWeb->flags & WEB_Download))         Cache_stop_client(Client->Key, 0);   }   if (!g_slist_find_custom(ClientQueue, url, Cache_client_url_cmp)) {      /* There're no clients for this entry */      DEBUG_MSG(2, "## No more clients for this entry\n");      Cache_entry_remove(NULL, url);      return 1;   } else {      MSG("Cache_prepare_reload: ERROR, entry still has clients\n");   }   return 0;}/* * Try finding the url in the cache. If it hits, send the cache contents * from there. If it misses, set up a new connection. * Return value: A primary key for identifying the client. */static gint Cache_open_url(DilloWeb *Web, CA_Callback_t Call, void *CbData){   void *link;   gint ClientKey;   ChainFunction_t cccFunct;   DilloUrl *Url = Web->url;   CacheData_t *entry = Cache_entry_search(Url);   _MSG("Cache_open_url: %s %sFOUND\n", URL_STR(Url), entry ? "" : "NOT ");   if ( entry ) {      /* URL is cached: feed our client with cached data */      ClientKey = Cache_client_enqueue(entry->Url, Web, Call, CbData);      Cache_delayed_process_queue(entry);   } else {      /* URL not cached: create an entry, send our client to the queue,       * and open a new connection */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -