📄 cache.c
字号:
}
else if (expire == 0 && mustRevalidate != 0){
/* Dummy value to mark that the content has expired. */
expire = 1;
}
/* Compute the required amount of free space. */
url_len = B_STRINGLENGTH (pvUrl);
if (etag != NULL) {
etag_len = B_STRINGLENGTH (etag);
}
tot_len = sizeof (CacheRecord) + url_len + iHeaderLen + iBodLen + etag_len;
#ifdef FILE_CACHE
if (tot_len > theCache.waeMainObj->liCacheSize) {
#else
if (tot_len > theCache.store.size - 4) {
#endif
/* Too large a record, it cannot possibly fit. */
DEALLOC (&etag);
return 0;
}
/* Check if URL is presently in cache; if so, remove it. */
p = Cache_Find ((BYTE*) pvUrl, &rec, (INT16)(isWTA ? 1 : 0));
if (p != NULL) {
if ((rec.date != 0) && (date != 0) && (date < rec.date)) {
DEALLOC (&etag);
return 1;
}
#ifdef FILE_CACHE
theCache.size -= FILEa_getSize ('C', p->id);
FILEa_delete ('C', p->id);
#else
Storage_DeleteBlock (&(theCache.store), p->id);
#endif
list_out (p);
DEALLOC (&p);
}
#ifdef FILE_CACHE
while (theCache.size + tot_len > theCache.waeMainObj->liCacheSize) {
p = reclist.next;
if (p == &reclist)
break;
list_out (p);
theCache.size -= FILEa_getSize ('C', p->id);
FILEa_delete ('C', p->id);
DEALLOC (&p);
}
if (FILEa_create ('C', &newid) < 0) {
return 0;
}
theCache.size += tot_len;
#else
if (cfg_wae_cc_cacheCompact > 0) {
/* Delete the oldest elements in the cache, until we have enough
* free bytes for the new element; then do compaction to collect
* the free areas into one that is large enough. In this manner
* we delete as few old records as possible. Hence, this strategy
* favors memory usage over speed. */
while (Storage_NumBytesFree (&(theCache.store)) < tot_len) {
p = reclist.next;
if (p == &reclist)
break;
list_out (p);
Storage_DeleteBlock (&(theCache.store), p->id);
DEALLOC (&p);
}
newid = 0;
/* Try to allocate a new block; if it fails, do some compaction. */
while (!Storage_AllocateBlock (&(theCache.store), tot_len, &newid)) {
if (!Storage_Compact (&(theCache.store))) {
/* Compaction did not accomplish anything: give up. */
DEALLOC (&etag);
return 0;
}
}
}
else {
/* Delete the oldest elements in the cache, until the allocation
* succeeds. No compaction is done. This strategy favors speed
* over memory usage. */
newid = 0;
while (!Storage_AllocateBlock (&(theCache.store), tot_len, &newid)) {
p = reclist.next;
if (p == &reclist) {
/* There are no more records in the cache. The new record
* is simply too large to fit in the cache: give up.
* (This should never happen.) */
DEALLOC (&etag);
return 0;
}
list_out (p);
Storage_DeleteBlock (&(theCache.store), p->id);
DEALLOC (&p);
}
}
#endif
p = NEWARRAY (ListNode, 1);
if (p == NULL) {
DEALLOC (&etag);
return 0;
}
p->id = newid;
/* Add to list, place it last. */
#ifdef FILE_CACHE
p->creation_time = currentTime;
#endif
list_addbefore (p, &reclist);
b_HashURL ((BYTE*) pvUrl, &(p->hashval));
p->isWTA = (isWTA ? 1 : 0);
/* Write new cache record */
rec.url_hash = p->hashval;
rec.url_len = url_len;
rec.header_len = (UINT16)iHeaderLen;
rec.body_len = iBodLen;
rec.etag_len = etag_len;
rec.expire = expire;
rec.date = date;
rec.last_mod = lastModified;
rec.flags = PRESENT | HASREAD;
if (mustRevalidate)
rec.flags |= MUSTREVALIDATE;
if (isWTA)
rec.flags |= BELONGS_TO_WTA;
#ifdef FILE_CACHE
rec.creation_time = p->creation_time;
#endif
#ifdef FILE_CACHE
if (FILEa_write ('C', p->id, &rec, 0, sizeof (CacheRecord))
!= sizeof (CacheRecord)) {
#else
if (!Storage_Put (&(theCache.store), p->id, 0,
sizeof (CacheRecord), &rec)) {
#endif
DEALLOC (&etag);
return 0;
}
/* Write URL, header, body and ETag. */
pos = sizeof (CacheRecord);
#ifdef FILE_CACHE
if (FILEa_write ('C', p->id, pvUrl, pos, rec.url_len)
!= (INT32)rec.url_len) {
#else
if (!Storage_Put (&(theCache.store), p->id, pos, rec.url_len, pvUrl)) {
#endif
DEALLOC (&etag);
return 0;
}
pos += rec.url_len;
if (rec.header_len > 0) {
#ifdef FILE_CACHE
if (FILEa_write ('C', p->id, pvHeader, pos, rec.header_len)
!= (INT32)rec.header_len) {
#else
if (!Storage_Put (&(theCache.store), p->id, pos,
rec.header_len, pvHeader)) {
#endif
DEALLOC (&etag);
return 0;
}
}
pos += rec.header_len;
if (rec.body_len > 0) {
#ifdef FILE_CACHE
if (FILEa_write ('C', p->id, pvBody, pos, rec.body_len)
!= (INT32)rec.body_len) {
#else
if (!Storage_Put (&(theCache.store), p->id, pos,
rec.body_len, pvBody)) {
#endif
DEALLOC (&etag);
return 0;
}
}
pos += rec.body_len;
if (rec.etag_len > 0) {
#ifdef FILE_CACHE
if (FILEa_write ('C', p->id, etag, pos, rec.etag_len)
!= (INT32)rec.etag_len) {
#else
if (!Storage_Put (&(theCache.store), p->id, pos, rec.etag_len, etag)) {
#endif
DEALLOC (&etag);
return 0;
}
}
DEALLOC (&etag);
return 1;
}
/*
* Cache_Delete
*
* Delete a record from the cache, given its URL.
* "pvUrl" is the URL as a null-terminated byte string.
*
* Returns 1 if succesful, otherwise 0.
*/
INT16
Cache_Delete (void *pvUrl)
{
CacheRecord rec;
ListNode *p;
if (!theCache.isInitialized) {
return 0;
}
if (pvUrl == NULL)
return 0;
p = Cache_Find ((BYTE*) pvUrl, &rec, -1);
if (p == NULL) {
return 1;
}
#ifdef FILE_CACHE
theCache.size -= FILEa_getSize ('C', p->id);
FILEa_delete ('C', p->id);
#else
Storage_DeleteBlock (&(theCache.store), p->id);
#endif
list_out (p);
DEALLOC (&p);
return 1;
}
/*
* Cache_Delete_Push
*
* Delete a record from the cache, given its URL.
* "pvUrl" is the URL as a null-terminated byte string.
*
* This function ignores the query-part of the URL.
*
* Returns 1 if succesful, otherwise 0.
*/
INT16
Cache_Delete_Push (void *pvUrl)
{
CacheRecord rec;
ListNode *p;
void *pvNormUrl;
URL url;
void *pvNoQUrl;
if (!theCache.isInitialized) {
return 0;
}
if (pvUrl == NULL)
return 0;
/* Normalize */
pvNormUrl = SDL_Normalise(NULL, pvUrl);
if (pvNormUrl == NULL)
return 0;
/* Remove query */
if(!URL_FromByteString(pvNormUrl, &url))
return 0;
URL_RemoveQuery(&url);
pvNoQUrl = URL_ToByteString(&url);
if (pvNoQUrl == NULL)
return 0;
p = Cache_Find (pvNoQUrl, &rec, -1);
DEALLOC (&pvNoQUrl);
if (p == NULL) {
return 1;
}
#ifdef FILE_CACHE
theCache.size -= FILEa_getSize ('C', p->id);
FILEa_delete ('C', p->id);
#else
Storage_DeleteBlock (&(theCache.store), p->id);
#endif
list_out (p);
DEALLOC (&p);
return 1;
}
/*
* Cache_DeleteMatchingPrefix
*
* Delete all records in the cache whose URL has the given
* URL as a prefix.
*
* Returns the number of records that were deleted.
*/
INT16
Cache_DeleteMatchingPrefix (void *pvUrl)
{
CacheRecord rec;
ListNode *p, *q;
INT16 n = 0;
BYTE *tmp_url;
if (!theCache.isInitialized ||
(pvUrl == NULL)) {
return 0;
}
p = reclist.next;
while (p != &reclist) {
q = p;
p = p->next;
#ifdef FILE_CACHE
if (FILEa_read ('C', q->id, &rec, 0, sizeof (CacheRecord))
!= sizeof (CacheRecord)) {
#else
if (!Storage_Get (&(theCache.store), q->id, 0,
sizeof (CacheRecord), &rec)) {
#endif
return n;
}
if ((tmp_url = NEWARRAY (BYTE, rec.url_len + 1)) == NULL) {
return n;
}
#ifdef FILE_CACHE
if (FILEa_read ('C', q->id, tmp_url, sizeof (CacheRecord),
rec.url_len) != rec.url_len) {
#else
if (!Storage_Get (&(theCache.store), q->id, sizeof (CacheRecord),
rec.url_len, tmp_url)) {
#endif
DEALLOC (&tmp_url);
return n;
}
tmp_url[rec.url_len] = '\0';
if (b_IsPrefix ((BYTE*) pvUrl, tmp_url)) {
list_out (q);
#ifdef FILE_CACHE
theCache.size -= FILEa_getSize ('C', q->id);
FILEa_delete ('C', q->id);
#else
Storage_DeleteBlock (&(theCache.store), q->id);
#endif
DEALLOC (&q);
n++;
}
DEALLOC (&tmp_url);
}
return n;
}
#ifdef LOG_INTERNAL
/*
* Cache_Debug
*
* Routine used for debugging purposes.
* This routine prints the URLs of all records in the cache
* on standard error.
*/
void
Cache_Debug (void)
{
UINT32 *ida;
INT16 i;
CacheRecord rec;
char tmp[256];
UINT16 len;
if (!theCache.isInitialized) {
return;
}
#ifdef FILE_CACHE
len = FILEa_getFileIds ('C', NULL, 0);
ida = OSConnectorAlloc (sizeof (UINT32) * len);
len = FILEa_getFileIds ('C', ida, len);
#else
Storage_GetAllBlockIds (&(theCache.store), &ida, &len);
#endif
for (i = 0; i < len; i++) {
#ifdef FILE_CACHE
if (ida[i] == 0)
continue;
FILEa_read ('C', ida[i], &rec, 0, sizeof (CacheRecord));
FILEa_read ('C', ida[i], tmp, sizeof (CacheRecord), rec.url_len);
#else
Storage_Get (&(theCache.store), ida[i], 0, sizeof (CacheRecord), &rec);
Storage_Get (&(theCache.store), ida[i], sizeof (CacheRecord),
rec.url_len, tmp);
#endif
tmp[rec.url_len] = '\0';
#ifdef FILE_CACHE
fprintf (stderr, "'%s' <%d>\n", tmp, rec.creation_time);
#else
fprintf (stderr, "'%s'\n", tmp);
#endif
}
OSConnectorFree (ida);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -