Changeset 988 for vendor/current/source3/lib/gencache.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/lib/gencache.c
r740 r988 26 26 #include "system/glob.h" 27 27 #include "util_tdb.h" 28 #include "tdb_wrap/tdb_wrap.h" 29 #include "../lib/util/memcache.h" 28 30 29 31 #undef DBGC_CLASS … … 36 38 #define BLOB_TYPE_LEN 9 37 39 38 static struct tdb_context *cache; 39 static struct tdb_context *cache_notrans; 40 static struct tdb_wrap *cache; 41 static struct tdb_wrap *cache_notrans; 42 static int cache_notrans_seqnum; 40 43 41 44 /** … … 59 62 char* cache_fname = NULL; 60 63 int open_flags = O_RDWR|O_CREAT; 61 bool first_try = true;62 64 63 65 /* skip file open if it's already opened */ 64 if (cache) return True; 65 66 cache_fname = lock_path("gencache.tdb"); 66 if (cache) { 67 return true; 68 } 69 70 cache_fname = cache_path("gencache.tdb"); 71 if (cache_fname == NULL) { 72 return false; 73 } 67 74 68 75 DEBUG(5, ("Opening cache file at %s\n", cache_fname)); 69 76 70 again: 71 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH, open_flags, 0644); 77 cache = tdb_wrap_open(NULL, cache_fname, 0, 78 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH, 79 open_flags, 0644); 72 80 if (cache) { 73 81 int ret; 74 ret = tdb_check(cache , NULL, NULL);82 ret = tdb_check(cache->tdb, NULL, NULL); 75 83 if (ret != 0) { 76 tdb_close(cache); 77 cache = NULL; 78 if (!first_try) { 79 DEBUG(0, ("gencache_init: tdb_check(%s) failed\n", 80 cache_fname)); 81 return false; 82 } 83 first_try = false; 84 DEBUG(0, ("gencache_init: tdb_check(%s) failed - retry after CLEAR_IF_FIRST\n", 85 cache_fname)); 86 cache = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, open_flags, 0644); 87 if (cache) { 88 tdb_close(cache); 89 cache = NULL; 90 goto again; 91 } 84 TALLOC_FREE(cache); 85 86 /* 87 * Retry with CLEAR_IF_FIRST. 88 * 89 * Warning: Converting this to dbwrap won't work 90 * directly. gencache.c does transactions on this tdb, 91 * and dbwrap forbids this for CLEAR_IF_FIRST 92 * databases. tdb does allow transactions on 93 * CLEAR_IF_FIRST databases, so lets use it here to 94 * clean up a broken database. 95 */ 96 cache = tdb_wrap_open(NULL, cache_fname, 0, 97 TDB_DEFAULT| 98 TDB_INCOMPATIBLE_HASH| 99 TDB_CLEAR_IF_FIRST, 100 open_flags, 0644); 92 101 } 93 102 } … … 95 104 if (!cache && (errno == EACCES)) { 96 105 open_flags = O_RDONLY; 97 cache = tdb_open_log(cache_fname, 0, TDB_DEFAULT|TDB_INCOMPATIBLE_HASH, open_flags, 98 0644); 106 cache = tdb_wrap_open(NULL, cache_fname, 0, 107 TDB_DEFAULT|TDB_INCOMPATIBLE_HASH, 108 open_flags, 0644); 99 109 if (cache) { 100 110 DEBUG(5, ("gencache_init: Opening cache file %s read-only.\n", cache_fname)); 101 111 } 102 112 } 113 TALLOC_FREE(cache_fname); 103 114 104 115 if (!cache) { 105 116 DEBUG(5, ("Attempt to open gencache.tdb has failed.\n")); 106 return False;117 return false; 107 118 } 108 119 109 120 cache_fname = lock_path("gencache_notrans.tdb"); 121 if (cache_fname == NULL) { 122 TALLOC_FREE(cache); 123 return false; 124 } 110 125 111 126 DEBUG(5, ("Opening cache file at %s\n", cache_fname)); 112 127 113 cache_notrans = tdb_open_log(cache_fname, 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, 114 open_flags, 0644); 128 cache_notrans = tdb_wrap_open(NULL, cache_fname, 0, 129 TDB_CLEAR_IF_FIRST| 130 TDB_INCOMPATIBLE_HASH| 131 TDB_SEQNUM| 132 TDB_NOSYNC| 133 TDB_MUTEX_LOCKING, 134 open_flags, 0644); 115 135 if (cache_notrans == NULL) { 116 136 DEBUG(5, ("Opening %s failed: %s\n", cache_fname, 117 137 strerror(errno))); 118 tdb_close(cache); 119 cache = NULL; 120 return false; 121 } 122 123 return True; 138 TALLOC_FREE(cache_fname); 139 TALLOC_FREE(cache); 140 return false; 141 } 142 TALLOC_FREE(cache_fname); 143 144 return true; 124 145 } 125 146 … … 127 148 { 128 149 TDB_DATA result; 129 result.dptr = (uint8_t *)"@LAST_STABILIZED";150 result.dptr = discard_const_p(uint8_t, "@LAST_STABILIZED"); 130 151 result.dsize = 17; 131 152 return result; 153 } 154 155 struct gencache_have_val_state { 156 time_t new_timeout; 157 const DATA_BLOB *data; 158 bool gotit; 159 }; 160 161 static void gencache_have_val_parser(time_t old_timeout, DATA_BLOB data, 162 void *private_data) 163 { 164 struct gencache_have_val_state *state = 165 (struct gencache_have_val_state *)private_data; 166 time_t now = time(NULL); 167 int cache_time_left, new_time_left, additional_time; 168 169 /* 170 * Excuse the many variables, but these time calculations are 171 * confusing to me. We do not want to write to gencache with a 172 * possibly expensive transaction if we are about to write the same 173 * value, just extending the remaining timeout by less than 10%. 174 */ 175 176 cache_time_left = old_timeout - now; 177 if (cache_time_left <= 0) { 178 /* 179 * timed out, write new value 180 */ 181 return; 182 } 183 184 new_time_left = state->new_timeout - now; 185 if (new_time_left <= 0) { 186 /* 187 * Huh -- no new timeout?? Write it. 188 */ 189 return; 190 } 191 192 if (new_time_left < cache_time_left) { 193 /* 194 * Someone wants to shorten the timeout. Let it happen. 195 */ 196 return; 197 } 198 199 /* 200 * By how much does the new timeout extend the remaining cache time? 201 */ 202 additional_time = new_time_left - cache_time_left; 203 204 if (additional_time * 10 < 0) { 205 /* 206 * Integer overflow. We extend by so much that we have to write it. 207 */ 208 return; 209 } 210 211 /* 212 * The comparison below is essentially equivalent to 213 * 214 * new_time_left > cache_time_left * 1.10 215 * 216 * but without floating point calculations. 217 */ 218 219 if (additional_time * 10 > cache_time_left) { 220 /* 221 * We extend the cache timeout by more than 10%. Do it. 222 */ 223 return; 224 } 225 226 /* 227 * Now the more expensive data compare. 228 */ 229 if (data_blob_cmp(state->data, &data) != 0) { 230 /* 231 * Write a new value. Certainly do it. 232 */ 233 return; 234 } 235 236 /* 237 * Extending the timeout by less than 10% for the same cache value is 238 * not worth the trouble writing a value into gencache under a 239 * possibly expensive transaction. 240 */ 241 state->gotit = true; 242 } 243 244 static bool gencache_have_val(const char *keystr, const DATA_BLOB *data, 245 time_t timeout) 246 { 247 struct gencache_have_val_state state; 248 249 state.new_timeout = timeout; 250 state.data = data; 251 state.gotit = false; 252 253 if (!gencache_parse(keystr, gencache_have_val_parser, &state)) { 254 return false; 255 } 256 return state.gotit; 257 } 258 259 static int last_stabilize_parser(TDB_DATA key, TDB_DATA data, 260 void *private_data) 261 { 262 time_t *last_stabilize = private_data; 263 264 if ((data.dsize != 0) && (data.dptr[data.dsize-1] == '\0')) { 265 *last_stabilize = atoi((char *)data.dptr); 266 } 267 return 0; 132 268 } 133 269 … … 140 276 * @param timeout time when the value is expired 141 277 * 142 * @retval true when entry is successful y stored278 * @retval true when entry is successfully stored 143 279 * @retval false on failure 144 280 **/ … … 148 284 { 149 285 int ret; 150 TDB_DATA databuf; 286 fstring hdr; 287 int hdr_len; 151 288 char* val; 152 289 time_t last_stabilize; … … 163 300 } 164 301 165 if (!gencache_init()) return False; 166 167 val = talloc_asprintf(talloc_tos(), CACHE_DATA_FMT, (int)timeout); 302 if (!gencache_init()) { 303 return false; 304 } 305 306 if (gencache_have_val(keystr, blob, timeout)) { 307 DEBUG(10, ("Did not store value for %s, we already got it\n", 308 keystr)); 309 return true; 310 } 311 312 hdr_len = fstr_sprintf(hdr, CACHE_DATA_FMT, (int)timeout); 313 314 if (hdr_len == -1) { 315 return false; 316 } 317 if ((blob->length + (size_t)hdr_len) < blob->length) { 318 return false; 319 } 320 321 val = talloc_array(talloc_tos(), char, hdr_len + blob->length); 168 322 if (val == NULL) { 169 return False; 170 } 171 val = talloc_realloc(NULL, val, char, talloc_array_length(val)-1); 172 if (val == NULL) { 173 return false; 174 } 175 val = (char *)talloc_append_blob(NULL, val, *blob); 176 if (val == NULL) { 177 return false; 178 } 179 180 DEBUG(10, ("Adding cache entry with key = %s and timeout =" 181 " %s (%d seconds %s)\n", keystr, ctime(&timeout), 323 return false; 324 } 325 326 memcpy(val, hdr, hdr_len); 327 memcpy(val+hdr_len, blob->data, blob->length); 328 329 DEBUG(10, ("Adding cache entry with key=[%s] and timeout=" 330 "[%s] (%d seconds %s)\n", keystr, 331 timestring(talloc_tos(), timeout), 182 332 (int)(timeout - time(NULL)), 183 333 timeout > time(NULL) ? "ahead" : "in the past")); 184 334 185 335 ret = tdb_store_bystring( 186 cache_notrans , keystr,336 cache_notrans->tdb, keystr, 187 337 make_tdb_data((uint8_t *)val, talloc_array_length(val)), 188 338 0); … … 211 361 212 362 last_stabilize = 0; 213 databuf = tdb_fetch(cache_notrans, last_stabilize_key()); 214 if ((databuf.dptr != NULL) 215 && (databuf.dptr[databuf.dsize-1] == '\0')) { 216 last_stabilize = atoi((char *)databuf.dptr); 217 SAFE_FREE(databuf.dptr); 218 } 363 364 tdb_parse_record(cache_notrans->tdb, last_stabilize_key(), 365 last_stabilize_parser, &last_stabilize); 366 219 367 if ((last_stabilize 220 368 + lp_parm_int(-1, "gencache", "stabilize_interval", 300)) … … 246 394 } 247 395 248 if (!gencache_init()) return False; 249 250 DEBUG(10, ("Deleting cache entry (key = %s)\n", keystr)); 396 if (!gencache_init()) { 397 return false; 398 } 399 400 DEBUG(10, ("Deleting cache entry (key=[%s])\n", keystr)); 251 401 252 402 /* … … 256 406 */ 257 407 258 exists = gencache_get_data_blob(keystr, &value, NULL, &was_expired); 408 exists = gencache_get_data_blob(keystr, NULL, &value, NULL, 409 &was_expired); 259 410 260 411 if (!exists && was_expired) { … … 300 451 void (*parser)(time_t timeout, DATA_BLOB blob, void *private_data); 301 452 void *private_data; 453 bool is_memcache; 302 454 }; 303 455 … … 321 473 endptr+1, data.dsize - PTR_DIFF(endptr+1, data.dptr)); 322 474 state->parser(t, blob, state->private_data); 475 476 if (!state->is_memcache) { 477 memcache_add(NULL, GENCACHE_RAM, 478 data_blob_const(key.dptr, key.dsize), 479 data_blob_const(data.dptr, data.dsize)); 480 } 481 323 482 return 0; 324 483 } … … 330 489 { 331 490 struct gencache_parse_state state; 332 TDB_DATA key; 491 TDB_DATA key = string_term_tdb_data(keystr); 492 DATA_BLOB memcache_val; 333 493 int ret; 334 494 … … 336 496 return false; 337 497 } 338 if (tdb_data_cmp(string_term_tdb_data(keystr), 339 last_stabilize_key()) == 0) { 498 if (tdb_data_cmp(key, last_stabilize_key()) == 0) { 340 499 return false; 341 500 } … … 344 503 } 345 504 346 key = string_term_tdb_data(keystr);347 505 state.parser = parser; 348 506 state.private_data = private_data; 349 507 350 ret = tdb_parse_record(cache_notrans, key, gencache_parse_fn, &state); 351 if (ret != -1) { 508 if (memcache_lookup(NULL, GENCACHE_RAM, 509 data_blob_const(key.dptr, key.dsize), 510 &memcache_val)) { 511 /* 512 * Make sure that nobody has changed the gencache behind our 513 * back. 514 */ 515 int current_seqnum = tdb_get_seqnum(cache_notrans->tdb); 516 if (current_seqnum == cache_notrans_seqnum) { 517 /* 518 * Ok, our memcache is still current, use it without 519 * going to the tdb files. 520 */ 521 state.is_memcache = true; 522 gencache_parse_fn(key, make_tdb_data(memcache_val.data, 523 memcache_val.length), 524 &state); 525 return true; 526 } 527 memcache_flush(NULL, GENCACHE_RAM); 528 cache_notrans_seqnum = current_seqnum; 529 } 530 531 state.is_memcache = false; 532 533 ret = tdb_parse_record(cache_notrans->tdb, key, 534 gencache_parse_fn, &state); 535 if (ret == 0) { 352 536 return true; 353 537 } 354 ret = tdb_parse_record(cache , key, gencache_parse_fn, &state);355 return (ret != -1);538 ret = tdb_parse_record(cache->tdb, key, gencache_parse_fn, &state); 539 return (ret == 0); 356 540 } 357 541 358 542 struct gencache_get_data_blob_state { 543 TALLOC_CTX *mem_ctx; 359 544 DATA_BLOB *blob; 360 545 time_t timeout; … … 379 564 } 380 565 381 *state->blob = data_blob(blob.data, blob.length); 566 *state->blob = data_blob_talloc(state->mem_ctx, blob.data, 567 blob.length); 382 568 if (state->blob->data == NULL) { 383 569 state->result = false; … … 396 582 * 397 583 * @retval true when entry is successfuly fetched 398 * @retval False for failure584 * @retval false for failure 399 585 **/ 400 586 401 bool gencache_get_data_blob(const char *keystr, DATA_BLOB *blob, 587 bool gencache_get_data_blob(const char *keystr, TALLOC_CTX *mem_ctx, 588 DATA_BLOB *blob, 402 589 time_t *timeout, bool *was_expired) 403 590 { … … 406 593 407 594 state.result = false; 595 state.mem_ctx = mem_ctx; 408 596 state.blob = blob; 409 597 … … 429 617 } 430 618 431 return True;619 return true; 432 620 433 621 fail: … … 443 631 struct stabilize_state { 444 632 bool written; 445 bool error;446 633 }; 447 634 static int stabilize_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, 448 635 void *priv); 449 636 637 static int wipe_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, 638 void *priv); 639 450 640 /** 451 641 * Stabilize gencache … … 465 655 } 466 656 467 res = tdb_transaction_start_nonblock(cache );468 if (res == -1) {469 470 if (tdb_error(cache) == TDB_ERR_NOLOCK){657 res = tdb_transaction_start_nonblock(cache->tdb); 658 if (res != 0) { 659 if (tdb_error(cache->tdb) == TDB_ERR_NOLOCK) 660 { 471 661 /* 472 662 * Someone else already does the stabilize, … … 477 667 478 668 DEBUG(10, ("Could not start transaction on gencache.tdb: " 479 "%s\n", tdb_errorstr(cache))); 480 return false; 481 } 482 res = tdb_transaction_start(cache_notrans); 483 if (res == -1) { 484 tdb_transaction_cancel(cache); 485 DEBUG(10, ("Could not start transaction on " 669 "%s\n", tdb_errorstr(cache->tdb))); 670 return false; 671 } 672 673 res = tdb_lockall(cache_notrans->tdb); 674 if (res != 0) { 675 tdb_transaction_cancel(cache->tdb); 676 DEBUG(10, ("Could not get allrecord lock on " 486 677 "gencache_notrans.tdb: %s\n", 487 tdb_errorstr(cache_notrans))); 488 return false; 489 } 490 491 state.error = false; 678 tdb_errorstr(cache_notrans->tdb))); 679 return false; 680 } 681 492 682 state.written = false; 493 683 494 res = tdb_traverse(cache_notrans, stabilize_fn, &state); 495 if ((res == -1) || state.error) { 496 if ((tdb_transaction_cancel(cache_notrans) == -1) 497 || (tdb_transaction_cancel(cache) == -1)) { 498 smb_panic("tdb_transaction_cancel failed\n"); 499 } 684 res = tdb_traverse(cache_notrans->tdb, stabilize_fn, &state); 685 if (res < 0) { 686 tdb_unlockall(cache_notrans->tdb); 687 tdb_transaction_cancel(cache->tdb); 500 688 return false; 501 689 } 502 690 503 691 if (!state.written) { 504 if ((tdb_transaction_cancel(cache_notrans) == -1) 505 || (tdb_transaction_cancel(cache) == -1)) { 506 smb_panic("tdb_transaction_cancel failed\n"); 507 } 692 tdb_unlockall(cache_notrans->tdb); 693 tdb_transaction_cancel(cache->tdb); 508 694 return true; 509 695 } 510 696 511 res = tdb_transaction_commit(cache );512 if (res == -1) {697 res = tdb_transaction_commit(cache->tdb); 698 if (res != 0) { 513 699 DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: " 514 "%s\n", tdb_errorstr(cache))); 515 if (tdb_transaction_cancel(cache_notrans) == -1) { 516 smb_panic("tdb_transaction_cancel failed\n"); 517 } 518 return false; 519 } 520 521 res = tdb_transaction_commit(cache_notrans); 522 if (res == -1) { 523 DEBUG(10, ("tdb_transaction_commit on gencache.tdb failed: " 524 "%s\n", tdb_errorstr(cache))); 700 "%s\n", tdb_errorstr(cache->tdb))); 701 tdb_unlockall(cache_notrans->tdb); 702 return false; 703 } 704 705 res = tdb_traverse(cache_notrans->tdb, wipe_fn, NULL); 706 if (res < 0) { 707 DEBUG(10, ("tdb_traverse with wipe_fn on gencache_notrans.tdb " 708 "failed: %s\n", 709 tdb_errorstr(cache_notrans->tdb))); 710 tdb_unlockall(cache_notrans->tdb); 711 return false; 712 } 713 714 res = tdb_unlockall(cache_notrans->tdb); 715 if (res != 0) { 716 DEBUG(10, ("tdb_unlockall on gencache.tdb failed: " 717 "%s\n", tdb_errorstr(cache->tdb))); 525 718 return false; 526 719 } … … 528 721 now = talloc_asprintf(talloc_tos(), "%d", (int)time(NULL)); 529 722 if (now != NULL) { 530 tdb_store(cache_notrans , last_stabilize_key(),723 tdb_store(cache_notrans->tdb, last_stabilize_key(), 531 724 string_term_tdb_data(now), 0); 532 725 TALLOC_FREE(now); … … 552 745 } 553 746 if ((timeout < time(NULL)) || (val.dsize == 0)) { 554 res = tdb_delete(cache, key); 555 if ((res == -1) && (tdb_error(cache) == TDB_ERR_NOEXIST)) { 747 res = tdb_delete(cache->tdb, key); 748 if (res == 0) { 749 state->written = true; 750 } else if (tdb_error(cache->tdb) == TDB_ERR_NOEXIST) { 556 751 res = 0; 557 } else {558 state->written = true;559 752 } 560 753 } else { 561 res = tdb_store(cache , key, val, 0);754 res = tdb_store(cache->tdb, key, val, 0); 562 755 if (res == 0) { 563 756 state->written = true; … … 565 758 } 566 759 567 if (res == -1) {760 if (res != 0) { 568 761 DEBUG(10, ("Transfer to gencache.tdb failed: %s\n", 569 tdb_errorstr(cache))); 570 state->error = true; 762 tdb_errorstr(cache->tdb))); 571 763 return -1; 572 764 } 573 765 574 if (tdb_delete(cache_notrans, key) == -1) { 766 return 0; 767 } 768 769 static int wipe_fn(struct tdb_context *tdb, TDB_DATA key, TDB_DATA val, 770 void *priv) 771 { 772 int res; 773 bool ok; 774 time_t timeout; 775 776 res = tdb_data_cmp(key, last_stabilize_key()); 777 if (res == 0) { 778 return 0; 779 } 780 781 ok = gencache_pull_timeout((char *)val.dptr, &timeout, NULL); 782 if (!ok) { 783 DEBUG(10, ("Ignoring invalid entry\n")); 784 return 0; 785 } 786 787 res = tdb_delete(tdb, key); 788 if (res != 0) { 575 789 DEBUG(10, ("tdb_delete from gencache_notrans.tdb failed: " 576 "%s\n", tdb_errorstr(cache_notrans))); 577 state->error = true; 790 "%s\n", tdb_errorstr(cache_notrans->tdb))); 578 791 return -1; 579 792 } 793 580 794 return 0; 581 795 } 796 582 797 583 798 /** … … 591 806 * 592 807 * @retval true when entry is successfuly fetched 593 * @retval False for failure808 * @retval false for failure 594 809 **/ 595 810 596 bool gencache_get(const char *keystr, char **value, time_t *ptimeout) 811 bool gencache_get(const char *keystr, TALLOC_CTX *mem_ctx, char **value, 812 time_t *ptimeout) 597 813 { 598 814 DATA_BLOB blob; 599 bool ret = False;600 601 ret = gencache_get_data_blob(keystr, &blob, ptimeout, NULL);815 bool ret = false; 816 817 ret = gencache_get_data_blob(keystr, mem_ctx, &blob, ptimeout, NULL); 602 818 if (!ret) { 603 819 return false; 604 820 } 605 821 if ((blob.data == NULL) || (blob.length == 0)) { 606 SAFE_FREE(blob.data);822 data_blob_free(&blob); 607 823 return false; 608 824 } 609 825 if (blob.data[blob.length-1] != '\0') { 610 826 /* Not NULL terminated, can't be a string */ 611 SAFE_FREE(blob.data);827 data_blob_free(&blob); 612 828 return false; 613 829 } 614 830 if (value) { 615 *value = SMB_STRDUP((char *)blob.data);616 data_blob_free(&blob);617 if (*value == NULL) {618 return false;619 }831 /* 832 * talloc_move generates a type-punned warning here. As we 833 * leave the function immediately, do a simple talloc_steal. 834 */ 835 *value = (char *)talloc_steal(mem_ctx, blob.data); 620 836 return true; 621 837 } … … 663 879 return 0; 664 880 } 665 if (state->in_persistent && tdb_exists(cache_notrans , key)) {881 if (state->in_persistent && tdb_exists(cache_notrans->tdb, key)) { 666 882 return 0; 667 883 } … … 671 887 } else { 672 888 /* ensure 0-termination */ 673 keystr = SMB_STRNDUP((char *)key.dptr, key.dsize);889 keystr = talloc_strndup(talloc_tos(), (char *)key.dptr, key.dsize); 674 890 free_key = keystr; 891 if (keystr == NULL) { 892 goto done; 893 } 675 894 } 676 895 … … 684 903 } 685 904 686 DEBUG(10, ("Calling function with arguments (key=%s, timeout=%s)\n", 687 keystr, ctime(&timeout))); 905 DEBUG(10, ("Calling function with arguments " 906 "(key=[%s], timeout=[%s])\n", 907 keystr, timestring(talloc_tos(), timeout))); 688 908 689 909 state->fn(keystr, … … 693 913 694 914 done: 695 SAFE_FREE(free_key);915 TALLOC_FREE(free_key); 696 916 return 0; 697 917 } … … 714 934 715 935 state.in_persistent = false; 716 tdb_traverse(cache_notrans , gencache_iterate_blobs_fn, &state);936 tdb_traverse(cache_notrans->tdb, gencache_iterate_blobs_fn, &state); 717 937 718 938 state.in_persistent = true; 719 tdb_traverse(cache , gencache_iterate_blobs_fn, &state);939 tdb_traverse(cache->tdb, gencache_iterate_blobs_fn, &state); 720 940 } 721 941 … … 749 969 } else { 750 970 /* ensure 0-termination */ 751 valstr = SMB_STRNDUP((char *)value.data, value.length);971 valstr = talloc_strndup(talloc_tos(), (char *)value.data, value.length); 752 972 free_val = valstr; 973 if (valstr == NULL) { 974 goto done; 975 } 753 976 } 754 977 755 978 DEBUG(10, ("Calling function with arguments " 756 "(key = %s, value = %s, timeout = %s)\n",757 key, valstr, ctime(&timeout)));979 "(key=[%s], value=[%s], timeout=[%s])\n", 980 key, valstr, timestring(talloc_tos(), timeout))); 758 981 759 982 state->fn(key, valstr, timeout, state->private_data); 760 983 761 SAFE_FREE(free_val); 984 done: 985 986 TALLOC_FREE(free_val); 762 987 } 763 988
Note:
See TracChangeset
for help on using the changeset viewer.