summaryrefslogtreecommitdiff
path: root/modules/cache/mod_cache.h
diff options
context:
space:
mode:
Diffstat (limited to 'modules/cache/mod_cache.h')
-rw-r--r--modules/cache/mod_cache.h68
1 files changed, 59 insertions, 9 deletions
diff --git a/modules/cache/mod_cache.h b/modules/cache/mod_cache.h
index 72653ae3..eca42c01 100644
--- a/modules/cache/mod_cache.h
+++ b/modules/cache/mod_cache.h
@@ -24,7 +24,7 @@
*/
#ifndef MOD_CACHE_H
-#define MOD_CACHE_H
+#define MOD_CACHE_H
#define CORE_PRIVATE
@@ -86,9 +86,13 @@
#define DEFAULT_CACHE_MAXEXPIRE MSEC_ONE_DAY
#define DEFAULT_CACHE_EXPIRE MSEC_ONE_HR
#define DEFAULT_CACHE_LMFACTOR (0.1)
+#define DEFAULT_CACHE_MAXAGE 5
+#define DEFAULT_CACHE_LOCKPATH "/mod_cache-lock"
+#define CACHE_LOCKNAME_KEY "mod_cache-lockname"
+#define CACHE_LOCKFILE_KEY "mod_cache-lockfile"
-/* Create a set of PROXY_DECLARE(type), PROXY_DECLARE_NONSTD(type) and
- * PROXY_DECLARE_DATA with appropriate export and import tags for the platform
+/* Create a set of CACHE_DECLARE(type), CACHE_DECLARE_NONSTD(type) and
+ * CACHE_DECLARE_DATA with appropriate export and import tags for the platform
*/
#if !defined(WIN32)
#define CACHE_DECLARE(type) type
@@ -134,7 +138,7 @@ typedef struct {
int factor_set;
/** ignore the last-modified header when deciding to cache this request */
int no_last_mod_ignore_set;
- int no_last_mod_ignore;
+ int no_last_mod_ignore;
/** ignore client's requests for uncached responses */
int ignorecachecontrol;
int ignorecachecontrol_set;
@@ -159,6 +163,13 @@ typedef struct {
#define CACHE_IGNORE_SESSION_ID_SET 1
#define CACHE_IGNORE_SESSION_ID_UNSET 0
int ignore_session_id_set;
+ /* thundering herd lock */
+ int lock;
+ int lock_set;
+ const char *lockpath;
+ int lockpath_set;
+ apr_time_t lockmaxage;
+ int lockmaxage_set;
} cache_server_conf;
/* cache info information */
@@ -173,11 +184,11 @@ struct cache_info {
/* cache handle information */
-/* XXX TODO On the next structure change/MMN bump,
+/* XXX TODO On the next structure change/MMN bump,
* count must become an apr_off_t, representing
* the potential size of disk cached objects.
* Then dig for
- * "XXX Bad Temporary Cast - see cache_object_t notes"
+ * "XXX Bad Temporary Cast - see cache_object_t notes"
*/
typedef struct cache_object cache_object_t;
struct cache_object {
@@ -206,7 +217,7 @@ typedef struct {
apr_status_t (*store_headers)(cache_handle_t *h, request_rec *r, cache_info *i);
apr_status_t (*store_body)(cache_handle_t *h, request_rec *r, apr_bucket_brigade *b);
apr_status_t (*recall_headers) (cache_handle_t *h, request_rec *r);
- apr_status_t (*recall_body) (cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb);
+ apr_status_t (*recall_body) (cache_handle_t *h, apr_pool_t *p, apr_bucket_brigade *bb);
int (*create_entity) (cache_handle_t *h, request_rec *r,
const char *urlkey, apr_off_t len);
int (*open_entity) (cache_handle_t *h, request_rec *r,
@@ -260,6 +271,45 @@ CACHE_DECLARE(apr_time_t) ap_cache_current_age(cache_info *info, const apr_time_
CACHE_DECLARE(int) ap_cache_check_freshness(cache_handle_t *h, request_rec *r);
/**
+ * Try obtain a cache wide lock on the given cache key.
+ *
+ * If we return APR_SUCCESS, we obtained the lock, and we are clear to
+ * proceed to the backend. If we return APR_EEXISTS, the the lock is
+ * already locked, someone else has gone to refresh the backend data
+ * already, so we must return stale data with a warning in the mean
+ * time. If we return anything else, then something has gone pear
+ * shaped, and we allow the request through to the backend regardless.
+ *
+ * This lock is created from the request pool, meaning that should
+ * something go wrong and the lock isn't deleted on return of the
+ * request headers from the backend for whatever reason, at worst the
+ * lock will be cleaned up when the request is dies or finishes.
+ *
+ * If something goes truly bananas and the lock isn't deleted when the
+ * request dies, the lock will be trashed when its max-age is reached,
+ * or when a request arrives containing a Cache-Control: no-cache. At
+ * no point is it possible for this lock to permanently deny access to
+ * the backend.
+ */
+CACHE_DECLARE(apr_status_t) ap_cache_try_lock(cache_server_conf *conf,
+ request_rec *r, char *key);
+
+/**
+ * Remove the cache lock, if present.
+ *
+ * First, try to close the file handle, whose delete-on-close should
+ * kill the file. Otherwise, just delete the file by name.
+ *
+ * If no lock name has yet been calculated, do the calculation of the
+ * lock name first before trying to delete the file.
+ *
+ * If an optional bucket brigade is passed, the lock will only be
+ * removed if the bucket brigade contains an EOS bucket.
+ */
+CACHE_DECLARE(apr_status_t) ap_cache_remove_lock(cache_server_conf *conf,
+ request_rec *r, char *key, apr_bucket_brigade *bb);
+
+/**
* Merge in cached headers into the response
* @param h cache_handle_t
* @param r request_rec
@@ -330,8 +380,8 @@ apr_status_t cache_recall_entity_body(cache_handle_t *h, apr_pool_t *p, apr_buck
#define CACHE_DECLARE_DATA __declspec(dllimport)
#endif
-APR_DECLARE_OPTIONAL_FN(apr_status_t,
- ap_cache_generate_key,
+APR_DECLARE_OPTIONAL_FN(apr_status_t,
+ ap_cache_generate_key,
(request_rec *r, apr_pool_t*p, char**key ));