📄 mod_disk_cache.c
字号:
len = sizeof(format); apr_file_read_full(dobj->hfd, &format, len, &len); if (format == VARY_FORMAT_VERSION) { apr_array_header_t* varray; apr_time_t expire; len = sizeof(expire); apr_file_read_full(dobj->hfd, &expire, len, &len); varray = apr_array_make(r->pool, 5, sizeof(char*)); rc = read_array(r, varray, dobj->hfd); if (rc != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rc, r->server, "disk_cache: Cannot parse vary header file: %s", dobj->hdrsfile); return DECLINED; } apr_file_close(dobj->hfd); nkey = regen_key(r->pool, r->headers_in, varray, key); dobj->hashfile = NULL; dobj->prefix = dobj->hdrsfile; dobj->hdrsfile = header_file(r->pool, conf, dobj, nkey); flags = APR_READ|APR_BINARY|APR_BUFFERED; rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, flags, 0, r->pool); if (rc != APR_SUCCESS) { return DECLINED; } } else if (format != DISK_FORMAT_VERSION) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "cache_disk: File '%s' has a version mismatch. File had version: %d.", dobj->hdrsfile, format); return DECLINED; } else { apr_off_t offset = 0; /* This wasn't a Vary Format file, so we must seek to the * start of the file again, so that later reads work. */ apr_file_seek(dobj->hfd, APR_SET, &offset); nkey = key; } obj->key = nkey; dobj->key = nkey; dobj->name = key; dobj->datafile = data_file(r->pool, conf, dobj, nkey); dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); /* Open the data file */ flags = APR_READ|APR_BINARY;#ifdef APR_SENDFILE_ENABLED flags |= APR_SENDFILE_ENABLED;#endif rc = apr_file_open(&dobj->fd, dobj->datafile, flags, 0, r->pool); if (rc != APR_SUCCESS) { /* XXX: Log message */ return DECLINED; } rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, dobj->fd); if (rc == APR_SUCCESS) { dobj->file_size = finfo.size; } /* Read the bytes to setup the cache_info fields */ rc = file_cache_recall_mydata(dobj->hfd, info, dobj, r); if (rc != APR_SUCCESS) { /* XXX log message */ return DECLINED; } /* Initialize the cache_handle callback functions */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Recalled cached URL info header %s", dobj->name); return OK;}static int remove_entity(cache_handle_t *h){ /* Null out the cache object pointer so next time we start from scratch */ h->cache_obj = NULL; return OK;}static int remove_url(cache_handle_t *h, apr_pool_t *p){ apr_status_t rc; disk_cache_object_t *dobj; /* Get disk cache object from cache handle */ dobj = (disk_cache_object_t *) h->cache_obj->vobj; if (!dobj) { return DECLINED; } /* Delete headers file */ if (dobj->hdrsfile) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "disk_cache: Deleting %s from cache.", dobj->hdrsfile); rc = apr_file_remove(dobj->hdrsfile, p); if ((rc != APR_SUCCESS) && !APR_STATUS_IS_ENOENT(rc)) { /* Will only result in an output if httpd is started with -e debug. * For reason see log_error_core for the case s == NULL. */ ap_log_error(APLOG_MARK, APLOG_DEBUG, rc, NULL, "disk_cache: Failed to delete headers file %s from cache.", dobj->hdrsfile); return DECLINED; } } /* Delete data file */ if (dobj->datafile) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "disk_cache: Deleting %s from cache.", dobj->datafile); rc = apr_file_remove(dobj->datafile, p); if ((rc != APR_SUCCESS) && !APR_STATUS_IS_ENOENT(rc)) { /* Will only result in an output if httpd is started with -e debug. * For reason see log_error_core for the case s == NULL. */ ap_log_error(APLOG_MARK, APLOG_DEBUG, rc, NULL, "disk_cache: Failed to delete data file %s from cache.", dobj->datafile); return DECLINED; } } /* now delete directories as far as possible up to our cache root */ if (dobj->root) { const char *str_to_copy; str_to_copy = dobj->hdrsfile ? dobj->hdrsfile : dobj->datafile; if (str_to_copy) { char *dir, *slash, *q; dir = apr_pstrdup(p, str_to_copy); /* remove filename */ slash = strrchr(dir, '/'); *slash = '\0'; /* * now walk our way back to the cache root, delete everything * in the way as far as possible * * Note: due to the way we constructed the file names in * header_file and data_file, we are guaranteed that the * cache_root is suffixed by at least one '/' which will be * turned into a terminating null by this loop. Therefore, * we won't either delete or go above our cache root. */ for (q = dir + dobj->root_len; *q ; ) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, NULL, "disk_cache: Deleting directory %s from cache", dir); rc = apr_dir_remove(dir, p); if (rc != APR_SUCCESS && !APR_STATUS_IS_ENOENT(rc)) { break; } slash = strrchr(q, '/'); *slash = '\0'; } } } return OK;}static apr_status_t read_array(request_rec *r, apr_array_header_t* arr, apr_file_t *file){ char w[MAX_STRING_LEN]; int p; apr_status_t rv; while (1) { rv = apr_file_gets(w, MAX_STRING_LEN - 1, file); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Premature end of vary array."); return rv; } p = strlen(w); if (p > 0 && w[p - 1] == '\n') { if (p > 1 && w[p - 2] == CR) { w[p - 2] = '\0'; } else { w[p - 1] = '\0'; } } /* If we've finished reading the array, break out of the loop. */ if (w[0] == '\0') { break; } *((const char **) apr_array_push(arr)) = apr_pstrdup(r->pool, w); } return APR_SUCCESS;}static apr_status_t store_array(apr_file_t *fd, apr_array_header_t* arr){ int i; apr_status_t rv; struct iovec iov[2]; apr_size_t amt; const char **elts; elts = (const char **) arr->elts; for (i = 0; i < arr->nelts; i++) { iov[0].iov_base = (char*) elts[i]; iov[0].iov_len = strlen(elts[i]); iov[1].iov_base = CRLF; iov[1].iov_len = sizeof(CRLF) - 1; rv = apr_file_writev(fd, (const struct iovec *) &iov, 2, &amt); if (rv != APR_SUCCESS) { return rv; } } iov[0].iov_base = CRLF; iov[0].iov_len = sizeof(CRLF) - 1; return apr_file_writev(fd, (const struct iovec *) &iov, 1, &amt);}static apr_status_t read_table(cache_handle_t *handle, request_rec *r, apr_table_t *table, apr_file_t *file){ char w[MAX_STRING_LEN]; char *l; int p; apr_status_t rv; while (1) { /* ### What about APR_EOF? */ rv = apr_file_gets(w, MAX_STRING_LEN - 1, file); if (rv != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Premature end of cache headers."); return rv; } /* Delete terminal (CR?)LF */ p = strlen(w); /* Indeed, the host's '\n': '\012' for UNIX; '\015' for MacOS; '\025' for OS/390 -- whatever the script generates. */ if (p > 0 && w[p - 1] == '\n') { if (p > 1 && w[p - 2] == CR) { w[p - 2] = '\0'; } else { w[p - 1] = '\0'; } } /* If we've finished reading the headers, break out of the loop. */ if (w[0] == '\0') { break; }#if APR_CHARSET_EBCDIC /* Chances are that we received an ASCII header text instead of * the expected EBCDIC header lines. Try to auto-detect: */ if (!(l = strchr(w, ':'))) { int maybeASCII = 0, maybeEBCDIC = 0; unsigned char *cp, native; apr_size_t inbytes_left, outbytes_left; for (cp = w; *cp != '\0'; ++cp) { native = apr_xlate_conv_byte(ap_hdrs_from_ascii, *cp); if (apr_isprint(*cp) && !apr_isprint(native)) ++maybeEBCDIC; if (!apr_isprint(*cp) && apr_isprint(native)) ++maybeASCII; } if (maybeASCII > maybeEBCDIC) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "CGI Interface Error: Script headers apparently ASCII: (CGI = %s)", r->filename); inbytes_left = outbytes_left = cp - w; apr_xlate_conv_buffer(ap_hdrs_from_ascii, w, &inbytes_left, w, &outbytes_left); } }#endif /*APR_CHARSET_EBCDIC*/ /* if we see a bogus header don't ignore it. Shout and scream */ if (!(l = strchr(w, ':'))) { return APR_EGENERAL; } *l++ = '\0'; while (*l && apr_isspace(*l)) { ++l; } apr_table_add(table, w, l); } return APR_SUCCESS;}/* * Reads headers from a buffer and returns an array of headers. * Returns NULL on file error * This routine tries to deal with too long lines and continuation lines. * @@@: XXX: FIXME: currently the headers are passed thru un-merged. * Is that okay, or should they be collapsed where possible? */static apr_status_t recall_headers(cache_handle_t *h, request_rec *r){ disk_cache_object_t *dobj = (disk_cache_object_t *) h->cache_obj->vobj; /* This case should not happen... */ if (!dobj->hfd) { /* XXX log message */ return APR_NOTFOUND; } h->req_hdrs = apr_table_make(r->pool, 20); h->resp_hdrs = apr_table_make(r->pool, 20); /* Call routine to read the header lines/status line */ read_table(h, r, h->resp_hdrs, dobj->hfd); read_table(h, r, h->req_hdrs, dobj->hfd); apr_file_close(dobj->hfd); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Recalled headers for URL %s", dobj->name); return APR_SUCCESS;}static apr_status_t recall_body(cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb){ apr_bucket *e; disk_cache_object_t *dobj = (disk_cache_object_t*) h->cache_obj->vobj; e = apr_bucket_file_create(dobj->fd, 0, (apr_size_t) dobj->file_size, p, bb->bucket_alloc); APR_BRIGADE_INSERT_HEAD(bb, e); e = apr_bucket_eos_create(bb->bucket_alloc); APR_BRIGADE_INSERT_TAIL(bb, e); return APR_SUCCESS;}static apr_status_t store_table(apr_file_t *fd, apr_table_t *table){ int i; apr_status_t rv; struct iovec iov[4]; apr_size_t amt; apr_table_entry_t *elts; elts = (apr_table_entry_t *) apr_table_elts(table)->elts; for (i = 0; i < apr_table_elts(table)->nelts; ++i) { if (elts[i].key != NULL) { iov[0].iov_base = elts[i].key; iov[0].iov_len = strlen(elts[i].key); iov[1].iov_base = ": "; iov[1].iov_len = sizeof(": ") - 1; iov[2].iov_base = elts[i].val; iov[2].iov_len = strlen(elts[i].val); iov[3].iov_base = CRLF; iov[3].iov_len = sizeof(CRLF) - 1; rv = apr_file_writev(fd, (const struct iovec *) &iov, 4, &amt); if (rv != APR_SUCCESS) { return rv; } } } iov[0].iov_base = CRLF; iov[0].iov_len = sizeof(CRLF) - 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -