summaryrefslogtreecommitdiffabout
path: root/cache.c
authorLars Hjemli <hjemli@gmail.com>2008-04-28 10:10:13 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2008-04-28 10:10:13 (UTC)
commit9000bbf865cb3578ba5ed3810dc44253cb46ec7f (patch) (unidiff)
treea9917628c40301862d1b1d6f5ecaf803ecc0f714 /cache.c
parent939d32fda70ea66c9db51687beb3cea6da7b0599 (diff)
downloadcgit-9000bbf865cb3578ba5ed3810dc44253cb46ec7f.zip
cgit-9000bbf865cb3578ba5ed3810dc44253cb46ec7f.tar.gz
cgit-9000bbf865cb3578ba5ed3810dc44253cb46ec7f.tar.bz2
Add page 'ls_cache'
This new page will list all entries found in the current cache, which is useful when reviewing the new cache implementation. There are no links to the new page, but it's reachable by adding 'p=ls_cache' to any cgit url. Signed-off-by: Lars Hjemli <hjemli@gmail.com>
Diffstat (limited to 'cache.c') (more/less context) (ignore whitespace changes)
-rw-r--r--cache.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/cache.c b/cache.c
index e590d7b..b701e13 100644
--- a/cache.c
+++ b/cache.c
@@ -239,105 +239,173 @@ static int process_slot(struct cache_slot *slot)
239 } 239 }
240 print_slot(slot); 240 print_slot(slot);
241 close_slot(slot); 241 close_slot(slot);
242 return 0; 242 return 0;
243 } 243 }
244 244
245 /* If the cache slot does not exist (or its key doesn't match the 245 /* If the cache slot does not exist (or its key doesn't match the
246 * current key), lets try to create a new cache slot for this 246 * current key), lets try to create a new cache slot for this
247 * request. If this fails (for whatever reason), lets just generate 247 * request. If this fails (for whatever reason), lets just generate
248 * the content without caching it and fool the caller to belive 248 * the content without caching it and fool the caller to belive
249 * everything worked out (but print a warning on stdout). 249 * everything worked out (but print a warning on stdout).
250 */ 250 */
251 251
252 close_slot(slot); 252 close_slot(slot);
253 if ((err = lock_slot(slot)) != 0) { 253 if ((err = lock_slot(slot)) != 0) {
254 cache_log("[cgit] Unable to lock slot %s: %s (%d)\n", 254 cache_log("[cgit] Unable to lock slot %s: %s (%d)\n",
255 slot->lock_name, strerror(err), err); 255 slot->lock_name, strerror(err), err);
256 slot->fn(slot->cbdata); 256 slot->fn(slot->cbdata);
257 return 0; 257 return 0;
258 } 258 }
259 259
260 if ((err = fill_slot(slot)) != 0) { 260 if ((err = fill_slot(slot)) != 0) {
261 cache_log("[cgit] Unable to fill slot %s: %s (%d)\n", 261 cache_log("[cgit] Unable to fill slot %s: %s (%d)\n",
262 slot->lock_name, strerror(err), err); 262 slot->lock_name, strerror(err), err);
263 unlock_slot(slot, 0); 263 unlock_slot(slot, 0);
264 close_lock(slot); 264 close_lock(slot);
265 slot->fn(slot->cbdata); 265 slot->fn(slot->cbdata);
266 return 0; 266 return 0;
267 } 267 }
268 // We've got a valid cache slot in the lock file, which 268 // We've got a valid cache slot in the lock file, which
269 // is about to replace the old cache slot. But if we 269 // is about to replace the old cache slot. But if we
270 // release the lockfile and then try to open the new cache 270 // release the lockfile and then try to open the new cache
271 // slot, we might get a race condition with a concurrent 271 // slot, we might get a race condition with a concurrent
272 // writer for the same cache slot (with a different key). 272 // writer for the same cache slot (with a different key).
273 // Lets avoid such a race by just printing the content of 273 // Lets avoid such a race by just printing the content of
274 // the lock file. 274 // the lock file.
275 slot->cache_fd = slot->lock_fd; 275 slot->cache_fd = slot->lock_fd;
276 unlock_slot(slot, 1); 276 unlock_slot(slot, 1);
277 err = print_slot(slot); 277 err = print_slot(slot);
278 close_slot(slot); 278 close_slot(slot);
279 return err; 279 return err;
280} 280}
281 281
282/* Print cached content to stdout, generate the content if necessary. */ 282/* Print cached content to stdout, generate the content if necessary. */
283int cache_process(int size, const char *path, const char *key, int ttl, 283int cache_process(int size, const char *path, const char *key, int ttl,
284 cache_fill_fn fn, void *cbdata) 284 cache_fill_fn fn, void *cbdata)
285{ 285{
286 unsigned long hash; 286 unsigned long hash;
287 int len, i; 287 int len, i;
288 char filename[1024]; 288 char filename[1024];
289 char lockname[1024 + 5]; /* 5 = ".lock" */ 289 char lockname[1024 + 5]; /* 5 = ".lock" */
290 struct cache_slot slot; 290 struct cache_slot slot;
291 291
292 /* If the cache is disabled, just generate the content */ 292 /* If the cache is disabled, just generate the content */
293 if (size <= 0) { 293 if (size <= 0) {
294 fn(cbdata); 294 fn(cbdata);
295 return 0; 295 return 0;
296 } 296 }
297 297
298 /* Verify input, calculate filenames */ 298 /* Verify input, calculate filenames */
299 if (!path) { 299 if (!path) {
300 cache_log("[cgit] Cache path not specified, caching is disabled\n"); 300 cache_log("[cgit] Cache path not specified, caching is disabled\n");
301 fn(cbdata); 301 fn(cbdata);
302 return 0; 302 return 0;
303 } 303 }
304 len = strlen(path); 304 len = strlen(path);
305 if (len > sizeof(filename) - 10) { /* 10 = "/01234567\0" */ 305 if (len > sizeof(filename) - 10) { /* 10 = "/01234567\0" */
306 cache_log("[cgit] Cache path too long, caching is disabled: %s\n", 306 cache_log("[cgit] Cache path too long, caching is disabled: %s\n",
307 path); 307 path);
308 fn(cbdata); 308 fn(cbdata);
309 return 0; 309 return 0;
310 } 310 }
311 if (!key) 311 if (!key)
312 key = ""; 312 key = "";
313 hash = hash_str(key) % size; 313 hash = hash_str(key) % size;
314 strcpy(filename, path); 314 strcpy(filename, path);
315 if (filename[len - 1] != '/') 315 if (filename[len - 1] != '/')
316 filename[len++] = '/'; 316 filename[len++] = '/';
317 for(i = 0; i < 8; i++) { 317 for(i = 0; i < 8; i++) {
318 sprintf(filename + len++, "%x", 318 sprintf(filename + len++, "%x",
319 (unsigned char)(hash & 0xf)); 319 (unsigned char)(hash & 0xf));
320 hash >>= 4; 320 hash >>= 4;
321 } 321 }
322 filename[len] = '\0'; 322 filename[len] = '\0';
323 strcpy(lockname, filename); 323 strcpy(lockname, filename);
324 strcpy(lockname + len, ".lock"); 324 strcpy(lockname + len, ".lock");
325 slot.fn = fn; 325 slot.fn = fn;
326 slot.cbdata = cbdata; 326 slot.cbdata = cbdata;
327 slot.ttl = ttl; 327 slot.ttl = ttl;
328 slot.cache_name = filename; 328 slot.cache_name = filename;
329 slot.lock_name = lockname; 329 slot.lock_name = lockname;
330 slot.key = key; 330 slot.key = key;
331 slot.keylen = strlen(key); 331 slot.keylen = strlen(key);
332 return process_slot(&slot); 332 return process_slot(&slot);
333} 333}
334 334
335/* Return a strftime formatted date/time
336 * NB: the result from this function is to shared memory
337 */
338char *sprintftime(const char *format, time_t time)
339{
340 static char buf[64];
341 struct tm *tm;
342
343 if (!time)
344 return NULL;
345 tm = gmtime(&time);
346 strftime(buf, sizeof(buf)-1, format, tm);
347 return buf;
348}
349
350int cache_ls(const char *path)
351{
352 DIR *dir;
353 struct dirent *ent;
354 int err = 0;
355 struct cache_slot slot;
356 char fullname[1024];
357 char *name;
358
359 if (!path) {
360 cache_log("[cgit] cache path not specified\n");
361 return -1;
362 }
363 if (strlen(path) > 1024 - 10) {
364 cache_log("[cgit] cache path too long: %s\n",
365 path);
366 return -1;
367 }
368 dir = opendir(path);
369 if (!dir) {
370 err = errno;
371 cache_log("[cgit] unable to open path %s: %s (%d)\n",
372 path, strerror(err), err);
373 return err;
374 }
375 strcpy(fullname, path);
376 name = fullname + strlen(path);
377 if (*(name - 1) != '/') {
378 *name++ = '/';
379 *name = '\0';
380 }
381 slot.cache_name = fullname;
382 while((ent = readdir(dir)) != NULL) {
383 if (strlen(ent->d_name) != 8)
384 continue;
385 strcpy(name, ent->d_name);
386 if ((err = open_slot(&slot)) != 0) {
387 cache_log("[cgit] unable to open path %s: %s (%d)\n",
388 fullname, strerror(err), err);
389 continue;
390 }
391 printf("%s %s %10lld %s\n",
392 name,
393 sprintftime("%Y-%m-%d %H:%M:%S",
394 slot.cache_st.st_mtime),
395 slot.cache_st.st_size,
396 slot.buf);
397 close_slot(&slot);
398 }
399 closedir(dir);
400 return 0;
401}
402
335/* Print a message to stdout */ 403/* Print a message to stdout */
336void cache_log(const char *format, ...) 404void cache_log(const char *format, ...)
337{ 405{
338 va_list args; 406 va_list args;
339 va_start(args, format); 407 va_start(args, format);
340 vfprintf(stderr, format, args); 408 vfprintf(stderr, format, args);
341 va_end(args); 409 va_end(args);
342} 410}
343 411