Changeset 740 for vendor/current/lib/tdb


Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

Location:
vendor/current/lib/tdb
Files:
20 added
15 deleted
26 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/lib/tdb/common/check.c

    r414 r740  
    2929{
    3030        struct tdb_header hdr;
    31 
    32         if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), DOCONV()) == -1)
     31        uint32_t h1, h2;
     32
     33        if (tdb->methods->tdb_read(tdb, 0, &hdr, sizeof(hdr), 0) == -1)
    3334                return false;
    3435        if (strcmp(hdr.magic_food, TDB_MAGIC_FOOD) != 0)
     
    3940                goto corrupt;
    4041
    41         if (hdr.rwlocks != 0)
     42        if (hdr.rwlocks != 0 && hdr.rwlocks != TDB_HASH_RWLOCK_MAGIC)
     43                goto corrupt;
     44
     45        tdb_header_hash(tdb, &h1, &h2);
     46        if (hdr.magic1_hash && hdr.magic2_hash &&
     47            (hdr.magic1_hash != h1 || hdr.magic2_hash != h2))
    4248                goto corrupt;
    4349
     
    302308}
    303309
    304 int tdb_check(struct tdb_context *tdb,
     310/* Slow, but should be very rare. */
     311size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off)
     312{
     313        size_t len;
     314
     315        for (len = 0; off + len < tdb->map_size; len++) {
     316                char c;
     317                if (tdb->methods->tdb_read(tdb, off, &c, 1, 0))
     318                        return 0;
     319                if (c != 0 && c != 0x42)
     320                        break;
     321        }
     322        return len;
     323}
     324
     325_PUBLIC_ int tdb_check(struct tdb_context *tdb,
    305326              int (*check)(TDB_DATA key, TDB_DATA data, void *private_data),
    306327              void *private_data)
     
    311332        struct tdb_record rec;
    312333        bool found_recovery = false;
    313 
    314         if (tdb_lockall(tdb) == -1)
    315                 return -1;
     334        tdb_len_t dead;
     335        bool locked;
     336
     337        /* Read-only databases use no locking at all: it's best-effort.
     338         * We may have a write lock already, so skip that case too. */
     339        if (tdb->read_only || tdb->allrecord_lock.count != 0) {
     340                locked = false;
     341        } else {
     342                if (tdb_lockall_read(tdb) == -1)
     343                        return -1;
     344                locked = true;
     345        }
    316346
    317347        /* Make sure we know true size of the underlying file. */
     
    370400                                goto free;
    371401                        break;
     402                /* If we crash after ftruncate, we can get zeroes or fill. */
     403                case TDB_RECOVERY_INVALID_MAGIC:
     404                case 0x42424242:
     405                        if (recovery_start == off) {
     406                                found_recovery = true;
     407                                break;
     408                        }
     409                        dead = tdb_dead_space(tdb, off);
     410                        if (dead < sizeof(rec))
     411                                goto corrupt;
     412
     413                        TDB_LOG((tdb, TDB_DEBUG_ERROR,
     414                                 "Dead space at %d-%d (of %u)\n",
     415                                 off, off + dead, tdb->map_size));
     416                        rec.rec_len = dead - sizeof(rec);
     417                        break;
    372418                case TDB_RECOVERY_MAGIC:
    373                 case 0: /* Used for invalid (or in-progress) recovery area. */
    374419                        if (recovery_start != off) {
    375420                                TDB_LOG((tdb, TDB_DEBUG_ERROR,
     
    380425                        found_recovery = true;
    381426                        break;
    382                 default:
     427                default: ;
     428                corrupt:
    383429                        tdb->ecode = TDB_ERR_CORRUPT;
    384430                        TDB_LOG((tdb, TDB_DEBUG_ERROR,
     
    406452        if (recovery_start != 0 && !found_recovery) {
    407453                TDB_LOG((tdb, TDB_DEBUG_ERROR,
    408                          "Expected %s recovery area, got %s\n",
    409                          recovery_start ? "a" : "no",
    410                          found_recovery ? "one" : "none"));
     454                         "Expected a recovery area at %u\n",
     455                         recovery_start));
    411456                goto free;
    412457        }
    413458
    414459        free(hashes);
    415         tdb_unlockall(tdb);
     460        if (locked) {
     461                tdb_unlockall_read(tdb);
     462        }
    416463        return 0;
    417464
     
    419466        free(hashes);
    420467unlock:
    421         tdb_unlockall(tdb);
     468        if (locked) {
     469                tdb_unlockall_read(tdb);
     470        }
    422471        return -1;
    423472}
  • vendor/current/lib/tdb/common/dump.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    8181}
    8282
    83 void tdb_dump_all(struct tdb_context *tdb)
     83_PUBLIC_ void tdb_dump_all(struct tdb_context *tdb)
    8484{
    8585        int i;
     
    9191}
    9292
    93 int tdb_printfreelist(struct tdb_context *tdb)
     93_PUBLIC_ int tdb_printfreelist(struct tdb_context *tdb)
    9494{
    9595        int ret;
  • vendor/current/lib/tdb/common/error.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 enum TDB_ERROR tdb_error(struct tdb_context *tdb)
     30_PUBLIC_ enum TDB_ERROR tdb_error(struct tdb_context *tdb)
    3131{
    3232        return tdb->ecode;
     
    4747
    4848/* Error string for the last tdb error */
    49 const char *tdb_errorstr(struct tdb_context *tdb)
     49_PUBLIC_ const char *tdb_errorstr(struct tdb_context *tdb)
    5050{
    5151        uint32_t i;
  • vendor/current/lib/tdb/common/freelist.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    9999
    100100/* Add an element into the freelist. Merge adjacent records if
    101    neccessary. */
     101   necessary. */
    102102int tdb_free(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec)
    103103{
     
    144144                struct tdb_record l;
    145145                tdb_off_t leftsize;
    146                
     146
    147147                /* Read in tailer and jump back to header */
    148148                if (tdb_ofs_read(tdb, left, &leftsize) == -1) {
     
    335335                        break;
    336336                }
    337                
     337
    338338                /* this multiplier means we only extremely rarely
    339339                   search more than 50 or so records. At 50 records we
     
    368368   return the size of the freelist - used to decide if we should repack
    369369*/
    370 int tdb_freelist_size(struct tdb_context *tdb)
     370_PUBLIC_ int tdb_freelist_size(struct tdb_context *tdb)
    371371{
    372372        tdb_off_t ptr;
  • vendor/current/lib/tdb/common/freelistcheck.c

    r414 r740  
    4444}
    4545
    46 int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
     46_PUBLIC_ int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries)
    4747{
    4848        struct tdb_context *mem_tdb = NULL;
  • vendor/current/lib/tdb/common/io.c

    r597 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    477477        tdb_oob,
    478478        tdb_expand_file,
    479         tdb_brlock
    480479};
    481480
  • vendor/current/lib/tdb/common/lock.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 #define TDB_MARK_LOCK 0x80000000
    31 
    32 void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr)
     30_PUBLIC_ void tdb_setalarm_sigptr(struct tdb_context *tdb, volatile sig_atomic_t *ptr)
    3331{
    3432        tdb->interrupt_sig_ptr = ptr;
     33}
     34
     35static int fcntl_lock(struct tdb_context *tdb,
     36                      int rw, off_t off, off_t len, bool waitflag)
     37{
     38        struct flock fl;
     39
     40        fl.l_type = rw;
     41        fl.l_whence = SEEK_SET;
     42        fl.l_start = off;
     43        fl.l_len = len;
     44        fl.l_pid = 0;
     45
     46        if (waitflag)
     47                return fcntl(tdb->fd, F_SETLKW, &fl);
     48        else
     49                return fcntl(tdb->fd, F_SETLK, &fl);
     50}
     51
     52static int fcntl_unlock(struct tdb_context *tdb, int rw, off_t off, off_t len)
     53{
     54        struct flock fl;
     55#if 0 /* Check they matched up locks and unlocks correctly. */
     56        char line[80];
     57        FILE *locks;
     58        bool found = false;
     59
     60        locks = fopen("/proc/locks", "r");
     61
     62        while (fgets(line, 80, locks)) {
     63                char *p;
     64                int type, start, l;
     65
     66                /* eg. 1: FLOCK  ADVISORY  WRITE 2440 08:01:2180826 0 EOF */
     67                p = strchr(line, ':') + 1;
     68                if (strncmp(p, " POSIX  ADVISORY  ", strlen(" POSIX  ADVISORY  ")))
     69                        continue;
     70                p += strlen(" FLOCK  ADVISORY  ");
     71                if (strncmp(p, "READ  ", strlen("READ  ")) == 0)
     72                        type = F_RDLCK;
     73                else if (strncmp(p, "WRITE ", strlen("WRITE ")) == 0)
     74                        type = F_WRLCK;
     75                else
     76                        abort();
     77                p += 6;
     78                if (atoi(p) != getpid())
     79                        continue;
     80                p = strchr(strchr(p, ' ') + 1, ' ') + 1;
     81                start = atoi(p);
     82                p = strchr(p, ' ') + 1;
     83                if (strncmp(p, "EOF", 3) == 0)
     84                        l = 0;
     85                else
     86                        l = atoi(p) - start + 1;
     87
     88                if (off == start) {
     89                        if (len != l) {
     90                                fprintf(stderr, "Len %u should be %u: %s",
     91                                        (int)len, l, line);
     92                                abort();
     93                        }
     94                        if (type != rw) {
     95                                fprintf(stderr, "Type %s wrong: %s",
     96                                        rw == F_RDLCK ? "READ" : "WRITE", line);
     97                                abort();
     98                        }
     99                        found = true;
     100                        break;
     101                }
     102        }
     103
     104        if (!found) {
     105                fprintf(stderr, "Unlock on %u@%u not found!\n",
     106                        (int)off, (int)len);
     107                abort();
     108        }
     109
     110        fclose(locks);
     111#endif
     112
     113        fl.l_type = F_UNLCK;
     114        fl.l_whence = SEEK_SET;
     115        fl.l_start = off;
     116        fl.l_len = len;
     117        fl.l_pid = 0;
     118
     119        return fcntl(tdb->fd, F_SETLKW, &fl);
     120}
     121
     122/* list -1 is the alloc list, otherwise a hash chain. */
     123static tdb_off_t lock_offset(int list)
     124{
     125        return FREELIST_TOP + 4*list;
    35126}
    36127
     
    43134   note that a len of zero means lock to end of file
    44135*/
    45 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset,
    46                int rw_type, int lck_type, int probe, size_t len)
    47 {
    48         struct flock fl;
     136int tdb_brlock(struct tdb_context *tdb,
     137               int rw_type, tdb_off_t offset, size_t len,
     138               enum tdb_lock_flags flags)
     139{
    49140        int ret;
    50141
    51142        if (tdb->flags & TDB_NOLOCK) {
     143                return 0;
     144        }
     145
     146        if (flags & TDB_LOCK_MARK_ONLY) {
    52147                return 0;
    53148        }
     
    58153        }
    59154
    60         fl.l_type = rw_type;
    61         fl.l_whence = SEEK_SET;
    62         fl.l_start = offset;
    63         fl.l_len = len;
    64         fl.l_pid = 0;
    65 
    66155        do {
    67                 ret = fcntl(tdb->fd,lck_type,&fl);
    68 
     156                ret = fcntl_lock(tdb, rw_type, offset, len,
     157                                 flags & TDB_LOCK_WAIT);
    69158                /* Check for a sigalarm break. */
    70159                if (ret == -1 && errno == EINTR &&
     
    80169                 * EAGAIN is an expected return from non-blocking
    81170                 * locks. */
    82                 if (!probe && lck_type != F_SETLK) {
    83                         TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
    84                                  tdb->fd, offset, rw_type, lck_type, (int)len));
     171                if (!(flags & TDB_LOCK_PROBE) && errno != EAGAIN) {
     172                        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d flags=%d len=%d\n",
     173                                 tdb->fd, offset, rw_type, flags, (int)len));
    85174                }
    86175                return -1;
     
    89178}
    90179
     180int tdb_brunlock(struct tdb_context *tdb,
     181                 int rw_type, tdb_off_t offset, size_t len)
     182{
     183        int ret;
     184
     185        if (tdb->flags & TDB_NOLOCK) {
     186                return 0;
     187        }
     188
     189        do {
     190                ret = fcntl_unlock(tdb, rw_type, offset, len);
     191        } while (ret == -1 && errno == EINTR);
     192
     193        if (ret == -1) {
     194                TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brunlock failed (fd=%d) at offset %d rw_type=%d len=%d\n",
     195                         tdb->fd, offset, rw_type, (int)len));
     196        }
     197        return ret;
     198}
    91199
    92200/*
     
    96204  made. For those OSes we may loop for a while. 
    97205*/
    98 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
     206int tdb_allrecord_upgrade(struct tdb_context *tdb)
    99207{
    100208        int count = 1000;
     209
     210        if (tdb->allrecord_lock.count != 1) {
     211                TDB_LOG((tdb, TDB_DEBUG_ERROR,
     212                         "tdb_allrecord_upgrade failed: count %u too high\n",
     213                         tdb->allrecord_lock.count));
     214                return -1;
     215        }
     216
     217        if (tdb->allrecord_lock.off != 1) {
     218                TDB_LOG((tdb, TDB_DEBUG_ERROR,
     219                         "tdb_allrecord_upgrade failed: already upgraded?\n"));
     220                return -1;
     221        }
     222
    101223        while (count--) {
    102224                struct timeval tv;
    103                 if (tdb_brlock(tdb, offset, F_WRLCK, F_SETLKW, 1, len) == 0) {
     225                if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0,
     226                               TDB_LOCK_WAIT|TDB_LOCK_PROBE) == 0) {
     227                        tdb->allrecord_lock.ltype = F_WRLCK;
     228                        tdb->allrecord_lock.off = 0;
    104229                        return 0;
    105230                }
     
    112237                select(0, NULL, NULL, NULL, &tv);
    113238        }
    114         TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset));
     239        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_allrecord_upgrade failed\n"));
    115240        return -1;
    116241}
    117242
    118 
    119 /* lock a list in the database. list -1 is the alloc list */
    120 static int _tdb_lock(struct tdb_context *tdb, int list, int ltype, int op)
     243static struct tdb_lock_type *find_nestlock(struct tdb_context *tdb,
     244                                           tdb_off_t offset)
     245{
     246        unsigned int i;
     247
     248        for (i=0; i<tdb->num_lockrecs; i++) {
     249                if (tdb->lockrecs[i].off == offset) {
     250                        return &tdb->lockrecs[i];
     251                }
     252        }
     253        return NULL;
     254}
     255
     256/* lock an offset in the database. */
     257int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
     258                  enum tdb_lock_flags flags)
    121259{
    122260        struct tdb_lock_type *new_lck;
    123         int i;
    124         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    125 
    126         ltype &= ~TDB_MARK_LOCK;
    127 
    128         /* a global lock allows us to avoid per chain locks */
    129         if (tdb->global_lock.count &&
    130             (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
    131                 return 0;
    132         }
    133 
    134         if (tdb->global_lock.count) {
    135                 tdb->ecode = TDB_ERR_LOCK;
    136                 return -1;
    137         }
    138 
    139         if (list < -1 || list >= (int)tdb->header.hash_size) {
    140                 tdb->ecode = TDB_ERR_LOCK;
    141                 TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid list %d for ltype=%d\n",
    142                            list, ltype));
     261
     262        if (offset >= lock_offset(tdb->header.hash_size)) {
     263                tdb->ecode = TDB_ERR_LOCK;
     264                TDB_LOG((tdb, TDB_DEBUG_ERROR,"tdb_lock: invalid offset %u for ltype=%d\n",
     265                         offset, ltype));
    143266                return -1;
    144267        }
     
    146269                return 0;
    147270
    148         for (i=0; i<tdb->num_lockrecs; i++) {
    149                 if (tdb->lockrecs[i].list == list) {
    150                         if (tdb->lockrecs[i].count == 0) {
    151                                 /*
    152                                  * Can't happen, see tdb_unlock(). It should
    153                                  * be an assert.
    154                                  */
    155                                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock: "
    156                                          "lck->count == 0 for list %d", list));
    157                         }
    158                         /*
    159                          * Just increment the in-memory struct, posix locks
    160                          * don't stack.
    161                          */
    162                         tdb->lockrecs[i].count++;
    163                         return 0;
    164                 }
     271        new_lck = find_nestlock(tdb, offset);
     272        if (new_lck) {
     273                /*
     274                 * Just increment the in-memory struct, posix locks
     275                 * don't stack.
     276                 */
     277                new_lck->count++;
     278                return 0;
    165279        }
    166280
     
    176290        /* Since fcntl locks don't nest, we do a lock for the first one,
    177291           and simply bump the count for future ones */
    178         if (!mark_lock &&
    179             tdb->methods->tdb_brlock(tdb,FREELIST_TOP+4*list, ltype, op,
    180                                      0, 1)) {
    181                 return -1;
    182         }
    183 
    184         tdb->num_locks++;
    185 
    186         tdb->lockrecs[tdb->num_lockrecs].list = list;
     292        if (tdb_brlock(tdb, ltype, offset, 1, flags)) {
     293                return -1;
     294        }
     295
     296        tdb->lockrecs[tdb->num_lockrecs].off = offset;
    187297        tdb->lockrecs[tdb->num_lockrecs].count = 1;
    188298        tdb->lockrecs[tdb->num_lockrecs].ltype = ltype;
    189         tdb->num_lockrecs += 1;
     299        tdb->num_lockrecs++;
    190300
    191301        return 0;
     302}
     303
     304static int tdb_lock_and_recover(struct tdb_context *tdb)
     305{
     306        int ret;
     307
     308        /* We need to match locking order in transaction commit. */
     309        if (tdb_brlock(tdb, F_WRLCK, FREELIST_TOP, 0, TDB_LOCK_WAIT)) {
     310                return -1;
     311        }
     312
     313        if (tdb_brlock(tdb, F_WRLCK, OPEN_LOCK, 1, TDB_LOCK_WAIT)) {
     314                tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0);
     315                return -1;
     316        }
     317
     318        ret = tdb_transaction_recover(tdb);
     319
     320        tdb_brunlock(tdb, F_WRLCK, OPEN_LOCK, 1);
     321        tdb_brunlock(tdb, F_WRLCK, FREELIST_TOP, 0);
     322
     323        return ret;
     324}
     325
     326static bool have_data_locks(const struct tdb_context *tdb)
     327{
     328        unsigned int i;
     329
     330        for (i = 0; i < tdb->num_lockrecs; i++) {
     331                if (tdb->lockrecs[i].off >= lock_offset(-1))
     332                        return true;
     333        }
     334        return false;
     335}
     336
     337static int tdb_lock_list(struct tdb_context *tdb, int list, int ltype,
     338                         enum tdb_lock_flags waitflag)
     339{
     340        int ret;
     341        bool check = false;
     342
     343        /* a allrecord lock allows us to avoid per chain locks */
     344        if (tdb->allrecord_lock.count &&
     345            (ltype == tdb->allrecord_lock.ltype || ltype == F_RDLCK)) {
     346                return 0;
     347        }
     348
     349        if (tdb->allrecord_lock.count) {
     350                tdb->ecode = TDB_ERR_LOCK;
     351                ret = -1;
     352        } else {
     353                /* Only check when we grab first data lock. */
     354                check = !have_data_locks(tdb);
     355                ret = tdb_nest_lock(tdb, lock_offset(list), ltype, waitflag);
     356
     357                if (ret == 0 && check && tdb_needs_recovery(tdb)) {
     358                        tdb_nest_unlock(tdb, lock_offset(list), ltype, false);
     359
     360                        if (tdb_lock_and_recover(tdb) == -1) {
     361                                return -1;
     362                        }
     363                        return tdb_lock_list(tdb, list, ltype, waitflag);
     364                }
     365        }
     366        return ret;
    192367}
    193368
     
    196371{
    197372        int ret;
    198         ret = _tdb_lock(tdb, list, ltype, F_SETLKW);
     373
     374        ret = tdb_lock_list(tdb, list, ltype, TDB_LOCK_WAIT);
    199375        if (ret) {
    200376                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lock failed on list %d "
     
    207383int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype)
    208384{
    209         return _tdb_lock(tdb, list, ltype, F_SETLK);
    210 }
    211 
    212 
    213 /* unlock the database: returns void because it's too late for errors. */
    214         /* changed to return int it may be interesting to know there
    215            has been an error  --simo */
    216 int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
     385        return tdb_lock_list(tdb, list, ltype, TDB_LOCK_NOWAIT);
     386}
     387
     388
     389int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
     390                    bool mark_lock)
    217391{
    218392        int ret = -1;
    219         int i;
    220         struct tdb_lock_type *lck = NULL;
    221         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    222 
    223         ltype &= ~TDB_MARK_LOCK;
    224 
    225         /* a global lock allows us to avoid per chain locks */
    226         if (tdb->global_lock.count &&
    227             (ltype == tdb->global_lock.ltype || ltype == F_RDLCK)) {
    228                 return 0;
    229         }
    230 
    231         if (tdb->global_lock.count) {
    232                 tdb->ecode = TDB_ERR_LOCK;
    233                 return -1;
    234         }
     393        struct tdb_lock_type *lck;
    235394
    236395        if (tdb->flags & TDB_NOLOCK)
     
    238397
    239398        /* Sanity checks */
    240         if (list < -1 || list >= (int)tdb->header.hash_size) {
    241                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: list %d invalid (%d)\n", list, tdb->header.hash_size));
     399        if (offset >= lock_offset(tdb->header.hash_size)) {
     400                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: offset %u invalid (%d)\n", offset, tdb->header.hash_size));
    242401                return ret;
    243402        }
    244403
    245         for (i=0; i<tdb->num_lockrecs; i++) {
    246                 if (tdb->lockrecs[i].list == list) {
    247                         lck = &tdb->lockrecs[i];
    248                         break;
    249                 }
    250         }
    251 
     404        lck = find_nestlock(tdb, offset);
    252405        if ((lck == NULL) || (lck->count == 0)) {
    253406                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlock: count is 0\n"));
     
    270423                ret = 0;
    271424        } else {
    272                 ret = tdb->methods->tdb_brlock(tdb, FREELIST_TOP+4*list, F_UNLCK,
    273                                                F_SETLKW, 0, 1);
    274         }
    275         tdb->num_locks--;
     425                ret = tdb_brunlock(tdb, ltype, offset, 1);
     426        }
    276427
    277428        /*
     
    279430         * last array element.
    280431         */
    281 
    282         if (tdb->num_lockrecs > 1) {
    283                 *lck = tdb->lockrecs[tdb->num_lockrecs-1];
    284         }
    285         tdb->num_lockrecs -= 1;
     432        *lck = tdb->lockrecs[--tdb->num_lockrecs];
    286433
    287434        /*
     
    299446}
    300447
     448int tdb_unlock(struct tdb_context *tdb, int list, int ltype)
     449{
     450        /* a global lock allows us to avoid per chain locks */
     451        if (tdb->allrecord_lock.count &&
     452            (ltype == tdb->allrecord_lock.ltype || ltype == F_RDLCK)) {
     453                return 0;
     454        }
     455
     456        if (tdb->allrecord_lock.count) {
     457                tdb->ecode = TDB_ERR_LOCK;
     458                return -1;
     459        }
     460
     461        return tdb_nest_unlock(tdb, lock_offset(list), ltype, false);
     462}
     463
    301464/*
    302465  get the transaction lock
    303466 */
    304 int tdb_transaction_lock(struct tdb_context *tdb, int ltype)
    305 {
    306         if (tdb->global_lock.count) {
    307                 return 0;
    308         }
    309         if (tdb->transaction_lock_count > 0) {
    310                 tdb->transaction_lock_count++;
    311                 return 0;
    312         }
    313 
    314         if (tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, ltype,
    315                                      F_SETLKW, 0, 1) == -1) {
    316                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_lock: failed to get transaction lock\n"));
    317                 tdb->ecode = TDB_ERR_LOCK;
    318                 return -1;
    319         }
    320         tdb->transaction_lock_count++;
    321         return 0;
     467int tdb_transaction_lock(struct tdb_context *tdb, int ltype,
     468                         enum tdb_lock_flags lockflags)
     469{
     470        return tdb_nest_lock(tdb, TRANSACTION_LOCK, ltype, lockflags);
    322471}
    323472
     
    325474  release the transaction lock
    326475 */
    327 int tdb_transaction_unlock(struct tdb_context *tdb)
    328 {
    329         int ret;
    330         if (tdb->global_lock.count) {
    331                 return 0;
    332         }
    333         if (tdb->transaction_lock_count > 1) {
    334                 tdb->transaction_lock_count--;
    335                 return 0;
    336         }
    337         ret = tdb->methods->tdb_brlock(tdb, TRANSACTION_LOCK, F_UNLCK, F_SETLKW, 0, 1);
    338         if (ret == 0) {
    339                 tdb->transaction_lock_count = 0;
    340         }
    341         return ret;
    342 }
    343 
    344 
    345 
    346 
    347 /* lock/unlock entire database */
    348 static int _tdb_lockall(struct tdb_context *tdb, int ltype, int op)
    349 {
    350         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    351 
    352         ltype &= ~TDB_MARK_LOCK;
    353 
     476int tdb_transaction_unlock(struct tdb_context *tdb, int ltype)
     477{
     478        return tdb_nest_unlock(tdb, TRANSACTION_LOCK, ltype, false);
     479}
     480
     481/* Returns 0 if all done, -1 if error, 1 if ok. */
     482static int tdb_allrecord_check(struct tdb_context *tdb, int ltype,
     483                               enum tdb_lock_flags flags, bool upgradable)
     484{
    354485        /* There are no locks on read-only dbs */
    355486        if (tdb->read_only || tdb->traverse_read) {
     
    358489        }
    359490
    360         if (tdb->global_lock.count && tdb->global_lock.ltype == ltype) {
    361                 tdb->global_lock.count++;
    362                 return 0;
    363         }
    364 
    365         if (tdb->global_lock.count) {
     491        if (tdb->allrecord_lock.count && tdb->allrecord_lock.ltype == ltype) {
     492                tdb->allrecord_lock.count++;
     493                return 0;
     494        }
     495
     496        if (tdb->allrecord_lock.count) {
    366497                /* a global lock of a different type exists */
    367498                tdb->ecode = TDB_ERR_LOCK;
    368499                return -1;
    369500        }
    370        
    371         if (tdb->num_locks != 0) {
     501
     502        if (tdb_have_extra_locks(tdb)) {
    372503                /* can't combine global and chain locks */
    373504                tdb->ecode = TDB_ERR_LOCK;
     
    375506        }
    376507
    377         if (!mark_lock &&
    378             tdb->methods->tdb_brlock(tdb, FREELIST_TOP, ltype, op,
    379                                      0, 4*tdb->header.hash_size)) {
    380                 if (op == F_SETLKW) {
    381                         TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_lockall failed (%s)\n", strerror(errno)));
    382                 }
    383                 return -1;
    384         }
    385 
    386         tdb->global_lock.count = 1;
    387         tdb->global_lock.ltype = ltype;
    388 
     508        if (upgradable && ltype != F_RDLCK) {
     509                /* tdb error: you can't upgrade a write lock! */
     510                tdb->ecode = TDB_ERR_LOCK;
     511                return -1;
     512        }
     513        return 1;
     514}
     515
     516/* We only need to lock individual bytes, but Linux merges consecutive locks
     517 * so we lock in contiguous ranges. */
     518static int tdb_chainlock_gradual(struct tdb_context *tdb,
     519                                 int ltype, enum tdb_lock_flags flags,
     520                                 size_t off, size_t len)
     521{
     522        int ret;
     523        enum tdb_lock_flags nb_flags = (flags & ~TDB_LOCK_WAIT);
     524
     525        if (len <= 4) {
     526                /* Single record.  Just do blocking lock. */
     527                return tdb_brlock(tdb, ltype, off, len, flags);
     528        }
     529
     530        /* First we try non-blocking. */
     531        ret = tdb_brlock(tdb, ltype, off, len, nb_flags);
     532        if (ret == 0) {
     533                return 0;
     534        }
     535
     536        /* Try locking first half, then second. */
     537        ret = tdb_chainlock_gradual(tdb, ltype, flags, off, len / 2);
     538        if (ret == -1)
     539                return -1;
     540
     541        ret = tdb_chainlock_gradual(tdb, ltype, flags,
     542                                    off + len / 2, len - len / 2);
     543        if (ret == -1) {
     544                tdb_brunlock(tdb, ltype, off, len / 2);
     545                return -1;
     546        }
    389547        return 0;
    390548}
    391549
     550/* lock/unlock entire database.  It can only be upgradable if you have some
     551 * other way of guaranteeing exclusivity (ie. transaction write lock).
     552 * We do the locking gradually to avoid being starved by smaller locks. */
     553int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
     554                       enum tdb_lock_flags flags, bool upgradable)
     555{
     556        switch (tdb_allrecord_check(tdb, ltype, flags, upgradable)) {
     557        case -1:
     558                return -1;
     559        case 0:
     560                return 0;
     561        }
     562
     563        /* We cover two kinds of locks:
     564         * 1) Normal chain locks.  Taken for almost all operations.
     565         * 3) Individual records locks.  Taken after normal or free
     566         *    chain locks.
     567         *
     568         * It is (1) which cause the starvation problem, so we're only
     569         * gradual for that. */
     570        if (tdb_chainlock_gradual(tdb, ltype, flags, FREELIST_TOP,
     571                                  tdb->header.hash_size * 4) == -1) {
     572                return -1;
     573        }
     574
     575        /* Grab individual record locks. */
     576        if (tdb_brlock(tdb, ltype, lock_offset(tdb->header.hash_size), 0,
     577                       flags) == -1) {
     578                tdb_brunlock(tdb, ltype, FREELIST_TOP,
     579                             tdb->header.hash_size * 4);
     580                return -1;
     581        }
     582
     583        tdb->allrecord_lock.count = 1;
     584        /* If it's upgradable, it's actually exclusive so we can treat
     585         * it as a write lock. */
     586        tdb->allrecord_lock.ltype = upgradable ? F_WRLCK : ltype;
     587        tdb->allrecord_lock.off = upgradable;
     588
     589        if (tdb_needs_recovery(tdb)) {
     590                bool mark = flags & TDB_LOCK_MARK_ONLY;
     591                tdb_allrecord_unlock(tdb, ltype, mark);
     592                if (mark) {
     593                        tdb->ecode = TDB_ERR_LOCK;
     594                        TDB_LOG((tdb, TDB_DEBUG_ERROR,
     595                                 "tdb_lockall_mark cannot do recovery\n"));
     596                        return -1;
     597                }
     598                if (tdb_lock_and_recover(tdb) == -1) {
     599                        return -1;
     600                }
     601                return tdb_allrecord_lock(tdb, ltype, flags, upgradable);
     602        }
     603
     604        return 0;
     605}
     606
    392607
    393608
    394609/* unlock entire db */
    395 static int _tdb_unlockall(struct tdb_context *tdb, int ltype)
    396 {
    397         bool mark_lock = ((ltype & TDB_MARK_LOCK) == TDB_MARK_LOCK);
    398 
    399         ltype &= ~TDB_MARK_LOCK;
    400 
     610int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock)
     611{
    401612        /* There are no locks on read-only dbs */
    402613        if (tdb->read_only || tdb->traverse_read) {
     
    405616        }
    406617
    407         if (tdb->global_lock.ltype != ltype || tdb->global_lock.count == 0) {
    408                 tdb->ecode = TDB_ERR_LOCK;
    409                 return -1;
    410         }
    411 
    412         if (tdb->global_lock.count > 1) {
    413                 tdb->global_lock.count--;
    414                 return 0;
    415         }
    416 
    417         if (!mark_lock &&
    418             tdb->methods->tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW,
    419                                      0, 4*tdb->header.hash_size)) {
     618        if (tdb->allrecord_lock.count == 0) {
     619                tdb->ecode = TDB_ERR_LOCK;
     620                return -1;
     621        }
     622
     623        /* Upgradable locks are marked as write locks. */
     624        if (tdb->allrecord_lock.ltype != ltype
     625            && (!tdb->allrecord_lock.off || ltype != F_RDLCK)) {
     626                tdb->ecode = TDB_ERR_LOCK;
     627                return -1;
     628        }
     629
     630        if (tdb->allrecord_lock.count > 1) {
     631                tdb->allrecord_lock.count--;
     632                return 0;
     633        }
     634
     635        if (!mark_lock && tdb_brunlock(tdb, ltype, FREELIST_TOP, 0)) {
    420636                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_unlockall failed (%s)\n", strerror(errno)));
    421637                return -1;
    422638        }
    423639
    424         tdb->global_lock.count = 0;
    425         tdb->global_lock.ltype = 0;
     640        tdb->allrecord_lock.count = 0;
     641        tdb->allrecord_lock.ltype = 0;
    426642
    427643        return 0;
     
    429645
    430646/* lock entire database with write lock */
    431 int tdb_lockall(struct tdb_context *tdb)
     647_PUBLIC_ int tdb_lockall(struct tdb_context *tdb)
    432648{
    433649        tdb_trace(tdb, "tdb_lockall");
    434         return _tdb_lockall(tdb, F_WRLCK, F_SETLKW);
     650        return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_WAIT, false);
    435651}
    436652
    437653/* lock entire database with write lock - mark only */
    438 int tdb_lockall_mark(struct tdb_context *tdb)
     654_PUBLIC_ int tdb_lockall_mark(struct tdb_context *tdb)
    439655{
    440656        tdb_trace(tdb, "tdb_lockall_mark");
    441         return _tdb_lockall(tdb, F_WRLCK | TDB_MARK_LOCK, F_SETLKW);
     657        return tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_MARK_ONLY, false);
    442658}
    443659
    444660/* unlock entire database with write lock - unmark only */
    445 int tdb_lockall_unmark(struct tdb_context *tdb)
     661_PUBLIC_ int tdb_lockall_unmark(struct tdb_context *tdb)
    446662{
    447663        tdb_trace(tdb, "tdb_lockall_unmark");
    448         return _tdb_unlockall(tdb, F_WRLCK | TDB_MARK_LOCK);
     664        return tdb_allrecord_unlock(tdb, F_WRLCK, true);
    449665}
    450666
    451667/* lock entire database with write lock - nonblocking varient */
    452 int tdb_lockall_nonblock(struct tdb_context *tdb)
    453 {
    454         int ret = _tdb_lockall(tdb, F_WRLCK, F_SETLK);
     668_PUBLIC_ int tdb_lockall_nonblock(struct tdb_context *tdb)
     669{
     670        int ret = tdb_allrecord_lock(tdb, F_WRLCK, TDB_LOCK_NOWAIT, false);
    455671        tdb_trace_ret(tdb, "tdb_lockall_nonblock", ret);
    456672        return ret;
     
    458674
    459675/* unlock entire database with write lock */
    460 int tdb_unlockall(struct tdb_context *tdb)
     676_PUBLIC_ int tdb_unlockall(struct tdb_context *tdb)
    461677{
    462678        tdb_trace(tdb, "tdb_unlockall");
    463         return _tdb_unlockall(tdb, F_WRLCK);
     679        return tdb_allrecord_unlock(tdb, F_WRLCK, false);
    464680}
    465681
    466682/* lock entire database with read lock */
    467 int tdb_lockall_read(struct tdb_context *tdb)
     683_PUBLIC_ int tdb_lockall_read(struct tdb_context *tdb)
    468684{
    469685        tdb_trace(tdb, "tdb_lockall_read");
    470         return _tdb_lockall(tdb, F_RDLCK, F_SETLKW);
     686        return tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, false);
    471687}
    472688
    473689/* lock entire database with read lock - nonblock varient */
    474 int tdb_lockall_read_nonblock(struct tdb_context *tdb)
    475 {
    476         int ret = _tdb_lockall(tdb, F_RDLCK, F_SETLK);
     690_PUBLIC_ int tdb_lockall_read_nonblock(struct tdb_context *tdb)
     691{
     692        int ret = tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_NOWAIT, false);
    477693        tdb_trace_ret(tdb, "tdb_lockall_read_nonblock", ret);
    478694        return ret;
     
    480696
    481697/* unlock entire database with read lock */
    482 int tdb_unlockall_read(struct tdb_context *tdb)
     698_PUBLIC_ int tdb_unlockall_read(struct tdb_context *tdb)
    483699{
    484700        tdb_trace(tdb, "tdb_unlockall_read");
    485         return _tdb_unlockall(tdb, F_RDLCK);
     701        return tdb_allrecord_unlock(tdb, F_RDLCK, false);
    486702}
    487703
    488704/* lock/unlock one hash chain. This is meant to be used to reduce
    489705   contention - it cannot guarantee how many records will be locked */
    490 int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
     706_PUBLIC_ int tdb_chainlock(struct tdb_context *tdb, TDB_DATA key)
    491707{
    492708        int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
     
    498714   to reduce contention - it cannot guarantee how many records will be
    499715   locked */
    500 int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
     716_PUBLIC_ int tdb_chainlock_nonblock(struct tdb_context *tdb, TDB_DATA key)
    501717{
    502718        int ret = tdb_lock_nonblock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK);
     
    506722
    507723/* mark a chain as locked without actually locking it. Warning! use with great caution! */
    508 int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
    509 {
    510         int ret = tdb_lock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
     724_PUBLIC_ int tdb_chainlock_mark(struct tdb_context *tdb, TDB_DATA key)
     725{
     726        int ret = tdb_nest_lock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))),
     727                                F_WRLCK, TDB_LOCK_MARK_ONLY);
    511728        tdb_trace_1rec(tdb, "tdb_chainlock_mark", key);
    512729        return ret;
     
    514731
    515732/* unmark a chain as locked without actually locking it. Warning! use with great caution! */
    516 int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
     733_PUBLIC_ int tdb_chainlock_unmark(struct tdb_context *tdb, TDB_DATA key)
    517734{
    518735        tdb_trace_1rec(tdb, "tdb_chainlock_unmark", key);
    519         return tdb_unlock(tdb, BUCKET(tdb->hash_fn(&key)), F_WRLCK | TDB_MARK_LOCK);
    520 }
    521 
    522 int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
     736        return tdb_nest_unlock(tdb, lock_offset(BUCKET(tdb->hash_fn(&key))),
     737                               F_WRLCK, true);
     738}
     739
     740_PUBLIC_ int tdb_chainunlock(struct tdb_context *tdb, TDB_DATA key)
    523741{
    524742        tdb_trace_1rec(tdb, "tdb_chainunlock", key);
     
    526744}
    527745
    528 int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
     746_PUBLIC_ int tdb_chainlock_read(struct tdb_context *tdb, TDB_DATA key)
    529747{
    530748        int ret;
     
    534752}
    535753
    536 int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
     754_PUBLIC_ int tdb_chainunlock_read(struct tdb_context *tdb, TDB_DATA key)
    537755{
    538756        tdb_trace_1rec(tdb, "tdb_chainunlock_read", key);
     
    540758}
    541759
    542 
    543 
    544760/* record lock stops delete underneath */
    545761int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off)
    546762{
    547         if (tdb->global_lock.count) {
    548                 return 0;
    549         }
    550         return off ? tdb->methods->tdb_brlock(tdb, off, F_RDLCK, F_SETLKW, 0, 1) : 0;
     763        if (tdb->allrecord_lock.count) {
     764                return 0;
     765        }
     766        return off ? tdb_brlock(tdb, F_RDLCK, off, 1, TDB_LOCK_WAIT) : 0;
    551767}
    552768
     
    562778                if (i->off == off)
    563779                        return -1;
    564         return tdb->methods->tdb_brlock(tdb, off, F_WRLCK, F_SETLK, 1, 1);
    565 }
    566 
    567 /*
    568   Note this is meant to be F_SETLK, *not* F_SETLKW, as it's not
    569   an error to fail to get the lock here.
    570 */
     780        if (tdb->allrecord_lock.count) {
     781                if (tdb->allrecord_lock.ltype == F_WRLCK) {
     782                        return 0;
     783                }
     784                return -1;
     785        }
     786        return tdb_brlock(tdb, F_WRLCK, off, 1, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
     787}
     788
    571789int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off)
    572790{
    573         return tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLK, 0, 1);
     791        if (tdb->allrecord_lock.count) {
     792                return 0;
     793        }
     794        return tdb_brunlock(tdb, F_WRLCK, off, 1);
    574795}
    575796
     
    580801        uint32_t count = 0;
    581802
    582         if (tdb->global_lock.count) {
     803        if (tdb->allrecord_lock.count) {
    583804                return 0;
    584805        }
     
    589810                if (i->off == off)
    590811                        count++;
    591         return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0);
    592 }
     812        return (count == 1 ? tdb_brunlock(tdb, F_RDLCK, off, 1) : 0);
     813}
     814
     815bool tdb_have_extra_locks(struct tdb_context *tdb)
     816{
     817        unsigned int extra = tdb->num_lockrecs;
     818
     819        /* A transaction holds the lock for all records. */
     820        if (!tdb->transaction && tdb->allrecord_lock.count) {
     821                return true;
     822        }
     823
     824        /* We always hold the active lock if CLEAR_IF_FIRST. */
     825        if (find_nestlock(tdb, ACTIVE_LOCK)) {
     826                extra--;
     827        }
     828
     829        /* In a transaction, we expect to hold the transaction lock */
     830        if (tdb->transaction && find_nestlock(tdb, TRANSACTION_LOCK)) {
     831                extra--;
     832        }
     833
     834        return extra;
     835}
     836
     837/* The transaction code uses this to remove all locks. */
     838void tdb_release_transaction_locks(struct tdb_context *tdb)
     839{
     840        unsigned int i, active = 0;
     841
     842        if (tdb->allrecord_lock.count != 0) {
     843                tdb_brunlock(tdb, tdb->allrecord_lock.ltype, FREELIST_TOP, 0);
     844                tdb->allrecord_lock.count = 0;
     845        }
     846
     847        for (i=0;i<tdb->num_lockrecs;i++) {
     848                struct tdb_lock_type *lck = &tdb->lockrecs[i];
     849
     850                /* Don't release the active lock!  Copy it to first entry. */
     851                if (lck->off == ACTIVE_LOCK) {
     852                        tdb->lockrecs[active++] = *lck;
     853                } else {
     854                        tdb_brunlock(tdb, lck->ltype, lck->off, 1);
     855                }
     856        }
     857        tdb->num_lockrecs = active;
     858        if (tdb->num_lockrecs == 0) {
     859                SAFE_FREE(tdb->lockrecs);
     860        }
     861}
  • vendor/current/lib/tdb/common/open.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    3131static struct tdb_context *tdbs = NULL;
    3232
    33 
    34 /* This is based on the hash algorithm from gdbm */
    35 static unsigned int default_tdb_hash(TDB_DATA *key)
    36 {
    37         uint32_t value; /* Used to compute the hash value.  */
    38         uint32_t   i;   /* Used to cycle through random values. */
    39 
    40         /* Set the initial value from the key size. */
    41         for (value = 0x238F13AF * key->dsize, i=0; i < key->dsize; i++)
    42                 value = (value + (key->dptr[i] << (i*5 % 24)));
    43 
    44         return (1103515243 * value + 12345); 
    45 }
    46 
     33/* We use two hashes to double-check they're using the right hash function. */
     34void tdb_header_hash(struct tdb_context *tdb,
     35                     uint32_t *magic1_hash, uint32_t *magic2_hash)
     36{
     37        TDB_DATA hash_key;
     38        uint32_t tdb_magic = TDB_MAGIC;
     39
     40        hash_key.dptr = discard_const_p(unsigned char, TDB_MAGIC_FOOD);
     41        hash_key.dsize = sizeof(TDB_MAGIC_FOOD);
     42        *magic1_hash = tdb->hash_fn(&hash_key);
     43
     44        hash_key.dptr = (unsigned char *)CONVERT(tdb_magic);
     45        hash_key.dsize = sizeof(tdb_magic);
     46        *magic2_hash = tdb->hash_fn(&hash_key);
     47
     48        /* Make sure at least one hash is non-zero! */
     49        if (*magic1_hash == 0 && *magic2_hash == 0)
     50                *magic1_hash = 1;
     51}
    4752
    4853/* initialise a new database with a specified hash size */
     
    5257        size_t size;
    5358        int ret = -1;
    54         ssize_t written;
    5559
    5660        /* We make it up in memory, then write it out if not internal */
     
    6468        newdb->version = TDB_VERSION;
    6569        newdb->hash_size = hash_size;
     70
     71        tdb_header_hash(tdb, &newdb->magic1_hash, &newdb->magic2_hash);
     72
     73        /* Make sure older tdbs (which don't check the magic hash fields)
     74         * will refuse to open this TDB. */
     75        if (tdb->flags & TDB_INCOMPATIBLE_HASH)
     76                newdb->rwlocks = TDB_HASH_RWLOCK_MAGIC;
     77
    6678        if (tdb->flags & TDB_INTERNAL) {
    6779                tdb->map_size = size;
     
    8496        memcpy(newdb->magic_food, TDB_MAGIC_FOOD, strlen(TDB_MAGIC_FOOD)+1);
    8597        /* we still have "ret == -1" here */
    86         written = write(tdb->fd, newdb, size);
    87         if (written == size) {
     98        if (tdb_write_all(tdb->fd, newdb, size))
    8899                ret = 0;
    89         } else if (written != -1) {
    90                 /* call write once again, this usually should return -1 and
    91                  * set errno appropriately */
    92                 size -= written;
    93                 written = write(tdb->fd, newdb+written, size);
    94                 if (written == size) {
    95                 ret = 0;
    96                 } else if (written >= 0) {
    97                         /* a second incomplete write - we give up.
    98                          * guessing the errno... */
    99                         errno = ENOSPC;
    100                 }
    101         }
    102100
    103101  fail:
     
    112110{
    113111        struct tdb_context *i;
    114        
     112
    115113        for (i = tdbs; i; i = i->next) {
    116114                if (i->device == device && i->inode == ino) {
     
    132130
    133131   @param name may be NULL for internal databases. */
    134 struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
     132_PUBLIC_ struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
    135133                      int open_flags, mode_t mode)
    136134{
     
    144142}
    145143
    146 
    147 struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
     144static bool check_header_hash(struct tdb_context *tdb,
     145                              bool default_hash, uint32_t *m1, uint32_t *m2)
     146{
     147        tdb_header_hash(tdb, m1, m2);
     148        if (tdb->header.magic1_hash == *m1 &&
     149            tdb->header.magic2_hash == *m2) {
     150                return true;
     151        }
     152
     153        /* If they explicitly set a hash, always respect it. */
     154        if (!default_hash)
     155                return false;
     156
     157        /* Otherwise, try the other inbuilt hash. */
     158        if (tdb->hash_fn == tdb_old_hash)
     159                tdb->hash_fn = tdb_jenkins_hash;
     160        else
     161                tdb->hash_fn = tdb_old_hash;
     162        return check_header_hash(tdb, false, m1, m2);
     163}
     164
     165_PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
    148166                                int open_flags, mode_t mode,
    149167                                const struct tdb_logging_context *log_ctx,
     
    156174        uint32_t vertest;
    157175        unsigned v;
     176        const char *hash_alg;
     177        uint32_t magic1, magic2;
    158178
    159179        if (!(tdb = (struct tdb_context *)calloc(1, sizeof *tdb))) {
     
    177197                tdb->log.log_private = NULL;
    178198        }
    179         tdb->hash_fn = hash_fn ? hash_fn : default_tdb_hash;
     199
     200        if (name == NULL && (tdb_flags & TDB_INTERNAL)) {
     201                name = "__TDB_INTERNAL__";
     202        }
     203
     204        if (name == NULL) {
     205                tdb->name = discard_const_p(char, "__NULL__");
     206                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: called with name == NULL\n"));
     207                tdb->name = NULL;
     208                errno = EINVAL;
     209                goto fail;
     210        }
     211
     212        /* now make a copy of the name, as the caller memory might went away */
     213        if (!(tdb->name = (char *)strdup(name))) {
     214                /*
     215                 * set the name as the given string, so that tdb_name() will
     216                 * work in case of an error.
     217                 */
     218                tdb->name = discard_const_p(char, name);
     219                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: can't strdup(%s)\n",
     220                         name));
     221                tdb->name = NULL;
     222                errno = ENOMEM;
     223                goto fail;
     224        }
     225
     226        if (hash_fn) {
     227                tdb->hash_fn = hash_fn;
     228                hash_alg = "the user defined";
     229        } else {
     230                /* This controls what we use when creating a tdb. */
     231                if (tdb->flags & TDB_INCOMPATIBLE_HASH) {
     232                        tdb->hash_fn = tdb_jenkins_hash;
     233                } else {
     234                        tdb->hash_fn = tdb_old_hash;
     235                }
     236                hash_alg = "either default";
     237        }
    180238
    181239        /* cache the page size */
     
    193251                goto fail;
    194252        }
    195        
     253
    196254        if (hash_size == 0)
    197255                hash_size = DEFAULT_HASH_SIZE;
     
    212270        }
    213271
     272        if (getenv("TDB_NO_FSYNC")) {
     273                tdb->flags |= TDB_NOSYNC;
     274        }
     275
    214276        /*
    215277         * TDB_ALLOW_NESTING is the default behavior.
     
    242304
    243305        /* ensure there is only one process initialising at once */
    244         if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
    245                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get global lock on %s: %s\n",
     306        if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
     307                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to get open lock on %s: %s\n",
    246308                         name, strerror(errno)));
    247309                goto fail;      /* errno set by tdb_brlock */
     
    251313        if ((tdb_flags & TDB_CLEAR_IF_FIRST) &&
    252314            (!tdb->read_only) &&
    253             (locked = (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_WRLCK, F_SETLK, 0, 1) == 0))) {
     315            (locked = (tdb_nest_lock(tdb, ACTIVE_LOCK, F_WRLCK, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE) == 0))) {
    254316                open_flags |= O_CREAT;
    255317                if (ftruncate(tdb->fd, 0) == -1) {
     
    290352                goto fail;
    291353
    292         if (tdb->header.rwlocks != 0) {
     354        if (tdb->header.rwlocks != 0 &&
     355            tdb->header.rwlocks != TDB_HASH_RWLOCK_MAGIC) {
    293356                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: spinlocks no longer supported\n"));
     357                goto fail;
     358        }
     359
     360        if ((tdb->header.magic1_hash == 0) && (tdb->header.magic2_hash == 0)) {
     361                /* older TDB without magic hash references */
     362                tdb->hash_fn = tdb_old_hash;
     363        } else if (!check_header_hash(tdb, !hash_fn, &magic1, &magic2)) {
     364                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_open_ex: "
     365                         "%s was not created with %s hash function we are using\n"
     366                         "magic1_hash[0x%08X %s 0x%08X] "
     367                         "magic2_hash[0x%08X %s 0x%08X]\n",
     368                         name, hash_alg,
     369                         tdb->header.magic1_hash,
     370                         (tdb->header.magic1_hash == magic1) ? "==" : "!=",
     371                         magic1,
     372                         tdb->header.magic2_hash,
     373                         (tdb->header.magic2_hash == magic2) ? "==" : "!=",
     374                         magic2));
     375                errno = EINVAL;
    294376                goto fail;
    295377        }
     
    304386        }
    305387
    306         if (!(tdb->name = (char *)strdup(name))) {
    307                 errno = ENOMEM;
    308                 goto fail;
    309         }
    310 
    311388        tdb->map_size = st.st_size;
    312389        tdb->device = st.st_dev;
     
    314391        tdb_mmap(tdb);
    315392        if (locked) {
    316                 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_UNLCK, F_SETLK, 0, 1) == -1) {
     393                if (tdb_nest_unlock(tdb, ACTIVE_LOCK, F_WRLCK, false) == -1) {
    317394                        TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: "
    318                                  "failed to take ACTIVE_LOCK on %s: %s\n",
     395                                 "failed to release ACTIVE_LOCK on %s: %s\n",
    319396                                 name, strerror(errno)));
    320397                        goto fail;
     
    329406        if (tdb_flags & TDB_CLEAR_IF_FIRST) {
    330407                /* leave this lock in place to indicate it's in use */
    331                 if (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)
     408                if (tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
    332409                        goto fail;
     410                }
    333411        }
    334412
     
    357435        /* Internal (memory-only) databases skip all the code above to
    358436         * do with disk files, and resume here by releasing their
    359          * global lock and hooking into the active list. */
    360         if (tdb->methods->tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1) == -1)
    361                 goto fail;
     437         * open lock and hooking into the active list. */
     438        if (tdb_nest_unlock(tdb, OPEN_LOCK, F_WRLCK, false) == -1) {
     439                goto fail;
     440        }
    362441        tdb->next = tdbs;
    363442        tdbs = tdb;
     
    379458                        tdb_munmap(tdb);
    380459        }
    381         SAFE_FREE(tdb->name);
    382460        if (tdb->fd != -1)
    383461                if (close(tdb->fd) != 0)
    384462                        TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_open_ex: failed to close tdb->fd on error!\n"));
     463        SAFE_FREE(tdb->lockrecs);
     464        SAFE_FREE(tdb->name);
    385465        SAFE_FREE(tdb);
    386466        errno = save_errno;
     
    393473 */
    394474
    395 void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
     475_PUBLIC_ void tdb_set_max_dead(struct tdb_context *tdb, int max_dead)
    396476{
    397477        tdb->max_dead_records = max_dead;
     
    403483 * @returns -1 for error; 0 for success.
    404484 **/
    405 int tdb_close(struct tdb_context *tdb)
     485_PUBLIC_ int tdb_close(struct tdb_context *tdb)
    406486{
    407487        struct tdb_context **i;
    408488        int ret = 0;
    409489
     490        if (tdb->transaction) {
     491                tdb_transaction_cancel(tdb);
     492        }
    410493        tdb_trace(tdb, "tdb_close");
    411         if (tdb->transaction) {
    412                 _tdb_transaction_cancel(tdb);
    413         }
    414494
    415495        if (tdb->map_ptr) {
     
    444524
    445525/* register a loging function */
    446 void tdb_set_logging_function(struct tdb_context *tdb,
    447                               const struct tdb_logging_context *log_ctx)
     526_PUBLIC_ void tdb_set_logging_function(struct tdb_context *tdb,
     527                                       const struct tdb_logging_context *log_ctx)
    448528{
    449529        tdb->log = *log_ctx;
    450530}
    451531
    452 void *tdb_get_logging_private(struct tdb_context *tdb)
     532_PUBLIC_ void *tdb_get_logging_private(struct tdb_context *tdb)
    453533{
    454534        return tdb->log.log_private;
     
    466546        }
    467547
    468         if (tdb->num_locks != 0 || tdb->global_lock.count) {
     548        if (tdb_have_extra_locks(tdb)) {
    469549                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_reopen: reopen not allowed with locks held\n"));
    470550                goto fail;
     
    501581#endif /* fake pread or pwrite */
    502582
    503         if (active_lock &&
    504             (tdb->methods->tdb_brlock(tdb, ACTIVE_LOCK, F_RDLCK, F_SETLKW, 0, 1) == -1)) {
     583        /* We may still think we hold the active lock. */
     584        tdb->num_lockrecs = 0;
     585        SAFE_FREE(tdb->lockrecs);
     586
     587        if (active_lock && tdb_nest_lock(tdb, ACTIVE_LOCK, F_RDLCK, TDB_LOCK_WAIT) == -1) {
    505588                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_reopen: failed to obtain active lock\n"));
    506589                goto fail;
     
    516599/* reopen a tdb - this can be used after a fork to ensure that we have an independent
    517600   seek pointer from our parent and to re-establish locks */
    518 int tdb_reopen(struct tdb_context *tdb)
     601_PUBLIC_ int tdb_reopen(struct tdb_context *tdb)
    519602{
    520603        return tdb_reopen_internal(tdb, tdb->flags & TDB_CLEAR_IF_FIRST);
     
    522605
    523606/* reopen all tdb's */
    524 int tdb_reopen_all(int parent_longlived)
     607_PUBLIC_ int tdb_reopen_all(int parent_longlived)
    525608{
    526609        struct tdb_context *tdb;
  • vendor/current/lib/tdb/common/tdb.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    2828#include "tdb_private.h"
    2929
    30 TDB_DATA tdb_null;
     30_PUBLIC_ TDB_DATA tdb_null;
    3131
    3232/*
     
    3434  the TDB_SEQNUM flag
    3535*/
    36 void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
     36_PUBLIC_ void tdb_increment_seqnum_nonblock(struct tdb_context *tdb)
    3737{
    3838        tdb_off_t seqnum=0;
    39        
     39
    4040        if (!(tdb->flags & TDB_SEQNUM)) {
    4141                return;
     
    6060        }
    6161
    62         if (tdb_brlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, F_SETLKW, 1, 1) != 0) {
     62        if (tdb_nest_lock(tdb, TDB_SEQNUM_OFS, F_WRLCK,
     63                          TDB_LOCK_WAIT|TDB_LOCK_PROBE) != 0) {
    6364                return;
    6465        }
     
    6667        tdb_increment_seqnum_nonblock(tdb);
    6768
    68         tdb_brlock(tdb, TDB_SEQNUM_OFS, F_UNLCK, F_SETLKW, 1, 1);
     69        tdb_nest_unlock(tdb, TDB_SEQNUM_OFS, F_WRLCK, false);
    6970}
    7071
     
    8081{
    8182        tdb_off_t rec_ptr;
    82        
     83
    8384        /* read in the hash top */
    8485        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    154155                }
    155156        }
    156          
    157157
    158158        /* must be long enough key, data and tailer */
     
    171171                return tdb_rec_write(tdb, rec_ptr, &rec);
    172172        }
    173  
     173
    174174        return 0;
    175175}
     
    200200}
    201201
    202 TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
     202_PUBLIC_ TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key)
    203203{
    204204        TDB_DATA ret = _tdb_fetch(tdb, key);
     
    213213 * should be fast and should not block on other syscalls.
    214214 *
    215  * DONT CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.
     215 * DON'T CALL OTHER TDB CALLS FROM THE PARSER, THIS MIGHT LEAD TO SEGFAULTS.
    216216 *
    217217 * For mmapped tdb's that do not have a transaction open it points the parsing
     
    222222 * This is interesting for all readers of potentially large data structures in
    223223 * the tdb records, ldb indexes being one example.
     224 *
     225 * Return -1 if the record was not found.
    224226 */
    225227
    226 int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
     228_PUBLIC_ int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
    227229                     int (*parser)(TDB_DATA key, TDB_DATA data,
    228230                                   void *private_data),
     
    238240
    239241        if (!(rec_ptr = tdb_find_lock_hash(tdb,key,hash,F_RDLCK,&rec))) {
     242                /* record not found */
    240243                tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, -1);
    241244                tdb->ecode = TDB_ERR_NOEXIST;
    242                 return 0;
     245                return -1;
    243246        }
    244247        tdb_trace_1rec_ret(tdb, "tdb_parse_record", key, 0);
     
    261264{
    262265        struct tdb_record rec;
    263        
     266
    264267        if (tdb_find_lock_hash(tdb, key, hash, F_RDLCK, &rec) == 0)
    265268                return 0;
     
    268271}
    269272
    270 int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
     273_PUBLIC_ int tdb_exists(struct tdb_context *tdb, TDB_DATA key)
    271274{
    272275        uint32_t hash = tdb->hash_fn(&key);
     
    319322        tdb_off_t rec_ptr;
    320323        struct tdb_record rec;
    321        
     324
    322325        /* read in the hash top */
    323326        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    348351                return -1;
    349352        }
    350        
     353
    351354        /* read in the hash top */
    352355        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    427430}
    428431
    429 int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
     432_PUBLIC_ int tdb_delete(struct tdb_context *tdb, TDB_DATA key)
    430433{
    431434        uint32_t hash = tdb->hash_fn(&key);
     
    444447{
    445448        tdb_off_t rec_ptr;
    446        
     449
    447450        /* read in the hash top */
    448451        if (tdb_ofs_read(tdb, TDB_HASH_TOP(hash), &rec_ptr) == -1)
     
    597600   return 0 on success, -1 on failure
    598601*/
    599 int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
     602_PUBLIC_ int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag)
    600603{
    601604        uint32_t hash;
     
    620623
    621624/* Append to an entry. Create if not exist. */
    622 int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
     625_PUBLIC_ int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf)
    623626{
    624627        uint32_t hash;
     
    659662        ret = _tdb_store(tdb, key, dbuf, 0, hash);
    660663        tdb_trace_2rec_retrec(tdb, "tdb_append", key, new_dbuf, dbuf);
    661        
     664
    662665failed:
    663666        tdb_unlock(tdb, BUCKET(hash), F_WRLCK);
     
    671674  useful for external logging functions
    672675*/
    673 const char *tdb_name(struct tdb_context *tdb)
     676_PUBLIC_ const char *tdb_name(struct tdb_context *tdb)
    674677{
    675678        return tdb->name;
     
    681684  of the fd
    682685*/
    683 int tdb_fd(struct tdb_context *tdb)
     686_PUBLIC_ int tdb_fd(struct tdb_context *tdb)
    684687{
    685688        return tdb->fd;
     
    690693  useful for external tdb routines that wish to log tdb errors
    691694*/
    692 tdb_log_func tdb_log_fn(struct tdb_context *tdb)
     695_PUBLIC_ tdb_log_func tdb_log_fn(struct tdb_context *tdb)
    693696{
    694697        return tdb->log.log_fn;
     
    706709  test of a possible tdb change.
    707710*/
    708 int tdb_get_seqnum(struct tdb_context *tdb)
     711_PUBLIC_ int tdb_get_seqnum(struct tdb_context *tdb)
    709712{
    710713        tdb_off_t seqnum=0;
     
    714717}
    715718
    716 int tdb_hash_size(struct tdb_context *tdb)
     719_PUBLIC_ int tdb_hash_size(struct tdb_context *tdb)
    717720{
    718721        return tdb->header.hash_size;
    719722}
    720723
    721 size_t tdb_map_size(struct tdb_context *tdb)
     724_PUBLIC_ size_t tdb_map_size(struct tdb_context *tdb)
    722725{
    723726        return tdb->map_size;
    724727}
    725728
    726 int tdb_get_flags(struct tdb_context *tdb)
     729_PUBLIC_ int tdb_get_flags(struct tdb_context *tdb)
    727730{
    728731        return tdb->flags;
    729732}
    730733
    731 void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
     734_PUBLIC_ void tdb_add_flags(struct tdb_context *tdb, unsigned flags)
    732735{
    733736        if ((flags & TDB_ALLOW_NESTING) &&
     
    749752}
    750753
    751 void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
     754_PUBLIC_ void tdb_remove_flags(struct tdb_context *tdb, unsigned flags)
    752755{
    753756        if ((flags & TDB_ALLOW_NESTING) &&
     
    773776  enable sequence number handling on an open tdb
    774777*/
    775 void tdb_enable_seqnum(struct tdb_context *tdb)
     778_PUBLIC_ void tdb_enable_seqnum(struct tdb_context *tdb)
    776779{
    777780        tdb->flags |= TDB_SEQNUM;
     
    805808/*
    806809  wipe the entire database, deleting all records. This can be done
    807   very fast by using a global lock. The entire data portion of the
     810  very fast by using a allrecord lock. The entire data portion of the
    808811  file becomes a single entry in the freelist.
    809812
    810813  This code carefully steps around the recovery area, leaving it alone
    811814 */
    812 int tdb_wipe_all(struct tdb_context *tdb)
     815_PUBLIC_ int tdb_wipe_all(struct tdb_context *tdb)
    813816{
    814817        int i;
     
    917920  repack a tdb
    918921 */
    919 int tdb_repack(struct tdb_context *tdb)
     922_PUBLIC_ int tdb_repack(struct tdb_context *tdb)
    920923{
    921924        struct tdb_context *tmp_db;
     
    987990}
    988991
     992/* Even on files, we can get partial writes due to signals. */
     993bool tdb_write_all(int fd, const void *buf, size_t count)
     994{
     995        while (count) {
     996                ssize_t ret;
     997                ret = write(fd, buf, count);
     998                if (ret < 0)
     999                        return false;
     1000                buf = (const char *)buf + ret;
     1001                count -= ret;
     1002        }
     1003        return true;
     1004}
     1005
    9891006#ifdef TDB_TRACE
    9901007static void tdb_trace_write(struct tdb_context *tdb, const char *str)
    9911008{
    992         if (write(tdb->tracefd, str, strlen(str)) != strlen(str)) {
     1009        if (!tdb_write_alltdb->tracefd, str, strlen(str)) {
    9931010                close(tdb->tracefd);
    9941011                tdb->tracefd = -1;
  • vendor/current/lib/tdb/common/tdb_private.h

    r414 r740  
    55
    66   Copyright (C) Andrew Tridgell              2005
    7    
     7
    88     ** NOTE! The following LGPL license applies to the tdb
    99     ** library. This does NOT imply that all of Samba is released
    1010     ** under the LGPL
    11    
     11
    1212   This library is free software; you can redistribute it and/or
    1313   modify it under the terms of the GNU Lesser General Public
     
    5050#define TDB_DEAD_MAGIC (0xFEE1DEAD)
    5151#define TDB_RECOVERY_MAGIC (0xf53bc0e7U)
     52#define TDB_RECOVERY_INVALID_MAGIC (0x0)
     53#define TDB_HASH_RWLOCK_MAGIC (0xbad1a51U)
    5254#define TDB_ALIGNMENT 4
    5355#define DEFAULT_HASH_SIZE 131
     
    102104
    103105/* lock offsets */
    104 #define GLOBAL_LOCK      0
     106#define OPEN_LOCK        0
    105107#define ACTIVE_LOCK      4
    106108#define TRANSACTION_LOCK 8
     
    147149        tdb_off_t recovery_start; /* offset of transaction recovery region */
    148150        tdb_off_t sequence_number; /* used when TDB_SEQNUM is set */
    149         tdb_off_t reserved[29];
     151        uint32_t magic1_hash; /* hash of TDB_MAGIC_FOOD. */
     152        uint32_t magic2_hash; /* hash of TDB_MAGIC. */
     153        tdb_off_t reserved[27];
    150154};
    151155
    152156struct tdb_lock_type {
    153         int list;
     157        uint32_t off;
    154158        uint32_t count;
    155159        uint32_t ltype;
     
    163167};
    164168
     169enum tdb_lock_flags {
     170        /* WAIT == F_SETLKW, NOWAIT == F_SETLK */
     171        TDB_LOCK_NOWAIT = 0,
     172        TDB_LOCK_WAIT = 1,
     173        /* If set, don't log an error on failure. */
     174        TDB_LOCK_PROBE = 2,
     175        /* If set, don't actually lock at all. */
     176        TDB_LOCK_MARK_ONLY = 4,
     177};
    165178
    166179struct tdb_methods {
     
    170183        int (*tdb_oob)(struct tdb_context *, tdb_off_t , int );
    171184        int (*tdb_expand_file)(struct tdb_context *, tdb_off_t , tdb_off_t );
    172         int (*tdb_brlock)(struct tdb_context *, tdb_off_t , int, int, int, size_t);
    173185};
    174186
     
    181193        int traverse_read; /* read-only traversal */
    182194        int traverse_write; /* read-write traversal */
    183         struct tdb_lock_type global_lock;
     195        struct tdb_lock_type allrecord_lock; /* .offset == upgradable */
    184196        int num_lockrecs;
    185197        struct tdb_lock_type *lockrecs; /* only real locks, all with count>0 */
     
    194206        unsigned int (*hash_fn)(TDB_DATA *key);
    195207        int open_flags; /* flags used in the open - needed by reopen */
    196         unsigned int num_locks; /* number of chain locks held */
    197208        const struct tdb_methods *methods;
    198209        struct tdb_transaction *transaction;
    199210        int page_size;
    200211        int max_dead_records;
    201         int transaction_lock_count;
    202212#ifdef TDB_TRACE
    203213        int tracefd;
     
    214224int tdb_lock(struct tdb_context *tdb, int list, int ltype);
    215225int tdb_lock_nonblock(struct tdb_context *tdb, int list, int ltype);
     226int tdb_nest_lock(struct tdb_context *tdb, uint32_t offset, int ltype,
     227                  enum tdb_lock_flags flags);
     228int tdb_nest_unlock(struct tdb_context *tdb, uint32_t offset, int ltype,
     229                    bool mark_lock);
    216230int tdb_unlock(struct tdb_context *tdb, int list, int ltype);
    217 int tdb_brlock(struct tdb_context *tdb, tdb_off_t offset, int rw_type, int lck_type, int probe, size_t len);
    218 int tdb_transaction_lock(struct tdb_context *tdb, int ltype);
    219 int tdb_transaction_unlock(struct tdb_context *tdb);
    220 int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len);
     231int tdb_brlock(struct tdb_context *tdb,
     232               int rw_type, tdb_off_t offset, size_t len,
     233               enum tdb_lock_flags flags);
     234int tdb_brunlock(struct tdb_context *tdb,
     235                 int rw_type, tdb_off_t offset, size_t len);
     236bool tdb_have_extra_locks(struct tdb_context *tdb);
     237void tdb_release_transaction_locks(struct tdb_context *tdb);
     238int tdb_transaction_lock(struct tdb_context *tdb, int ltype,
     239                         enum tdb_lock_flags lockflags);
     240int tdb_transaction_unlock(struct tdb_context *tdb, int ltype);
     241int tdb_recovery_area(struct tdb_context *tdb,
     242                      const struct tdb_methods *methods,
     243                      tdb_off_t *recovery_offset,
     244                      struct tdb_record *rec);
     245int tdb_allrecord_lock(struct tdb_context *tdb, int ltype,
     246                       enum tdb_lock_flags flags, bool upgradable);
     247int tdb_allrecord_unlock(struct tdb_context *tdb, int ltype, bool mark_lock);
     248int tdb_allrecord_upgrade(struct tdb_context *tdb);
    221249int tdb_write_lock_record(struct tdb_context *tdb, tdb_off_t off);
    222250int tdb_write_unlock_record(struct tdb_context *tdb, tdb_off_t off);
     
    230258int tdb_lock_record(struct tdb_context *tdb, tdb_off_t off);
    231259int tdb_unlock_record(struct tdb_context *tdb, tdb_off_t off);
    232 int _tdb_transaction_cancel(struct tdb_context *tdb);
     260bool tdb_needs_recovery(struct tdb_context *tdb);
    233261int tdb_rec_read(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
    234262int tdb_rec_write(struct tdb_context *tdb, tdb_off_t offset, struct tdb_record *rec);
     
    246274int tdb_rec_free_read(struct tdb_context *tdb, tdb_off_t off,
    247275                      struct tdb_record *rec);
    248 
    249 
     276bool tdb_write_all(int fd, const void *buf, size_t count);
     277int tdb_transaction_recover(struct tdb_context *tdb);
     278void tdb_header_hash(struct tdb_context *tdb,
     279                     uint32_t *magic1_hash, uint32_t *magic2_hash);
     280unsigned int tdb_old_hash(TDB_DATA *key);
     281size_t tdb_dead_space(struct tdb_context *tdb, tdb_off_t off);
  • vendor/current/lib/tdb/common/transaction.c

    r414 r740  
    99     ** library. This does NOT imply that all of Samba is released
    1010     ** under the LGPL
    11    
     11
    1212   This library is free software; you can redistribute it and/or
    1313   modify it under the terms of the GNU Lesser General Public
     
    6060    existing transaction record. If the inner transaction is cancelled
    6161    then a subsequent commit will fail
    62  
     62
    6363  - keep a mirrored copy of the tdb hash chain heads to allow for the
    6464    fast hash heads scan on traverse, updating the mirrored copy in
     
    7777
    7878  - check for a valid recovery record on open of the tdb, while the
    79     global lock is held. Automatically recover from the transaction
     79    open lock is held. Automatically recover from the transaction
    8080    recovery area if needed, then continue with the open as
    8181    usual. This allows for smooth crash recovery with no administrator
     
    136136        tdb_off_t magic_offset;
    137137
    138         /* set when the GLOBAL_LOCK has been taken */
    139         bool global_lock_taken;
    140 
    141138        /* old file size before transaction */
    142139        tdb_len_t old_map_size;
    143140
    144         /* we should re-pack on commit */
    145         bool need_repack;
     141        /* did we expand in this transaction */
     142        bool expanded;
    146143};
    147144
     
    189186                }
    190187        }
    191        
     188
    192189        /* now copy it out of this block */
    193190        memcpy(buf, tdb->transaction->blocks[blk] + (off % tdb->transaction->block_size), len);
     
    296293                }
    297294        }
    298        
     295
    299296        /* overwrite part of an existing block */
    300297        if (buf == NULL) {
     
    407404        }
    408405
    409         tdb->transaction->need_repack = true;
    410 
    411         return 0;
    412 }
    413 
    414 /*
    415   brlock during a transaction - ignore them
    416 */
    417 static int transaction_brlock(struct tdb_context *tdb, tdb_off_t offset,
    418                               int rw_type, int lck_type, int probe, size_t len)
    419 {
     406        tdb->transaction->expanded = true;
     407
    420408        return 0;
    421409}
     
    427415        transaction_oob,
    428416        transaction_expand_file,
    429         transaction_brlock
    430417};
    431418
     
    435422  transaction is allowed to be pending per tdb_context
    436423*/
    437 int tdb_transaction_start(struct tdb_context *tdb)
     424static int _tdb_transaction_start(struct tdb_context *tdb,
     425                                  enum tdb_lock_flags lockflags)
    438426{
    439427        /* some sanity checks */
     
    456444        }
    457445
    458         if (tdb->num_locks != 0 || tdb->global_lock.count) {
     446        if (tdb_have_extra_locks(tdb)) {
    459447                /* the caller must not have any locks when starting a
    460448                   transaction as otherwise we'll be screwed by lack
     
    487475           discussed with Volker, there are a number of ways we could
    488476           make this async, which we will probably do in the future */
    489         if (tdb_transaction_lock(tdb, F_WRLCK) == -1) {
     477        if (tdb_transaction_lock(tdb, F_WRLCK, lockflags) == -1) {
    490478                SAFE_FREE(tdb->transaction->blocks);
    491479                SAFE_FREE(tdb->transaction);
    492                 return -1;
    493         }
    494        
     480                if ((lockflags & TDB_LOCK_WAIT) == 0) {
     481                        tdb->ecode = TDB_ERR_NOLOCK;
     482                }
     483                return -1;
     484        }
     485
    495486        /* get a read lock from the freelist to the end of file. This
    496487           is upgraded to a write lock during the commit */
    497         if (tdb_brlock(tdb, FREELIST_TOP, F_RDLCK, F_SETLKW, 0, 0) == -1) {
     488        if (tdb_allrecord_lock(tdb, F_RDLCK, TDB_LOCK_WAIT, true) == -1) {
    498489                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_start: failed to get hash locks\n"));
    499                 tdb->ecode = TDB_ERR_LOCK;
    500                 goto fail;
     490                goto fail_allrecord_lock;
    501491        }
    502492
     
    529519        tdb_trace(tdb, "tdb_transaction_start");
    530520        return 0;
    531        
     521
    532522fail:
    533         tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
    534         tdb_transaction_unlock(tdb);
     523        tdb_allrecord_unlock(tdb, F_RDLCK, false);
     524fail_allrecord_lock:
     525        tdb_transaction_unlock(tdb, F_WRLCK);
    535526        SAFE_FREE(tdb->transaction->blocks);
    536527        SAFE_FREE(tdb->transaction->hash_heads);
     
    539530}
    540531
     532_PUBLIC_ int tdb_transaction_start(struct tdb_context *tdb)
     533{
     534        return _tdb_transaction_start(tdb, TDB_LOCK_WAIT);
     535}
     536
     537_PUBLIC_ int tdb_transaction_start_nonblock(struct tdb_context *tdb)
     538{
     539        return _tdb_transaction_start(tdb, TDB_LOCK_NOWAIT|TDB_LOCK_PROBE);
     540}
    541541
    542542/*
     
    549549        }
    550550
     551#ifdef HAVE_FDATASYNC
     552        if (fdatasync(tdb->fd) != 0) {
     553#else
    551554        if (fsync(tdb->fd) != 0) {
     555#endif
    552556                tdb->ecode = TDB_ERR_IO;
    553557                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction: fsync failed\n"));
     
    570574
    571575
    572 int _tdb_transaction_cancel(struct tdb_context *tdb)
     576static int _tdb_transaction_cancel(struct tdb_context *tdb)
    573577{       
    574578        int i, ret = 0;
     
    597601        if (tdb->transaction->magic_offset) {
    598602                const struct tdb_methods *methods = tdb->transaction->io_methods;
    599                 uint32_t zero = 0;
     603                const uint32_t invalid = TDB_RECOVERY_INVALID_MAGIC;
    600604
    601605                /* remove the recovery marker */
    602                 if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &zero, 4) == -1 ||
     606                if (methods->tdb_write(tdb, tdb->transaction->magic_offset, &invalid, 4) == -1 ||
    603607                transaction_sync(tdb, tdb->transaction->magic_offset, 4) == -1) {
    604608                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_cancel: failed to remove recovery magic\n"));
     
    607611        }
    608612
    609         if (tdb->transaction->global_lock_taken) {
    610                 tdb_brlock(tdb, GLOBAL_LOCK, F_UNLCK, F_SETLKW, 0, 1);
    611                 tdb->transaction->global_lock_taken = false;
    612         }
    613 
    614         /* remove any global lock created during the transaction */
    615         if (tdb->global_lock.count != 0) {
    616                 tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 4*tdb->header.hash_size);
    617                 tdb->global_lock.count = 0;
    618         }
    619 
    620         /* remove any locks created during the transaction */
    621         if (tdb->num_locks != 0) {
    622                 for (i=0;i<tdb->num_lockrecs;i++) {
    623                         tdb_brlock(tdb,FREELIST_TOP+4*tdb->lockrecs[i].list,
    624                                    F_UNLCK,F_SETLKW, 0, 1);
    625                 }
    626                 tdb->num_locks = 0;
    627                 tdb->num_lockrecs = 0;
    628                 SAFE_FREE(tdb->lockrecs);
    629         }
     613        /* This also removes the OPEN_LOCK, if we have it. */
     614        tdb_release_transaction_locks(tdb);
    630615
    631616        /* restore the normal io methods */
    632617        tdb->methods = tdb->transaction->io_methods;
    633618
    634         tdb_brlock(tdb, FREELIST_TOP, F_UNLCK, F_SETLKW, 0, 0);
    635         tdb_transaction_unlock(tdb);
    636619        SAFE_FREE(tdb->transaction->hash_heads);
    637620        SAFE_FREE(tdb->transaction);
    638        
     621
    639622        return ret;
    640623}
     
    643626  cancel the current transaction
    644627*/
    645 int tdb_transaction_cancel(struct tdb_context *tdb)
     628_PUBLIC_ int tdb_transaction_cancel(struct tdb_context *tdb)
    646629{
    647630        tdb_trace(tdb, "tdb_transaction_cancel");
     
    676659}
    677660
     661int tdb_recovery_area(struct tdb_context *tdb,
     662                      const struct tdb_methods *methods,
     663                      tdb_off_t *recovery_offset,
     664                      struct tdb_record *rec)
     665{
     666        if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, recovery_offset) == -1) {
     667                return -1;
     668        }
     669
     670        if (*recovery_offset == 0) {
     671                rec->rec_len = 0;
     672                return 0;
     673        }
     674
     675        if (methods->tdb_read(tdb, *recovery_offset, rec, sizeof(*rec),
     676                              DOCONV()) == -1) {
     677                return -1;
     678        }
     679
     680        /* ignore invalid recovery regions: can happen in crash */
     681        if (rec->magic != TDB_RECOVERY_MAGIC &&
     682            rec->magic != TDB_RECOVERY_INVALID_MAGIC) {
     683                *recovery_offset = 0;
     684                rec->rec_len = 0;
     685        }
     686        return 0;
     687}
     688
    678689/*
    679690  allocate the recovery area, or use an existing recovery area if it is
     
    689700        tdb_off_t recovery_head;
    690701
    691         if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
     702        if (tdb_recovery_area(tdb, methods, &recovery_head, &rec) == -1) {
    692703                TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery head\n"));
    693                 return -1;
    694         }
    695 
    696         rec.rec_len = 0;
    697 
    698         if (recovery_head != 0 &&
    699             methods->tdb_read(tdb, recovery_head, &rec, sizeof(rec), DOCONV()) == -1) {
    700                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_recovery_allocate: failed to read recovery record\n"));
    701704                return -1;
    702705        }
     
    794797        memset(rec, 0, sizeof(*rec));
    795798
    796         rec->magic    = 0;
     799        rec->magic    = TDB_RECOVERY_INVALID_MAGIC;
    797800        rec->data_len = recovery_size;
    798801        rec->rec_len  = recovery_max_size;
    799802        rec->key_len  = old_map_size;
    800         CONVERT(rec);
     803        CONVERT(*rec);
    801804
    802805        /* build the recovery data into a single blob to allow us to do a single
     
    816819                        length = tdb->transaction->last_block_size;
    817820                }
    818                
     821
    819822                if (offset >= old_map_size) {
    820823                        continue;
     
    845848        tailer = sizeof(*rec) + recovery_max_size;
    846849        memcpy(p, &tailer, 4);
    847         CONVERT(p);
     850        if (DOCONV()) {
     851                tdb_convert(p, 4);
     852        }
    848853
    849854        /* write the recovery data to the recovery area */
     
    929934
    930935        methods = tdb->transaction->io_methods;
    931        
     936
    932937        /* if there are any locks pending then the caller has not
    933938           nested their locks properly, so fail the transaction */
    934         if (tdb->num_locks || tdb->global_lock.count) {
     939        if (tdb_have_extra_locks(tdb)) {
    935940                tdb->ecode = TDB_ERR_LOCK;
    936941                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: locks pending on commit\n"));
     
    940945
    941946        /* upgrade the main transaction lock region to a write lock */
    942         if (tdb_brlock_upgrade(tdb, FREELIST_TOP, 0) == -1) {
     947        if (tdb_allrecord_upgrade(tdb) == -1) {
    943948                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to upgrade hash locks\n"));
    944                 tdb->ecode = TDB_ERR_LOCK;
    945949                _tdb_transaction_cancel(tdb);
    946950                return -1;
    947951        }
    948952
    949         /* get the global lock - this prevents new users attaching to the database
     953        /* get the open lock - this prevents new users attaching to the database
    950954           during the commit */
    951         if (tdb_brlock(tdb, GLOBAL_LOCK, F_WRLCK, F_SETLKW, 0, 1) == -1) {
    952                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get global lock\n"));
    953                 tdb->ecode = TDB_ERR_LOCK;
     955        if (tdb_nest_lock(tdb, OPEN_LOCK, F_WRLCK, TDB_LOCK_WAIT) == -1) {
     956                TDB_LOG((tdb, TDB_DEBUG_ERROR, "tdb_transaction_prepare_commit: failed to get open lock\n"));
    954957                _tdb_transaction_cancel(tdb);
    955958                return -1;
    956959        }
    957 
    958         tdb->transaction->global_lock_taken = true;
    959960
    960961        if (!(tdb->flags & TDB_NOSYNC)) {
     
    983984        }
    984985
    985         /* Keep the global lock until the actual commit */
     986        /* Keep the open lock until the actual commit */
    986987
    987988        return 0;
     
    991992   prepare to commit the current transaction
    992993*/
    993 int tdb_transaction_prepare_commit(struct tdb_context *tdb)
    994 {       
     994_PUBLIC_ int tdb_transaction_prepare_commit(struct tdb_context *tdb)
     995{
    995996        tdb_trace(tdb, "tdb_transaction_prepare_commit");
    996997        return _tdb_transaction_prepare_commit(tdb);
    997998}
    998999
     1000/* A repack is worthwhile if the largest is less than half total free. */
     1001static bool repack_worthwhile(struct tdb_context *tdb)
     1002{
     1003        tdb_off_t ptr;
     1004        struct tdb_record rec;
     1005        tdb_len_t total = 0, largest = 0;
     1006
     1007        if (tdb_ofs_read(tdb, FREELIST_TOP, &ptr) == -1) {
     1008                return false;
     1009        }
     1010
     1011        while (ptr != 0 && tdb_rec_free_read(tdb, ptr, &rec) == 0) {
     1012                total += rec.rec_len;
     1013                if (rec.rec_len > largest) {
     1014                        largest = rec.rec_len;
     1015                }
     1016                ptr = rec.next;
     1017        }
     1018
     1019        return total > largest * 2;
     1020}
     1021
    9991022/*
    10001023  commit the current transaction
    10011024*/
    1002 int tdb_transaction_commit(struct tdb_context *tdb)
    1003 {       
     1025_PUBLIC_ int tdb_transaction_commit(struct tdb_context *tdb)
     1026{
    10041027        const struct tdb_methods *methods;
    10051028        int i;
    1006         bool need_repack;
     1029        bool need_repack = false;
    10071030
    10081031        if (tdb->transaction == NULL) {
     
    10571080                if (methods->tdb_write(tdb, offset, tdb->transaction->blocks[i], length) == -1) {
    10581081                        TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_commit: write failed during commit\n"));
    1059                        
     1082
    10601083                        /* we've overwritten part of the data and
    10611084                           possibly expanded the file, so we need to
     
    10711094                SAFE_FREE(tdb->transaction->blocks[i]);
    10721095        }
     1096
     1097        /* Do this before we drop lock or blocks. */
     1098        if (tdb->transaction->expanded) {
     1099                need_repack = repack_worthwhile(tdb);
     1100        }
    10731101
    10741102        SAFE_FREE(tdb->transaction->blocks);
     
    10951123#endif
    10961124
    1097         need_repack = tdb->transaction->need_repack;
    1098 
    10991125        /* use a transaction cancel to free memory and remove the
    11001126           transaction locks */
     
    11111137/*
    11121138  recover from an aborted transaction. Must be called with exclusive
    1113   database write access already established (including the global
     1139  database write access already established (including the open
    11141140  lock to prevent new processes attaching)
    11151141*/
     
    12121238                return -1;                     
    12131239        }
    1214        
    1215         /* reduce the file size to the old size */
    1216         tdb_munmap(tdb);
    1217         if (ftruncate(tdb->fd, recovery_eof) != 0) {
    1218                 TDB_LOG((tdb, TDB_DEBUG_FATAL, "tdb_transaction_recover: failed to reduce to recovery size\n"));
    1219                 tdb->ecode = TDB_ERR_IO;
    1220                 return -1;                     
    1221         }
    1222         tdb->map_size = recovery_eof;
    1223         tdb_mmap(tdb);
    12241240
    12251241        if (transaction_sync(tdb, 0, recovery_eof) == -1) {
     
    12351251        return 0;
    12361252}
     1253
     1254/* Any I/O failures we say "needs recovery". */
     1255bool tdb_needs_recovery(struct tdb_context *tdb)
     1256{
     1257        tdb_off_t recovery_head;
     1258        struct tdb_record rec;
     1259
     1260        /* find the recovery area */
     1261        if (tdb_ofs_read(tdb, TDB_RECOVERY_HEAD, &recovery_head) == -1) {
     1262                return true;
     1263        }
     1264
     1265        if (recovery_head == 0) {
     1266                /* we have never allocated a recovery record */
     1267                return false;
     1268        }
     1269
     1270        /* read the recovery record */
     1271        if (tdb->methods->tdb_read(tdb, recovery_head, &rec,
     1272                                   sizeof(rec), DOCONV()) == -1) {
     1273                return true;
     1274        }
     1275
     1276        return (rec.magic == TDB_RECOVERY_MAGIC);
     1277}
  • vendor/current/lib/tdb/common/traverse.c

    r414 r740  
    77   Copyright (C) Paul `Rusty' Russell              2000
    88   Copyright (C) Jeremy Allison                    2000-2003
    9    
     9
    1010     ** NOTE! The following LGPL license applies to the tdb
    1111     ** library. This does NOT imply that all of Samba is released
    1212     ** under the LGPL
    13    
     13
    1414   This library is free software; you can redistribute it and/or
    1515   modify it under the terms of the GNU Lesser General Public
     
    4545                           hashes are used. In that case we spend most of our
    4646                           time in tdb_brlock(), locking empty hash chains.
    47                            
     47
    4848                           To avoid this, we do an unlocked pre-check to see
    4949                           if the hash chain is empty before starting to look
     
    5353                           lock, so instead we get the lock and re-fetch the
    5454                           value below.
    55                            
     55
    5656                           Notice that not doing this optimisation on the
    5757                           first hash chain is critical. We must guarantee
     
    6363                           could miss them anyway without this trick, so the
    6464                           semantics don't change.
    65                            
     65
    6666                           With a non-indexed ldb search this trick gains us a
    6767                           factor of around 80 in speed on a linux 2.6.x
     
    213213  a write style traverse - temporarily marks the db read only
    214214*/
    215 int tdb_traverse_read(struct tdb_context *tdb,
     215_PUBLIC_ int tdb_traverse_read(struct tdb_context *tdb,
    216216                      tdb_traverse_func fn, void *private_data)
    217217{
     
    221221        /* we need to get a read lock on the transaction lock here to
    222222           cope with the lock ordering semantics of solaris10 */
    223         if (tdb_transaction_lock(tdb, F_RDLCK)) {
     223        if (tdb_transaction_lock(tdb, F_RDLCK, TDB_LOCK_WAIT)) {
    224224                return -1;
    225225        }
     
    230230        tdb->traverse_read--;
    231231
    232         tdb_transaction_unlock(tdb);
     232        tdb_transaction_unlock(tdb, F_RDLCK);
    233233
    234234        return ret;
     
    242242  alignment restrictions malloc gives you.
    243243*/
    244 int tdb_traverse(struct tdb_context *tdb,
     244_PUBLIC_ int tdb_traverse(struct tdb_context *tdb,
    245245                 tdb_traverse_func fn, void *private_data)
    246246{
     
    252252        }
    253253
    254         if (tdb_transaction_lock(tdb, F_WRLCK)) {
     254        if (tdb_transaction_lock(tdb, F_WRLCK, TDB_LOCK_WAIT)) {
    255255                return -1;
    256256        }
     
    261261        tdb->traverse_write--;
    262262
    263         tdb_transaction_unlock(tdb);
     263        tdb_transaction_unlock(tdb, F_WRLCK);
    264264
    265265        return ret;
     
    268268
    269269/* find the first entry in the database and return its key */
    270 TDB_DATA tdb_firstkey(struct tdb_context *tdb)
     270_PUBLIC_ TDB_DATA tdb_firstkey(struct tdb_context *tdb)
    271271{
    272272        TDB_DATA key;
     
    299299
    300300/* find the next entry in the database, returning its key */
    301 TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
     301_PUBLIC_ TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA oldkey)
    302302{
    303303        uint32_t oldhash;
  • vendor/current/lib/tdb/docs/README

    r414 r740  
    106106
    107107----------------------------------------------------------------------
     108int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
     109                     int (*parser)(TDB_DATA key, TDB_DATA data,
     110                                   void *private_data),
     111                     void *private_data);
     112
     113   Hand a record to a parser function without allocating it.
     114
     115   This function is meant as a fast tdb_fetch alternative for large records
     116   that are frequently read. The "key" and "data" arguments point directly
     117   into the tdb shared memory, they are not aligned at any boundary.
     118
     119   WARNING: The parser is called while tdb holds a lock on the record. DO NOT
     120   call other tdb routines from within the parser. Also, for good performance
     121   you should make the parser fast to allow parallel operations.
     122
     123   tdb_parse_record returns -1 if the record was not found.  If the record was
     124   found, the return value of "parser" is passed up to the caller.
     125
     126----------------------------------------------------------------------
    108127int tdb_exists(TDB_CONTEXT *tdb, TDB_DATA key);
    109128
  • vendor/current/lib/tdb/include/tdb.h

    r414 r740  
    3131#endif
    3232
    33 #include "signal.h"
    34 
    35 /* flags to tdb_store() */
    36 #define TDB_REPLACE 1           /* Unused */
    37 #define TDB_INSERT 2            /* Don't overwrite an existing entry */
    38 #define TDB_MODIFY 3            /* Don't create an existing entry    */
    39 
    40 /* flags for tdb_open() */
    41 #define TDB_DEFAULT 0 /* just a readability place holder */
    42 #define TDB_CLEAR_IF_FIRST 1
    43 #define TDB_INTERNAL 2 /* don't store on disk */
    44 #define TDB_NOLOCK   4 /* don't do any locking */
    45 #define TDB_NOMMAP   8 /* don't use mmap */
    46 #define TDB_CONVERT 16 /* convert endian (internal use) */
    47 #define TDB_BIGENDIAN 32 /* header is big-endian (internal use) */
    48 #define TDB_NOSYNC   64 /* don't use synchronous transactions */
    49 #define TDB_SEQNUM   128 /* maintain a sequence number */
    50 #define TDB_VOLATILE   256 /* Activate the per-hashchain freelist, default 5 */
    51 #define TDB_ALLOW_NESTING 512 /* Allow transactions to nest */
    52 #define TDB_DISALLOW_NESTING 1024 /* Disallow transactions to nest */
    53 
    54 /* error codes */
     33#include <signal.h>
     34
     35/**
     36 * @defgroup tdb The tdb API
     37 *
     38 * tdb is a Trivial database. In concept, it is very much like GDBM, and BSD's
     39 * DB except that it allows multiple simultaneous writers and uses locking
     40 * internally to keep writers from trampling on each other. tdb is also
     41 * extremely small.
     42 *
     43 * @section tdb_interface Interface
     44 *
     45 * The interface is very similar to gdbm except for the following:
     46 *
     47 * <ul>
     48 * <li>different open interface. The tdb_open call is more similar to a
     49 * traditional open()</li>
     50 * <li>no tdbm_reorganise() function</li>
     51 * <li>no tdbm_sync() function. No operations are cached in the library
     52 *     anyway</li>
     53 * <li>added a tdb_traverse() function for traversing the whole database</li>
     54 * <li>added transactions support</li>
     55 * </ul>
     56 *
     57 * A general rule for using tdb is that the caller frees any returned TDB_DATA
     58 * structures. Just call free(p.dptr) to free a TDB_DATA return value called p.
     59 * This is the same as gdbm.
     60 *
     61 * @{
     62 */
     63
     64/** Flags to tdb_store() */
     65#define TDB_REPLACE 1           /** Unused */
     66#define TDB_INSERT 2            /** Don't overwrite an existing entry */
     67#define TDB_MODIFY 3            /** Don't create an existing entry    */
     68
     69/** Flags for tdb_open() */
     70#define TDB_DEFAULT 0 /** just a readability place holder */
     71#define TDB_CLEAR_IF_FIRST 1 /** If this is the first open, wipe the db */
     72#define TDB_INTERNAL 2 /** Don't store on disk */
     73#define TDB_NOLOCK   4 /** Don't do any locking */
     74#define TDB_NOMMAP   8 /** Don't use mmap */
     75#define TDB_CONVERT 16 /** Convert endian (internal use) */
     76#define TDB_BIGENDIAN 32 /** Header is big-endian (internal use) */
     77#define TDB_NOSYNC   64 /** Don't use synchronous transactions */
     78#define TDB_SEQNUM   128 /** Maintain a sequence number */
     79#define TDB_VOLATILE   256 /** Activate the per-hashchain freelist, default 5 */
     80#define TDB_ALLOW_NESTING 512 /** Allow transactions to nest */
     81#define TDB_DISALLOW_NESTING 1024 /** Disallow transactions to nest */
     82#define TDB_INCOMPATIBLE_HASH 2048 /** Better hashing: can't be opened by tdb < 1.2.6. */
     83
     84/** The tdb error codes */
    5585enum TDB_ERROR {TDB_SUCCESS=0, TDB_ERR_CORRUPT, TDB_ERR_IO, TDB_ERR_LOCK,
    5686                TDB_ERR_OOM, TDB_ERR_EXISTS, TDB_ERR_NOLOCK, TDB_ERR_LOCK_TIMEOUT,
     
    5888                TDB_ERR_NESTING};
    5989
    60 /* debugging uses one of the following levels */
     90/** Debugging uses one of the following levels */
    6191enum tdb_debug_level {TDB_DEBUG_FATAL = 0, TDB_DEBUG_ERROR,
    6292                      TDB_DEBUG_WARNING, TDB_DEBUG_TRACE};
    6393
     94/** The tdb data structure */
    6495typedef struct TDB_DATA {
    6596        unsigned char *dptr;
     
    79110#endif
    80111
    81 /* this is the context structure that is returned from a db open */
     112/** This is the context structure that is returned from a db open. */
    82113typedef struct tdb_context TDB_CONTEXT;
    83114
     
    91122};
    92123
     124/**
     125 * @brief Open the database and creating it if necessary.
     126 *
     127 * @param[in]  name     The name of the db to open.
     128 *
     129 * @param[in]  hash_size The hash size is advisory, use zero for a default
     130 *                       value.
     131 *
     132 * @param[in]  tdb_flags The flags to use to open the db:\n\n
     133 *                         TDB_CLEAR_IF_FIRST - Clear database if we are the
     134 *                                              only one with it open\n
     135 *                         TDB_INTERNAL - Don't use a file, instaed store the
     136 *                                        data in memory. The filename is
     137 *                                        ignored in this case.\n
     138 *                         TDB_NOLOCK - Don't do any locking\n
     139 *                         TDB_NOMMAP - Don't use mmap\n
     140 *                         TDB_NOSYNC - Don't synchronise transactions to disk\n
     141 *                         TDB_SEQNUM - Maintain a sequence number\n
     142 *                         TDB_VOLATILE - activate the per-hashchain freelist,
     143 *                                        default 5.\n
     144 *                         TDB_ALLOW_NESTING - Allow transactions to nest.\n
     145 *                         TDB_DISALLOW_NESTING - Disallow transactions to nest.\n
     146 *
     147 * @param[in]  open_flags Flags for the open(2) function.
     148 *
     149 * @param[in]  mode     The mode for the open(2) function.
     150 *
     151 * @return              A tdb context structure, NULL on error.
     152 */
    93153struct tdb_context *tdb_open(const char *name, int hash_size, int tdb_flags,
    94154                      int open_flags, mode_t mode);
     155
     156/**
     157 * @brief Open the database and creating it if necessary.
     158 *
     159 * This is like tdb_open(), but allows you to pass an initial logging and
     160 * hash function. Be careful when passing a hash function - all users of the
     161 * database must use the same hash function or you will get data corruption.
     162 *
     163 * @param[in]  name     The name of the db to open.
     164 *
     165 * @param[in]  hash_size The hash size is advisory, use zero for a default
     166 *                       value.
     167 *
     168 * @param[in]  tdb_flags The flags to use to open the db:\n\n
     169 *                         TDB_CLEAR_IF_FIRST - Clear database if we are the
     170 *                                              only one with it open\n
     171 *                         TDB_INTERNAL - Don't use a file, instaed store the
     172 *                                        data in memory. The filename is
     173 *                                        ignored in this case.\n
     174 *                         TDB_NOLOCK - Don't do any locking\n
     175 *                         TDB_NOMMAP - Don't use mmap\n
     176 *                         TDB_NOSYNC - Don't synchronise transactions to disk\n
     177 *                         TDB_SEQNUM - Maintain a sequence number\n
     178 *                         TDB_VOLATILE - activate the per-hashchain freelist,
     179 *                                        default 5.\n
     180 *                         TDB_ALLOW_NESTING - Allow transactions to nest.\n
     181 *                         TDB_DISALLOW_NESTING - Disallow transactions to nest.\n
     182 *
     183 * @param[in]  open_flags Flags for the open(2) function.
     184 *
     185 * @param[in]  mode     The mode for the open(2) function.
     186 *
     187 * @param[in]  log_ctx  The logging function to use.
     188 *
     189 * @param[in]  hash_fn  The hash function you want to use.
     190 *
     191 * @return              A tdb context structure, NULL on error.
     192 *
     193 * @see tdb_open()
     194 */
    95195struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
    96196                         int open_flags, mode_t mode,
    97197                         const struct tdb_logging_context *log_ctx,
    98198                         tdb_hash_func hash_fn);
     199
     200/**
     201 * @brief Set the maximum number of dead records per hash chain.
     202 *
     203 * @param[in]  tdb      The database handle to set the maximum.
     204 *
     205 * @param[in]  max_dead The maximum number of dead records per hash chain.
     206 */
    99207void tdb_set_max_dead(struct tdb_context *tdb, int max_dead);
    100208
     209/**
     210 * @brief Reopen a tdb.
     211 *
     212 * This can be used after a fork to ensure that we have an independent seek
     213 * pointer from our parent and to re-establish locks.
     214 *
     215 * @param[in]  tdb      The database to reopen.
     216 *
     217 * @return              0 on success, -1 on error.
     218 */
    101219int tdb_reopen(struct tdb_context *tdb);
     220
     221/**
     222 * @brief Reopen all tdb's
     223 *
     224 * If the parent is longlived (ie. a parent daemon architecture), we know it
     225 * will keep it's active lock on a tdb opened with CLEAR_IF_FIRST. Thus for
     226 * child processes we don't have to add an active lock. This is essential to
     227 * improve performance on systems that keep POSIX locks as a non-scalable data
     228 * structure in the kernel.
     229 *
     230 * @param[in]  parent_longlived Wether the parent is longlived or not.
     231 *
     232 * @return              0 on success, -1 on error.
     233 */
    102234int tdb_reopen_all(int parent_longlived);
     235
     236/**
     237 * @brief Set a different tdb logging function.
     238 *
     239 * @param[in]  tdb      The tdb to set the logging function.
     240 *
     241 * @param[in]  log_ctx  The logging function to set.
     242 */
    103243void tdb_set_logging_function(struct tdb_context *tdb, const struct tdb_logging_context *log_ctx);
     244
     245/**
     246 * @brief Get the tdb last error code.
     247 *
     248 * @param[in]  tdb      The tdb to get the error code from.
     249 *
     250 * @return              A TDB_ERROR code.
     251 *
     252 * @see TDB_ERROR
     253 */
    104254enum TDB_ERROR tdb_error(struct tdb_context *tdb);
     255
     256/**
     257 * @brief Get a error string for the last tdb error
     258 *
     259 * @param[in]  tdb      The tdb to get the error code from.
     260 *
     261 * @return              An error string.
     262 */
    105263const char *tdb_errorstr(struct tdb_context *tdb);
     264
     265/**
     266 * @brief Fetch an entry in the database given a key.
     267 *
     268 * The caller must free the resulting data.
     269 *
     270 * @param[in]  tdb      The tdb to fetch the key.
     271 *
     272 * @param[in]  key      The key to fetch.
     273 *
     274 * @return              The key entry found in the database, NULL on error with
     275 *                      TDB_ERROR set.
     276 *
     277 * @see tdb_error()
     278 * @see tdb_errorstr()
     279 */
    106280TDB_DATA tdb_fetch(struct tdb_context *tdb, TDB_DATA key);
     281
     282/**
     283 * @brief Hand a record to a parser function without allocating it.
     284 *
     285 * This function is meant as a fast tdb_fetch alternative for large records
     286 * that are frequently read. The "key" and "data" arguments point directly
     287 * into the tdb shared memory, they are not aligned at any boundary.
     288 *
     289 * @warning The parser is called while tdb holds a lock on the record. DO NOT
     290 * call other tdb routines from within the parser. Also, for good performance
     291 * you should make the parser fast to allow parallel operations.
     292 *
     293 * @param[in]  tdb      The tdb to parse the record.
     294 *
     295 * @param[in]  key      The key to parse.
     296 *
     297 * @param[in]  parser   The parser to use to parse the data.
     298 *
     299 * @param[in]  private_data A private data pointer which is passed to the parser
     300 *                          function.
     301 *
     302 * @return              -1 if the record was not found. If the record was found,
     303 *                      the return value of "parser" is passed up to the caller.
     304 */
    107305int tdb_parse_record(struct tdb_context *tdb, TDB_DATA key,
    108                      int (*parser)(TDB_DATA key, TDB_DATA data,
    109                                    void *private_data),
    110                      void *private_data);
     306                              int (*parser)(TDB_DATA key, TDB_DATA data,
     307                                            void *private_data),
     308                              void *private_data);
     309
     310/**
     311 * @brief Delete an entry in the database given a key.
     312 *
     313 * @param[in]  tdb      The tdb to delete the key.
     314 *
     315 * @param[in]  key      The key to delete.
     316 *
     317 * @return              0 on success, -1 if the key doesn't exist.
     318 */
    111319int tdb_delete(struct tdb_context *tdb, TDB_DATA key);
     320
     321/**
     322 * @brief Store an element in the database.
     323 *
     324 * This replaces any existing element with the same key.
     325 *
     326 * @param[in]  tdb      The tdb to store the entry.
     327 *
     328 * @param[in]  key      The key to use to store the entry.
     329 *
     330 * @param[in]  dbuf     The data to store under the key.
     331 *
     332 * @param[in]  flag     The flags to store the key:\n\n
     333 *                      TDB_INSERT: Don't overwrite an existing entry.\n
     334 *                      TDB_MODIFY: Don't create a new entry\n
     335 *
     336 * @return              0 on success, -1 on error with error code set.
     337 *
     338 * @see tdb_error()
     339 * @see tdb_errorstr()
     340 */
    112341int tdb_store(struct tdb_context *tdb, TDB_DATA key, TDB_DATA dbuf, int flag);
     342
     343/**
     344 * @brief Append data to an entry.
     345 *
     346 * If the entry doesn't exist, it will create a new one.
     347 *
     348 * @param[in]  tdb      The database to use.
     349 *
     350 * @param[in]  key      The key to append the data.
     351 *
     352 * @param[in]  new_dbuf The data to append to the key.
     353 *
     354 * @return              0 on success, -1 on error with error code set.
     355 *
     356 * @see tdb_error()
     357 * @see tdb_errorstr()
     358 */
    113359int tdb_append(struct tdb_context *tdb, TDB_DATA key, TDB_DATA new_dbuf);
     360
     361/**
     362 * @brief Close a database.
     363 *
     364 * @param[in]  tdb      The database to close.
     365 *
     366 * @return              0 for success, -1 on error.
     367 */
    114368int tdb_close(struct tdb_context *tdb);
     369
     370/**
     371 * @brief Find the first entry in the database and return its key.
     372 *
     373 * The caller must free the returned data.
     374 *
     375 * @param[in]  tdb      The database to use.
     376 *
     377 * @return              The first entry of the database, an empty TDB_DATA entry
     378 *                      if the database is empty.
     379 */
    115380TDB_DATA tdb_firstkey(struct tdb_context *tdb);
     381
     382/**
     383 * @brief Find the next entry in the database, returning its key.
     384 *
     385 * The caller must free the returned data.
     386 *
     387 * @param[in]  tdb      The database to use.
     388 *
     389 * @param[in]  key      The key from which you want the next key.
     390 *
     391 * @return              The next entry of the current key, an empty TDB_DATA
     392 *                      entry if there is no entry.
     393 */
    116394TDB_DATA tdb_nextkey(struct tdb_context *tdb, TDB_DATA key);
    117 int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *);
    118 int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *);
     395
     396/**
     397 * @brief Traverse the entire database.
     398 *
     399 * While travering the function fn(tdb, key, data, state) is called on each
     400 * element. If fn is NULL then it is not called. A non-zero return value from
     401 * fn() indicates that the traversal should stop. Traversal callbacks may not
     402 * start transactions.
     403 *
     404 * @warning The data buffer given to the callback fn does NOT meet the alignment
     405 * restrictions malloc gives you.
     406 *
     407 * @param[in]  tdb      The database to traverse.
     408 *
     409 * @param[in]  fn       The function to call on each entry.
     410 *
     411 * @param[in]  private_data The private data which should be passed to the
     412 *                          traversing function.
     413 *
     414 * @return              The record count traversed, -1 on error.
     415 */
     416int tdb_traverse(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data);
     417
     418/**
     419 * @brief Traverse the entire database.
     420 *
     421 * While traversing the database the function fn(tdb, key, data, state) is
     422 * called on each element, but marking the database read only during the
     423 * traversal, so any write operations will fail. This allows tdb to use read
     424 * locks, which increases the parallelism possible during the traversal.
     425 *
     426 * @param[in]  tdb      The database to traverse.
     427 *
     428 * @param[in]  fn       The function to call on each entry.
     429 *
     430 * @param[in]  private_data The private data which should be passed to the
     431 *                          traversing function.
     432 *
     433 * @return              The record count traversed, -1 on error.
     434 */
     435int tdb_traverse_read(struct tdb_context *tdb, tdb_traverse_func fn, void *private_data);
     436
     437/**
     438 * @brief Check if an entry in the database exists.
     439 *
     440 * @note 1 is returned if the key is found and 0 is returned if not found this
     441 * doesn't match the conventions in the rest of this module, but is compatible
     442 * with gdbm.
     443 *
     444 * @param[in]  tdb      The database to check if the entry exists.
     445 *
     446 * @param[in]  key      The key to check if the entry exists.
     447 *
     448 * @return              1 if the key is found, 0 if not.
     449 */
    119450int tdb_exists(struct tdb_context *tdb, TDB_DATA key);
     451
     452/**
     453 * @brief Lock entire database with a write lock.
     454 *
     455 * @param[in]  tdb      The database to lock.
     456 *
     457 * @return              0 on success, -1 on error with error code set.
     458 *
     459 * @see tdb_error()
     460 * @see tdb_errorstr()
     461 */
    120462int tdb_lockall(struct tdb_context *tdb);
     463
     464/**
     465 * @brief Lock entire database with a write lock.
     466 *
     467 * This is the non-blocking call.
     468 *
     469 * @param[in]  tdb      The database to lock.
     470 *
     471 * @return              0 on success, -1 on error with error code set.
     472 *
     473 * @see tdb_lockall()
     474 * @see tdb_error()
     475 * @see tdb_errorstr()
     476 */
    121477int tdb_lockall_nonblock(struct tdb_context *tdb);
     478
     479/**
     480 * @brief Unlock entire database with write lock.
     481 *
     482 * @param[in]  tdb      The database to unlock.
     483 *
     484 * @return              0 on success, -1 on error with error code set.
     485 *
     486 * @see tdb_lockall()
     487 * @see tdb_error()
     488 * @see tdb_errorstr()
     489 */
    122490int tdb_unlockall(struct tdb_context *tdb);
     491
     492/**
     493 * @brief Lock entire database with a read lock.
     494 *
     495 * @param[in]  tdb      The database to lock.
     496 *
     497 * @return              0 on success, -1 on error with error code set.
     498 *
     499 * @see tdb_error()
     500 * @see tdb_errorstr()
     501 */
    123502int tdb_lockall_read(struct tdb_context *tdb);
     503
     504/**
     505 * @brief Lock entire database with a read lock.
     506 *
     507 * This is the non-blocking call.
     508 *
     509 * @param[in]  tdb      The database to lock.
     510 *
     511 * @return              0 on success, -1 on error with error code set.
     512 *
     513 * @see tdb_lockall_read()
     514 * @see tdb_error()
     515 * @see tdb_errorstr()
     516 */
    124517int tdb_lockall_read_nonblock(struct tdb_context *tdb);
     518
     519/**
     520 * @brief Unlock entire database with read lock.
     521 *
     522 * @param[in]  tdb      The database to unlock.
     523 *
     524 * @return              0 on success, -1 on error with error code set.
     525 *
     526 * @see tdb_lockall_read()
     527 * @see tdb_error()
     528 * @see tdb_errorstr()
     529 */
    125530int tdb_unlockall_read(struct tdb_context *tdb);
     531
     532/**
     533 * @brief Lock entire database with write lock - mark only.
     534 *
     535 * @todo Add more details.
     536 *
     537 * @param[in]  tdb      The database to mark.
     538 *
     539 * @return              0 on success, -1 on error with error code set.
     540 *
     541 * @see tdb_error()
     542 * @see tdb_errorstr()
     543 */
    126544int tdb_lockall_mark(struct tdb_context *tdb);
     545
     546/**
     547 * @brief Lock entire database with write lock - unmark only.
     548 *
     549 * @todo Add more details.
     550 *
     551 * @param[in]  tdb      The database to mark.
     552 *
     553 * @return              0 on success, -1 on error with error code set.
     554 *
     555 * @see tdb_error()
     556 * @see tdb_errorstr()
     557 */
    127558int tdb_lockall_unmark(struct tdb_context *tdb);
     559
     560/**
     561 * @brief Get the name of the current tdb file.
     562 *
     563 * This is useful for external logging functions.
     564 *
     565 * @param[in]  tdb      The database to get the name from.
     566 *
     567 * @return              The name of the database.
     568 */
    128569const char *tdb_name(struct tdb_context *tdb);
     570
     571/**
     572 * @brief Get the underlying file descriptor being used by tdb.
     573 *
     574 * This is useful for external routines that want to check the device/inode
     575 * of the fd.
     576 *
     577 * @param[in]  tdb      The database to get the fd from.
     578 *
     579 * @return              The file descriptor or -1.
     580 */
    129581int tdb_fd(struct tdb_context *tdb);
     582
     583/**
     584 * @brief Get the current logging function.
     585 *
     586 * This is useful for external tdb routines that wish to log tdb errors.
     587 *
     588 * @param[in]  tdb      The database to get the logging function from.
     589 *
     590 * @return              The logging function of the database.
     591 *
     592 * @see tdb_get_logging_private()
     593 */
    130594tdb_log_func tdb_log_fn(struct tdb_context *tdb);
     595
     596/**
     597 * @brief Get the private data of the logging function.
     598 *
     599 * @param[in]  tdb      The database to get the data from.
     600 *
     601 * @return              The private data pointer of the logging function.
     602 *
     603 * @see tdb_log_fn()
     604 */
    131605void *tdb_get_logging_private(struct tdb_context *tdb);
     606
     607/**
     608 * @brief Start a transaction.
     609 *
     610 * All operations after the transaction start can either be committed with
     611 * tdb_transaction_commit() or cancelled with tdb_transaction_cancel().
     612 *
     613 * If you call tdb_transaction_start() again on the same tdb context while a
     614 * transaction is in progress, then the same transaction buffer is re-used. The
     615 * number of tdb_transaction_{commit,cancel} operations must match the number
     616 * of successful tdb_transaction_start() calls.
     617 *
     618 * Note that transactions are by default disk synchronous, and use a recover
     619 * area in the database to automatically recover the database on the next open
     620 * if the system crashes during a transaction. You can disable the synchronous
     621 * transaction recovery setup using the TDB_NOSYNC flag, which will greatly
     622 * speed up operations at the risk of corrupting your database if the system
     623 * crashes.
     624 *
     625 * Operations made within a transaction are not visible to other users of the
     626 * database until a successful commit.
     627 *
     628 * @param[in]  tdb      The database to start the transaction.
     629 *
     630 * @return              0 on success, -1 on error with error code set.
     631 *
     632 * @see tdb_error()
     633 * @see tdb_errorstr()
     634 */
    132635int tdb_transaction_start(struct tdb_context *tdb);
     636
     637/**
     638 * @brief Start a transaction, non-blocking.
     639 *
     640 * @param[in]  tdb      The database to start the transaction.
     641 *
     642 * @return              0 on success, -1 on error with error code set.
     643 *
     644 * @see tdb_error()
     645 * @see tdb_errorstr()
     646 * @see tdb_transaction_start()
     647 */
     648int tdb_transaction_start_nonblock(struct tdb_context *tdb);
     649
     650/**
     651 * @brief Prepare to commit a current transaction, for two-phase commits.
     652 *
     653 * Once prepared for commit, the only allowed calls are tdb_transaction_commit()
     654 * or tdb_transaction_cancel(). Preparing allocates disk space for the pending
     655 * updates, so a subsequent commit should succeed (barring any hardware
     656 * failures).
     657 *
     658 * @param[in]  tdb      The database to prepare the commit.
     659 *
     660 * @return              0 on success, -1 on error with error code set.
     661 *
     662 * @see tdb_error()
     663 * @see tdb_errorstr()
     664 */
    133665int tdb_transaction_prepare_commit(struct tdb_context *tdb);
     666
     667/**
     668 * @brief Commit a current transaction.
     669 *
     670 * This updates the database and releases the current transaction locks.
     671 *
     672 * @param[in]  tdb      The database to commit the transaction.
     673 *
     674 * @return              0 on success, -1 on error with error code set.
     675 *
     676 * @see tdb_error()
     677 * @see tdb_errorstr()
     678 */
    134679int tdb_transaction_commit(struct tdb_context *tdb);
     680
     681/**
     682 * @brief Cancel a current transaction.
     683 *
     684 * This discards all write and lock operations that have been made since the
     685 * transaction started.
     686 *
     687 * @param[in]  tdb      The tdb to cancel the transaction on.
     688 *
     689 * @return              0 on success, -1 on error with error code set.
     690 *
     691 * @see tdb_error()
     692 * @see tdb_errorstr()
     693 */
    135694int tdb_transaction_cancel(struct tdb_context *tdb);
    136 int tdb_transaction_recover(struct tdb_context *tdb);
     695
     696/**
     697 * @brief Get the tdb sequence number.
     698 *
     699 * Only makes sense if the writers opened with TDB_SEQNUM set. Note that this
     700 * sequence number will wrap quite quickly, so it should only be used for a
     701 * 'has something changed' test, not for code that relies on the count of the
     702 * number of changes made. If you want a counter then use a tdb record.
     703 *
     704 * The aim of this sequence number is to allow for a very lightweight test of a
     705 * possible tdb change.
     706 *
     707 * @param[in]  tdb      The database to get the sequence number from.
     708 *
     709 * @return              The sequence number or 0.
     710 *
     711 * @see tdb_open()
     712 * @see tdb_enable_seqnum()
     713 */
    137714int tdb_get_seqnum(struct tdb_context *tdb);
     715
     716/**
     717 * @brief Get the hash size.
     718 *
     719 * @param[in]  tdb      The database to get the hash size from.
     720 *
     721 * @return              The hash size.
     722 */
    138723int tdb_hash_size(struct tdb_context *tdb);
     724
     725/**
     726 * @brief Get the map size.
     727 *
     728 * @param[in]  tdb     The database to get the map size from.
     729 *
     730 * @return             The map size.
     731 */
    139732size_t tdb_map_size(struct tdb_context *tdb);
     733
     734/**
     735 * @brief Get the tdb flags set during open.
     736 *
     737 * @param[in]  tdb      The database to get the flags form.
     738 *
     739 * @return              The flags set to on the database.
     740 */
    140741int tdb_get_flags(struct tdb_context *tdb);
     742
     743/**
     744 * @brief Add flags to the database.
     745 *
     746 * @param[in]  tdb      The database to add the flags.
     747 *
     748 * @param[in]  flag     The tdb flags to add.
     749 */
    141750void tdb_add_flags(struct tdb_context *tdb, unsigned flag);
     751
     752/**
     753 * @brief Remove flags from the database.
     754 *
     755 * @param[in]  tdb      The database to remove the flags.
     756 *
     757 * @param[in]  flag     The tdb flags to remove.
     758 */
    142759void tdb_remove_flags(struct tdb_context *tdb, unsigned flag);
     760
     761/**
     762 * @brief Enable sequence number handling on an open tdb.
     763 *
     764 * @param[in]  tdb      The database to enable sequence number handling.
     765 *
     766 * @see tdb_get_seqnum()
     767 */
    143768void tdb_enable_seqnum(struct tdb_context *tdb);
     769
     770/**
     771 * @brief Increment the tdb sequence number.
     772 *
     773 * This only works if the tdb has been opened using the TDB_SEQNUM flag or
     774 * enabled useing tdb_enable_seqnum().
     775 *
     776 * @param[in]  tdb      The database to increment the sequence number.
     777 *
     778 * @see tdb_enable_seqnum()
     779 * @see tdb_get_seqnum()
     780 */
    144781void tdb_increment_seqnum_nonblock(struct tdb_context *tdb);
     782
     783/**
     784 * @brief Create a hash of the key.
     785 *
     786 * @param[in]  key      The key to hash
     787 *
     788 * @return              The hash.
     789 */
     790unsigned int tdb_jenkins_hash(TDB_DATA *key);
     791
     792/**
     793 * @brief Check the consistency of the database.
     794 *
     795 * This check the consistency of the database calling back the check function
     796 * (if non-NULL) on each record.  If some consistency check fails, or the
     797 * supplied check function returns -1, tdb_check returns -1, otherwise 0.
     798 *
     799 * @note The logging function (if set) will be called with additional
     800 * information on the corruption found.
     801 *
     802 * @param[in]  tdb      The database to check.
     803 *
     804 * @param[in]  check    The check function to use.
     805 *
     806 * @param[in]  private_data the private data to pass to the check function.
     807 *
     808 * @return              0 on success, -1 on error with error code set.
     809 *
     810 * @see tdb_error()
     811 * @see tdb_errorstr()
     812 */
    145813int tdb_check(struct tdb_context *tdb,
    146814              int (*check) (TDB_DATA key, TDB_DATA data, void *private_data),
    147815              void *private_data);
     816
     817/* @} ******************************************************************/
    148818
    149819/* Low level locking functions: use with care */
     
    167837int tdb_validate_freelist(struct tdb_context *tdb, int *pnum_entries);
    168838int tdb_freelist_size(struct tdb_context *tdb);
     839char *tdb_summary(struct tdb_context *tdb);
    169840
    170841extern TDB_DATA tdb_null;
  • vendor/current/lib/tdb/libtdb.m4

    r414 r740  
    1414fi
    1515TDB_OBJ="common/tdb.o common/dump.o common/transaction.o common/error.o common/traverse.o"
    16 TDB_OBJ="$TDB_OBJ common/freelist.o common/freelistcheck.o common/io.o common/lock.o common/open.o common/check.o"
     16TDB_OBJ="$TDB_OBJ common/freelist.o common/freelistcheck.o common/io.o common/lock.o common/open.o common/check.o common/hash.o common/summary.o"
    1717AC_SUBST(TDB_OBJ)
    1818AC_SUBST(LIBREPLACEOBJ)
     
    2020TDB_LIBS=""
    2121AC_SUBST(TDB_LIBS)
     22
     23TDB_DEPS=""
     24if test x$libreplace_cv_HAVE_FDATASYNC_IN_LIBRT = xyes ; then
     25        TDB_DEPS="$TDB_DEPS -lrt"
     26fi
     27AC_SUBST(TDB_DEPS)
    2228
    2329TDB_CFLAGS="-I$tdbdir/include"
  • vendor/current/lib/tdb/manpages/tdbbackup.8.xml

    r414 r740  
    11<?xml version="1.0" encoding="iso-8859-1"?>
    2 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
     2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
    33<refentry id="tdbbackup.8">
    44
     
    88        <refmiscinfo class="source">Samba</refmiscinfo>
    99        <refmiscinfo class="manual">System Administration tools</refmiscinfo>
    10         <refmiscinfo class="version">3.5</refmiscinfo>
     10        <refmiscinfo class="version">3.6</refmiscinfo>
    1111</refmeta>
    1212
  • vendor/current/lib/tdb/manpages/tdbdump.8.xml

    r414 r740  
    11<?xml version="1.0" encoding="iso-8859-1"?>
    2 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
     2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
    33<refentry id="tdbdump.8">
    44
     
    88        <refmiscinfo class="source">Samba</refmiscinfo>
    99        <refmiscinfo class="manual">System Administration tools</refmiscinfo>
    10         <refmiscinfo class="version">3.5</refmiscinfo>
     10        <refmiscinfo class="version">3.6</refmiscinfo>
    1111</refmeta>
    1212
  • vendor/current/lib/tdb/manpages/tdbtool.8.xml

    r414 r740  
    11<?xml version="1.0" encoding="iso-8859-1"?>
    2 <!DOCTYPE refentry PUBLIC "-//Samba-Team//DTD DocBook V4.2-Based Variant V1.0//EN" "http://www.samba.org/samba/DTD/samba-doc">
     2<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
    33<refentry id="tdbtool.8">
    44
     
    88        <refmiscinfo class="source">Samba</refmiscinfo>
    99        <refmiscinfo class="manual">System Administration tools</refmiscinfo>
    10         <refmiscinfo class="version">3.5</refmiscinfo>
     10        <refmiscinfo class="version">3.6</refmiscinfo>
    1111</refmeta>
    1212
  • vendor/current/lib/tdb/pytdb.c

    r414 r740  
    1010     ** library. This does NOT imply that all of Samba is released
    1111     ** under the LGPL
    12    
     12
    1313   This library is free software; you can redistribute it and/or
    1414   modify it under the terms of the GNU Lesser General Public
     
    2525*/
    2626
     27#include <Python.h>
    2728#include "replace.h"
    2829#include "system/filesys.h"
    2930
    30 #include <Python.h>
    3131#ifndef Py_RETURN_NONE
    3232#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
     
    4242} PyTdbObject;
    4343
    44 PyAPI_DATA(PyTypeObject) PyTdb;
     44staticforward PyTypeObject PyTdb;
    4545
    4646static void PyErr_SetTDBError(TDB_CONTEXT *tdb)
     
    7878static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    7979{
    80         char *name;
     80        char *name = NULL;
    8181        int hash_size = 0, tdb_flags = TDB_DEFAULT, flags = O_RDWR, mode = 0600;
    8282        TDB_CONTEXT *ctx;
     
    8484        const char *kwnames[] = { "name", "hash_size", "tdb_flags", "flags", "mode", NULL };
    8585
    86         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", (char **)kwnames, &name, &hash_size, &tdb_flags, &flags, &mode))
    87                 return NULL;
     86        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|siiii", (char **)kwnames, &name, &hash_size, &tdb_flags, &flags, &mode))
     87                return NULL;
     88
     89        if (name == NULL) {
     90                tdb_flags |= TDB_INTERNAL;
     91        }
    8892
    8993        ctx = tdb_open(name, hash_size, tdb_flags, flags, mode);
     
    9498
    9599        ret = PyObject_New(PyTdbObject, &PyTdb);
     100        if (!ret) {
     101                tdb_close(ctx);
     102                return NULL;
     103        }
     104
    96105        ret->ctx = ctx;
    97106        ret->closed = false;
     
    113122}
    114123
    115 static PyObject *obj_transaction_recover(PyTdbObject *self)
    116 {
    117         int ret = tdb_transaction_recover(self->ctx);
     124static PyObject *obj_transaction_prepare_commit(PyTdbObject *self)
     125{
     126        int ret = tdb_transaction_prepare_commit(self->ctx);
    118127        PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
    119128        Py_RETURN_NONE;
     
    267276}
    268277
     278static PyObject *obj_add_flags(PyTdbObject *self, PyObject *args)
     279{
     280        unsigned flags;
     281
     282        if (!PyArg_ParseTuple(args, "I", &flags))
     283                return NULL;
     284
     285        tdb_add_flags(self->ctx, flags);
     286        Py_RETURN_NONE;
     287}
     288
     289static PyObject *obj_remove_flags(PyTdbObject *self, PyObject *args)
     290{
     291        unsigned flags;
     292
     293        if (!PyArg_ParseTuple(args, "I", &flags))
     294                return NULL;
     295
     296        tdb_remove_flags(self->ctx, flags);
     297        Py_RETURN_NONE;
     298}
    269299
    270300typedef struct {
     
    306336
    307337        ret = PyObject_New(PyTdbIteratorObject, &PyTdbIterator);
     338        if (!ret)
     339                return NULL;
    308340        ret->current = tdb_firstkey(self->ctx);
    309341        ret->iteratee = self;
     
    316348        int ret = tdb_wipe_all(self->ctx);
    317349        PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
     350        Py_RETURN_NONE;
     351}
     352
     353static PyObject *obj_repack(PyTdbObject *self)
     354{
     355        int ret = tdb_repack(self->ctx);
     356        PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx);
     357        Py_RETURN_NONE;
     358}
     359
     360static PyObject *obj_enable_seqnum(PyTdbObject *self)
     361{
     362        tdb_enable_seqnum(self->ctx);
     363        Py_RETURN_NONE;
     364}
     365
     366static PyObject *obj_increment_seqnum_nonblock(PyTdbObject *self)
     367{
     368        tdb_increment_seqnum_nonblock(self->ctx);
    318369        Py_RETURN_NONE;
    319370}
     
    326377                "S.transaction_commit() -> None\n"
    327378                "Commit the currently active transaction." },
    328         { "transaction_recover", (PyCFunction)obj_transaction_recover, METH_NOARGS,
    329                 "S.transaction_recover() -> None\n"
    330                 "Recover the currently active transaction." },
     379        { "transaction_prepare_commit", (PyCFunction)obj_transaction_prepare_commit, METH_NOARGS,
     380                "S.transaction_prepare_commit() -> None\n"
     381                "Prepare to commit the currently active transaction" },
    331382        { "transaction_start", (PyCFunction)obj_transaction_start, METH_NOARGS,
    332383                "S.transaction_start() -> None\n"
     
    352403        { "store", (PyCFunction)obj_store, METH_VARARGS, "S.store(key, data, flag=REPLACE) -> None"
    353404                "Store data." },
     405        { "add_flags", (PyCFunction)obj_add_flags, METH_VARARGS, "S.add_flags(flags) -> None" },
     406        { "remove_flags", (PyCFunction)obj_remove_flags, METH_VARARGS, "S.remove_flags(flags) -> None" },
    354407        { "iterkeys", (PyCFunction)tdb_object_iter, METH_NOARGS, "S.iterkeys() -> iterator" },
    355408        { "clear", (PyCFunction)obj_clear, METH_NOARGS, "S.clear() -> None\n"
    356409                "Wipe the entire database." },
     410        { "repack", (PyCFunction)obj_repack, METH_NOARGS, "S.repack() -> None\n"
     411                "Repack the entire database." },
     412        { "enable_seqnum", (PyCFunction)obj_enable_seqnum, METH_NOARGS,
     413                "S.enable_seqnum() -> None" },
     414        { "increment_seqnum_nonblock", (PyCFunction)obj_increment_seqnum_nonblock, METH_NOARGS,
     415                "S.increment_seqnum_nonblock() -> None" },
    357416        { NULL }
    358417};
     
    376435}
    377436
     437static PyObject *obj_get_freelist_size(PyTdbObject *self, void *closure)
     438{
     439        return PyInt_FromLong(tdb_freelist_size(self->ctx));
     440}
     441
    378442static PyObject *obj_get_flags(PyTdbObject *self, void *closure)
    379443{
     
    385449        return PyString_FromString(tdb_name(self->ctx));
    386450}
     451
     452static PyObject *obj_get_seqnum(PyTdbObject *self, void *closure)
     453{
     454        return PyInt_FromLong(tdb_get_seqnum(self->ctx));
     455}
     456
    387457
    388458static PyGetSetDef tdb_object_getsetters[] = {
    389459        { (char *)"hash_size", (getter)obj_get_hash_size, NULL, NULL },
    390460        { (char *)"map_size", (getter)obj_get_map_size, NULL, NULL },
     461        { (char *)"freelist_size", (getter)obj_get_freelist_size, NULL, NULL },
    391462        { (char *)"flags", (getter)obj_get_flags, NULL, NULL },
    392463        { (char *)"max_dead", NULL, (setter)obj_set_max_dead, NULL },
    393464        { (char *)"filename", (getter)obj_get_filename, NULL, (char *)"The filename of this TDB file."},
     465        { (char *)"seqnum", (getter)obj_get_seqnum, NULL, NULL },
    394466        { NULL }
    395467};
     
    397469static PyObject *tdb_object_repr(PyTdbObject *self)
    398470{
    399         return PyString_FromFormat("Tdb('%s')", tdb_name(self->ctx));
     471        if (tdb_get_flags(self->ctx) & TDB_INTERNAL) {
     472                return PyString_FromString("Tdb(<internal>)");
     473        } else {
     474                return PyString_FromFormat("Tdb('%s')", tdb_name(self->ctx));
     475        }
    400476}
    401477
     
    404480        if (!self->closed)
    405481                tdb_close(self->ctx);
    406         PyObject_Del(self);
     482        self->ob_type->tp_free(self);
    407483}
    408484
     
    463539        .mp_ass_subscript = (objobjargproc)obj_setitem,
    464540};
    465 PyTypeObject PyTdb = {
     541static PyTypeObject PyTdb = {
    466542        .tp_name = "Tdb",
    467543        .tp_basicsize = sizeof(PyTdbObject),
     
    483559};
    484560
     561void inittdb(void);
    485562void inittdb(void)
    486563{
     
    508585        PyModule_AddObject(m, "CONVERT", PyInt_FromLong(TDB_CONVERT));
    509586        PyModule_AddObject(m, "BIGENDIAN", PyInt_FromLong(TDB_BIGENDIAN));
     587        PyModule_AddObject(m, "NOSYNC", PyInt_FromLong(TDB_NOSYNC));
     588        PyModule_AddObject(m, "SEQNUM", PyInt_FromLong(TDB_SEQNUM));
     589        PyModule_AddObject(m, "VOLATILE", PyInt_FromLong(TDB_VOLATILE));
     590        PyModule_AddObject(m, "ALLOW_NESTING", PyInt_FromLong(TDB_ALLOW_NESTING));
     591        PyModule_AddObject(m, "DISALLOW_NESTING", PyInt_FromLong(TDB_DISALLOW_NESTING));
     592        PyModule_AddObject(m, "INCOMPATIBLE_HASH", PyInt_FromLong(TDB_INCOMPATIBLE_HASH));
     593
    510594        PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
     595
     596        PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
    511597
    512598        Py_INCREF(&PyTdb);
  • vendor/current/lib/tdb/python/tdbdump.py

    r414 r740  
    1 #!/usr/bin/python
     1#!/usr/bin/env python
    22# Trivial reimplementation of tdbdump in Python
    33
  • vendor/current/lib/tdb/python/tests/simple.py

    r414 r740  
    1 #!/usr/bin/python
     1#!/usr/bin/env python
    22# Some simple tests for the Python bindings for TDB
    33# Note that this tests the interface of the Python bindings
     
    1313
    1414class OpenTdbTests(TestCase):
     15
    1516    def test_nonexistant_read(self):
    16         self.assertRaises(IOError, tdb.Tdb, "/some/nonexistant/file", 0, tdb.DEFAULT, os.O_RDWR)
     17        self.assertRaises(IOError, tdb.Tdb, "/some/nonexistant/file", 0,
     18                tdb.DEFAULT, os.O_RDWR)
    1719
    1820class CloseTdbTests(TestCase):
     21
    1922    def test_double_close(self):
    20         self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, os.O_CREAT|os.O_RDWR)
     23        self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT,
     24                os.O_CREAT|os.O_RDWR)
    2125        self.assertNotEqual(None, self.tdb)
    2226
     
    2630
    2731
     32class InternalTdbTests(TestCase):
     33
     34    def test_repr(self):
     35        self.tdb = tdb.Tdb()
     36
     37        # repr used to crash on internal db
     38        self.assertEquals(repr(self.tdb), "Tdb(<internal>)")
     39
     40
    2841class SimpleTdbTests(TestCase):
     42
    2943    def setUp(self):
    3044        super(SimpleTdbTests, self).setUp()
    31         self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT, os.O_CREAT|os.O_RDWR)
     45        self.tdb = tdb.Tdb(tempfile.mkstemp()[1], 0, tdb.DEFAULT,
     46                os.O_CREAT|os.O_RDWR)
    3247        self.assertNotEqual(None, self.tdb)
    3348
     
    8297        self.tdb.map_size
    8398
     99    def test_freelist_size(self):
     100        self.tdb.freelist_size
     101
    84102    def test_name(self):
    85103        self.tdb.filename
     
    104122        self.assertEquals("1", self.tdb["bloe"])
    105123
    106     def test_iterator(self):
     124    def test_transaction_prepare_commit(self):
    107125        self.tdb["bloe"] = "2"
    108         self.tdb["bla"] = "hoi"
    109         i = iter(self.tdb)
    110         self.assertEquals(set(["bloe", "bla"]), set([i.next(), i.next()]))
     126        self.tdb.transaction_start()
     127        self.tdb["bloe"] = "1"
     128        self.tdb.transaction_prepare_commit()
     129        self.tdb.transaction_commit()
     130        self.assertEquals("1", self.tdb["bloe"])
    111131
    112132    def test_iterkeys(self):
     
    123143        self.assertEquals(0, len(list(self.tdb)))
    124144
     145    def test_repack(self):
     146        self.tdb["foo"] = "abc"
     147        self.tdb["bar"] = "def"
     148        del self.tdb["foo"]
     149        self.tdb.repack()
     150
     151    def test_seqnum(self):
     152        self.tdb.enable_seqnum()
     153        seq1 = self.tdb.seqnum
     154        self.tdb.increment_seqnum_nonblock()
     155        seq2 = self.tdb.seqnum
     156        self.assertEquals(seq2-seq1, 1)
     157
    125158    def test_len(self):
    126159        self.assertEquals(0, len(list(self.tdb)))
     
    128161        self.assertEquals(1, len(list(self.tdb)))
    129162
     163    def test_add_flags(self):
     164        self.tdb.add_flags(tdb.NOMMAP)
     165        self.tdb.remove_flags(tdb.NOMMAP)
     166
     167
     168class VersionTests(TestCase):
     169
     170    def test_present(self):
     171        self.assertTrue(isinstance(tdb.__version__, str))
     172
    130173
    131174if __name__ == '__main__':
  • vendor/current/lib/tdb/tdb.pc.in

    r414 r740  
    77Description: A trivial database
    88Version: @PACKAGE_VERSION@
    9 Libs: -L${libdir} -ltdb
     9Libs: @LIB_RPATH@ -L${libdir} -ltdb
    1010Cflags: -I${includedir}
    1111URL: http://tdb.samba.org/
  • vendor/current/lib/tdb/tools/tdbbackup.c

    r414 r740  
    153153        }
    154154
    155         if (tdb_transaction_start(tdb_new) != 0) {
    156                 printf("Failed to start transaction on new tdb\n");
     155        /* lock the backup tdb so that nobody else can change it */
     156        if (tdb_lockall(tdb_new) != 0) {
     157                printf("Failed to lock backup tdb\n");
    157158                tdb_close(tdb);
    158159                tdb_close(tdb_new);
     
    178179        tdb_close(tdb);
    179180
    180         if (tdb_transaction_commit(tdb_new) != 0) {
    181                 fprintf(stderr, "Failed to commit new tdb\n");
    182                 tdb_close(tdb_new);
    183                 unlink(tmp_name);
    184                 free(tmp_name);         
    185                 return 1;
     181        /* copy done, unlock the backup tdb */
     182        tdb_unlockall(tdb_new);
     183
     184#ifdef HAVE_FDATASYNC
     185        if (fdatasync(tdb_fd(tdb_new)) != 0) {
     186#else
     187        if (fsync(tdb_fd(tdb_new)) != 0) {
     188#endif
     189                /* not fatal */
     190                fprintf(stderr, "failed to fsync backup file\n");
    186191        }
    187192
  • vendor/current/lib/tdb/tools/tdbtest.c

    r414 r740  
    216216}
    217217
     218static char *test_path(const char *filename)
     219{
     220        const char *prefix = getenv("TEST_DATA_PREFIX");
     221
     222        if (prefix) {
     223                char *path = NULL;
     224                int ret;
     225
     226                ret = asprintf(&path, "%s/%s", prefix, filename);
     227                if (ret == -1) {
     228                        return NULL;
     229                }
     230                return path;
     231        }
     232
     233        return strdup(filename);
     234}
     235
    218236 int main(int argc, const char *argv[])
    219237{
     
    221239        int loops = 10000;
    222240        int num_entries;
    223         char test_gdbm[] = "test.gdbm";
    224 
    225         unlink("test.gdbm");
    226 
    227         db = tdb_open("test.tdb", 0, TDB_CLEAR_IF_FIRST,
     241        char test_gdbm[1] = "test.gdbm";
     242        char *test_tdb;
     243
     244        test_gdbm[0] = test_path("test.gdbm");
     245        test_tdb = test_path("test.tdb");
     246
     247        unlink(test_gdbm[0]);
     248
     249        db = tdb_open(test_tdb, 0, TDB_CLEAR_IF_FIRST,
    228250                      O_RDWR | O_CREAT | O_TRUNC, 0600);
    229251        gdbm = gdbm_open(test_gdbm, 512, GDBM_WRITER|GDBM_NEWDB|GDBM_FAST,
     
    262284        gdbm_close(gdbm);
    263285
     286        free(test_gdbm[0]);
     287        free(test_tdb);
     288
    264289        return 0;
    265290}
  • vendor/current/lib/tdb/tools/tdbtool.c

    r414 r740  
    410410static void info_tdb(void)
    411411{
    412         int count;
    413         total_bytes = 0;
    414         if ((count = tdb_traverse(tdb, traverse_fn, NULL)) == -1)
     412        char *summary = tdb_summary(tdb);
     413
     414        if (!summary) {
    415415                printf("Error = %s\n", tdb_errorstr(tdb));
    416         else
    417                 printf("%d records totalling %d bytes\n", count, total_bytes);
     416        } else {
     417                printf("%s", summary);
     418                free(summary);
     419        }
    418420}
    419421
  • vendor/current/lib/tdb/tools/tdbtorture.c

    r414 r740  
    3131static int error_count;
    3232static int always_transaction = 0;
     33static int hash_size = 2;
     34static int loopnum;
     35static int count_pipe;
     36static struct tdb_logging_context log_ctx;
    3337
    3438#ifdef PRINTF_ATTRIBUTE
     
    4953        fflush(stdout);
    5054#if 0
    51         {
     55        if (level != TDB_DEBUG_TRACE) {
    5256                char *ptr;
     57                signal(SIGUSR1, SIG_IGN);
    5358                asprintf(&ptr,"xterm -e gdb /proc/%d/exe %d", getpid(), getpid());
    5459                system(ptr);
     
    212217static void usage(void)
    213218{
    214         printf("Usage: tdbtorture [-t] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
     219        printf("Usage: tdbtorture [-t] [-k] [-n NUM_PROCS] [-l NUM_LOOPS] [-s SEED] [-H HASH_SIZE]\n");
    215220        exit(0);
    216221}
    217222
    218  int main(int argc, char * const *argv)
    219 {
    220         int i, seed = -1;
    221         int num_procs = 3;
    222         int num_loops = 5000;
    223         int hash_size = 2;
    224         int c;
    225         extern char *optarg;
    226         pid_t *pids;
    227 
    228         struct tdb_logging_context log_ctx;
    229         log_ctx.log_fn = tdb_log;
    230 
    231         while ((c = getopt(argc, argv, "n:l:s:H:th")) != -1) {
    232                 switch (c) {
    233                 case 'n':
    234                         num_procs = strtol(optarg, NULL, 0);
    235                         break;
    236                 case 'l':
    237                         num_loops = strtol(optarg, NULL, 0);
    238                         break;
    239                 case 'H':
    240                         hash_size = strtol(optarg, NULL, 0);
    241                         break;
    242                 case 's':
    243                         seed = strtol(optarg, NULL, 0);
    244                         break;
    245                 case 't':
    246                         always_transaction = 1;
    247                         break;
    248                 default:
    249                         usage();
    250                 }
    251         }
    252 
    253         unlink("torture.tdb");
    254 
    255         pids = (pid_t *)calloc(sizeof(pid_t), num_procs);
    256         pids[0] = getpid();
    257 
    258         for (i=0;i<num_procs-1;i++) {
    259                 if ((pids[i+1]=fork()) == 0) break;
    260         }
    261 
    262         db = tdb_open_ex("torture.tdb", hash_size, TDB_CLEAR_IF_FIRST,
     223static void send_count_and_suicide(int sig)
     224{
     225        /* This ensures our successor can continue where we left off. */
     226        write(count_pipe, &loopnum, sizeof(loopnum));
     227        /* This gives a unique signature. */
     228        kill(getpid(), SIGUSR2);
     229}
     230
     231static int run_child(const char *filename, int i, int seed, unsigned num_loops, unsigned start)
     232{
     233        db = tdb_open_ex(filename, hash_size, TDB_DEFAULT,
    263234                         O_RDWR | O_CREAT, 0600, &log_ctx, NULL);
    264235        if (!db) {
     
    266237        }
    267238
    268         if (seed == -1) {
    269                 seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
    270         }
    271 
    272         if (i == 0) {
    273                 printf("testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
    274                        num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : "");
    275         }
    276 
    277239        srand(seed + i);
    278240        srandom(seed + i);
    279241
    280         for (i=0;i<num_loops && error_count == 0;i++) {
     242        /* Set global, then we're ready to handle being killed. */
     243        loopnum = start;
     244        signal(SIGUSR1, send_count_and_suicide);
     245
     246        for (;loopnum<num_loops && error_count == 0;loopnum++) {
    281247                addrec_db();
    282248        }
     
    302268        tdb_close(db);
    303269
    304         if (getpid() != pids[0]) {
    305                 return error_count;
    306         }
    307 
    308         for (i=1;i<num_procs;i++) {
     270        return (error_count < 100 ? error_count : 100);
     271}
     272
     273static char *test_path(const char *filename)
     274{
     275        const char *prefix = getenv("TEST_DATA_PREFIX");
     276
     277        if (prefix) {
     278                char *path = NULL;
     279                int ret;
     280
     281                ret = asprintf(&path, "%s/%s", prefix, filename);
     282                if (ret == -1) {
     283                        return NULL;
     284                }
     285                return path;
     286        }
     287
     288        return strdup(filename);
     289}
     290
     291int main(int argc, char * const *argv)
     292{
     293        int i, seed = -1;
     294        int num_loops = 5000;
     295        int num_procs = 3;
     296        int c, pfds[2];
     297        extern char *optarg;
     298        pid_t *pids;
     299        int kill_random = 0;
     300        int *done;
     301        char *test_tdb;
     302
     303        log_ctx.log_fn = tdb_log;
     304
     305        while ((c = getopt(argc, argv, "n:l:s:H:thk")) != -1) {
     306                switch (c) {
     307                case 'n':
     308                        num_procs = strtol(optarg, NULL, 0);
     309                        break;
     310                case 'l':
     311                        num_loops = strtol(optarg, NULL, 0);
     312                        break;
     313                case 'H':
     314                        hash_size = strtol(optarg, NULL, 0);
     315                        break;
     316                case 's':
     317                        seed = strtol(optarg, NULL, 0);
     318                        break;
     319                case 't':
     320                        always_transaction = 1;
     321                        break;
     322                case 'k':
     323                        kill_random = 1;
     324                        break;
     325                default:
     326                        usage();
     327                }
     328        }
     329
     330        test_tdb = test_path("torture.tdb");
     331
     332        unlink(test_tdb);
     333
     334        if (seed == -1) {
     335                seed = (getpid() + time(NULL)) & 0x7FFFFFFF;
     336        }
     337
     338        if (num_procs == 1 && !kill_random) {
     339                /* Don't fork for this case, makes debugging easier. */
     340                error_count = run_child(test_tdb, 0, seed, num_loops, 0);
     341                goto done;
     342        }
     343
     344        pids = (pid_t *)calloc(sizeof(pid_t), num_procs);
     345        done = (int *)calloc(sizeof(int), num_procs);
     346
     347        if (pipe(pfds) != 0) {
     348                perror("Creating pipe");
     349                exit(1);
     350        }
     351        count_pipe = pfds[1];
     352
     353        for (i=0;i<num_procs;i++) {
     354                if ((pids[i]=fork()) == 0) {
     355                        close(pfds[0]);
     356                        if (i == 0) {
     357                                printf("Testing with %d processes, %d loops, %d hash_size, seed=%d%s\n",
     358                                       num_procs, num_loops, hash_size, seed, always_transaction ? " (all within transactions)" : "");
     359                        }
     360                        exit(run_child(test_tdb, i, seed, num_loops, 0));
     361                }
     362        }
     363
     364        while (num_procs) {
    309365                int status, j;
    310366                pid_t pid;
     367
    311368                if (error_count != 0) {
    312369                        /* try and stop the test on any failure */
    313                         for (j=1;j<num_procs;j++) {
     370                        for (j=0;j<num_procs;j++) {
    314371                                if (pids[j] != 0) {
    315372                                        kill(pids[j], SIGTERM);
     
    317374                        }
    318375                }
    319                 pid = waitpid(-1, &status, 0);
     376
     377                pid = waitpid(-1, &status, kill_random ? WNOHANG : 0);
     378                if (pid == 0) {
     379                        struct timeval tv;
     380
     381                        /* Sleep for 1/10 second. */
     382                        tv.tv_sec = 0;
     383                        tv.tv_usec = 100000;
     384                        select(0, NULL, NULL, NULL, &tv);
     385
     386                        /* Kill someone. */
     387                        kill(pids[random() % num_procs], SIGUSR1);
     388                        continue;
     389                }
     390
    320391                if (pid == -1) {
    321392                        perror("failed to wait for child\n");
    322393                        exit(1);
    323394                }
    324                 for (j=1;j<num_procs;j++) {
     395
     396                for (j=0;j<num_procs;j++) {
    325397                        if (pids[j] == pid) break;
    326398                }
     
    329401                        exit(1);
    330402                }
    331                 if (WEXITSTATUS(status) != 0) {
    332                         printf("child %d exited with status %d\n",
    333                                (int)pid, WEXITSTATUS(status));
     403                if (WIFSIGNALED(status)) {
     404                        if (WTERMSIG(status) == SIGUSR2
     405                            || WTERMSIG(status) == SIGUSR1) {
     406                                /* SIGUSR2 means they wrote to pipe. */
     407                                if (WTERMSIG(status) == SIGUSR2) {
     408                                        read(pfds[0], &done[j],
     409                                             sizeof(done[j]));
     410                                }
     411                                pids[j] = fork();
     412                                if (pids[j] == 0)
     413                                        exit(run_child(test_tdb, j, seed,
     414                                                       num_loops, done[j]));
     415                                printf("Restarting child %i for %u-%u\n",
     416                                       j, done[j], num_loops);
     417                                continue;
     418                        }
     419                        printf("child %d exited with signal %d\n",
     420                               (int)pid, WTERMSIG(status));
    334421                        error_count++;
    335                 }
    336                 pids[j] = 0;
     422                } else {
     423                        if (WEXITSTATUS(status) != 0) {
     424                                printf("child %d exited with status %d\n",
     425                                       (int)pid, WEXITSTATUS(status));
     426                                error_count++;
     427                        }
     428                }
     429                memmove(&pids[j], &pids[j+1],
     430                        (num_procs - j - 1)*sizeof(pids[0]));
     431                num_procs--;
    337432        }
    338433
    339434        free(pids);
    340435
     436done:
    341437        if (error_count == 0) {
     438                db = tdb_open_ex(test_tdb, hash_size, TDB_DEFAULT,
     439                                 O_RDWR, 0, &log_ctx, NULL);
     440                if (!db) {
     441                        fatal("db open failed");
     442                }
     443                if (tdb_check(db, NULL, NULL) == -1) {
     444                        printf("db check failed");
     445                        exit(1);
     446                }
     447                tdb_close(db);
    342448                printf("OK\n");
    343449        }
    344450
     451        free(test_tdb);
    345452        return error_count;
    346453}
Note: See TracChangeset for help on using the changeset viewer.