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

📄 cache.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 3 页
字号:
  }
  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 + -