]> git.ipfire.org Git - thirdparty/squid.git/blame - src/store_swapout.cc
STORE fixes and async cleanup from trying to get ASYNCUFS working
[thirdparty/squid.git] / src / store_swapout.cc
CommitLineData
9cef6668 1
2/*
5bd1abac 3 * $Id: store_swapout.cc,v 1.55 1999/06/25 23:37:34 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);
1792fbdb 181 if (e->store_status == STORE_PENDING)
182 if (swapout_size < DISK_PAGE_SIZE)
183 break;
184 } while (swapout_size > 0);
185 if (e->store_status == STORE_OK) {
186 /*
187 * If the state is STORE_OK, then all data must have been given
188 * to the filesystem at this point because storeSwapOut() is
189 * not going to be called again for this entry.
190 */
191 assert(mem->inmem_hi == mem->swapout.queue_offset);
192 storeSwapOutFileClose(e);
193 }
f09f5b26 194}
195
196void
197storeSwapOutFileClose(StoreEntry * e)
198{
199 MemObject *mem = e->mem_obj;
4215b049 200 assert(mem != NULL);
2ac76861 201 debug(20, 3) ("storeSwapOutFileClose: %s\n", storeKeyText(e->key));
5bd1abac 202 debug(20, 3) ("storeSwapOutFileClose: sio = %p\n", mem->swapout.sio);
2391a162 203 if (mem->swapout.sio == NULL)
25354045 204 return;
2391a162 205 storeClose(mem->swapout.sio);
f09f5b26 206}
207
208static void
2391a162 209storeSwapOutFileClosed(void *data, int errflag, storeIOState * sio)
f09f5b26 210{
2391a162 211 generic_cbdata *c = data;
212 StoreEntry *e = c->data;
25354045 213 MemObject *mem = e->mem_obj;
2391a162 214 assert(e->swap_status == SWAPOUT_WRITING);
215 cbdataFree(c);
216 if (errflag) {
217 debug(20, 1) ("storeSwapOutFileClosed: swapfile %08X, errflag=%d\n\t%s\n",
218 e->swap_file_number, errflag, xstrerror());
b2f9d4cd 219 /*
220 * yuck. don't clear the filemap bit for some errors so that
221 * we don't try re-using it over and over
222 */
223 if (errno != EPERM)
224 storeDirMapBitReset(e->swap_file_number);
2391a162 225 if (errflag == DISK_NO_SPACE_LEFT) {
226 storeDirDiskFull(e->swap_file_number);
227 storeDirConfigure();
228 storeConfigure();
229 }
5bd1abac 230 storeReleaseRequest(e);
f09f5b26 231 e->swap_file_number = -1;
2391a162 232 e->swap_status = SWAPOUT_NONE;
2391a162 233 } else {
234 /* swapping complete */
235 debug(20, 3) ("storeSwapOutFileClosed: SwapOut complete: '%s' to %08X\n",
236 storeUrl(e), e->swap_file_number);
237 e->swap_file_sz = objectLen(e) + mem->swap_hdr_sz;
2b906e48 238#if HEAP_REPLACEMENT
239 storeHeapPositionUpdate(e);
240#endif
2391a162 241 e->swap_status = SWAPOUT_DONE;
242 storeDirUpdateSwapSize(e->swap_file_number, e->swap_file_sz, 1);
243 if (storeCheckCachable(e)) {
244 storeLog(STORE_LOG_SWAPOUT, e);
245 storeDirSwapLog(e, SWAP_LOG_ADD);
246 }
f09f5b26 247 }
5bd1abac 248 debug(20, 3) ("storeSwapOutFileClosed: %s:%d\n", __FILE__, __LINE__);
249 mem->swapout.sio = NULL;
2391a162 250 cbdataUnlock(sio);
5bd1abac 251 storeUnlockObject(e);
f09f5b26 252}
61038223 253
bbcd7374 254/*
255 * How much of the object data is on the disk?
256 */
257static off_t
258storeSwapOutObjectBytesOnDisk(const MemObject * mem)
259{
260 /*
2391a162 261 * NOTE: storeOffset() represents the disk file size,
bbcd7374 262 * not the amount of object data on disk.
263 *
264 * If we don't have at least 'swap_hdr_sz' bytes
265 * then none of the object data is on disk.
266 *
267 * This should still be safe if swap_hdr_sz == 0,
268 * meaning we haven't even opened the swapout file
269 * yet.
270 */
2391a162 271 off_t nwritten;
60df005c 272 if (mem->swapout.sio == NULL)
bbcd7374 273 return 0;
2391a162 274 nwritten = storeOffset(mem->swapout.sio);
275 if (nwritten <= mem->swap_hdr_sz)
276 return 0;
277 return nwritten - mem->swap_hdr_sz;
bbcd7374 278}
c2725718 279
280/*
281 * Is this entry a candidate for writing to disk?
282 */
5f25e839 283int
c2725718 284storeSwapOutAble(const StoreEntry * e)
285{
5f25e839 286 store_client *sc;
2391a162 287 if (e->mem_obj->swapout.sio != NULL)
c2725718 288 return 1;
289 if (e->mem_obj->inmem_lo > 0)
290 return 0;
5f25e839 291 /*
292 * If there are DISK clients, we must write to disk
293 * even if its not cachable
294 */
135171fe 295 for (sc = e->mem_obj->clients; sc; sc = sc->next)
5f25e839 296 if (sc->type == STORE_DISK_CLIENT)
297 return 1;
1792fbdb 298 if (store_dirs_rebuilding)
299 if (!EBIT_TEST(e->flags, ENTRY_SPECIAL))
300 return 0;
d46a87a8 301 return EBIT_TEST(e->flags, ENTRY_CACHABLE);
c2725718 302}