/ Check-in [c20aca06]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Change the windows backend to retry read and write requests if the encounter ERROR_LOCK_VIOLATION and ERROR_SHARING_VIOLATION errors - which we think sometimes happens due to aggressive anti-virus software.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c20aca06610407c197ea50ea77c2591aacf2252a
User & Date: drh 2011-07-11 18:17:56
Original Comment: Change the windows backend to retry read and write requests if the encounter ERROR_LOCK_VIOLATION and ERROR_SHARING_VIOLATION errors - which we think sometimes happens due to agressive anti-virus software.
Context
2011-07-11
23:45
Update the TCL commands for setting windows manditory locks. Add test cases for manditory lock delays under windows. check-in: 03af4c17 user: drh tags: trunk
18:17
Change the windows backend to retry read and write requests if the encounter ERROR_LOCK_VIOLATION and ERROR_SHARING_VIOLATION errors - which we think sometimes happens due to aggressive anti-virus software. check-in: c20aca06 user: drh tags: trunk
2011-07-09
16:17
Fix harmless compiler warnings on unix. check-in: 90b1aea1 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/os_win.c.

   397    397     sqlite3_log(errcode,
   398    398         "os_win.c:%d: (%d) %s(%s) - %s",
   399    399         iLine, iErrno, zFunc, zPath, zMsg
   400    400     );
   401    401   
   402    402     return errcode;
   403    403   }
          404  +
          405  +/*
          406  +** The number of times that a ReadFile() or WriteFile() will be retried
          407  +** following a locking error.
          408  +*/
          409  +#ifndef SQLITE_WIN32_IOERR_RETRY
          410  +# define SQLITE_WIN32_IOERR_RETRY 5
          411  +#endif
          412  +
          413  +/*
          414  +** If a ReadFile() or WriteFile() error occurs, invoke this routine
          415  +** to see if it should be retried.  Return TRUE to retry.  Return FALSE
          416  +** to give up with an error.
          417  +*/
          418  +static int retryIoerr(int *pnRetry){
          419  +  DWORD e;
          420  +  if( *pnRetry>=SQLITE_WIN32_IOERR_RETRY ){
          421  +    return 0;
          422  +  }
          423  +  e = GetLastError();
          424  +  if( e==ERROR_LOCK_VIOLATION || e==ERROR_SHARING_VIOLATION ){
          425  +    Sleep(50 + 50*(*pnRetry));
          426  +    ++*pnRetry;
          427  +    return 1;
          428  +  }
          429  +  return 0;
          430  +}
   404    431   
   405    432   #if SQLITE_OS_WINCE
   406    433   /*************************************************************************
   407    434   ** This section contains code for WinCE only.
   408    435   */
   409    436   /*
   410    437   ** WindowsCE does not have a localtime() function.  So create a
................................................................................
   816    843     sqlite3_file *id,          /* File to read from */
   817    844     void *pBuf,                /* Write content into this buffer */
   818    845     int amt,                   /* Number of bytes to read */
   819    846     sqlite3_int64 offset       /* Begin reading at this offset */
   820    847   ){
   821    848     winFile *pFile = (winFile*)id;  /* file handle */
   822    849     DWORD nRead;                    /* Number of bytes actually read from file */
          850  +  int nRetry = 0;                 /* Number of retrys */
   823    851   
   824    852     assert( id!=0 );
   825    853     SimulateIOError(return SQLITE_IOERR_READ);
   826    854     OSTRACE(("READ %d lock=%d\n", pFile->h, pFile->locktype));
   827    855   
   828    856     if( seekWinFile(pFile, offset) ){
   829    857       return SQLITE_FULL;
   830    858     }
   831         -  if( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
          859  +  while( !ReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
          860  +    if( retryIoerr(&nRetry) ) continue;
   832    861       pFile->lastErrno = GetLastError();
   833    862       return winLogError(SQLITE_IOERR_READ, "winRead", pFile->zPath);
   834    863     }
   835    864     if( nRead<(DWORD)amt ){
   836    865       /* Unread parts of the buffer must be zero-filled */
   837    866       memset(&((char*)pBuf)[nRead], 0, amt-nRead);
   838    867       return SQLITE_IOERR_SHORT_READ;
................................................................................
   862    891     OSTRACE(("WRITE %d lock=%d\n", pFile->h, pFile->locktype));
   863    892   
   864    893     rc = seekWinFile(pFile, offset);
   865    894     if( rc==0 ){
   866    895       u8 *aRem = (u8 *)pBuf;        /* Data yet to be written */
   867    896       int nRem = amt;               /* Number of bytes yet to be written */
   868    897       DWORD nWrite;                 /* Bytes written by each WriteFile() call */
          898  +    int nRetry = 0;               /* Number of retries */
   869    899   
   870         -    while( nRem>0 && WriteFile(pFile->h, aRem, nRem, &nWrite, 0) && nWrite>0 ){
          900  +    while( nRem>0 ){
          901  +      if( !WriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){
          902  +        if( retryIoerr(&nRetry) ) continue;
          903  +        break;
          904  +      }
          905  +      if( nWrite<=0 ) break;
   871    906         aRem += nWrite;
   872    907         nRem -= nWrite;
   873    908       }
   874    909       if( nRem>0 ){
   875    910         pFile->lastErrno = GetLastError();
   876    911         rc = 1;
   877    912       }