Ignore:
Timestamp:
Nov 27, 2012, 4:43:17 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: updated trunk to 3.6.0

Location:
trunk/server
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/server

  • trunk/server/source3/lib/gencache.c

    r414 r745  
    2323
    2424#include "includes.h"
     25#include "system/filesys.h"
     26#include "system/glob.h"
     27#include "util_tdb.h"
    2528
    2629#undef  DBGC_CLASS
     
    6669
    6770again:
    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);
    6972        if (cache) {
    7073                int ret;
     
    8184                        DEBUG(0, ("gencache_init: tdb_check(%s) failed - retry after CLEAR_IF_FIRST\n",
    8285                                  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);
    8487                        if (cache) {
    8588                                tdb_close(cache);
     
    9295        if (!cache && (errno == EACCES)) {
    9396                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,
    9598                                     0644);
    9699                if (cache) {
     
    108111        DEBUG(5, ("Opening cache file at %s\n", cache_fname));
    109112
    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,
    111114                                     open_flags, 0644);
    112115        if (cache_notrans == NULL) {
     
    275278        char *endptr;
    276279
     280        if (val == NULL) {
     281                return false;
     282        }
     283
    277284        res = strtol(val, &endptr, 10);
    278285
     
    288295        }
    289296        return true;
     297}
     298
     299struct gencache_parse_state {
     300        void (*parser)(time_t timeout, DATA_BLOB blob, void *private_data);
     301        void *private_data;
     302};
     303
     304static 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
     326bool 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
     358struct gencache_get_data_blob_state {
     359        DATA_BLOB *blob;
     360        time_t timeout;
     361        bool result;
     362};
     363
     364static 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;
    290387}
    291388
     
    305402                            time_t *timeout, bool *was_expired)
    306403{
    307         TDB_DATA databuf;
    308         time_t t;
    309         char *endptr;
     404        struct gencache_get_data_blob_state state;
    310405        bool expired = false;
    311406
    312         if (keystr == NULL) {
     407        state.result = false;
     408        state.blob = blob;
     409
     410        if (!gencache_parse(keystr, gencache_get_data_blob_parser, &state)) {
    313411                goto fail;
    314412        }
    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) {
    319414                goto fail;
    320415        }
    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)) {
    355417                /*
    356418                 * We're expired, delete the entry. We can't use gencache_del
     
    360422                 */
    361423                gencache_set(keystr, "", 0);
    362 
    363                 SAFE_FREE(databuf.dptr);
    364 
    365424                expired = true;
    366425                goto fail;
    367426        }
    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 
    382427        if (timeout) {
    383                 *timeout = t;
     428                *timeout = state.timeout;
    384429        }
    385430
     
    389434        if (was_expired != NULL) {
    390435                *was_expired = expired;
     436        }
     437        if (state.result && state.blob) {
     438                data_blob_free(state.blob);
    391439        }
    392440        return false;
     
    417465        }
    418466
    419         res = tdb_transaction_start(cache);
     467        res = tdb_transaction_start_nonblock(cache);
    420468        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
    421478                DEBUG(10, ("Could not start transaction on gencache.tdb: "
    422479                           "%s\n", tdb_errorstr(cache)));
     
    585642}
    586643
    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);
     644struct gencache_iterate_blobs_state {
     645        void (*fn)(const char *key, DATA_BLOB value,
     646                   time_t timeout, void *private_data);
    601647        const char *pattern;
    602         void *priv;
     648        void *private_data;
    603649        bool in_persistent;
    604650};
    605651
    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;
     652static 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;
    611657        char *keystr;
    612658        char *free_key = NULL;
    613         char *valstr;
    614         char *free_val = NULL;
    615         unsigned long u;
    616659        time_t timeout;
    617         char *timeout_endp;
     660        char *endptr;
    618661
    619662        if (tdb_data_cmp(key, last_stabilize_key()) == 0) {
    620663                return 0;
    621664        }
    622 
    623665        if (state->in_persistent && tdb_exists(cache_notrans, key)) {
    624666                return 0;
     
    633675        }
    634676
    635         if ((value.dptr == NULL) || (value.dsize <= TIMEOUT_LEN)) {
     677        if (!gencache_pull_timeout((char *)data.dptr, &timeout, &endptr)) {
    636678                goto done;
    637679        }
     680        endptr += 1;
    638681
    639682        if (fnmatch(state->pattern, keystr, 0) != 0) {
     
    641684        }
    642685
    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
     699void 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
     733struct gencache_iterate_state {
     734        void (*fn)(const char *key, const char *value, time_t timeout,
     735                   void *priv);
     736        void *private_data;
     737};
     738
     739static 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;
    645749        } else {
    646750                /* ensure 0-termination */
    647                 valstr = SMB_STRNDUP((char *)value.dptr, value.dsize);
     751                valstr = SMB_STRNDUP((char *)value.data, value.length);
    648752                free_val = valstr;
    649753        }
    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;
    659754
    660755        DEBUG(10, ("Calling function with arguments "
    661756                   "(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
    667761        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
     764void gencache_iterate(void (*fn)(const char *key, const char *value,
     765                                 time_t timeout, void *dptr),
     766                      void *private_data, const char *pattern)
    673767{
    674768        struct gencache_iterate_state state;
    675769
    676         if ((fn == NULL) || (keystr_pattern == NULL)) {
     770        if (fn == NULL) {
    677771                return;
    678772        }
    679 
    680         if (!gencache_init()) return;
    681 
    682         DEBUG(5, ("Searching cache keys with pattern %s\n", keystr_pattern));
    683 
    684773        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.