Ignore:
Timestamp:
Mar 25, 2007, 1:33:05 PM (18 years ago)
Author:
Yuri Dario
Message:

Rewrote of locking code, closes ticket:4.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/samba-3.0.25pre1/source/tdb/common/lock.c

    r1 r10  
    2929#include "tdb_private.h"
    3030
     31#ifdef __OS2__
     32#define INCL_ERRORS
     33#define INCL_DOS
     34#include <os2.h>
     35#endif
     36
     37#if 0 // for debugging...
     38#include "tdb/tools/printf.c"
     39
     40#if 0
     41#define F_GETLK         7               /* get record locking information */
     42#define F_SETLK         8               /* set record locking information */
     43#define F_SETLKW        9               /* F_SETLK; wait if blocked */
     44#define F_RDLCK         1               /* shared or read lock */
     45#define F_UNLCK         2               /* unlock */
     46#define F_WRLCK         3               /* exclusive or write lock */
     47#endif
     48
     49static char* lock_type( int lck)
     50{
     51        static char buffer[16];
     52        switch(lck) {
     53        case F_GETLK: return "F_GETLK";
     54        case F_SETLK: return "F_SETLK";
     55        case F_SETLKW: return "F_SETLKW";
     56        default:
     57                sprintf( buffer, "unknown %d", lck);
     58        }
     59        return buffer;
     60}
     61static char* read_type( int rw)
     62{
     63        static char buffer[16];
     64        switch(rw) {
     65        case F_RDLCK: return "F_RDLCK";
     66        case F_UNLCK: return "F_UNLCK";
     67        case F_WRLCK: return "F_WRLCK";
     68        default:
     69                sprintf( buffer, "unknown %d", rw);
     70        }
     71        return buffer;
     72}
     73#endif
     74
     75#ifdef __OS2__
     76
     77static int _mutex_brlock(struct tdb_context *tdb, tdb_off_t offset,
     78               int rw_type, int lck_type, int probe, size_t len)
     79{
     80        HMTX    hSem;
     81        ULONG   ulTimeout;
     82        APIRET  rc;
     83       
     84        switch( offset) {
     85        case GLOBAL_LOCK:
     86                hSem = tdb->hGlobalLock;
     87                break;
     88        case ACTIVE_LOCK:
     89                hSem = tdb->hActiveLock;
     90                break;
     91        case TRANSACTION_LOCK:
     92                hSem = tdb->hTransactionLock;
     93                break;
     94        default:
     95                printf( "_mutex_brlock unknown offset %d\n", offset);
     96                exit(1);
     97        }
     98        if (hSem == 0) {
     99                printf( "_mutex_brlock unknown sem handle offset %d\n", offset);
     100                exit(1);
     101        }
     102
     103        if (lck_type == F_SETLKW)
     104                ulTimeout = SEM_INDEFINITE_WAIT;
     105        else
     106                ulTimeout = SEM_IMMEDIATE_RETURN;
     107
     108        switch (rw_type) {
     109        case F_UNLCK:
     110                rc = DosReleaseMutexSem( hSem);
     111                break;
     112        case F_RDLCK:
     113        case F_WRLCK:
     114                rc = DosRequestMutexSem( hSem, ulTimeout);
     115                break;
     116        default:
     117                printf( "_mutex_brlock unknown rw_type request %d\n", rw_type);
     118                exit(1);
     119                        break;
     120        }
     121
     122        if (rc == NO_ERROR
     123                || rc == ERROR_SEM_OWNER_DIED
     124                || rc == ERROR_NOT_OWNER)
     125                return 0;
     126
     127        errno = EINVAL;
     128#if 0
     129        debug_printf("_mutex_brlock pid %X, failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d, rc=%d\n",
     130                 getpid(), tdb->fd, offset, rw_type, lck_type, (int)len, rc);
     131#endif
     132        return TDB_ERRCODE(TDB_ERR_LOCK, -1);
     133}
     134
     135#endif
     136
    31137/* a byte range locking function - return 0 on success
    32138   this functions locks/unlocks 1 byte at the specified offset.
     
    40146               int rw_type, int lck_type, int probe, size_t len)
    41147{
     148#ifdef __OS2__
     149        APIRET      rc;
     150        ULONG       fAccess = 0;
     151        int         fLock = 0;
     152        ULONG       ulTimeout;
     153        off_t       cbFile;
     154        off_t       offStart;
     155        off_t       cbRange;
     156
     157        switch( offset) {
     158        case GLOBAL_LOCK:
     159        case ACTIVE_LOCK:
     160        case TRANSACTION_LOCK:
     161                return _mutex_brlock( tdb, offset,
     162                rw_type,  lck_type,  probe, len);
     163        }
     164
     165        if (tdb->flags & TDB_NOLOCK) {
     166                return 0;
     167        }
     168
     169        if ((rw_type == F_WRLCK) && (tdb->read_only || tdb->traverse_read)) {
     170                tdb->ecode = TDB_ERR_RDONLY;
     171                return -1;
     172        }
     173
     174#if 0
     175        debug_printf("tdb_brlock pid %X, fd %d, lck_type %s, rw_type %s, offset %d, len %d\n",
     176                getpid(), tdb->fd, lock_type(lck_type), read_type(rw_type), offset, len);
     177#endif
     178       
     179        /* flags and order */
     180        fAccess = 0; /* exclusive */
     181        switch (rw_type)
     182        {
     183                case F_UNLCK:
     184                        fLock = 0;
     185                        break;
     186                case F_RDLCK:
     187                case F_WRLCK:
     188                        fLock = 1;
     189                        break;
     190                default:
     191                        break;
     192        }
     193       
     194        if (lck_type == F_SETLKW)
     195                ulTimeout = SEM_INDEFINITE_WAIT;
     196        else
     197                ulTimeout = SEM_IMMEDIATE_RETURN;
     198       
     199        FILELOCK   aflock[2];
     200        bzero(&aflock[(fLock + 1) & 1], sizeof(aflock[0]));
     201        aflock[fLock].lOffset = offset;
     202        aflock[fLock].lRange  = len ? len : LONG_MAX;
     203        rc = DosSetFileLocks(tdb->fd, &aflock[0], &aflock[1], SEM_IMMEDIATE_RETURN, fAccess);
     204#if 0
     205        if (rc != NO_ERROR) {
     206                debug_printf("tdb_brlock pid %X, fd %d, rc=%d FAILED\n",
     207                        getpid(), tdb->fd, rc);
     208        }
     209#endif
     210        if (rc != NO_ERROR && lck_type == F_SETLKW) {
     211#if 0
     212                debug_printf("tdb_brlock pid %X, fd %d, rc=%d RETRY WAIT\n",
     213                        getpid(), tdb->fd, rc);
     214#endif
     215                int     count = 10;
     216                do {
     217                        rc = DosSetFileLocks(tdb->fd, &aflock[0], &aflock[1], 1000, fAccess);
     218#if 0
     219                        debug_printf("tdb_brlock pid %X, fd %d, rc=%d RETRY WAIT(%d)\n",
     220                                getpid(), tdb->fd, rc,count);
     221#endif
     222                        count--;
     223                } while( count>0 && rc !=NO_ERROR);
     224
     225        }
     226        if (rc != NO_ERROR) {
     227                errno  = EINVAL;
     228                /* Generic lock error. errno set by fcntl.
     229                 * EAGAIN is an expected return from non-blocking
     230                 * locks. */
     231                if (!probe && lck_type != F_SETLK) {
     232                        /* Ensure error code is set for log fun to examine. */
     233                        tdb->ecode = TDB_ERR_LOCK;
     234                        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
     235                                 tdb->fd, offset, rw_type, lck_type, (int)len));
     236                }
     237#if 0
     238                debug_printf("tdb_brlock pid %X, failed (fd=%d) at offset %d rw_type=%d lck_type=%d len=%d\n",
     239                         getpid(), tdb->fd, offset, rw_type, lck_type, (int)len);
     240#endif
     241                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
     242        }
     243#if 0
     244        debug_printf("tdb_brlock pid %X, fd %d, lck_type %s, rw_type %s, offset %d, len %d DONE\n",
     245                getpid(), tdb->fd, lock_type(lck_type), read_type(rw_type), offset, len);
     246#endif
     247
     248#else
     249
    42250        struct flock fl;
    43251        int ret;
     
    62270        } while (ret == -1 && errno == EINTR);
    63271
    64 #ifndef __OS2__
    65         /* Sigh - again locking errors on OS/2 */
    66272        if (ret == -1) {
    67273                /* Generic lock error. errno set by fcntl.
     
    76282                return TDB_ERRCODE(TDB_ERR_LOCK, -1);
    77283        }
     284
    78285#endif
    79286        return 0;
     
    89296int tdb_brlock_upgrade(struct tdb_context *tdb, tdb_off_t offset, size_t len)
    90297{
     298#ifdef __OS2__
     299        // YD we use exclusive locks, no need to upgrade.
     300        return 0;
     301#else
    91302        int count = 1000;
    92303        while (count--) {
     
    98309                        break;
    99310                }
     311
    100312                /* sleep for as short a time as we can - more portable than usleep() */
    101313                tv.tv_sec = 0;
     
    103315                select(0, NULL, NULL, NULL, &tv);
    104316        }
     317
    105318        TDB_LOG((tdb, TDB_DEBUG_TRACE,"tdb_brlock_upgrade failed at offset %d\n", offset));
    106319        return -1;
     320#endif
    107321}
    108322
     
    414628        return (count == 1 ? tdb->methods->tdb_brlock(tdb, off, F_UNLCK, F_SETLKW, 0, 1) : 0);
    415629}
     630
Note: See TracChangeset for help on using the changeset viewer.