📄 proxy_cache.c
字号:
fprintf(stderr, "Would unlink %s\n", filename);#else if (unlink(filename) == -1) { if (errno != ENOENT) ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: unlink(%s)", filename); } else#endif { sub_long61(&curbytes, ROUNDUP2BLOCKS(fent->len)); if (cmp_long61(&curbytes, &cachesize) < 0) break; } } ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "proxy GC: Cache is %ld%% full (%d deleted)", (long)(((curbytes.upper << 20) | (curbytes.lower >> 10)) * 100 / conf->space), i); ap_unblock_alarms();}static int sub_garbage_coll(request_rec *r, array_header *files, const char *cachebasedir, const char *cachesubdir){ char line[17 * (3)]; char cachedir[HUGE_STRING_LEN]; struct stat buf; int fd, i; DIR *dir;#if defined(NEXT) || defined(WIN32) struct DIR_TYPE *ent;#else struct dirent *ent;#endif struct gc_ent *fent; int nfiles = 0; char *filename; ap_snprintf(cachedir, sizeof(cachedir), "%s%s", cachebasedir, cachesubdir); filename = ap_palloc(r->pool, strlen(cachedir) + HASH_LEN + 2); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Examining directory %s", cachedir); dir = opendir(cachedir); if (dir == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: opendir(%s)", cachedir); return 0; } while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') continue; sprintf(filename, "%s%s", cachedir, ent->d_name); ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC Examining file %s", filename);/* is it a temporary file? */ if (strncmp(ent->d_name, "tmp", 3) == 0) {/* then stat it to see how old it is; delete temporary files > 1 day old */ if (stat(filename, &buf) == -1) { if (errno != ENOENT) ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: stat(%s)", filename); } else if (garbage_now != -1 && buf.st_atime < garbage_now - SEC_ONE_DAY && buf.st_mtime < garbage_now - SEC_ONE_DAY) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r->server, "GC unlink %s", filename); ap_log_error(APLOG_MARK, APLOG_INFO | APLOG_NOERRNO, r->server, "proxy gc: deleting orphaned cache file %s", filename);#if TESTING fprintf(stderr, "Would unlink %s\n", filename);#else unlink(filename);#endif } continue; } ++nfiles;/* is it another file? */ /* FIXME: Shouldn't any unexpected files be deleted? */ /* if (strlen(ent->d_name) != HASH_LEN) continue; *//* under OS/2 use dirent's d_attr to identify a diretory *//* under TPF use stat to identify a directory */#if defined(OS2) || defined(TPF)/* is it a directory? */#ifdef OS2 if (ent->d_attr & A_DIR)#elif defined(TPF) if (stat(filename, &buf) == -1) { if (errno != ENOENT) ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: stat(%s)", filename); } if (S_ISDIR(buf.st_mode))#endif { char newcachedir[HUGE_STRING_LEN]; ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s/", cachesubdir, ent->d_name); if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) { ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s", cachedir, ent->d_name);#if TESTING fprintf(stderr, "Would remove directory %s\n", newcachedir);#else rmdir(newcachedir);#endif --nfiles; } continue; }#endif/* read the file */#if defined(WIN32) /* * On WIN32 open does not work for directories, so we us stat instead * of fstat to determine if the file is a directory */ if (stat(filename, &buf) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: stat(%s)", filename); continue; } fd = -1;#else fd = open(filename, O_RDONLY | O_BINARY); if (fd == -1) { if (errno != ENOENT) ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: open(%s)", filename); continue; } if (fstat(fd, &buf) == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: fstat(%s)", filename); close(fd); continue; }#endif/* In OS/2 and TPF this has already been done above */#if !defined(OS2) && !defined(TPF) if (S_ISDIR(buf.st_mode)) { char newcachedir[HUGE_STRING_LEN];#if !defined(WIN32) /* Win32 used stat, no file to close */ close(fd);#endif ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s/", cachesubdir, ent->d_name); if (!sub_garbage_coll(r, files, cachebasedir, newcachedir)) { ap_snprintf(newcachedir, sizeof(newcachedir), "%s%s", cachedir, ent->d_name);#if TESTING fprintf(stderr, "Would remove directory %s\n", newcachedir);#else rmdir(newcachedir);#endif --nfiles; } else { /* Directory is not empty. Account for its size: */ add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size)); } continue; }#endif#if defined(WIN32) /* * Since we have determined above that the file is not a directory, * it should be safe to open it now */ fd = open(filename, O_RDONLY | O_BINARY); if (fd == -1) { if (errno != ENOENT) ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: open(%s) = %d", filename, errno); continue; }#endif i = read(fd, line, 17 * (3) - 1); close(fd); if (i == -1) { ap_log_error(APLOG_MARK, APLOG_ERR, r->server, "proxy gc: read(%s)", filename); continue; } line[i] = '\0'; garbage_expire = ap_proxy_hex2sec(line + 17 * (2)); if (!ap_checkmask(line, "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&") || garbage_expire == BAD_DATE) { /* bad file */ if (garbage_now != -1 && buf.st_atime > garbage_now + SEC_ONE_DAY && buf.st_mtime > garbage_now + SEC_ONE_DAY) { ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_NOERRNO, r->server, "proxy: deleting bad cache file with future date: %s", filename);#if TESTING fprintf(stderr, "Would unlink bad file %s\n", filename);#else unlink(filename);#endif } continue; }/* * we need to calculate an 'old' factor, and remove the 'oldest' files * so that the space requirement is met; sort by the expires date of the * file. * */ fent = (struct gc_ent *) ap_push_array(files); fent->len = buf.st_size; fent->expire = garbage_expire; strcpy(fent->file, cachesubdir); strcat(fent->file, ent->d_name);/* accumulate in blocks, to cope with directories > 4Gb */ add_long61(&curbytes, ROUNDUP2BLOCKS(buf.st_size)); } closedir(dir); return nfiles;}/* * Read a cache file; * returns 1 on success, * 0 on failure (bad file or wrong URL) * -1 on UNIX error * * We read the cache hex header, then the message response line and * response headers, and finally we return with the filepointer * pointing at the start of the message body itself, ready to be * shipped to the client later on, if appropriate. */static int rdcache(request_rec *r, BUFF *cachefp, cache_req *c){ char urlbuff[HUGE_STRING_LEN], *strp; int len; /* read the data from the cache file */ /* * Format: * * The cache needs to keep track of the following information: - Date, * LastMod, Version, ReqTime, RespTime, ContentLength - The original * request headers (for Vary) - The original response headers (for * returning with a cached response) - The body of the message * * date SP lastmod SP expire SP count SP request-time SP response-time SP * content-lengthCRLF (dates are stored as hex seconds since 1970) * Original URLCRLF Original Request Headers CRLF Original Response * Headers CRLF Body * */ /* retrieve cachefile information values */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) { /* Delete broken cache file */ unlink(c->filename); return -1; } if (len == 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[len - 1] = '\0'; if (!ap_checkmask(urlbuff, "&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&")) return 0; c->date = ap_proxy_hex2sec(urlbuff + 17 * (0)); c->lmod = ap_proxy_hex2sec(urlbuff + 17 * (1)); c->expire = ap_proxy_hex2sec(urlbuff + 17 * (2)); c->version = ap_proxy_hex2sec(urlbuff + 17 * (3)); c->req_time = ap_proxy_hex2sec(urlbuff + 17 * (4)); c->resp_time = ap_proxy_hex2sec(urlbuff + 17 * (5)); c->len = ap_proxy_hex2sec(urlbuff + 17 * (6)); /* check that we have the same URL */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) { /* Delete broken cache file */ unlink(c->filename); return -1; } if (len == 0 || strncmp(urlbuff, "X-URL: ", 7) != 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[len - 1] = '\0'; if (strcmp(urlbuff + 7, c->url) != 0) return 0; /* then the original request headers */ c->req_hdrs = ap_proxy_read_headers(r, urlbuff, sizeof urlbuff, cachefp); if (c->req_hdrs == NULL) { /* Delete broken cache file */ unlink(c->filename); return -1; } /* then the original response headers */ len = ap_bgets(urlbuff, sizeof urlbuff, cachefp); if (len == -1) { /* Delete broken cache file */ unlink(c->filename); return -1; } if (len == 0 || urlbuff[len - 1] != '\n') return 0; urlbuff[--len] = '\0'; c->resp_line = ap_pstrdup(r->pool, urlbuff); strp = strchr(urlbuff, ' '); if (strp == NULL) return 0; c->status = atoi(strp); c->hdrs = ap_proxy_read_headers(r, urlbuff, sizeof urlbuff, cachefp); if (c->hdrs == NULL) { /* Delete broken cache file */ unlink(c->filename); return -1; } if (c->len != -1) /* add a content-length header */ if (ap_table_get(c->hdrs, "Content-Length") == NULL) { ap_table_set(c->hdrs, "Content-Length", ap_psprintf(r->pool, "%lu", (unsigned long)c->len)); } return 1;}/* * Call this to check the possible conditional status of * the client request, and return the response from the cache * * Conditionals include If-Modified-Since, If-Match, If-Unmodified-Since * and If-None-Match. * * We don't yet understand If-Range, but we will... */int ap_proxy_cache_conditional(request_rec *r, cache_req *c, BUFF *cachefp){ const char *etag, *wetag = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -