Changeset 745 for trunk/server/source3/lib/gencache.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/lib/gencache.c
r414 r745 23 23 24 24 #include "includes.h" 25 #include "system/filesys.h" 26 #include "system/glob.h" 27 #include "util_tdb.h" 25 28 26 29 #undef DBGC_CLASS … … 66 69 67 70 again: 68 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT , open_flags, 0644);71 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH, open_flags, 0644); 69 72 if (cache) { 70 73 int ret; … … 81 84 DEBUG(0, ("gencache_init: tdb_check(%s) failed - retry after CLEAR_IF_FIRST\n", 82 85 cache_fname)); 83 cache = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST , open_flags, 0644);86 cache = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, open_flags, 0644); 84 87 if (cache) { 85 88 tdb_close(cache); … … 92 95 if (!cache && (errno == EACCES)) { 93 96 open_flags = O_RDONLY; 94 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT , open_flags,97 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH, open_flags, 95 98 0644); 96 99 if (cache) { … … 108 111 DEBUG(5, ("Opening cache file at %s\n", cache_fname)); 109 112 110 cache_notrans = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST ,113 cache_notrans = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, 111 114 open_flags, 0644); 112 115 if (cache_notrans == NULL) { … … 275 278 char *endptr; 276 279 280 if (val == NULL) { 281 return false; 282 } 283 277 284 res = strtol(val, &endptr, 10); 278 285 … … 288 295 } 289 296 return true; 297 } 298 299 struct gencache_parse_state { 300 void (*parser)(time_t timeout, DATA_BLOB blob, void *private_data); 301 void *private_data; 302 }; 303 304 static int gencache_parse_fn(TDB_DATA key, TDB_DATA data, void *private_data) 305 { 306 struct gencache_parse_state *state; 307 DATA_BLOB blob; 308 time_t t; 309 char *endptr; 310 bool ret; 311 312 if (data.dptr == NULL) { 313 return -1; 314 } 315 ret = gencache_pull_timeout((char *)data.dptr, &t, &endptr); 316 if (!ret) { 317 return -1; 318 } 319 state = (struct gencache_parse_state *)private_data; 320 blob = data_blob_const( 321 endptr+1, data.dsize - PTR_DIFF(endptr+1, data.dptr)); 322 state->parser(t, blob, state->private_data); 323 return 0; 324 } 325 326 bool gencache_parse(const char *keystr, 327 void (*parser)(time_t timeout, DATA_BLOB blob, 328 void *private_data), 329 void *private_data) 330 { 331 struct gencache_parse_state state; 332 TDB_DATA key; 333 int ret; 334 335 if (keystr == NULL) { 336 return false; 337 } 338 if (tdb_data_cmp(string_term_tdb_data(keystr), 339 last_stabilize_key()) == 0) { 340 return false; 341 } 342 if (!gencache_init()) { 343 return false; 344 } 345 346 key = string_term_tdb_data(keystr); 347 state.parser = parser; 348 state.private_data = private_data; 349 350 ret = tdb_parse_record(cache_notrans, key, gencache_parse_fn, &state); 351 if (ret != -1) { 352 return true; 353 } 354 ret = tdb_parse_record(cache, key, gencache_parse_fn, &state); 355 return (ret != -1); 356 } 357 358 struct gencache_get_data_blob_state { 359 DATA_BLOB *blob; 360 time_t timeout; 361 bool result; 362 }; 363 364 static void gencache_get_data_blob_parser(time_t timeout, DATA_BLOB blob, 365 void *private_data) 366 { 367 struct gencache_get_data_blob_state *state = 368 (struct gencache_get_data_blob_state *)private_data; 369 370 if (timeout == 0) { 371 state->result = false; 372 return; 373 } 374 state->timeout = timeout; 375 376 if (state->blob == NULL) { 377 state->result = true; 378 return; 379 } 380 381 *state->blob = data_blob(blob.data, blob.length); 382 if (state->blob->data == NULL) { 383 state->result = false; 384 return; 385 } 386 state->result = true; 290 387 } 291 388 … … 305 402 time_t *timeout, bool *was_expired) 306 403 { 307 TDB_DATA databuf; 308 time_t t; 309 char *endptr; 404 struct gencache_get_data_blob_state state; 310 405 bool expired = false; 311 406 312 if (keystr == NULL) { 407 state.result = false; 408 state.blob = blob; 409 410 if (!gencache_parse(keystr, gencache_get_data_blob_parser, &state)) { 313 411 goto fail; 314 412 } 315 316 if (tdb_data_cmp(string_term_tdb_data(keystr), 317 last_stabilize_key()) == 0) { 318 DEBUG(10, ("Can't get %s as a key\n", keystr)); 413 if (!state.result) { 319 414 goto fail; 320 415 } 321 322 if (!gencache_init()) { 323 goto fail; 324 } 325 326 databuf = tdb_fetch_bystring(cache_notrans, keystr); 327 328 if (databuf.dptr == NULL) { 329 databuf = tdb_fetch_bystring(cache, keystr); 330 } 331 332 if (databuf.dptr == NULL) { 333 DEBUG(10, ("Cache entry with key = %s couldn't be found \n", 334 keystr)); 335 goto fail; 336 } 337 338 if (!gencache_pull_timeout((char *)databuf.dptr, &t, &endptr)) { 339 SAFE_FREE(databuf.dptr); 340 goto fail; 341 } 342 343 DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " 344 "timeout = %s", t > time(NULL) ? "valid" : 345 "expired", keystr, endptr+1, ctime(&t))); 346 347 if (t == 0) { 348 /* Deleted */ 349 SAFE_FREE(databuf.dptr); 350 goto fail; 351 } 352 353 if (t <= time(NULL)) { 354 416 if (state.timeout <= time(NULL)) { 355 417 /* 356 418 * We're expired, delete the entry. We can't use gencache_del … … 360 422 */ 361 423 gencache_set(keystr, "", 0); 362 363 SAFE_FREE(databuf.dptr);364 365 424 expired = true; 366 425 goto fail; 367 426 } 368 369 if (blob != NULL) {370 *blob = data_blob(371 endptr+1,372 databuf.dsize - PTR_DIFF(endptr+1, databuf.dptr));373 if (blob->data == NULL) {374 SAFE_FREE(databuf.dptr);375 DEBUG(0, ("memdup failed\n"));376 goto fail;377 }378 }379 380 SAFE_FREE(databuf.dptr);381 382 427 if (timeout) { 383 *timeout = t;428 *timeout = state.timeout; 384 429 } 385 430 … … 389 434 if (was_expired != NULL) { 390 435 *was_expired = expired; 436 } 437 if (state.result && state.blob) { 438 data_blob_free(state.blob); 391 439 } 392 440 return false; … … 417 465 } 418 466 419 res = tdb_transaction_start (cache);467 res = tdb_transaction_start_nonblock(cache); 420 468 if (res == -1) { 469 470 if (tdb_error(cache) == TDB_ERR_NOLOCK) { 471 /* 472 * Someone else already does the stabilize, 473 * this does not have to be done twice 474 */ 475 return true; 476 } 477 421 478 DEBUG(10, ("Could not start transaction on gencache.tdb: " 422 479 "%s\n", tdb_errorstr(cache))); … … 585 642 } 586 643 587 /** 588 * Iterate through all entries which key matches to specified pattern 589 * 590 * @param fn pointer to the function that will be supplied with each single 591 * matching cache entry (key, value and timeout) as an arguments 592 * @param data void pointer to an arbitrary data that is passed directly to the fn 593 * function on each call 594 * @param keystr_pattern pattern the existing entries' keys are matched to 595 * 596 **/ 597 598 struct gencache_iterate_state { 599 void (*fn)(const char *key, const char *value, time_t timeout, 600 void *priv); 644 struct gencache_iterate_blobs_state { 645 void (*fn)(const char *key, DATA_BLOB value, 646 time_t timeout, void *private_data); 601 647 const char *pattern; 602 void *priv ;648 void *private_data; 603 649 bool in_persistent; 604 650 }; 605 651 606 static int gencache_iterate_ fn(struct tdb_context *tdb, TDB_DATA key,607 TDB_DATA value, void *priv)608 { 609 struct gencache_iterate_ state *state =610 (struct gencache_iterate_ state *)priv;652 static int gencache_iterate_blobs_fn(struct tdb_context *tdb, TDB_DATA key, 653 TDB_DATA data, void *priv) 654 { 655 struct gencache_iterate_blobs_state *state = 656 (struct gencache_iterate_blobs_state *)priv; 611 657 char *keystr; 612 658 char *free_key = NULL; 613 char *valstr;614 char *free_val = NULL;615 unsigned long u;616 659 time_t timeout; 617 char * timeout_endp;660 char *endptr; 618 661 619 662 if (tdb_data_cmp(key, last_stabilize_key()) == 0) { 620 663 return 0; 621 664 } 622 623 665 if (state->in_persistent && tdb_exists(cache_notrans, key)) { 624 666 return 0; … … 633 675 } 634 676 635 if ( (value.dptr == NULL) || (value.dsize <= TIMEOUT_LEN)) {677 if (!gencache_pull_timeout((char *)data.dptr, &timeout, &endptr)) { 636 678 goto done; 637 679 } 680 endptr += 1; 638 681 639 682 if (fnmatch(state->pattern, keystr, 0) != 0) { … … 641 684 } 642 685 643 if (value.dptr[value.dsize-1] == '\0') { 644 valstr = (char *)value.dptr; 686 DEBUG(10, ("Calling function with arguments (key=%s, timeout=%s)\n", 687 keystr, ctime(&timeout))); 688 689 state->fn(keystr, 690 data_blob_const(endptr, 691 data.dsize - PTR_DIFF(endptr, data.dptr)), 692 timeout, state->private_data); 693 694 done: 695 SAFE_FREE(free_key); 696 return 0; 697 } 698 699 void gencache_iterate_blobs(void (*fn)(const char *key, DATA_BLOB value, 700 time_t timeout, void *private_data), 701 void *private_data, const char *pattern) 702 { 703 struct gencache_iterate_blobs_state state; 704 705 if ((fn == NULL) || (pattern == NULL) || !gencache_init()) { 706 return; 707 } 708 709 DEBUG(5, ("Searching cache keys with pattern %s\n", pattern)); 710 711 state.fn = fn; 712 state.pattern = pattern; 713 state.private_data = private_data; 714 715 state.in_persistent = false; 716 tdb_traverse(cache_notrans, gencache_iterate_blobs_fn, &state); 717 718 state.in_persistent = true; 719 tdb_traverse(cache, gencache_iterate_blobs_fn, &state); 720 } 721 722 /** 723 * Iterate through all entries which key matches to specified pattern 724 * 725 * @param fn pointer to the function that will be supplied with each single 726 * matching cache entry (key, value and timeout) as an arguments 727 * @param data void pointer to an arbitrary data that is passed directly to the fn 728 * function on each call 729 * @param keystr_pattern pattern the existing entries' keys are matched to 730 * 731 **/ 732 733 struct gencache_iterate_state { 734 void (*fn)(const char *key, const char *value, time_t timeout, 735 void *priv); 736 void *private_data; 737 }; 738 739 static void gencache_iterate_fn(const char *key, DATA_BLOB value, 740 time_t timeout, void *private_data) 741 { 742 struct gencache_iterate_state *state = 743 (struct gencache_iterate_state *)private_data; 744 char *valstr; 745 char *free_val = NULL; 746 747 if (value.data[value.length-1] == '\0') { 748 valstr = (char *)value.data; 645 749 } else { 646 750 /* ensure 0-termination */ 647 valstr = SMB_STRNDUP((char *)value.d ptr, value.dsize);751 valstr = SMB_STRNDUP((char *)value.data, value.length); 648 752 free_val = valstr; 649 753 } 650 651 u = strtoul(valstr, &timeout_endp, 10);652 653 if ((*timeout_endp != '/') || ((timeout_endp-valstr) != TIMEOUT_LEN)) {654 goto done;655 }656 657 timeout = u;658 timeout_endp += 1;659 754 660 755 DEBUG(10, ("Calling function with arguments " 661 756 "(key = %s, value = %s, timeout = %s)\n", 662 keystr, timeout_endp, ctime(&timeout))); 663 state->fn(keystr, timeout_endp, timeout, state->priv); 664 665 done: 666 SAFE_FREE(free_key); 757 key, valstr, ctime(&timeout))); 758 759 state->fn(key, valstr, timeout, state->private_data); 760 667 761 SAFE_FREE(free_val); 668 return 0; 669 } 670 671 void gencache_iterate(void (*fn)(const char* key, const char *value, time_t timeout, void*dptr),672 void * data, const char* keystr_pattern)762 } 763 764 void gencache_iterate(void (*fn)(const char *key, const char *value, 765 time_t timeout, void *dptr), 766 void *private_data, const char *pattern) 673 767 { 674 768 struct gencache_iterate_state state; 675 769 676 if ( (fn == NULL) || (keystr_pattern == NULL)) {770 if (fn == NULL) { 677 771 return; 678 772 } 679 680 if (!gencache_init()) return;681 682 DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern));683 684 773 state.fn = fn; 685 state.pattern = keystr_pattern; 686 state.priv = data; 687 688 state.in_persistent = false; 689 tdb_traverse(cache_notrans, gencache_iterate_fn, &state); 690 691 state.in_persistent = true; 692 tdb_traverse(cache, gencache_iterate_fn, &state); 693 } 774 state.private_data = private_data; 775 gencache_iterate_blobs(gencache_iterate_fn, &state, pattern); 776 }
Note:
See TracChangeset
for help on using the changeset viewer.