📄 store.c
字号:
storeUnlockObject(e);#endif}void#if STDC_HEADERSstoreAppendPrintf(StoreEntry * e, const char *fmt,...)#elsestoreAppendPrintf(va_alist) va_dcl#endif{#if STDC_HEADERS va_list args; va_start(args, fmt);#else va_list args; StoreEntry *e = NULL; const char *fmt = NULL; va_start(args); e = va_arg(args, StoreEntry *); fmt = va_arg(args, char *);#endif storeAppendVPrintf(e, fmt, args); va_end(args);}/* used be storeAppendPrintf and Packer */voidstoreAppendVPrintf(StoreEntry * e, const char *fmt, va_list vargs){ LOCAL_ARRAY(char, buf, 4096); buf[0] = '\0'; vsnprintf(buf, 4096, fmt, vargs); storeAppend(e, buf, strlen(buf));}struct _store_check_cachable_hist { struct { int non_get; int not_entry_cachable; int release_request; int wrong_content_length; int negative_cached; int too_big; int private_key; int too_many_open_files; int too_many_open_fds; int lru_age_too_low; } no; struct { int Default; } yes;} store_check_cachable_hist;intstoreTooManyDiskFilesOpen(void){ if (Config.max_open_disk_fds == 0) return 0; if (store_open_disk_fd > Config.max_open_disk_fds) return 1; return 0;}intstoreCheckCachable(StoreEntry * e){#if CACHE_ALL_METHODS if (e->mem_obj->method != METHOD_GET) { debug(20, 2) ("storeCheckCachable: NO: non-GET method\n"); store_check_cachable_hist.no.non_get++; } else#endif if (!EBIT_TEST(e->flags, ENTRY_CACHABLE)) { debug(20, 2) ("storeCheckCachable: NO: not cachable\n"); store_check_cachable_hist.no.not_entry_cachable++; } else if (EBIT_TEST(e->flags, RELEASE_REQUEST)) { debug(20, 2) ("storeCheckCachable: NO: release requested\n"); store_check_cachable_hist.no.release_request++; } else if (e->store_status == STORE_OK && EBIT_TEST(e->flags, ENTRY_BAD_LENGTH)) { debug(20, 2) ("storeCheckCachable: NO: wrong content-length\n"); store_check_cachable_hist.no.wrong_content_length++; } else if (EBIT_TEST(e->flags, ENTRY_NEGCACHED)) { debug(20, 3) ("storeCheckCachable: NO: negative cached\n"); store_check_cachable_hist.no.negative_cached++; return 0; /* avoid release call below */ } else if (e->mem_obj->inmem_hi > Config.Store.maxObjectSize) { debug(20, 2) ("storeCheckCachable: NO: too big\n"); store_check_cachable_hist.no.too_big++; } else if (EBIT_TEST(e->flags, KEY_PRIVATE)) { debug(20, 3) ("storeCheckCachable: NO: private key\n"); store_check_cachable_hist.no.private_key++; } else if (e->swap_status != SWAPOUT_NONE) { /* * here we checked the swap_status because the remaining * cases are only relevant only if we haven't started swapping * out the object yet. */ return 1; } else if (storeTooManyDiskFilesOpen()) { debug(20, 2) ("storeCheckCachable: NO: too many disk files open\n"); store_check_cachable_hist.no.too_many_open_files++; } else if (fdNFree() < RESERVED_FD) { debug(20, 2) ("storeCheckCachable: NO: too many FD's open\n"); store_check_cachable_hist.no.too_many_open_fds++; } else if (storeExpiredReferenceAge() < 300) { debug(20, 2) ("storeCheckCachable: NO: LRU Age = %d\n", storeExpiredReferenceAge()); store_check_cachable_hist.no.lru_age_too_low++; } else { store_check_cachable_hist.yes.Default++; return 1; } storeReleaseRequest(e); EBIT_CLR(e->flags, ENTRY_CACHABLE); return 0;}static voidstoreCheckCachableStats(StoreEntry * sentry){ storeAppendPrintf(sentry, "Category\t Count\n"); storeAppendPrintf(sentry, "no.non_get\t%d\n", store_check_cachable_hist.no.non_get); storeAppendPrintf(sentry, "no.not_entry_cachable\t%d\n", store_check_cachable_hist.no.not_entry_cachable); storeAppendPrintf(sentry, "no.release_request\t%d\n", store_check_cachable_hist.no.release_request); storeAppendPrintf(sentry, "no.wrong_content_length\t%d\n", store_check_cachable_hist.no.wrong_content_length); storeAppendPrintf(sentry, "no.negative_cached\t%d\n", store_check_cachable_hist.no.negative_cached); storeAppendPrintf(sentry, "no.too_big\t%d\n", store_check_cachable_hist.no.too_big); storeAppendPrintf(sentry, "no.private_key\t%d\n", store_check_cachable_hist.no.private_key); storeAppendPrintf(sentry, "no.too_many_open_files\t%d\n", store_check_cachable_hist.no.too_many_open_files); storeAppendPrintf(sentry, "no.too_many_open_fds\t%d\n", store_check_cachable_hist.no.too_many_open_fds); storeAppendPrintf(sentry, "no.lru_age_too_low\t%d\n", store_check_cachable_hist.no.lru_age_too_low); storeAppendPrintf(sentry, "yes.default\t%d\n", store_check_cachable_hist.yes.Default);}/* Complete transfer into the local cache. */voidstoreComplete(StoreEntry * e){ debug(20, 3) ("storeComplete: '%s'\n", storeKeyText(e->key)); if (e->store_status != STORE_PENDING) { /* * if we're not STORE_PENDING, then probably we got aborted * and there should be NO clients on this entry */ assert(EBIT_TEST(e->flags, ENTRY_ABORTED)); assert(e->mem_obj->nclients == 0); return; } e->mem_obj->object_sz = e->mem_obj->inmem_hi; e->store_status = STORE_OK; assert(e->mem_status == NOT_IN_MEMORY); if (!storeEntryValidLength(e)) { EBIT_SET(e->flags, ENTRY_BAD_LENGTH); storeReleaseRequest(e); }#if USE_CACHE_DIGESTS if (e->mem_obj->request) e->mem_obj->request->hier.store_complete_stop = current_time;#endif InvokeHandlers(e); storeCheckSwapOut(e);}/* * Someone wants to abort this transfer. Set the reason in the * request structure, call the server-side callback and mark the * entry for releasing */voidstoreAbort(StoreEntry * e){ MemObject *mem = e->mem_obj; assert(e->store_status == STORE_PENDING); assert(mem != NULL); debug(20, 6) ("storeAbort: %s\n", storeKeyText(e->key)); storeLockObject(e); /* lock while aborting */ storeNegativeCache(e); storeReleaseRequest(e); EBIT_SET(e->flags, ENTRY_ABORTED); storeSetMemStatus(e, NOT_IN_MEMORY); /* No DISK swap for negative cached object */ e->swap_status = SWAPOUT_NONE; e->store_status = STORE_OK; /* * We assign an object length here. The only other place we assign * the object length is in storeComplete() */ mem->object_sz = mem->inmem_hi; /* Notify the server side */ if (mem->abort.callback) { eventAdd("mem->abort.callback", mem->abort.callback, mem->abort.data, 0.0, 0); mem->abort.callback = NULL; mem->abort.data = NULL; } /* Notify the client side */ InvokeHandlers(e); /* Do we need to close the swapout file? */ /* Not if we never started swapping out */ /* But we may need to cancel an open/stat in progress if using ASYNC */#if USE_ASYNC_IO aioCancel(-1, e);#endif if (e->swap_file_number > -1) {#if USE_ASYNC_IO /* Need to cancel any pending ASYNC writes right now */ if (mem->swapout.fd >= 0) aioCancel(mem->swapout.fd, NULL);#endif /* we have to close the disk file if there is no write pending */ if (!storeSwapOutWriteQueued(mem)) storeSwapOutFileClose(e); } storeUnlockObject(e); /* unlock */}/* Clear Memory storage to accommodate the given object len */static voidstoreGetMemSpace(int size){ StoreEntry *e = NULL; int released = 0; static time_t last_check = 0; int pages_needed; dlink_node *m; dlink_node *head; dlink_node *prev = NULL; if (squid_curtime == last_check) return; last_check = squid_curtime; pages_needed = (size / SM_PAGE_SIZE) + 1; if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max) return; if (store_rebuilding) return; debug(20, 2) ("storeGetMemSpace: Starting, need %d pages\n", pages_needed); head = inmem_list.head; for (m = inmem_list.tail; m; m = prev) { if (m == head) break; prev = m->prev; e = m->data; if (storeEntryLocked(e)) { dlinkDelete(m, &inmem_list); dlinkAdd(e, m, &inmem_list); continue; } released++; storePurgeMem(e); if (memInUse(MEM_STMEM_BUF) + pages_needed < store_pages_max) break; } debug(20, 3) ("storeGetMemSpace stats:\n"); debug(20, 3) (" %6d HOT objects\n", hot_obj_count); debug(20, 3) (" %6d were released\n", released);}/* The maximum objects to scan for maintain storage space */#define MAINTAIN_MAX_SCAN 1024#define MAINTAIN_MAX_REMOVE 64/* * This routine is to be called by main loop in main.c. * It removes expired objects on only one bucket for each time called. * returns the number of objects removed * * This should get called 1/s from main(). */voidstoreMaintainSwapSpace(void *datanotused){ dlink_node *m; dlink_node *prev = NULL; StoreEntry *e = NULL; int scanned = 0; int locked = 0; int expired = 0; int max_scan; int max_remove; double f; static time_t last_warn_time = 0; /* We can't delete objects while rebuilding swap */ if (store_rebuilding) { eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0, 1); return; } else { f = (double) (store_swap_size - store_swap_low) / (store_swap_high - store_swap_low); f = f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; max_scan = (int) (f * 400.0 + 100.0); max_remove = (int) (f * 70.0 + 10.0); eventAdd("MaintainSwapSpace", storeMaintainSwapSpace, NULL, 1.0 - f, 1); } debug(20, 3) ("storeMaintainSwapSpace: f=%f, max_scan=%d, max_remove=%d\n", f, max_scan, max_remove); for (m = store_list.tail; m; m = prev) { prev = m->prev; e = m->data; scanned++; if (storeEntryLocked(e)) { /* * If there is a locked entry at the tail of the LRU list, * move it to the beginning to get it out of the way. * Theoretically, we might have all locked objects at the * tail, and then we'll never remove anything here and the * LRU age will go to zero. */ if (memInUse(MEM_STOREENTRY) > max_scan) { dlinkDelete(&e->lru, &store_list); dlinkAdd(e, &e->lru, &store_list); } locked++; } else if (storeCheckExpired(e)) { expired++; storeRelease(e); } if (expired >= max_remove) break; if (scanned >= max_scan) break; } debug(20, 3) ("storeMaintainSwapSpace stats:\n"); debug(20, 3) (" %6d objects\n", memInUse(MEM_STOREENTRY)); debug(20, 3) (" %6d were scanned\n", scanned); debug(20, 3) (" %6d were locked\n", locked); debug(20, 3) (" %6d were expired\n", expired); if (store_swap_size < Config.Swap.maxSize) return; if (squid_curtime - last_warn_time < 10) return; debug(20, 0) ("WARNING: Disk space over limit: %d KB > %d KB\n", store_swap_size, Config.Swap.maxSize); last_warn_time = squid_curtime;}/* release an object from a cache *//* return number of objects released. */voidstoreRelease(StoreEntry * e){ debug(20, 3) ("storeRelease: Releasing: '%s'\n", storeKeyText(e->key)); /* If, for any reason we can't discard this object because of an * outstanding request, mark it for pending release */ if (storeEntryLocked(e)) { storeExpireNow(e); debug(20, 3) ("storeRelease: Only setting RELEASE_REQUEST bit\n"); storeReleaseRequest(e); return; }#if USE_ASYNC_IO /* * Make sure all forgotten async ops are cancelled */ aioCancel(-1, e);#endif if (store_rebuilding) { storeSetPrivateKey(e); if (e->mem_obj) { storeSetMemStatus(e, NOT_IN_MEMORY); destroy_MemObject(e); } /* * Fake a call to storeLockObject(). When rebuilding is done, * we'll just call storeUnlockObject() on these. */ e->lock_count++; stackPush(&LateReleaseStack, e); return; } storeLog(STORE_LOG_RELEASE, e); if (e->swap_file_number > -1) { storeUnlinkFileno(e->swap_file_number); storeDirMapBitReset(e->swap_file_number); if (e->swap_status == SWAPOUT_DONE) if (EBIT_TEST(e->flags, ENTRY_VALIDATED)) storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, -1); if (!EBIT_TEST(e->flags, KEY_PRIVATE)) storeDirSwapLog(e, SWAP_LOG_DEL); } storeSetMemStatus(e, NOT_IN_MEMORY); destroy_StoreEntry(e);}static voidstoreLateRelease(void *unused){ StoreEntry *e; int i; static int n = 0; if (store_rebuilding) { eventAdd("storeLateRelease", storeLateRelease, NULL, 1.0, 1); return; } for (i = 0; i < 10; i++) { e = stackPop(&LateReleaseStack); if (e == NULL) { /* done! */ debug(20, 1) ("storeLateRelease: released %d objects\n", n); return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -