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

📄 htcache.c

📁 Open VXI. This is a open source.
💻 C
📖 第 1 页 / 共 5 页
字号:
	/* the cache size is 0 when we want to force the     	   revalidation of the cache, for example, after a PUT */#if 0	/* @@ JK: trying the following instruction */    	if (cache->size == 0)     	  return HT_CACHE_FLUSH;#endif	/*	**  If we only have a part of this request then make a range request	**  using the If-Range condition GET request	*/	if (cache->range) {	    char buf[20];	    sprintf(buf, "%ld-", cache->size);	    HTTRACE(CACHE_TRACE, "Cache....... Asking for range `%s\'\n" _ buf);	    HTRequest_addRange(request, "bytes", buf);	    HTRequest_addRqHd(request, HT_C_RANGE);	    	    return HT_CACHE_RANGE_VALIDATE;	}	/*	**  In case this entry is of type "must-revalidate" then we just	**  go ahead and validate it.	*/	if (cache->must_revalidate)	    return HT_CACHE_VALIDATE;	/*	**  Check whether we have any special constraints like min-fresh in	**  the cache control	*/	if (cc) {	    char * token = NULL;	    if ((token = HTAssocList_findObject(cc, "max-age")))		max_age = atol(token);	    if ((token = HTAssocList_findObject(cc, "max-stale")))		max_stale = atol(token);	    if ((token = HTAssocList_findObject(cc, "min-fresh")))		min_fresh = atol(token);	}	/*	**  Now do the checking against the age constraints that we've got	*/	{	    time_t resident_time = time(NULL) - cache->response_time;	    time_t current_age = cache->corrected_initial_age + resident_time;	    /*	    ** Check that the max-age, max-stale, and min-fresh directives	    ** given in the request cache control header is followed.	    */	    if (max_age >= 0 && current_age > max_age) {		HTTRACE(CACHE_TRACE, "Cache....... Max-age validation\n");		return HT_CACHE_VALIDATE;	    }	    if (min_fresh >= 0 &&		cache->freshness_lifetime < current_age + min_fresh) {		HTTRACE(CACHE_TRACE, "Cache....... Min-fresh validation\n");		return HT_CACHE_VALIDATE;	    }	    return (cache->freshness_lifetime +		    (max_stale >= 0 ? max_stale : 0) > current_age) ?		HT_CACHE_OK : HT_CACHE_VALIDATE;	}    }    return HT_CACHE_FLUSH;}/***  While we are creating a new cache object or while we are validating an**  existing one, we must have a lock on the entry so that not other**  requests can get to it in the mean while.*/PUBLIC BOOL HTCache_getLock (HTCache * cache, HTRequest * request){    if (cache && request) {	HTTRACE(CACHE_TRACE, "Cache....... Locking cache entry %p\n" _ cache);	cache->lock = request;	return YES;    }    return NO;}PUBLIC BOOL HTCache_releaseLock (HTCache * cache){    if (cache) {	HTTRACE(CACHE_TRACE, "Cache....... Unlocking cache entry %p\n" _ cache);	cache->lock = NULL;	return YES;    }    return NO;}PUBLIC BOOL HTCache_hasLock (HTCache * cache){    return cache && cache->lock;}PUBLIC BOOL HTCache_breakLock (HTCache * cache, HTRequest * request){    if (cache && cache->lock) {	if (cache->lock == request) {	    HTTRACE(CACHE_TRACE, "Cache....... Breaking lock on entry %p\n" _ cache);	    cache->lock = NULL;	    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*/PUBLIC char * HTCache_name (HTCache * cache){    if (cache) {	char * local = cache->cachename;	char * url = HTLocalToWWW(local, "cache:");	return url;    }    return NULL;}/***  Remove from memory AND from disk. You must explicitly remove a lock**  before this operation can succeed*/PUBLIC BOOL HTCache_remove (HTCache * cache){    return flush_object(cache) && HTCache_delete(cache);}PUBLIC BOOL HTCache_addHit (HTCache * cache){    if (cache) {	cache->hits++;	HTTRACE(CACHE_TRACE, "Cache....... Hits for %p is %d\n" _ 				 cache _ cache->hits);	return YES;    }    return NO;}/* ------------------------------------------------------------------------- *//*  			        CACHE WRITER				     *//* ------------------------------------------------------------------------- */PRIVATE BOOL free_stream (HTStream * me, BOOL abort){    if (me) {	HTCache * cache = me->cache;	/*	**  We close the file object. This does not mean that we have the	**  complete object. In case of an "abort" then we only have a part,	**  however, next time we do a load we can use byte ranges to complete	**  the request.	*/    /* OSB: Now also setting fp to NULL */    if (me->fp) {        fclose(me->fp);        me->fp = NULL;    }	/*	**  We are done storing the object body and can update the cache entry.	**  Also update the meta information entry on disk as well. When we	**  are done we don't need the lock anymore.	*/	if (cache) {	    HTCache_writeMeta(cache, me->request, me->response);	    HTCache_releaseLock(cache);	    /*	    **  Remember if this is the full entity body or only a subpart	    **  We assume that an abort will only give a part of the object.	    */	    cache->range = abort;	    /*	    **  Set the size and maybe do gc. If it is an abort then set the	    **  byte range so that we can start from this point next time. We	    **  take the byte range as the number of bytes that we have already	    **  written to the cache entry.	    */	    HTCache_setSize(cache, me->bytes_written, me->append);	}	/*	**  In order not to loose information, we dump the current cache index	**  every time we have created DUMP_FREQUENCY new entries	*/	if (new_entries > DUMP_FREQUENCY) {	    HTCacheIndex_write(HTCacheRoot);	    new_entries = 0;	}	HT_FREE(me);	return YES;    }    return NO;}PRIVATE int HTCache_free (HTStream * me){    return free_stream(me, NO) ? HT_OK : HT_ERROR;}PRIVATE int HTCache_abort (HTStream * me, HTList * e){    HTTRACE(CACHE_TRACE, "Cache....... ABORTING\n");    free_stream(me, YES);    return HT_ERROR;}PRIVATE int HTCache_flush (HTStream * me){    return (fflush(me->fp) == EOF) ? HT_ERROR : HT_OK;}PRIVATE int HTCache_putBlock (HTStream * me, const char * s, int  l){    int status = (fwrite(s, 1, l, me->fp) != (size_t) l) ? HT_ERROR : HT_OK;    if (l > 1 && status == HT_OK) {	HTCache_flush(me);	me->bytes_written += l;    }    return status;}PRIVATE int HTCache_putChar (HTStream * me, char c){    return HTCache_putBlock(me, &c, 1);}PRIVATE int HTCache_putString (HTStream * me, const char * s){    return HTCache_putBlock(me, s, (int) strlen(s));}PRIVATE const HTStreamClass HTCacheClass ={		    "Cache",    HTCache_flush,    HTCache_free,    HTCache_abort,    HTCache_putChar,    HTCache_putString,    HTCache_putBlock};PRIVATE HTStream * HTCacheStream (HTRequest * request, BOOL append){    HTCache * cache = NULL;    FILE * fp = NULL;    HTResponse * response = HTRequest_response(request);    HTParentAnchor * anchor = HTRequest_anchor(request);    /* If cache is not enabled then exit now */    if (!HTCacheEnable || !HTCacheInitialized) {	HTTRACE(CACHE_TRACE, "Cache....... Not enabled\n");	return NULL;    }    /* don't cache protected documents */    if (HTRequest_credentials (request) && !HTCacheProtected) {	HTTRACE(CACHE_TRACE, "Cache....... won't cache protected objects\n");	return NULL;    }    /*    ** Check to see if we already now can see that the entry is going    ** to be too big.    */    if (HTAnchor_length(anchor) > HTCacheMaxEntrySize) {	HTTRACE(CACHE_TRACE, "Cache....... Entry is too big - won't cache\n");	return NULL;    }    /* Get a new cache entry */    if ((cache = HTCache_new(request, response, anchor)) == NULL) {	HTTRACE(CACHE_TRACE, "Cache....... Can't get a cache object\n");	return NULL;    }    /* Test that the cached object is not locked */    if (HTCache_hasLock(cache)) {	if (HTCache_breakLock(cache, request) == NO) {	    HTTRACE(CACHE_TRACE, "Cache....... Entry already in use\n");	    return NULL;	}    }    HTCache_getLock(cache, request);    /*    ** Test that we can actually write to the cache file. If the entry already    ** existed then it will be overridden with the new data.    */    if ((fp = fopen(cache->cachename, append ? "ab" : "wb")) == NULL) {	HTTRACE(CACHE_TRACE, "Cache....... Can't open `%s\' for writing\n" _ cache->cachename);	HTCache_delete(cache);	return NULL;    } else {	HTTRACE(CACHE_TRACE, "Cache....... %s file `%s\'\n" _ 		    append ? "Append to" : "Creating" _ cache->cachename);    }    /* Set up the stream */    {	HTStream * me = NULL;	if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)	    HT_OUTOFMEM("Cache");	me->isa = &HTCacheClass;	me->request = request;	me->response = response;	me->cache = cache;	me->fp = fp;	me->append = append;	return me;    }    return NULL;}PUBLIC HTStream * HTCacheWriter (HTRequest *	request,				 void *		param,				 HTFormat	input_format,				 HTFormat	output_format,				 HTStream *	output_stream){    return HTCacheStream(request, NO);}PUBLIC HTStream * HTCacheAppend (HTRequest *	request,				 void *		param,				 HTFormat	input_format,				 HTFormat	output_format,				 HTStream *	output_stream){    return HTCacheStream(request, YES);}/* ------------------------------------------------------------------------- *//*  			        CACHE READER				     *//* ------------------------------------------------------------------------- *//***      This function copies the headers associated with a cached**      object to closes the connection and frees memory.**      Returns YES on OK, else NO*/PRIVATE void HTCache_copyHeaders (HTRequest * req){  HTParentAnchor * anchor;  char * url;  anchor = HTRequest_anchor (req);  url = HTAnchor_physical(anchor);  if (url && !strncmp (url,  "cache:", sizeof ("cache:") - 1 ))    {      /*	HTMIME_anchor2response (req);      */      /* set up a "dummy" stack just for copying the MIME type.       We need this to remove any dependencies between the MIME        and CACHE minilibs */      HTStreamStack(WWW_MIME_COPYHEADERS, WWW_DEBUG,		    HTBlackHole(), req, NO);    }}/***      This function closes the connection and frees memory.**      Returns YES on OK, else NO*/PRIVATE int CacheCleanup (HTRequest * req, int status){    HTNet * net = HTRequest_net(req);    cache_info * cache = (cache_info *) HTNet_context(net);    HTStream * input = HTRequest_inputStream(req);    /* Free stream with data TO Local cache system */    if (input) {	if (status == HT_INTERRUPTED)	    (*input->isa->abort)(input, NULL);	else	    (*input->isa->_free)(input);	HTRequest_setInputStream(req, NULL);    }    /*    **  Remove if we have registered a timer function as a callback    */    if (cache->timer) {        HTTimer_delete(cache->timer);        cache->timer = NULL;    }        if (cache) {        HT_FREE(cache->local);        HT_FREE(cache);    }    /* if the object was cached, we copy the pertinent HTTP headers       from the anchor object (where they are stored) to the       response object */    if (status == HT_NOT_MODIFIED)	HTCache_copyHeaders (req);    HTNet_delete(net, status);    return YES;}/***  This load function loads an object from the cache and puts it to the**  output defined by the request object. For the moment, this load function**  handles the persistent cache as if it was on local file but in fact **  it could be anywhere.****  Returns		HT_ERROR	Error has occured in call back**			HT_OK		Call back was OK*/PRIVATE int CacheEvent (SOCKET soc, void * pVoid, HTEventType type);PUBLIC int HTLoadCache (SOCKET soc, HTRequest * request){    cache_info * cache;			      /* Specific access information */    HTParentAnchor * anchor = HTRequest_anchor(request);    HTNet * net = HTRequest_net(request);    /*    ** Initiate a new cache structure and bind to request structure    ** This is actually state CACHE_BEGIN, but it can't be in the state    ** machine as we need the structure first.    */    HTTRACE(PROT_TRACE, "Load Cache.. Looking for `%s\'\n" _ 			    HTAnchor_physical(anchor));    if ((cache = (cache_info *) HT_CALLOC(1, sizeof(cache_info))) == NULL)	HT_OUTOFMEM("HTLoadCACHE");    cache->state = CL_BEGIN;    cache->net = net;    HTNet_setContext(net, cache);    HTNet_setEventCallback(net, CacheEvent);    HTNet_setEventParam(net, cache);  /* callbacks get http* */    return CacheEvent(soc, cache, HTEvent_BEGIN);		/* get it started - ops is ignored */}PRIVATE int ReturnEvent (HTTimer * timer, void * param, HTEventType type){    cache_info * cache = (cache_info *) param;    if (timer != cache->timer)	HTDEBUGBREAK("File timer %p not in sync\n" _

⌨️ 快捷键说明

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