]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/store_dir.cc
3 * $Id: store_dir.cc,v 1.81 1998/09/22 18:55:01 wessels Exp $
5 * DEBUG: section 47 Store Directory Routines
6 * AUTHOR: Duane Wessels
8 * SQUID Internet Object Cache http://squid.nlanr.net/Squid/
9 * ----------------------------------------------------------
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.
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.
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.
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.
38 #if HAVE_SYS_STATVFS_H
39 #include <sys/statvfs.h>
43 #define SWAP_DIR_SHIFT 24
44 #define SWAP_FILE_MASK 0x00FFFFFF
45 #define DefaultLevelOneDirs 16
46 #define DefaultLevelTwoDirs 256
48 static char *storeSwapSubDir(int dirn
, int subdirn
);
49 static int storeDirSelectSwapDir(void);
50 static int storeVerifyDirectory(const char *path
);
51 static int storeCreateDirectory(const char *path
, int);
52 static void storeCreateSwapSubDirs(int j
);
54 /* return full name to swapfile */
56 storeSwapFullPath(int fn
, char *fullpath
)
58 LOCAL_ARRAY(char, fullfilename
, SQUID_MAXPATHLEN
);
59 int dirn
= (fn
>> SWAP_DIR_SHIFT
) % Config
.cacheSwap
.n_configured
;
60 int filn
= fn
& SWAP_FILE_MASK
;
61 int L1
= Config
.cacheSwap
.swapDirs
[dirn
].l1
;
62 int L2
= Config
.cacheSwap
.swapDirs
[dirn
].l2
;
64 fullpath
= fullfilename
;
66 snprintf(fullpath
, SQUID_MAXPATHLEN
, "%s/%02X/%02X/%08X",
67 Config
.cacheSwap
.swapDirs
[dirn
].path
,
68 ((filn
/ L2
) / L2
) % L1
,
75 storeSwapSubDir(int dirn
, int subdirn
)
77 LOCAL_ARRAY(char, fullfilename
, SQUID_MAXPATHLEN
);
79 assert(0 <= dirn
&& dirn
< Config
.cacheSwap
.n_configured
);
80 SD
= &Config
.cacheSwap
.swapDirs
[dirn
];
81 assert(0 <= subdirn
&& subdirn
< SD
->l1
);
82 snprintf(fullfilename
, SQUID_MAXPATHLEN
, "%s/%02X",
83 Config
.cacheSwap
.swapDirs
[dirn
].path
,
89 storeSwapSubSubDir(int fn
, char *fullpath
)
91 LOCAL_ARRAY(char, fullfilename
, SQUID_MAXPATHLEN
);
92 int dirn
= (fn
>> SWAP_DIR_SHIFT
) % Config
.cacheSwap
.n_configured
;
93 int filn
= fn
& SWAP_FILE_MASK
;
94 int L1
= Config
.cacheSwap
.swapDirs
[dirn
].l1
;
95 int L2
= Config
.cacheSwap
.swapDirs
[dirn
].l2
;
97 fullpath
= fullfilename
;
99 snprintf(fullpath
, SQUID_MAXPATHLEN
, "%s/%02X/%02X",
100 Config
.cacheSwap
.swapDirs
[dirn
].path
,
101 ((filn
/ L2
) / L2
) % L1
,
107 * Does swapfile number 'fn' belong in cachedir #F0,
108 * level1 dir #F1, level2 dir #F2?
110 * This is called by storeDirClean(), but placed here because
111 * the algorithm needs to match storeSwapSubSubDir().
113 * Don't check that (fn >> SWAP_DIR_SHIFT) == F0 because
114 * 'fn' may not have the directory bits set.
117 storeFilenoBelongsHere(int fn
, int F0
, int F1
, int F2
)
121 int filn
= fn
& SWAP_FILE_MASK
;
122 assert(F0
< Config
.cacheSwap
.n_configured
);
123 L1
= Config
.cacheSwap
.swapDirs
[F0
].l1
;
124 L2
= Config
.cacheSwap
.swapDirs
[F0
].l2
;
125 D1
= ((filn
/ L2
) / L2
) % L1
;
128 D2
= (filn
/ L2
) % L2
;
135 storeCreateDirectory(const char *path
, int should_exist
)
140 if (0 == stat(path
, &st
)) {
141 if (S_ISDIR(st
.st_mode
)) {
142 debug(20, should_exist
? 3 : 1) ("%s exists\n", path
);
144 fatalf("Swap directory %s is not a directory.", path
);
146 } else if (0 == mkdir(path
, 0755)) {
147 debug(20, should_exist
? 1 : 3) ("%s created\n", path
);
150 fatalf("Failed to make swap directory %s: %s",
157 storeVerifyDirectory(const char *path
)
160 if (stat(path
, &sb
) < 0) {
161 debug(20, 0) ("%s: %s\n", path
, xstrerror());
164 if (S_ISDIR(sb
.st_mode
) == 0) {
165 debug(20, 0) ("%s is not a directory\n", path
);
172 * This function is called by storeInit(). If this returns < 0,
173 * then Squid exits, complains about swap directories not
174 * existing, and instructs the admin to run 'squid -z'
177 storeVerifyCacheDirs(void)
182 for (i
= 0; i
< Config
.cacheSwap
.n_configured
; i
++) {
183 path
= Config
.cacheSwap
.swapDirs
[i
].path
;
184 if (storeVerifyDirectory(path
) < 0)
186 for (j
= 0; j
< Config
.cacheSwap
.swapDirs
[i
].l1
; j
++) {
187 path
= storeSwapSubDir(i
, j
);
188 if (storeVerifyDirectory(path
) < 0)
196 storeCreateSwapDirectories(void)
199 const char *path
= NULL
;
200 for (i
= 0; i
< Config
.cacheSwap
.n_configured
; i
++) {
201 path
= Config
.cacheSwap
.swapDirs
[i
].path
;
202 debug(47, 3) ("Creating swap space in %s\n", path
);
203 storeCreateDirectory(path
, 0);
204 storeCreateSwapSubDirs(i
);
209 storeCreateSwapSubDirs(int j
)
213 SwapDir
*SD
= &Config
.cacheSwap
.swapDirs
[j
];
214 LOCAL_ARRAY(char, name
, MAXPATHLEN
);
215 for (i
= 0; i
< SD
->l1
; i
++) {
216 snprintf(name
, MAXPATHLEN
, "%s/%02X", SD
->path
, i
);
217 if (storeCreateDirectory(name
, 0))
221 debug(47, 1) ("Making directories in %s\n", name
);
222 for (k
= 0; k
< SD
->l2
; k
++) {
223 snprintf(name
, MAXPATHLEN
, "%s/%02X/%02X", SD
->path
, i
, k
);
224 storeCreateDirectory(name
, should_exist
);
230 *Spread load across least 3/4 of the store directories
233 storeDirSelectSwapDir(void)
235 double least_used
= 1.0;
239 static int nleast
= 0;
240 static int nconf
= 0;
241 static int *dirq
= NULL
;
242 static double *diru
= NULL
;
244 * Handle simplest case of a single swap directory immediately
246 if (Config
.cacheSwap
.n_configured
== 1)
249 * Initialise dirq on the first call or on change of number of dirs
251 if (nconf
!= Config
.cacheSwap
.n_configured
) {
252 nconf
= Config
.cacheSwap
.n_configured
;
253 nleast
= (nconf
* 3) / 4;
255 dirq
= (int *) xmalloc(sizeof(int) * nleast
);
257 diru
= (double *) xmalloc(sizeof(double) * nconf
);
258 for (j
= 0; j
< nleast
; j
++)
262 * Scan for a non-negative dirn in the dirq array and return that one
265 for (j
= 0; j
< nleast
; j
++) {
273 * If we found a valid dirn return it
278 * Now for the real guts of the algorithm - building the dirq array
280 for (i
= 0; i
< nconf
; i
++) {
282 SD
= &Config
.cacheSwap
.swapDirs
[i
];
285 diru
[i
] = (double) SD
->cur_size
;
286 diru
[i
] /= SD
->max_size
;
288 for (j
= 0; j
< nleast
; j
++) {
292 for (i
= 0; i
< nconf
; i
++) {
293 if (diru
[i
] < least_used
) {
294 least_used
= diru
[i
];
304 * Setup default return of 0 if no least found
314 storeDirValidFileno(int fn
)
316 int dirn
= fn
>> SWAP_DIR_SHIFT
;
317 int filn
= fn
& SWAP_FILE_MASK
;
318 if (dirn
> Config
.cacheSwap
.n_configured
)
324 if (filn
> Config
.cacheSwap
.swapDirs
[dirn
].map
->max_n_files
)
330 storeDirMapBitTest(int fn
)
332 int dirn
= fn
>> SWAP_DIR_SHIFT
;
333 int filn
= fn
& SWAP_FILE_MASK
;
334 return file_map_bit_test(Config
.cacheSwap
.swapDirs
[dirn
].map
, filn
);
338 storeDirMapBitSet(int fn
)
340 int dirn
= fn
>> SWAP_DIR_SHIFT
;
341 int filn
= fn
& SWAP_FILE_MASK
;
342 file_map_bit_set(Config
.cacheSwap
.swapDirs
[dirn
].map
, filn
);
346 storeDirMapBitReset(int fn
)
348 int dirn
= fn
>> SWAP_DIR_SHIFT
;
349 int filn
= fn
& SWAP_FILE_MASK
;
350 file_map_bit_reset(Config
.cacheSwap
.swapDirs
[dirn
].map
, filn
);
354 storeDirMapAllocate(void)
356 int dirn
= storeDirSelectSwapDir();
357 SwapDir
*SD
= &Config
.cacheSwap
.swapDirs
[dirn
];
358 int filn
= file_map_allocate(SD
->map
, SD
->suggest
);
359 SD
->suggest
= filn
+ 1;
360 return (dirn
<< SWAP_DIR_SHIFT
) | (filn
& SWAP_FILE_MASK
);
364 storeSwapDir(int dirn
)
366 assert(0 <= dirn
&& dirn
< Config
.cacheSwap
.n_configured
);
367 return Config
.cacheSwap
.swapDirs
[dirn
].path
;
371 storeDirNumber(int swap_file_number
)
373 return swap_file_number
>> SWAP_DIR_SHIFT
;
377 storeDirProperFileno(int dirn
, int fn
)
379 return (dirn
<< SWAP_DIR_SHIFT
) | (fn
& SWAP_FILE_MASK
);
383 * An entry written to the swap log MUST have the following
385 * 1. It MUST be a public key. It does no good to log
386 * a public ADD, change the key, then log a private
387 * DEL. So we need to log a DEL before we change a
388 * key from public to private.
389 * 2. It MUST have a valid (> -1) swap_file_number.
392 storeDirSwapLog(const StoreEntry
* e
, int op
)
396 dirn
= e
->swap_file_number
>> SWAP_DIR_SHIFT
;
397 assert(dirn
< Config
.cacheSwap
.n_configured
);
398 assert(!EBIT_TEST(e
->flags
, KEY_PRIVATE
));
399 assert(e
->swap_file_number
>= 0);
401 * icons and such; don't write them to the swap log
403 if (EBIT_TEST(e
->flags
, ENTRY_SPECIAL
))
405 assert(op
> SWAP_LOG_NOP
&& op
< SWAP_LOG_MAX
);
406 debug(20, 3) ("storeDirSwapLog: %s %s %08X\n",
408 storeKeyText(e
->key
),
409 e
->swap_file_number
);
410 s
= xcalloc(1, sizeof(storeSwapLogData
));
412 s
->swap_file_number
= e
->swap_file_number
;
413 s
->timestamp
= e
->timestamp
;
414 s
->lastref
= e
->lastref
;
415 s
->expires
= e
->expires
;
416 s
->lastmod
= e
->lastmod
;
417 s
->swap_file_sz
= e
->swap_file_sz
;
418 s
->refcount
= e
->refcount
;
420 xmemcpy(s
->key
, e
->key
, MD5_DIGEST_CHARS
);
421 file_write(Config
.cacheSwap
.swapDirs
[dirn
].swaplog_fd
,
424 sizeof(storeSwapLogData
),
431 storeDirSwapLogFile(int dirn
, const char *ext
)
433 LOCAL_ARRAY(char, path
, SQUID_MAXPATHLEN
);
434 LOCAL_ARRAY(char, digit
, 32);
435 if (Config
.Log
.swap
) {
436 xstrncpy(path
, Config
.Log
.swap
, SQUID_MAXPATHLEN
- 64);
438 snprintf(digit
, 32, "%02d", dirn
);
439 strncat(path
, digit
, 3);
441 xstrncpy(path
, storeSwapDir(dirn
), SQUID_MAXPATHLEN
- 64);
442 strcat(path
, "/swap.state");
445 strncat(path
, ext
, 16);
450 storeDirOpenSwapLogs(void)
456 for (i
= 0; i
< Config
.cacheSwap
.n_configured
; i
++) {
457 SD
= &Config
.cacheSwap
.swapDirs
[i
];
458 path
= storeDirSwapLogFile(i
, NULL
);
459 fd
= file_open(path
, O_WRONLY
| O_CREAT
, NULL
, NULL
, NULL
);
461 debug(50, 1) ("%s: %s\n", path
, xstrerror());
462 fatal("storeDirOpenSwapLogs: Failed to open swap log.");
464 debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", i
, fd
);
470 storeDirCloseSwapLogs(void)
474 for (i
= 0; i
< Config
.cacheSwap
.n_configured
; i
++) {
475 SD
= &Config
.cacheSwap
.swapDirs
[i
];
476 if (SD
->swaplog_fd
< 0) /* not open */
478 file_close(SD
->swaplog_fd
);
479 debug(47, 3) ("Cache Dir #%d log closed on FD %d\n", i
, SD
->swaplog_fd
);
485 storeDirOpenTmpSwapLog(int dirn
, int *clean_flag
, int *zero_flag
)
487 char *swaplog_path
= xstrdup(storeDirSwapLogFile(dirn
, NULL
));
488 char *clean_path
= xstrdup(storeDirSwapLogFile(dirn
, ".last-clean"));
489 char *new_path
= xstrdup(storeDirSwapLogFile(dirn
, ".new"));
491 struct stat clean_sb
;
492 SwapDir
*SD
= &Config
.cacheSwap
.swapDirs
[dirn
];
495 if (stat(swaplog_path
, &log_sb
) < 0) {
496 debug(47, 1) ("Cache Dir #%d: No log file\n", dirn
);
497 safe_free(swaplog_path
);
498 safe_free(clean_path
);
502 *zero_flag
= log_sb
.st_size
== 0 ? 1 : 0;
503 /* close the existing write-only FD */
504 if (SD
->swaplog_fd
>= 0)
505 file_close(SD
->swaplog_fd
);
506 /* open a write-only FD for the new log */
507 fd
= file_open(new_path
, O_WRONLY
| O_CREAT
| O_TRUNC
, NULL
, NULL
, NULL
);
509 debug(50, 1) ("%s: %s\n", new_path
, xstrerror());
510 fatal("storeDirOpenTmpSwapLog: Failed to open swap log.");
513 /* open a read-only stream of the old log */
514 fp
= fopen(swaplog_path
, "r");
516 debug(50, 0) ("%s: %s\n", swaplog_path
, xstrerror());
517 fatal("Failed to open swap log for reading");
519 memset(&clean_sb
, '\0', sizeof(struct stat
));
520 if (stat(clean_path
, &clean_sb
) < 0)
522 else if (clean_sb
.st_mtime
< log_sb
.st_mtime
)
526 safeunlink(clean_path
, 1);
527 safe_free(swaplog_path
);
528 safe_free(clean_path
);
534 storeDirCloseTmpSwapLog(int dirn
)
536 char *swaplog_path
= xstrdup(storeDirSwapLogFile(dirn
, NULL
));
537 char *new_path
= xstrdup(storeDirSwapLogFile(dirn
, ".new"));
538 SwapDir
*SD
= &Config
.cacheSwap
.swapDirs
[dirn
];
540 file_close(SD
->swaplog_fd
);
541 if (rename(new_path
, swaplog_path
) < 0) {
542 debug(50, 0) ("%s,%s: %s\n", new_path
, swaplog_path
, xstrerror());
543 fatal("storeDirCloseTmpSwapLog: rename failed");
545 fd
= file_open(swaplog_path
, O_WRONLY
| O_CREAT
, NULL
, NULL
, NULL
);
547 debug(50, 1) ("%s: %s\n", swaplog_path
, xstrerror());
548 fatal("storeDirCloseTmpSwapLog: Failed to open swap log.");
550 safe_free(swaplog_path
);
553 debug(47, 3) ("Cache Dir #%d log opened on FD %d\n", dirn
, fd
);
557 storeDirUpdateSwapSize(int fn
, size_t size
, int sign
)
559 int dirn
= (fn
>> SWAP_DIR_SHIFT
) % Config
.cacheSwap
.n_configured
;
560 int k
= ((size
+ 1023) >> 10) * sign
;
561 Config
.cacheSwap
.swapDirs
[dirn
].cur_size
+= k
;
562 store_swap_size
+= k
;
570 storeDirStats(StoreEntry
* sentry
)
577 storeAppendPrintf(sentry
, "Store Directory Statistics:\n");
578 storeAppendPrintf(sentry
, "Store Entries : %d\n",
579 memInUse(MEM_STOREENTRY
));
580 storeAppendPrintf(sentry
, "Maximum Swap Size : %8d KB\n",
581 Config
.Swap
.maxSize
);
582 storeAppendPrintf(sentry
, "Current Store Swap Size: %8d KB\n",
584 storeAppendPrintf(sentry
, "Current Capacity : %d%% used, %d%% free\n",
585 percent((int) store_swap_size
, (int) Config
.Swap
.maxSize
),
586 percent((int) (Config
.Swap
.maxSize
- store_swap_size
), (int) Config
.Swap
.maxSize
));
587 for (i
= 0; i
< Config
.cacheSwap
.n_configured
; i
++) {
588 SD
= &Config
.cacheSwap
.swapDirs
[i
];
589 storeAppendPrintf(sentry
, "\n");
590 storeAppendPrintf(sentry
, "Store Directory #%d: %s\n", i
, SD
->path
);
591 storeAppendPrintf(sentry
, "First level subdirectories: %d\n", SD
->l1
);
592 storeAppendPrintf(sentry
, "Second level subdirectories: %d\n", SD
->l2
);
593 storeAppendPrintf(sentry
, "Maximum Size: %d KB\n", SD
->max_size
);
594 storeAppendPrintf(sentry
, "Current Size: %d KB\n", SD
->cur_size
);
595 storeAppendPrintf(sentry
, "Percent Used: %0.2f%%\n",
596 100.0 * SD
->cur_size
/ SD
->max_size
);
597 storeAppendPrintf(sentry
, "Filemap bits in use: %d of %d (%d%%)\n",
598 SD
->map
->n_files_in_map
, SD
->map
->max_n_files
,
599 percent(SD
->map
->n_files_in_map
, SD
->map
->max_n_files
));
601 #define fsbtoblk(num, fsbs, bs) \
602 (((fsbs) != 0 && (fsbs) < (bs)) ? \
603 (num) / ((bs) / (fsbs)) : (num) * ((fsbs) / (bs)))
604 if (!statvfs(SD
->path
, &sfs
)) {
605 storeAppendPrintf(sentry
, "Filesystem Space in use: %d/%d (%d%%)\n",
606 fsbtoblk((sfs
.f_blocks
- sfs
.f_bfree
), sfs
.f_bsize
, 1024),
607 fsbtoblk(sfs
.f_blocks
, sfs
.f_bsize
, 1024),
608 percent(sfs
.f_blocks
- sfs
.f_bfree
, sfs
.f_blocks
));
609 storeAppendPrintf(sentry
, "Filesystem Inodes in use: %d/%d (%d%%)\n",
610 sfs
.f_files
- sfs
.f_ffree
, sfs
.f_files
,
611 percent(sfs
.f_files
- sfs
.f_ffree
, sfs
.f_files
));
618 storeDirMapBitsInUse(void)
622 for (i
= 0; i
< Config
.cacheSwap
.n_configured
; i
++)
623 n
+= Config
.cacheSwap
.swapDirs
[i
].map
->n_files_in_map
;
628 * storeDirWriteCleanLogs
630 * Writes a "clean" swap log file from in-memory metadata.
632 #define CLEAN_BUF_SZ 16384
634 storeDirWriteCleanLogs(int reopen
)
636 StoreEntry
*e
= NULL
;
639 time_t start
, stop
, r
;
645 int N
= Config
.cacheSwap
.n_configured
;
650 size_t ss
= sizeof(storeSwapLogData
);
651 if (store_rebuilding
) {
652 debug(20, 1) ("Not currently OK to rewrite swap log.\n");
653 debug(20, 1) ("storeDirWriteCleanLogs: Operation aborted.\n");
656 debug(20, 1) ("storeDirWriteCleanLogs: Starting...\n");
657 start
= squid_curtime
;
658 fd
= xcalloc(N
, sizeof(int));
659 cur
= xcalloc(N
, sizeof(char *));
660 new = xcalloc(N
, sizeof(char *));
661 cln
= xcalloc(N
, sizeof(char *));
662 for (dirn
= 0; dirn
< N
; dirn
++) {
664 cur
[dirn
] = xstrdup(storeDirSwapLogFile(dirn
, NULL
));
665 new[dirn
] = xstrdup(storeDirSwapLogFile(dirn
, ".clean"));
666 cln
[dirn
] = xstrdup(storeDirSwapLogFile(dirn
, ".last-clean"));
669 fd
[dirn
] = file_open(new[dirn
],
670 O_WRONLY
| O_CREAT
| O_TRUNC
,
675 debug(50, 0) ("storeDirWriteCleanLogs: %s: %s\n", new[dirn
], xstrerror());
678 debug(20, 3) ("storeDirWriteCleanLogs: opened %s, FD %d\n",
679 new[dirn
], fd
[dirn
]);
681 if (stat(cur
[dirn
], &sb
) == 0)
682 fchmod(fd
[dirn
], sb
.st_mode
);
685 outbuf
= xcalloc(N
, sizeof(char *));
686 outbufoffset
= xcalloc(N
, sizeof(*outbufoffset
));
687 for (dirn
= 0; dirn
< N
; dirn
++) {
688 outbuf
[dirn
] = xcalloc(CLEAN_BUF_SZ
, 1);
689 outbufoffset
[dirn
] = 0;
691 for (m
= store_list
.tail
; m
; m
= m
->prev
) {
693 if (e
->swap_file_number
< 0)
695 if (e
->swap_status
!= SWAPOUT_DONE
)
697 if (e
->swap_file_sz
<= 0)
699 if (EBIT_TEST(e
->flags
, RELEASE_REQUEST
))
701 if (EBIT_TEST(e
->flags
, KEY_PRIVATE
))
703 if (EBIT_TEST(e
->flags
, ENTRY_SPECIAL
))
705 dirn
= storeDirNumber(e
->swap_file_number
);
709 memset(&s
, '\0', ss
);
710 s
.op
= (char) SWAP_LOG_ADD
;
711 s
.swap_file_number
= e
->swap_file_number
;
712 s
.timestamp
= e
->timestamp
;
713 s
.lastref
= e
->lastref
;
714 s
.expires
= e
->expires
;
715 s
.lastmod
= e
->lastmod
;
716 s
.swap_file_sz
= e
->swap_file_sz
;
717 s
.refcount
= e
->refcount
;
719 xmemcpy(&s
.key
, e
->key
, MD5_DIGEST_CHARS
);
720 xmemcpy(outbuf
[dirn
] + outbufoffset
[dirn
], &s
, ss
);
721 outbufoffset
[dirn
] += ss
;
723 if (outbufoffset
[dirn
] + ss
> CLEAN_BUF_SZ
) {
724 if (write(fd
[dirn
], outbuf
[dirn
], outbufoffset
[dirn
]) < 0) {
725 debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
726 new[dirn
], xstrerror());
727 debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n");
728 file_close(fd
[dirn
]);
733 outbufoffset
[dirn
] = 0;
735 if ((++n
& 0xFFFF) == 0) {
737 debug(20, 1) (" %7d entries written so far.\n", n
);
741 for (dirn
= 0; dirn
< N
; dirn
++) {
742 if (outbufoffset
[dirn
] == 0)
746 if (write(fd
[dirn
], outbuf
[dirn
], outbufoffset
[dirn
]) < 0) {
747 debug(50, 0) ("storeDirWriteCleanLogs: %s: write: %s\n",
748 new[dirn
], xstrerror());
749 debug(20, 0) ("storeDirWriteCleanLogs: Current swap logfile not replaced.\n");
750 file_close(fd
[dirn
]);
755 safe_free(outbuf
[dirn
]);
758 safe_free(outbufoffset
);
761 * You can't rename open files on Microsoft "operating systems"
762 * so we close before renaming.
764 storeDirCloseSwapLogs();
767 for (dirn
= 0; dirn
< N
; dirn
++) {
770 if (rename(new[dirn
], cur
[dirn
]) < 0) {
771 debug(50, 0) ("storeDirWriteCleanLogs: rename failed: %s, %s -> %s\n",
772 xstrerror(), new[dirn
], cur
[dirn
]);
775 #ifndef _SQUID_MSWIN_
776 storeDirCloseSwapLogs();
779 storeDirOpenSwapLogs();
780 stop
= squid_curtime
;
782 debug(20, 1) (" Finished. Wrote %d entries.\n", n
);
783 debug(20, 1) (" Took %d seconds (%6.1f entries/sec).\n",
785 (double) n
/ (r
> 0 ? r
: 1));
786 /* touch a timestamp file if we're not still validating */
787 if (!store_rebuilding
) {
788 for (dirn
= 0; dirn
< N
; dirn
++) {
791 file_close(file_open(cln
[dirn
],
792 O_WRONLY
| O_CREAT
| O_TRUNC
, NULL
, NULL
, NULL
));
796 for (dirn
= 0; dirn
< N
; dirn
++) {
797 safe_free(cur
[dirn
]);
798 safe_free(new[dirn
]);
799 safe_free(cln
[dirn
]);
802 file_close(fd
[dirn
]);
814 storeDirConfigure(void)
820 Config
.Swap
.maxSize
= 0;
821 for (i
= 0; i
< Config
.cacheSwap
.n_configured
; i
++) {
822 SD
= &Config
.cacheSwap
.swapDirs
[i
];;
823 Config
.Swap
.maxSize
+= SD
->max_size
;
824 n
= 2 * SD
->max_size
/ Config
.Store
.avgObjectSize
;
825 if (NULL
== SD
->map
) {
827 SD
->map
= file_map_create(n
);
828 } else if (n
> SD
->map
->max_n_files
) {
829 /* it grew, need to expand */
830 fm
= file_map_create(n
);
831 filemapCopy(SD
->map
, fm
);
832 filemapFreeMemory(SD
->map
);
835 /* else it shrunk, and we leave the old one in place */
840 storeDirDiskFull(int fn
)
842 int dirn
= fn
>> SWAP_DIR_SHIFT
;
843 SwapDir
*SD
= &Config
.cacheSwap
.swapDirs
[dirn
];
844 assert(0 <= dirn
&& dirn
< Config
.cacheSwap
.n_configured
);
845 SD
->max_size
= SD
->cur_size
;
846 debug(20, 1) ("WARNING: Shrinking cache_dir #%d to %d KB\n",