Ignore:
Timestamp:
Mar 18, 2016, 7:53:30 PM (9 years ago)
Author:
Silvan Scherrer
Message:

tdb: Use DosSetFileLocks directly for db locks.

This is to overcome some fcntl() API incompleteness in kLIBC
(like inability to upgrade locks or join adjacent lock regions
into one). It made the torture test run a bit better but there
are still two major problems both coming from DosSetFileLocks
impl (which fcntl() is currently based upon too): a) inability to
detect deadlocks and b) missing atomic unlock/lock support if
unlock/lock regions don't match.

With the current implementation, tdborture works fine for 1 or 2
worker processes but hangs when there are 3 or more. [Before that,
it would only work with 1 process and would likely to corrupt
the database and terminate if there were 2 or more processes].

Author: Dmitriy Kuminov (@dmik).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/server/lib/tdb/common/open.c

    r866 r895  
    162162        return check_header_hash(tdb, false, m1, m2);
    163163}
     164
     165#ifdef __OS2__
     166static int os2_create_lockfile(struct tdb_context *tdb, const char *name, const char *origin)
     167{
     168        /* name could be null, so handle it */
     169        if (name == NULL)
     170                return 0;
     171
     172        char lock_name[_MAX_PATH + 5];
     173        snprintf(lock_name, sizeof(lock_name), "%s.lock", name);
     174        tdb->lock_fd = open(lock_name, tdb->open_flags | O_CREAT | O_TRUNC, 0777);
     175        if (tdb->lock_fd == -1) {
     176                TDB_LOG((tdb, TDB_DEBUG_ERROR, "os2_create_lockfile: cannot create lock file %s, errno=%d\n",
     177                         lock_name, errno));
     178                return -1;
     179        }
     180
     181        return 0;
     182}
     183#endif
    164184
    165185_PUBLIC_ struct tdb_context *tdb_open_ex(const char *name, int hash_size, int tdb_flags,
     
    304324
    305325#ifdef __OS2__
    306         if (os2_crtActiveLock(tdb, name, "tdb_open_ex") != 0)
     326        if (os2_create_lockfile(tdb, name, "tdb_open_ex") != 0)
    307327                goto fail;
    308328#endif
     
    476496
    477497#ifdef __OS2__
    478         close(tdb->hActiveLock);
    479         tdb->hActiveLock = -1;
     498        close(tdb->lock_fd);
     499        tdb->lock_fd = -1;
    480500#endif
    481501        if (!tdb)
     
    548568
    549569#ifdef __OS2__
    550         close(tdb->hActiveLock);
    551         tdb->hActiveLock = -1;
     570        close(tdb->lock_fd);
     571        tdb->lock_fd = -1;
    552572#endif
    553573
     
    620640
    621641#ifdef __OS2__
    622         close(tdb->hActiveLock);
    623         tdb->hActiveLock = -1;
    624 
    625         if (os2_crtActiveLock(tdb, tdb->name, "tdb_reopen") != 0)
     642        close(tdb->lock_fd);
     643        tdb->lock_fd = -1;
     644
     645        if (os2_create_lockfile(tdb, tdb->name, "tdb_reopen") != 0)
    626646                goto fail;
    627647#endif
     
    679699        return 0;
    680700}
    681 #ifdef __OS2__
    682 int os2_crtActiveLock(struct tdb_context *tdb, const char *name, const char *origin)
    683 {
    684         // name could be null, so handle it
    685         if (name == NULL)
    686                 return 0;
    687 
    688         struct stat st;
    689         bool emptytdb = false;
    690         char activeLockName[_MAX_PATH];
    691         char *emptyString = "used for active lock\n\0";
    692         sprintf(activeLockName, "%s_AL", name);
    693 
    694         if ((stat(activeLockName, &st) == -1) || (st.st_size < strlen(emptyString)))
    695                 emptytdb = true;
    696 
    697         tdb->hActiveLock = open(activeLockName, tdb->open_flags | O_CREAT, 0777);
    698         if (tdb->hActiveLock == -1) {
    699                 TDB_LOG((tdb, TDB_DEBUG_ERROR, "os2_crtActiveLock: cannot create activeLock %s called from %s %s\n",
    700                         activeLockName, origin, strerror(errno)));
    701                 errno = EINVAL;
    702                 return -1;
    703         }
    704 
    705         // we try to truncate the db when called from tdb_open_ex
    706         // but if it's not working it's ok as well
    707         if (emptytdb)
    708                 tdb_write_all(tdb->hActiveLock, emptyString, strlen(emptyString));
    709 
    710         return 0;
    711 }
    712 #endif
Note: See TracChangeset for help on using the changeset viewer.