* 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_EEXIST, then 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
| 277 | * the backend. |
| 278 | */ |
| 279 | apr_status_t cache_try_lock(cache_server_conf *conf, cache_request_rec *cache, |
| 280 | request_rec *r) |
| 281 | { |
| 282 | apr_status_t status; |
| 283 | const char *lockname; |
| 284 | const char *path; |
| 285 | char dir[5]; |
| 286 | apr_time_t now = apr_time_now(); |
| 287 | apr_finfo_t finfo; |
| 288 | apr_file_t *lockfile; |
| 289 | void *dummy; |
| 290 | |
| 291 | finfo.mtime = 0; |
| 292 | |
| 293 | if (!conf || !conf->lock || !conf->lockpath) { |
| 294 | /* no locks configured, leave */ |
| 295 | return APR_SUCCESS; |
| 296 | } |
| 297 | |
| 298 | /* lock already obtained earlier? if so, success */ |
| 299 | apr_pool_userdata_get(&dummy, CACHE_LOCKFILE_KEY, r->pool); |
| 300 | if (dummy) { |
| 301 | return APR_SUCCESS; |
| 302 | } |
| 303 | |
| 304 | /* create the key if it doesn't exist */ |
| 305 | if (!cache->key) { |
| 306 | cache_handle_t *h; |
| 307 | /* |
| 308 | * Try to use the key of a possible open but stale cache |
| 309 | * entry if we have one. |
| 310 | */ |
| 311 | if (cache->handle != NULL) { |
| 312 | h = cache->handle; |
| 313 | } |
| 314 | else { |
| 315 | h = cache->stale_handle; |
| 316 | } |
| 317 | if ((h != NULL) && |
| 318 | (h->cache_obj != NULL) && |
| 319 | (h->cache_obj->key != NULL)) { |
| 320 | cache->key = apr_pstrdup(r->pool, h->cache_obj->key); |
| 321 | } |
| 322 | else { |
| 323 | cache_generate_key(r, r->pool, &cache->key); |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | /* create a hashed filename from the key, and save it for later */ |
| 328 | lockname = ap_cache_generate_name(r->pool, 0, 0, cache->key); |
| 329 | |
| 330 | /* lock files represent discrete just-went-stale URLs "in flight", so |
| 331 | * we support a simple two level directory structure, more is overkill. |
| 332 | */ |
| 333 | dir[0] = '/'; |
| 334 | dir[1] = lockname[0]; |
| 335 | dir[2] = '/'; |
| 336 | dir[3] = lockname[1]; |
no test coverage detected