📄 store_client.c
字号:
/* * $Id: store_client.c,v 1.59.2.8 1999/06/19 16:19:34 wessels Exp $ * * DEBUG: section 20 Storage Manager Client-Side Interface * AUTHOR: Duane Wessels * * SQUID Internet Object Cache http://squid.nlanr.net/Squid/ * ---------------------------------------------------------- * * Squid is the result of efforts by numerous individuals from the * Internet community. Development is led by Duane Wessels of the * National Laboratory for Applied Network Research and funded by the * National Science Foundation. Squid is Copyrighted (C) 1998 by * Duane Wessels and the University of California San Diego. Please * see the COPYRIGHT file for full details. Squid incorporates * software developed and/or copyrighted by other sources. Please see * the CREDITS file for full details. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"/* * NOTE: 'Header' refers to the swapfile metadata header. * 'Body' refers to the swapfile body, which is the full * HTTP reply (including HTTP headers and body). */static DRCB storeClientReadBody;static DRCB storeClientReadHeader;static SIH storeClientFileOpened;static void storeClientCopy2(StoreEntry * e, store_client * sc);static void storeClientFileRead(store_client * sc);static EVH storeClientCopyEvent;static store_client_t storeClientType(StoreEntry *);static int CheckQuickAbort2(StoreEntry * entry);static void CheckQuickAbort(StoreEntry * entry);/* check if there is any client waiting for this object at all *//* return 1 if there is at least one client */intstoreClientWaiting(const StoreEntry * e){ MemObject *mem = e->mem_obj; store_client *sc; for (sc = mem->clients; sc; sc = sc->next) { if (sc->callback_data != NULL) return 1; } return 0;}store_client *storeClientListSearch(const MemObject * mem, void *data){ store_client *sc; for (sc = mem->clients; sc; sc = sc->next) { if (sc->callback_data == data) break; } return sc;}static store_client_tstoreClientType(StoreEntry * e){ MemObject *mem = e->mem_obj; if (mem->inmem_lo) return STORE_DISK_CLIENT; if (EBIT_TEST(e->flags, ENTRY_ABORTED)) { /* I don't think we should be adding clients to aborted entries */ debug(20, 1) ("storeClientType: adding to ENTRY_ABORTED entry\n"); return STORE_MEM_CLIENT; } if (e->store_status == STORE_OK) { if (mem->inmem_lo == 0 && mem->inmem_hi > 0) return STORE_MEM_CLIENT; else return STORE_DISK_CLIENT; } /* here and past, entry is STORE_PENDING */ /* * If this is the first client, let it be the mem client */ else if (mem->nclients == 1) return STORE_MEM_CLIENT; /* * otherwise, make subsequent clients read from disk so they * can not delay the first, and vice-versa. */ else return STORE_DISK_CLIENT;}/* add client with fd to client list */voidstoreClientListAdd(StoreEntry * e, void *data){ MemObject *mem = e->mem_obj; store_client **T; store_client *sc; assert(mem); if (storeClientListSearch(mem, data) != NULL) return; mem->nclients++; sc = memAllocate(MEM_STORE_CLIENT); cbdataAdd(sc, memFree, MEM_STORE_CLIENT); /* sc is callback_data for file_read */ sc->callback_data = data; sc->seen_offset = 0; sc->copy_offset = 0; sc->swapin_fd = -1; sc->flags.disk_io_pending = 0; sc->entry = e; sc->type = storeClientType(e); if (sc->type == STORE_DISK_CLIENT) /* assert we'll be able to get the data we want */ /* maybe we should open swapin_fd here */ assert(e->swap_file_number > -1 || storeSwapOutAble(e)); for (T = &mem->clients; *T; T = &(*T)->next); *T = sc;#if DELAY_POOLS sc->delay_id = 0;#endif}static voidstoreClientCopyEvent(void *data){ store_client *sc = data; debug(20, 3) ("storeClientCopyEvent: Running\n"); sc->flags.copy_event_pending = 0; if (!sc->callback) return; storeClientCopy2(sc->entry, sc);}/* copy bytes requested by the client */voidstoreClientCopy(StoreEntry * e, off_t seen_offset, off_t copy_offset, size_t size, char *buf, STCB * callback, void *data){ store_client *sc; assert(!EBIT_TEST(e->flags, ENTRY_ABORTED)); debug(20, 3) ("storeClientCopy: %s, seen %d, want %d, size %d, cb %p, cbdata %p\n", storeKeyText(e->key), (int) seen_offset, (int) copy_offset, (int) size, callback, data); sc = storeClientListSearch(e->mem_obj, data); assert(sc != NULL); assert(sc->callback == NULL); sc->copy_offset = copy_offset; sc->seen_offset = seen_offset; sc->callback = callback; sc->copy_buf = buf; sc->copy_size = size; sc->copy_offset = copy_offset; storeClientCopy2(e, sc);}/* * This function is used below to decide if we have any more data to * send to the client. If the store_status is STORE_PENDING, then we * do have more data to send. If its STORE_OK, then * we continue checking. If the object length is negative, then we * don't know the real length and must open the swap file to find out. * If the length is >= 0, then we compare it to the requested copy * offset. */static intstoreClientNoMoreToSend(StoreEntry * e, store_client * sc){ ssize_t len; if (e->store_status == STORE_PENDING) return 0; if ((len = objectLen(e)) < 0) return 0; if (sc->copy_offset < len) return 0; return 1;}static voidstoreClientCopy2(StoreEntry * e, store_client * sc){ STCB *callback = sc->callback; MemObject *mem = e->mem_obj; size_t sz; if (sc->flags.copy_event_pending) return; if (EBIT_TEST(e->flags, ENTRY_FWD_HDR_WAIT)) { debug(20, 5) ("storeClientCopy2: returning because ENTRY_FWD_HDR_WAIT set\n"); return; } if (sc->flags.store_copying) { sc->flags.copy_event_pending = 1; debug(20, 3) ("storeClientCopy2: Queueing storeClientCopyEvent()\n"); eventAdd("storeClientCopyEvent", storeClientCopyEvent, sc, 0.0, 0); return; } cbdataLock(sc); /* ick, prevent sc from getting freed */ sc->flags.store_copying = 1; debug(20, 3) ("storeClientCopy2: %s\n", storeKeyText(e->key)); assert(callback != NULL); /* * We used to check for ENTRY_ABORTED here. But there were some * problems. For example, we might have a slow client (or two) and * the server-side is reading far ahead and swapping to disk. Even * if the server-side aborts, we want to give the client(s) * everything we got before the abort condition occurred. */ if (storeClientNoMoreToSend(e, sc)) { /* There is no more to send! */#if USE_ASYNC_IO if (sc->flags.disk_io_pending) { if (sc->swapin_fd >= 0) aioCancel(sc->swapin_fd, NULL); else aioCancel(-1, sc); }#endif sc->flags.disk_io_pending = 0; sc->callback = NULL; callback(sc->callback_data, sc->copy_buf, 0); } else if (e->store_status == STORE_PENDING && sc->seen_offset >= mem->inmem_hi) { /* client has already seen this, wait for more */ debug(20, 3) ("storeClientCopy2: Waiting for more\n"); } else if (sc->copy_offset >= mem->inmem_lo && sc->copy_offset < mem->inmem_hi) { /* What the client wants is in memory */ debug(20, 3) ("storeClientCopy2: Copying from memory\n"); sz = stmemCopy(&mem->data_hdr, sc->copy_offset, sc->copy_buf, sc->copy_size);#if USE_ASYNC_IO if (sc->flags.disk_io_pending) { if (sc->swapin_fd >= 0) aioCancel(sc->swapin_fd, NULL); else aioCancel(-1, sc); }#endif sc->flags.disk_io_pending = 0; sc->callback = NULL; callback(sc->callback_data, sc->copy_buf, sz); } else if (sc->swapin_fd < 0) { debug(20, 3) ("storeClientCopy2: Need to open swap in file\n"); assert(sc->type == STORE_DISK_CLIENT); /* gotta open the swapin file */ if (storeTooManyDiskFilesOpen()) { /* yuck -- this causes a TCP_SWAPFAIL_MISS on the client side */ sc->callback = NULL; callback(sc->callback_data, sc->copy_buf, -1); } else if (!sc->flags.disk_io_pending) { sc->flags.disk_io_pending = 1; storeSwapInStart(e, storeClientFileOpened, sc); } else { debug(20, 2) ("storeClientCopy2: Averted multiple fd operation\n"); } } else { debug(20, 3) ("storeClientCopy: reading from disk FD %d\n", sc->swapin_fd); assert(sc->type == STORE_DISK_CLIENT); if (!sc->flags.disk_io_pending) { storeClientFileRead(sc); } else { debug(20, 2) ("storeClientCopy2: Averted multiple fd operation\n"); } } sc->flags.store_copying = 0; cbdataUnlock(sc); /* ick, allow sc to be freed */}static voidstoreClientFileOpened(int fd, void *data){ store_client *sc = data; STCB *callback = sc->callback; if (fd < 0) { debug(20, 3) ("storeClientFileOpened: failed\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -