📄 mod_disk_cache.c
字号:
return DECLINED; } /* Create and init the cache object */ h->cache_obj = obj = apr_pcalloc(r->pool, sizeof(cache_object_t)); obj->vobj = dobj = apr_pcalloc(r->pool, sizeof(disk_cache_object_t)); info = &(obj->info); obj->key = (char *) key; dobj->name = (char *) key; dobj->datafile = data_file(r->pool, conf, dobj, key); dobj->hdrsfile = header_file(r->pool, conf, dobj, key); 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; } /* Open the headers file */ flags = APR_READ|APR_BINARY|APR_BUFFERED; rc = apr_file_open(&dobj->hfd, dobj->hdrsfile, 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(const char *key){ /* XXX: Delete file from cache! */ return OK;}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); h->resp_err_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); h->status = dobj->disk_info.status; h->content_type = apr_table_get(h->resp_hdrs, "Content-Type"); 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; rv = apr_file_writev(fd, (const struct iovec *) &iov, 1, &amt); return rv;}static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info *info){ disk_cache_conf *conf = ap_get_module_config(r->server->module_config, &disk_cache_module); apr_status_t rv; apr_size_t amt; disk_cache_object_t *dobj = (disk_cache_object_t*) h->cache_obj->vobj; if (!dobj->hfd) { disk_cache_info_t disk_info; struct iovec iov[2]; /* This is flaky... we need to manage the cache_info differently */ h->cache_obj->info = *info; /* Remove old file with the same name. If remove fails, then * perhaps we need to create the directory tree where we are * about to write the new headers file. */ rv = apr_file_remove(dobj->hdrsfile, r->pool); if (rv != APR_SUCCESS) { mkdir_structure(conf, dobj->hdrsfile, r->pool); } rv = apr_file_open(&dobj->hfd, dobj->hdrsfile, APR_WRITE | APR_CREATE | APR_EXCL, APR_OS_DEFAULT, r->pool); if (rv != APR_SUCCESS) { return rv; } dobj->name = h->cache_obj->key; disk_info.format = DISK_FORMAT_VERSION; disk_info.date = info->date; disk_info.expire = info->expire; disk_info.entity_version = dobj->disk_info.entity_version++; disk_info.request_time = info->request_time; disk_info.response_time = info->response_time; disk_info.status = info->status; disk_info.name_len = strlen(dobj->name); iov[0].iov_base = (void*)&disk_info; iov[0].iov_len = sizeof(disk_cache_info_t); iov[1].iov_base = dobj->name; iov[1].iov_len = disk_info.name_len; rv = apr_file_writev(dobj->hfd, (const struct iovec *) &iov, 2, &amt); if (rv != APR_SUCCESS) { return rv; } if (r->headers_out) { apr_table_t *headers_out; headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out, r->server); if (!apr_table_get(headers_out, "Content-Type") && r->content_type) { apr_table_setn(headers_out, "Content-Type", ap_make_content_type(r, r->content_type)); } rv = store_table(dobj->hfd, headers_out); if (rv != APR_SUCCESS) { return rv; } } /* Parse the vary header and dump those fields from the headers_in. */ /* Make call to the same thing cache_select_url calls to crack Vary. */ /* @@@ Some day, not today. */ if (r->headers_in) { apr_table_t *headers_in; headers_in = ap_cache_cacheable_hdrs_out(r->pool, r->headers_in, r->server); rv = store_table(dobj->hfd, headers_in); if (rv != APR_SUCCESS) { return rv; } } apr_file_close(dobj->hfd); /* flush and close */ } else { /* XXX log message */ } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Stored headers for URL %s", dobj->name); return APR_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -