]> git.ipfire.org Git - thirdparty/squid.git/blame - src/store_swapout.cc
Another while loop in storeCleanup() event so that we do at least
[thirdparty/squid.git] / src / store_swapout.cc
CommitLineData
9cef6668 1
2/*
614a44a6 3 * $Id: store_swapout.cc,v 1.52 1999/05/26 03:08:12 wessels Exp $
9cef6668 4 *
5 * DEBUG: section 20 Storage Manager Swapout Functions
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from the
12 * Internet community. Development is led by Duane Wessels of the
13 * National Laboratory for Applied Network Research and funded by the
14 * National Science Foundation. Squid is Copyrighted (C) 1998 by
15 * Duane Wessels and the University of California San Diego. Please
16 * see the COPYRIGHT file for full details. Squid incorporates
17 * software developed and/or copyrighted by other sources. Please see
18 * the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
f09f5b26 36#include "squid.h"
37
bbcd7374 38static off_t storeSwapOutObjectBytesOnDisk(const MemObject *);
d54f0ab3 39static void storeSwapOutStart(StoreEntry * e);
2391a162 40static STIOCB storeSwapOutFileClosed;
f09f5b26 41
42/* start swapping object to disk */
d54f0ab3 43static void
f09f5b26 44storeSwapOutStart(StoreEntry * e)
45{
2391a162 46 generic_cbdata *c;
47 MemObject *mem = e->mem_obj;
48 int swap_hdr_sz = 0;
49 tlv *tlv_list;
50 char *buf;
51 assert(mem);
f09f5b26 52 storeLockObject(e);
25535cbe 53 e->swap_file_number = storeDirMapAllocate();
2391a162 54 c = xcalloc(1, sizeof(*c));
55 c->data = e;
56 cbdataAdd(c, cbdataXfree, 0);
57 mem->swapout.sio = storeOpen(e->swap_file_number,
58 O_WRONLY, storeSwapOutFileClosed, c);
59 assert(mem->swapout.sio != NULL);
60 cbdataLock(mem->swapout.sio);
61 e->swap_status = SWAPOUT_WRITING;
62 debug(20, 5) ("storeSwapOutStart: Begin SwapOut '%s' to fileno %08X\n",
63 storeUrl(e), e->swap_file_number);
64 tlv_list = storeSwapMetaBuild(e);
65 buf = storeSwapMetaPack(tlv_list, &swap_hdr_sz);
66 storeSwapTLVFree(tlv_list);
67 mem->swap_hdr_sz = (size_t) swap_hdr_sz;
50f4d6ae 68 storeWrite(mem->swapout.sio, buf, mem->swap_hdr_sz, 0, xfree);
f09f5b26 69}
70
71void
2391a162 72storeSwapOut(StoreEntry * e)
f09f5b26 73{
74 MemObject *mem = e->mem_obj;
75 off_t lowest_offset;
76 off_t new_mem_lo;
2391a162 77 off_t on_disk = 0;
f09f5b26 78 size_t swapout_size;
79 char *swap_buf;
80 ssize_t swap_buf_len;
77b32a34 81 if (mem == NULL)
82 return;
f09f5b26 83 /* should we swap something out to disk? */
2391a162 84 debug(20, 7) ("storeSwapOut: %s\n", storeUrl(e));
85 debug(20, 7) ("storeSwapOut: store_status = %s\n",
f09f5b26 86 storeStatusStr[e->store_status]);
b7fe0ab0 87 if (EBIT_TEST(e->flags, ENTRY_ABORTED)) {
d46a87a8 88 assert(EBIT_TEST(e->flags, RELEASE_REQUEST));
f09f5b26 89 storeSwapOutFileClose(e);
90 return;
91 }
2391a162 92 debug(20, 7) ("storeSwapOut: mem->inmem_lo = %d\n",
f09f5b26 93 (int) mem->inmem_lo);
2391a162 94 debug(20, 7) ("storeSwapOut: mem->inmem_hi = %d\n",
f09f5b26 95 (int) mem->inmem_hi);
2391a162 96 debug(20, 7) ("storeSwapOut: swapout.queue_offset = %d\n",
f09f5b26 97 (int) mem->swapout.queue_offset);
2391a162 98 if (mem->swapout.sio)
60df005c 99 debug(20, 7) ("storeSwapOut: storeOffset() = %d\n",
2391a162 100 (int) storeOffset(mem->swapout.sio));
f09f5b26 101 assert(mem->inmem_hi >= mem->swapout.queue_offset);
f09f5b26 102 lowest_offset = storeLowestMemReaderOffset(e);
2391a162 103 debug(20, 7) ("storeSwapOut: lowest_offset = %d\n",
f09f5b26 104 (int) lowest_offset);
f09f5b26 105 new_mem_lo = lowest_offset;
c2725718 106 assert(new_mem_lo >= mem->inmem_lo);
3157c72f 107 /*
13193254 108 * We should only free up to what we know has been written to
109 * disk, not what has been queued for writing. Otherwise there
110 * will be a chunk of the data which is not in memory and is
111 * not yet on disk.
3157c72f 112 */
c2725718 113 if (storeSwapOutAble(e))
1b72bda1 114 if ((on_disk = storeSwapOutObjectBytesOnDisk(mem)) < new_mem_lo)
c2725718 115 new_mem_lo = on_disk;
18fe65d0 116 stmemFreeDataUpto(&mem->data_hdr, new_mem_lo);
f09f5b26 117 mem->inmem_lo = new_mem_lo;
c2725718 118 if (e->swap_status == SWAPOUT_WRITING)
2391a162 119 assert(mem->inmem_lo <= on_disk);
c2725718 120 if (!storeSwapOutAble(e))
1b72bda1 121 return;
f09f5b26 122 swapout_size = (size_t) (mem->inmem_hi - mem->swapout.queue_offset);
2391a162 123 debug(20, 7) ("storeSwapOut: swapout_size = %d\n",
f09f5b26 124 (int) swapout_size);
1b72bda1 125 if (swapout_size == 0) {
614a44a6 126 if (e->store_status == STORE_OK)
1b72bda1 127 storeSwapOutFileClose(e);
614a44a6 128 return; /* Nevermore! */
1b72bda1 129 }
c47511fd 130 if (e->store_status == STORE_PENDING) {
131 /* wait for a full block to write */
614a44a6 132 if (swapout_size < DISK_PAGE_SIZE)
c47511fd 133 return;
134 /*
135 * Wait until we are below the disk FD limit, only if the
136 * next server-side read won't be deferred.
137 */
138 if (storeTooManyDiskFilesOpen() && !fwdCheckDeferRead(-1, e))
139 return;
140 }
2391a162 141 /* Ok, we have stuff to swap out. Is there a swapout.sio open? */
f09f5b26 142 if (e->swap_status == SWAPOUT_NONE) {
2391a162 143 assert(mem->swapout.sio == NULL);
c2725718 144 assert(mem->inmem_lo == 0);
f09f5b26 145 if (storeCheckCachable(e))
146 storeSwapOutStart(e);
2391a162 147 else
148 return;
614a44a6 149 /* ENTRY_CACHABLE will be cleared and we'll never get here again */
f09f5b26 150 }
2391a162 151 assert(mem->swapout.sio != NULL);
614a44a6 152 do {
153 if (swapout_size > DISK_PAGE_SIZE)
154 swapout_size = DISK_PAGE_SIZE;
155 swap_buf = memAllocate(MEM_DISK_BUF);
156 swap_buf_len = stmemCopy(&mem->data_hdr,
157 mem->swapout.queue_offset,
158 swap_buf,
159 swapout_size);
160 if (swap_buf_len < 0) {
161 debug(20, 1) ("stmemCopy returned %d for '%s'\n", swap_buf_len, storeKeyText(e->key));
162 storeUnlink(e->swap_file_number);
163 storeDirMapBitReset(e->swap_file_number);
164 e->swap_file_number = -1;
165 e->swap_status = SWAPOUT_NONE;
166 memFree(swap_buf, MEM_DISK_BUF);
167 storeReleaseRequest(e);
168 storeSwapOutFileClose(e);
169 return;
170 }
171 debug(20, 3) ("storeSwapOut: swap_buf_len = %d\n", (int) swap_buf_len);
172 assert(swap_buf_len > 0);
173 debug(20, 3) ("storeSwapOut: swapping out %d bytes from %d\n",
174 swap_buf_len, (int) mem->swapout.queue_offset);
175 mem->swapout.queue_offset += swap_buf_len;
176 storeWrite(mem->swapout.sio, swap_buf, swap_buf_len, -1, memFreeDISK);
177 /* the storeWrite() call might generate an error */
178 if (e->swap_status != SWAPOUT_WRITING)
179 break;
180 swapout_size = (size_t) (mem->inmem_hi - mem->swapout.queue_offset);
181 } while (swapout_size >= DISK_PAGE_SIZE);
0d7313ac 182 if (e->store_status == STORE_OK)
183 if (mem->inmem_hi == mem->swapout.queue_offset)
184 storeSwapOutFileClose(e);
f09f5b26 185}
186
187void
188storeSwapOutFileClose(StoreEntry * e)
189{
190 MemObject *mem = e->mem_obj;
4215b049 191 assert(mem != NULL);
2ac76861 192 debug(20, 3) ("storeSwapOutFileClose: %s\n", storeKeyText(e->key));
2391a162 193 if (mem->swapout.sio == NULL)
25354045 194 return;
2391a162 195 storeClose(mem->swapout.sio);
196 mem->swapout.sio = NULL;
25354045 197 storeUnlockObject(e);
f09f5b26 198}
199
200static void
2391a162 201storeSwapOutFileClosed(void *data, int errflag, storeIOState * sio)
f09f5b26 202{
2391a162 203 generic_cbdata *c = data;
204 StoreEntry *e = c->data;
25354045 205 MemObject *mem = e->mem_obj;
2391a162 206 assert(e->swap_status == SWAPOUT_WRITING);
207 cbdataFree(c);
208 if (errflag) {
209 debug(20, 1) ("storeSwapOutFileClosed: swapfile %08X, errflag=%d\n\t%s\n",
210 e->swap_file_number, errflag, xstrerror());
211 storeDirMapBitReset(e->swap_file_number);
b2f9d4cd 212 /*
213 * yuck. don't clear the filemap bit for some errors so that
214 * we don't try re-using it over and over
215 */
216 if (errno != EPERM)
217 storeDirMapBitReset(e->swap_file_number);
2391a162 218 if (errflag == DISK_NO_SPACE_LEFT) {
219 storeDirDiskFull(e->swap_file_number);
220 storeDirConfigure();
221 storeConfigure();
222 }
f09f5b26 223 e->swap_file_number = -1;
2391a162 224 e->swap_status = SWAPOUT_NONE;
f09f5b26 225 return;
2391a162 226 } else {
227 /* swapping complete */
228 debug(20, 3) ("storeSwapOutFileClosed: SwapOut complete: '%s' to %08X\n",
229 storeUrl(e), e->swap_file_number);
230 e->swap_file_sz = objectLen(e) + mem->swap_hdr_sz;
231 e->swap_status = SWAPOUT_DONE;
232 storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1);
233 if (storeCheckCachable(e)) {
234 storeLog(STORE_LOG_SWAPOUT, e);
235 storeDirSwapLog(e, SWAP_LOG_ADD);
236 }
f09f5b26 237 }
2391a162 238 cbdataUnlock(sio);
f09f5b26 239}
61038223 240
bbcd7374 241/*
242 * How much of the object data is on the disk?
243 */
244static off_t
245storeSwapOutObjectBytesOnDisk(const MemObject * mem)
246{
247 /*
2391a162 248 * NOTE: storeOffset() represents the disk file size,
bbcd7374 249 * not the amount of object data on disk.
250 *
251 * If we don't have at least 'swap_hdr_sz' bytes
252 * then none of the object data is on disk.
253 *
254 * This should still be safe if swap_hdr_sz == 0,
255 * meaning we haven't even opened the swapout file
256 * yet.
257 */
2391a162 258 off_t nwritten;
60df005c 259 if (mem->swapout.sio == NULL)
bbcd7374 260 return 0;
2391a162 261 nwritten = storeOffset(mem->swapout.sio);
262 if (nwritten <= mem->swap_hdr_sz)
263 return 0;
264 return nwritten - mem->swap_hdr_sz;
bbcd7374 265}
c2725718 266
267/*
268 * Is this entry a candidate for writing to disk?
269 */
5f25e839 270int
c2725718 271storeSwapOutAble(const StoreEntry * e)
272{
5f25e839 273 store_client *sc;
2391a162 274 if (e->mem_obj->swapout.sio != NULL)
c2725718 275 return 1;
276 if (e->mem_obj->inmem_lo > 0)
277 return 0;
5f25e839 278 /*
279 * If there are DISK clients, we must write to disk
280 * even if its not cachable
281 */
135171fe 282 for (sc = e->mem_obj->clients; sc; sc = sc->next)
5f25e839 283 if (sc->type == STORE_DISK_CLIENT)
284 return 1;
d46a87a8 285 return EBIT_TEST(e->flags, ENTRY_CACHABLE);
c2725718 286}