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

📄 htcache.c

📁 Open VXI. This is a open source.
💻 C
📖 第 1 页 / 共 5 页
字号:
    	    if (!anchor) anchor = HTRequest_anchor(request);	    HTCache_touch(request, response, anchor);	} else {	    HTParentAnchor * anchor = HTRequest_anchor(request);	    char * default_name = HTRequest_defaultPutName(request);	    HTCache * cache = HTCache_find(anchor, default_name);	    if (cache) {		/* 		** If we receive a 204 and the method is unsafe then we have		** to delete the cache body but not the header information		*/		/*		** @@ JK: see how to add all the methods here (201, etc.) when		** it's a PUT		*/		if (status == 204) {		    HTCache_updateMeta(cache, request, response);		    cache->size = 0;		    cache->range = YES;		    /* @@ JK: update the cache meta data on disk */		    HTCache_writeMeta (cache, request, response);		    /* @@ JK: and we remove the file name as it's obsolete 		       now */		    REMOVE(cache->cachename);		} else		    HTCache_remove(cache);	    } 	    /* @@  this operation will clear the cache->size and cache_range */	    HTCache_touch(request, response, anchor);	}    }    return HT_OK;}/***  Set the size of a cached object. We don't consider the metainformation as**  part of the size which is the the reason for why the min cache size should**  not be less than 5M. When we set the cache size we also check whether we **  should run the gc or not.*/PRIVATE BOOL HTCache_setSize (HTCache * cache, long written, BOOL append){    if (cache) {	/*	**  First look to see if we already have registered this cache entry	**  with a certain size. This size may be a subpart of the total entity	**  (in case the download was interrupted)	*/	if (cache->size > 0 && !append) HTCacheContentSize -= cache->size;	cache->size = written;	HTCacheContentSize += written;	/*	**  Now add the new size to the total cache size. If the new size is	**  bigger than the legal cache size then start the gc.	*/	HTTRACE(CACHE_TRACE, "Cache....... Total size %ld\n" _ HTCacheContentSize);	if (startGC()) HTCacheGarbage();	return YES;    }    return NO;}/***  Verifies if a cache object exists for this URL and if so returns a URL**  for the cached object. It does not verify whether the object is valid or**  not, for example it might have expired.****  Returns: file name	If OK (must be freed by caller)**	     NULL	If no cache object found*/PUBLIC HTCache * HTCache_find (HTParentAnchor * anchor, char * default_name){    HTList * list = NULL;    HTCache * pres = NULL;    /* Find a hash entry for this URL */    if (HTCacheMode_enabled() && anchor && CacheTable) {	char * url = NULL;	int hash = 0;	char * ptr;	if (default_name)	    StrAllocCopy (url, default_name);	  else	    url = HTAnchor_address((HTAnchor *) anchor);	ptr = url;	for (; *ptr; ptr++)	    hash = (int) ((hash * 3 + (*(unsigned char *) ptr)) % HT_XL_HASH_SIZE);	if (!CacheTable[hash]) {	    HT_FREE(url);	    return NULL;	}	list = CacheTable[hash];	/* Search the cache */	{	    HTList * cur = list;	    while ((pres = (HTCache *) HTList_nextObject(cur))) {		if (!strcmp(pres->url, url)) {		    HTTRACE(CACHE_TRACE, "Cache....... Found %p hits %d\n" _ 					     pres _ pres->hits);		    break;		}	    }	}	HT_FREE(url);    }    return pres;}/*	HTCache_delete**	--------------**	Deletes a cache entry*/PRIVATE BOOL HTCache_delete (HTCache * cache){    if (cache && CacheTable) {	HTList * cur = CacheTable[cache->hash];	return cur && delete_object(cur, cache);    }    return NO;}/*	HTCache_deleteAll**	-----------------**	Destroys all cache entried in memory but does not write anything to**	disk*/PUBLIC BOOL HTCache_deleteAll (void){    if (CacheTable) {	HTList * cur;	int cnt;	/* Delete the rest */	for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {	    if ((cur = CacheTable[cnt])) { 		HTCache * pres;		while ((pres = (HTCache *) HTList_nextObject(cur)) != NULL)		    free_object(pres);	    }	    HTList_delete(CacheTable[cnt]);	}	HT_FREE(CacheTable);	HTCacheContentSize = 0L;	return YES;    }    return NO;}/***  Is we have a valid entry in the cache then we also need a location**  where we can get it. Hopefully, we may be able to access it**  thourgh one of our protocol modules, for example the local file**  module. The name returned is in URL syntax and must be freed by**  the caller*/PRIVATE char * HTCache_metaLocation (HTCache * cache){    char * local = NULL;    if (cache && cache->cachename && *cache->cachename) {	if ((local = (char *) HT_MALLOC(strlen(cache->cachename) +					strlen(HT_CACHE_META) + 5)) == NULL)	    HT_OUTOFMEM("HTCache_metaLocation");	sprintf(local, "%s%s", cache->cachename, HT_CACHE_META);    }    return local;}/***  Walk through the set of headers and write those out that we are allowed**  to store in the cache. We look into the connection header to see what the **  hop-by-hop headers are and also into the cache-control directive to see what**  headers should not be cached.*/PRIVATE BOOL meta_write (FILE * fp, HTRequest * request, HTResponse * response){    if (fp && request && response) {	HTAssocList * headers = HTAnchor_header(HTRequest_anchor(request));	HTAssocList * connection = HTResponse_connection(response);	char * nocache = HTResponse_noCache(response);	/*	**  If we don't have any headers then just return now.	*/	if (!headers) return NO;	/*	**  Check whether either the connection header or the cache control	**  header includes header names that we should not cache	*/	if (connection || nocache) {	    /*	    **  Walk though the cache control no-cache directive	    */	    if (nocache) {		char * line = NULL;		char * ptr = NULL;		char * field = NULL;		StrAllocCopy(line, nocache);		 /* Get our own copy */		ptr = line;		while ((field = HTNextField(&ptr)) != NULL)		    HTAssocList_removeObject(headers, field);		HT_FREE(line);	    }	    /*	    **  Walk though the connection header	    */	    if (connection) {		HTAssoc * pres;		while ((pres=(HTAssoc *) HTAssocList_nextObject(connection))) {		    char * field = HTAssoc_name(pres);		    HTAssocList_removeObject(headers, field);		}	    }	}	/*	**  Write out the remaining list of headers that we not already store	**  in the index file.	*/	{	    HTAssocList * cur = headers;	    HTAssoc * pres;	    while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {		char * name = HTAssoc_name(pres);		/* Don't write the headers that are already hop-by-hop */		if (strcasecomp(name, "connection") &&		    strcasecomp(name, "keep-alive") &&		    strcasecomp(name, "proxy-authenticate") &&		    strcasecomp(name, "proxy-authorization") &&		    strcasecomp(name, "transfer-encoding") &&		    strcasecomp(name, "upgrade")) {		    if (fprintf(fp, "%s: %s\n", name, HTAssoc_value(pres)) < 0) {			HTTRACE(CACHE_TRACE, "Cache....... Error writing metainfo\n");			return NO;		    }		}	    }	}	/*	**  Terminate the header with a newline	*/	if (fprintf(fp, "\n") < 0) {	    HTTRACE(CACHE_TRACE, "Cache....... Error writing metainfo\n");	    return NO;	}	return YES;    }    return NO;}/***  Save the metainformation for the data object. If no headers**  are available then the meta file is empty*/PUBLIC BOOL HTCache_writeMeta (HTCache * cache, HTRequest * request,			       HTResponse * response){    if (cache && request && response) {	BOOL status;	FILE * fp;	char * name = HTCache_metaLocation(cache);	if (!name) {	    HTTRACE(CACHE_TRACE, "Cache....... Invalid cache entry\n");	    HTCache_remove(cache);	    return NO;	}	if ((fp = fopen(name, "wb")) == NULL) {	    HTTRACE(CACHE_TRACE, "Cache....... Can't open `%s\' for writing\n" _ name);	    HTCache_remove(cache);	    HT_FREE(name);	    	    return NO;	}	status = meta_write(fp, request, response);	fclose(fp);	HT_FREE(name);	return status;    }    return NO;}PRIVATE BOOL meta_read (FILE * fp, HTRequest * request, HTStream * target){    if (fp && request && target) {	int status;	char buffer[512];	while (1) {	    if ((status = fread(buffer, 1, 512, fp)) <= 0) {		HTTRACE(PROT_TRACE, "Cache....... Meta information loaded\n");		return YES;	    }		    /* Send the data down the pipe */	    status = (*target->isa->put_block)(target, buffer, status);	    if (status == HT_LOADED) {		(*target->isa->flush)(target);		return YES;	    }	    if (status < 0) {		HTTRACE(PROT_TRACE, "Cache....... Target ERROR %d\n" _ status);		break;	    }	}    }    return NO;}/***  Read the metainformation for the data object. If no headers are**  available then the meta file is empty*/PRIVATE BOOL HTCache_readMeta (HTCache * cache, HTRequest * request){    HTParentAnchor * anchor = HTRequest_anchor(request);    if (cache && request && anchor) {	BOOL status;	FILE * fp;	char * name = HTCache_metaLocation(cache);	if (!name) {	    HTTRACE(CACHE_TRACE, "Cache....... Invalid meta name\n" _ name);	    HTCache_remove(cache);	    return NO;	}	HTTRACE(CACHE_TRACE, "Cache....... Looking for `%s\'\n" _ name);	if ((fp = fopen(name, "rb")) == NULL) {	    HTTRACE(CACHE_TRACE, "Cache....... Can't open `%s\' for reading\n" _ name);	    HTCache_remove(cache);	    HT_FREE(name);	    	} else {	    HTStream * target = HTStreamStack(WWW_MIME_HEAD, WWW_DEBUG,					      HTBlackHole(), request, NO);	    /*	    **  Make sure that we save the reponse information in the anchor	    */	    HTResponse_setCachable(HTRequest_response(request), HT_CACHE_ALL);	    status = meta_read(fp, request, target);	    (*target->isa->_free)(target);	    /* JK: Moved the delete outside of meta_read, because it was being	       deleted multiple times. 	       Delete the response headers. In principle, they are	       already available in the anchor */ 	    HTRequest_setResponse(request, NULL);	    fclose(fp);	    HT_FREE(name);	    return status;	}    }    return NO;}/***  Merge metainformation with existing version. This means that we have had a**  successful validation and hence a true cache hit. We only regard the**  following headers: Date, content-location, expires, cache-control, and vary.*/PUBLIC BOOL HTCache_updateMeta (HTCache * cache, HTRequest * request,				HTResponse * response){    if (cache && request && response) {	HTParentAnchor * anchor = HTRequest_anchor(request);	cache->hits++;	/* Calculate the various times */	calculate_time(cache, request, response);	/* Get the last-modified and etag values if any */	{	    char * etag = HTAnchor_etag(anchor);	    if (etag) StrAllocCopy(cache->etag, etag);	    cache->lm = HTAnchor_lastModified(anchor);	}	/* Must we revalidate this every time? */	cache->must_revalidate = HTResponse_mustRevalidate(response);	return YES;    }    return NO;}/***  Remove from disk. You must explicitly remove a lock**  before this operation can succeed*/PRIVATE BOOL flush_object (HTCache * cache){    if (cache && !HTCache_hasLock(cache)) {	char * head = HTCache_metaLocation(cache);	REMOVE(head);	HT_FREE(head);	REMOVE(cache->cachename);	return YES;    }    return NO;}/*	HTCache_flushAll**	----------------**	Destroys all cache entried in memory and on disk. Resets the cache**	to empty but the cache does not have to be reinitialized before we**	can use it again.*/PUBLIC BOOL HTCache_flushAll (void){    if (CacheTable) {	HTList * cur;	int cnt;	/* Delete the rest */	for (cnt=0; cnt<HT_XL_HASH_SIZE; cnt++) {	    if ((cur = CacheTable[cnt])) { 		HTCache * pres;		while ((pres = (HTCache *) HTList_nextObject(cur)) != NULL) {		    flush_object(pres);		    free_object(pres);		}	    }	    HTList_delete(CacheTable[cnt]);	    CacheTable[cnt] = NULL;	}	/* Write the new empty index to disk */	HTCacheIndex_write(HTCacheRoot);	HTCacheContentSize = 0L;	return YES;    }    return NO;}/***  This function checks whether a document has expired or not.**  The check is based on the metainformation passed in the anchor object**  The function returns the level of validation needed for getting a fresh**  version. We also check the cache control directives in the request to**  see if they change the freshness discission. */PUBLIC HTReload HTCache_isFresh (HTCache * cache, HTRequest * request){    HTAssocList * cc = HTRequest_cacheControl(request);    if (cache) {	time_t max_age = -1;	time_t max_stale = -1;	time_t min_fresh = -1;	/*	**  Make sure that we have the metainformation loaded from the	**  persistent cache	*/	HTParentAnchor * anchor = HTRequest_anchor(request);	if (!HTAnchor_headerParsed(anchor)) {	    if (HTCache_readMeta(cache, request) != YES)		return HT_CACHE_ERROR;	    HTAnchor_setHeaderParsed(anchor);	}

⌨️ 快捷键说明

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