/ Check-in [2017636e]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Work in progress porting lsm1 to Win32.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | lsm-vtab
Files: files | file ages | folders
SHA3-256: 2017636e93cf810fe4d1247c18de9f316fca037035a026f77c4588563d7bf0cc
User & Date: mistachkin 2017-06-27 05:59:47
Context
2017-06-27
06:28
Minor corrections to the previous check-in. check-in: e1cf8a78 user: mistachkin tags: lsm-vtab
05:59
Work in progress porting lsm1 to Win32. check-in: 2017636e user: mistachkin tags: lsm-vtab
2017-06-26
11:46
Remove an invalid assert() from lsm test code. check-in: ca8a7e99 user: dan tags: lsm-vtab
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.msc.

  2238   2238   dbselftest.exe:	$(TOP)\test\dbselftest.c $(SQLITE3C) $(SQLITE3H)
  2239   2239   	$(LTLINK) $(NO_WARN) $(DBSELFTEST_COMPILE_OPTS) $(TOP)\test\dbselftest.c $(SQLITE3C)
  2240   2240   
  2241   2241   rbu.exe:	$(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H)
  2242   2242   	$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
  2243   2243   		$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
  2244   2244   
         2245  +LSMDIR=$(TOP)\ext\lsm1
         2246  +!INCLUDE $(LSMDIR)\Makefile.msc
         2247  +
  2245   2248   moreclean:	clean
  2246   2249   	del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
  2247   2250   # <</mark>>
  2248   2251   
  2249   2252   clean:
  2250   2253   	del /Q *.exp *.lo *.ilk *.lib *.obj *.ncb *.pdb *.sdf *.suo 2>NUL
  2251   2254   	del /Q *.bsc *.def *.cod *.da *.bb *.bbg *.vc gmon.out 2>NUL

Added ext/lsm1/Makefile.msc.

            1  +#
            2  +# This Makefile is designed for use with main.mk in the root directory of
            3  +# this project. After including main.mk, the users makefile should contain:
            4  +#
            5  +#    LSMDIR=$(TOP)\ext\lsm1\
            6  +#    include $(LSMDIR)\Makefile.msc
            7  +#
            8  +# The most useful targets are [lsmtest.exe] and [lsm.dll].
            9  +#
           10  +
           11  +LSMOBJ    = \
           12  +  lsm_ckpt.lo \
           13  +  lsm_file.lo \
           14  +  lsm_log.lo \
           15  +  lsm_main.lo \
           16  +  lsm_mem.lo \
           17  +  lsm_mutex.lo \
           18  +  lsm_shared.lo \
           19  +  lsm_sorted.lo \
           20  +  lsm_str.lo \
           21  +  lsm_tree.lo \
           22  +  lsm_unix.lo \
           23  +  lsm_win32.lo \
           24  +  lsm_varint.lo \
           25  +  lsm_vtab.lo
           26  +
           27  +LSMHDR   = \
           28  +  $(LSMDIR)\lsm.h \
           29  +  $(LSMDIR)\lsmInt.h
           30  +
           31  +LSMTESTSRC = $(LSMDIR)\lsm-test\lsmtest1.c $(LSMDIR)\lsm-test\lsmtest2.c     \
           32  +             $(LSMDIR)\lsm-test\lsmtest3.c $(LSMDIR)\lsm-test\lsmtest4.c     \
           33  +             $(LSMDIR)\lsm-test\lsmtest5.c $(LSMDIR)\lsm-test\lsmtest6.c     \
           34  +             $(LSMDIR)\lsm-test\lsmtest7.c $(LSMDIR)\lsm-test\lsmtest8.c     \
           35  +             $(LSMDIR)\lsm-test\lsmtest9.c                                   \
           36  +             $(LSMDIR)\lsm-test\lsmtest_datasource.c \
           37  +             $(LSMDIR)\lsm-test\lsmtest_func.c $(LSMDIR)\lsm-test\lsmtest_io.c  \
           38  +             $(LSMDIR)\lsm-test\lsmtest_main.c $(LSMDIR)\lsm-test\lsmtest_mem.c \
           39  +             $(LSMDIR)\lsm-test\lsmtest_tdb.c $(LSMDIR)\lsm-test\lsmtest_tdb3.c \
           40  +             $(LSMDIR)\lsm-test\lsmtest_util.c
           41  +
           42  +# all: lsm.dll
           43  +
           44  +LSMOPTS = -DLSM_MUTEX_WIN32=1 -I$(LSMDIR)
           45  +
           46  +lsm_ckpt.lo:	$(LSMDIR)\lsm_ckpt.c $(LSMHDR) $(SQLITE3H)
           47  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_ckpt.c
           48  +
           49  +lsm_file.lo:	$(LSMDIR)\lsm_file.c $(LSMHDR) $(SQLITE3H)
           50  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_file.c
           51  +
           52  +lsm_log.lo:	$(LSMDIR)\lsm_log.c $(LSMHDR) $(SQLITE3H)
           53  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_log.c
           54  +
           55  +lsm_main.lo:	$(LSMDIR)\lsm_main.c $(LSMHDR) $(SQLITE3H)
           56  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_main.c
           57  +
           58  +lsm_mem.lo:	$(LSMDIR)\lsm_mem.c $(LSMHDR) $(SQLITE3H)
           59  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_mem.c
           60  +
           61  +lsm_mutex.lo:	$(LSMDIR)\lsm_mutex.c $(LSMHDR) $(SQLITE3H)
           62  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_mutex.c
           63  +
           64  +lsm_shared.lo:	$(LSMDIR)\lsm_shared.c $(LSMHDR) $(SQLITE3H)
           65  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_shared.c
           66  +
           67  +lsm_sorted.lo:	$(LSMDIR)\lsm_sorted.c $(LSMHDR) $(SQLITE3H)
           68  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_sorted.c
           69  +
           70  +lsm_str.lo:	$(LSMDIR)\lsm_str.c $(LSMHDR) $(SQLITE3H)
           71  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_str.c
           72  +
           73  +lsm_tree.lo:	$(LSMDIR)\lsm_tree.c $(LSMHDR) $(SQLITE3H)
           74  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_tree.c
           75  +
           76  +lsm_unix.lo:	$(LSMDIR)\lsm_unix.c $(LSMHDR) $(SQLITE3H)
           77  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_unix.c
           78  +
           79  +lsm_win32.lo:	$(LSMDIR)\lsm_win32.c $(LSMHDR) $(SQLITE3H)
           80  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_win32.c
           81  +
           82  +lsm_varint.lo:	$(LSMDIR)\lsm_varint.c $(LSMHDR) $(SQLITE3H)
           83  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_varint.c
           84  +
           85  +lsm_vtab.lo:	$(LSMDIR)\lsm_vtab.c $(LSMHDR) $(SQLITE3H)
           86  +	$(LTCOMPILE) $(LSMOPTS) -c $(LSMDIR)\lsm_vtab.c
           87  +
           88  +lsm.dll:	$(LSMOBJ)
           89  +	$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /VERBOSE /DLL /OUT:$@ $(LSMOBJ)
           90  +
           91  +lsmtest.exe: $(LSMOBJ) $(LSMTESTSRC) $(LSMTESTHDR) $(LIBOBJS1)
           92  +	# $(LTCOMPILE) -c $(TOP)\lsm-test\lsmtest_tdb2.cc
           93  +	$(LTCOMPILE) $(LSMOPTS) $(LSMTESTSRC) $(LSMOBJ) $(LIBOBJS1) -Fe$@

Changes to ext/lsm1/lsmInt.h.

    19     19   #include <string.h>
    20     20   
    21     21   #include <stdarg.h>
    22     22   #include <stdlib.h>
    23     23   #include <stdio.h>
    24     24   #include <ctype.h>
    25     25   
    26         -#include <unistd.h>
           26  +#ifdef _WIN32
           27  +# define snprintf _snprintf
           28  +#else
           29  +# include <unistd.h>
           30  +#endif
    27     31   
    28     32   #ifdef NDEBUG
    29     33   # ifdef LSM_DEBUG_EXPENSIVE
    30     34   #  undef LSM_DEBUG_EXPENSIVE
    31     35   # endif
    32     36   # ifdef LSM_DEBUG
    33     37   #  undef LSM_DEBUG

Changes to ext/lsm1/lsm_file.c.

  2081   2081     Snapshot *pSnapshot,
  2082   2082     Level *pLvl,
  2083   2083     int bDefer,
  2084   2084     Page **ppOut
  2085   2085   ){
  2086   2086     int rc = LSM_OK;
  2087   2087     Page *pPg = 0;
  2088         -  *ppOut = 0;
  2089   2088     int iApp = 0;
  2090   2089     int iNext = 0;
  2091   2090     Segment *p = &pLvl->lhs;
  2092   2091     int iPrev = p->iLastPg;
  2093   2092   
         2093  +  *ppOut = 0;
  2094   2094     assert( p->pRedirect==0 );
  2095   2095   
  2096   2096     if( pFS->pCompress || bDefer ){
  2097   2097       /* In compressed database mode the page is not assigned a page number
  2098   2098       ** or location in the database file at this point. This will be done
  2099   2099       ** by the lsmFsPagePersist() call.  */
  2100   2100       rc = fsPageBuffer(pFS, &pPg);

Changes to ext/lsm1/lsm_unix.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** Unix-specific run-time environment implementation for LSM.
    14     14   */
    15     15   
    16         -#ifndef WIN32
           16  +#ifndef _WIN32
    17     17   
    18     18   #if defined(__GNUC__) || defined(__TINYC__)
    19     19   /* workaround for ftruncate() visibility on gcc. */
    20     20   # ifndef _XOPEN_SOURCE
    21     21   #  define _XOPEN_SOURCE 500
    22     22   # endif
    23     23   #endif

Changes to ext/lsm1/lsm_win32.c.

     6      6   **
     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   **
    13         -** Unix-specific run-time environment implementation for LSM.
           13  +** Win32-specific run-time environment implementation for LSM.
    14     14   */
    15     15   
    16         -#ifdef WIN32
           16  +#ifdef _WIN32
    17     17   
    18         -#if defined(__GNUC__) || defined(__TINYC__)
    19         -/* workaround for ftruncate() visibility on gcc. */
    20         -# ifndef _XOPEN_SOURCE
    21         -#  define _XOPEN_SOURCE 500
    22         -# endif
    23         -#endif
    24         -
    25         -#include <unistd.h>
    26         -#include <sys/types.h>
    27         -
    28         -#include <sys/stat.h>
    29         -#include <fcntl.h>
    30     18   #include <assert.h>
    31     19   #include <string.h>
    32     20   
    33     21   #include <stdlib.h>
    34     22   #include <stdarg.h>
    35     23   #include <stdio.h>
    36     24   #include <ctype.h>
    37     25   
    38         -#include <unistd.h>
    39         -#include <errno.h>
           26  +#include "windows.h"
    40     27   
    41     28   #include "lsmInt.h"
    42     29   
    43     30   /*
    44     31   ** An open file is an instance of the following object
    45     32   */
    46     33   typedef struct Win32File Win32File;
    47     34   struct Win32File {
    48     35     lsm_env *pEnv;                  /* The run-time environment */
    49     36     const char *zName;              /* Full path to file */
    50     37   
    51         -  HANDLE h;                       /* Open file descriptor */
    52         -  HANDLE shmh;                    /* File descriptor for *-shm file */
           38  +  HANDLE hFile;                   /* Open file handle */
           39  +  HANDLE hShmFile;                /* File handle for *-shm file */
    53     40   
           41  +  HANDLE hMap;                    /* File handle for mapping */
    54     42     void *pMap;                     /* Pointer to mapping of file fd */
    55         -  off_t nMap;                     /* Size of mapping at pMap in bytes */
           43  +  size_t nMap;                    /* Size of mapping at pMap in bytes */
    56     44     int nShm;                       /* Number of entries in array apShm[] */
    57     45     void **apShm;                   /* Array of 32K shared memory segments */
    58     46   };
    59     47   
           48  +int lsmWin32OsSleep(lsm_env *pEnv, int us);
           49  +
    60     50   static char *win32ShmFile(Win32File *p){
    61     51     char *zShm;
    62     52     int nName = strlen(p->zName);
    63         -  zShm = (char *)lsmMalloc(p->pEnv, nName+4+1);
           53  +  zShm = (char *)lsmMallocZero(p->pEnv, nName+4+1);
    64     54     if( zShm ){
    65     55       memcpy(zShm, p->zName, nName);
    66     56       memcpy(&zShm[nName], "-shm", 5);
    67     57     }
    68     58     return zShm;
    69     59   }
    70     60   
           61  +/*
           62  +** The number of times that an I/O operation will be retried following a
           63  +** locking error - probably caused by antivirus software.  Also the initial
           64  +** delay before the first retry.  The delay increases linearly with each
           65  +** retry.
           66  +*/
           67  +#ifndef LSM_WIN32_IOERR_RETRY
           68  +# define LSM_WIN32_IOERR_RETRY 10
           69  +#endif
           70  +#ifndef LSM_WIN32_IOERR_RETRY_DELAY
           71  +# define LSM_WIN32_IOERR_RETRY_DELAY 25000
           72  +#endif
           73  +static int win32IoerrRetry = LSM_WIN32_IOERR_RETRY;
           74  +static int win32IoerrRetryDelay = LSM_WIN32_IOERR_RETRY_DELAY;
           75  +
           76  +/*
           77  +** The "win32IoerrCanRetry1" macro is used to determine if a particular
           78  +** I/O error code obtained via GetLastError() is eligible to be retried.
           79  +** It must accept the error code DWORD as its only argument and should
           80  +** return non-zero if the error code is transient in nature and the
           81  +** operation responsible for generating the original error might succeed
           82  +** upon being retried.  The argument to this macro should be a variable.
           83  +**
           84  +** Additionally, a macro named "win32IoerrCanRetry2" may be defined.  If
           85  +** it is defined, it will be consulted only when the macro
           86  +** "win32IoerrCanRetry1" returns zero.  The "win32IoerrCanRetry2" macro
           87  +** is completely optional and may be used to include additional error
           88  +** codes in the set that should result in the failing I/O operation being
           89  +** retried by the caller.  If defined, the "win32IoerrCanRetry2" macro
           90  +** must exhibit external semantics identical to those of the
           91  +** "win32IoerrCanRetry1" macro.
           92  +*/
           93  +#if !defined(win32IoerrCanRetry1)
           94  +#define win32IoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED)        || \
           95  +                                ((a)==ERROR_SHARING_VIOLATION)    || \
           96  +                                ((a)==ERROR_LOCK_VIOLATION)       || \
           97  +                                ((a)==ERROR_DEV_NOT_EXIST)        || \
           98  +                                ((a)==ERROR_NETNAME_DELETED)      || \
           99  +                                ((a)==ERROR_SEM_TIMEOUT)          || \
          100  +                                ((a)==ERROR_NETWORK_UNREACHABLE))
          101  +#endif
          102  +
          103  +/*
          104  +** If an I/O error occurs, invoke this routine to see if it should be
          105  +** retried.  Return TRUE to retry.  Return FALSE to give up with an
          106  +** error.
          107  +*/
          108  +static int win32RetryIoerr(
          109  +  lsm_env *pEnv,
          110  +  int *pnRetry
          111  +){
          112  +  DWORD lastErrno;
          113  +  if( *pnRetry>=win32IoerrRetry ){
          114  +    return 0;
          115  +  }
          116  +  lastErrno = GetLastError();
          117  +  if( win32IoerrCanRetry1(lastErrno) ){
          118  +    lsmWin32OsSleep(pEnv, win32IoerrRetryDelay*(1+*pnRetry));
          119  +    ++*pnRetry;
          120  +    return 1;
          121  +  }
          122  +#if defined(win32IoerrCanRetry2)
          123  +  else if( win32IoerrCanRetry2(lastErrno) ){
          124  +    lsmWin32OsSleep(pEnv, win32IoerrRetryDelay*(1+*pnRetry));
          125  +    ++*pnRetry;
          126  +    return 1;
          127  +  }
          128  +#endif
          129  +  return 0;
          130  +}
          131  +
          132  +/*
          133  +** Convert a UTF-8 string to Microsoft Unicode.
          134  +**
          135  +** Space to hold the returned string is obtained from lsmMalloc().
          136  +*/
          137  +static LPWSTR win32Utf8ToUnicode(lsm_env *pEnv, const char *zText){
          138  +  int nChar;
          139  +  LPWSTR zWideText;
          140  +
          141  +  nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, NULL, 0);
          142  +  if( nChar==0 ){
          143  +    return 0;
          144  +  }
          145  +  zWideText = lsmMallocZero(pEnv, nChar * sizeof(WCHAR));
          146  +  if( zWideText==0 ){
          147  +    return 0;
          148  +  }
          149  +  nChar = MultiByteToWideChar(CP_UTF8, 0, zText, -1, zWideText, nChar);
          150  +  if( nChar==0 ){
          151  +    lsmFree(pEnv, zWideText);
          152  +    zWideText = 0;
          153  +  }
          154  +  return zWideText;
          155  +}
          156  +
          157  +#if !defined(win32IsNotFound)
          158  +#define win32IsNotFound(a) (((a)==ERROR_FILE_NOT_FOUND)  || \
          159  +                            ((a)==ERROR_PATH_NOT_FOUND))
          160  +#endif
          161  +
    71    162   static int lsmWin32OsOpen(
    72    163     lsm_env *pEnv,
    73    164     const char *zFile,
    74    165     int flags,
    75    166     lsm_file **ppFile
    76    167   ){
    77    168     int rc = LSM_OK;
    78         -  Win32File *p;
          169  +  Win32File *pWin32File;
    79    170   
    80         -  p = lsm_malloc(pEnv, sizeof(Win32File));
    81         -  if( p==0 ){
    82         -    rc = LSM_NOMEM;
          171  +  pWin32File = lsmMallocZero(pEnv, sizeof(Win32File));
          172  +  if( pWin32File==0 ){
          173  +    rc = LSM_NOMEM_BKPT;
    83    174     }else{
          175  +    LPCWSTR zConverted;
    84    176       int bReadonly = (flags & LSM_OPEN_READONLY);
    85         -    int oflags = (bReadonly ? O_RDONLY : (O_RDWR|O_CREAT));
    86         -    memset(p, 0, sizeof(Win32File));
    87         -    p->zName = zFile;
    88         -    p->pEnv = pEnv;
    89         -
    90         -    CreateFile((LPCWSTR)zConverted,
    91         -                              dwDesiredAccess,
    92         -                              dwShareMode, NULL,
    93         -                              dwCreationDisposition,
    94         -                              dwFlagsAndAttributes,
    95         -                              NULL))==INVALID_HANDLE_VALUE &&
    96         -                              winRetryIoerr(&cnt, &lastErrno) ){
    97         -
    98         -
    99         -    p->fd = open(zFile, oflags, 0644);
   100         -    if( p->fd<0 ){
   101         -      lsm_free(pEnv, p);
   102         -      p = 0;
   103         -      if( errno==ENOENT ){
   104         -        rc = lsmErrorBkpt(LSM_IOERR_NOENT);
          177  +    DWORD dwDesiredAccess;
          178  +    DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
          179  +    DWORD dwCreationDisposition;
          180  +    DWORD dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
          181  +    HANDLE hFile;
          182  +
          183  +    zConverted = win32Utf8ToUnicode(pEnv, zFile);
          184  +    if( zConverted==0 ){
          185  +      lsmFree(pEnv, pWin32File);
          186  +      pWin32File = 0;
          187  +      rc = LSM_NOMEM_BKPT;
          188  +    }else{
          189  +      int nRetry = 0;
          190  +      if( bReadonly ){
          191  +        dwDesiredAccess = GENERIC_READ;
          192  +        dwCreationDisposition = OPEN_EXISTING;
          193  +      }else{
          194  +        dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
          195  +        dwCreationDisposition = OPEN_ALWAYS;
          196  +      }
          197  +      while( (hFile = CreateFileW((LPCWSTR)zConverted,
          198  +                                  dwDesiredAccess,
          199  +                                  dwShareMode, NULL,
          200  +                                  dwCreationDisposition,
          201  +                                  dwFlagsAndAttributes,
          202  +                                  NULL))==INVALID_HANDLE_VALUE &&
          203  +                                  win32RetryIoerr(pEnv, &nRetry) ){
          204  +        /* Noop */
          205  +      }
          206  +      if( hFile!=INVALID_HANDLE_VALUE ){
          207  +        pWin32File->pEnv = pEnv;
          208  +        pWin32File->zName = zFile;
          209  +        pWin32File->hFile = hFile;
   105    210         }else{
   106         -        rc = LSM_IOERR_BKPT;
          211  +        lsmFree(pEnv, pWin32File);
          212  +        pWin32File = 0;
          213  +        if( win32IsNotFound(GetLastError()) ){
          214  +          rc = lsmErrorBkpt(LSM_IOERR_NOENT);
          215  +        }else{
          216  +          rc = LSM_IOERR_BKPT;
          217  +        }
   107    218         }
   108    219       }
   109    220     }
   110         -
   111         -  *ppFile = (lsm_file *)p;
          221  +  *ppFile = (lsm_file *)pWin32File;
   112    222     return rc;
   113    223   }
   114    224   
   115    225   static int lsmWin32OsWrite(
   116         -  lsm_file *pFile,                /* File to write to */
   117         -  lsm_i64 iOff,                   /* Offset to write to */
   118         -  void *pData,                    /* Write data from this buffer */
   119         -  int nData                       /* Bytes of data to write */
          226  +  lsm_file *pFile, /* File to write to */
          227  +  lsm_i64 iOff,    /* Offset to write to */
          228  +  void *pData,     /* Write data from this buffer */
          229  +  int nData        /* Bytes of data to write */
   120    230   ){
   121         -  int rc = LSM_OK;
   122         -  Win32File *p = (Win32File *)pFile;
   123         -  off_t offset;
          231  +  Win32File *pWin32File = (Win32File *)pFile;
          232  +  OVERLAPPED overlapped;  /* The offset for WriteFile. */
          233  +  u8 *aRem = (u8 *)pData; /* Data yet to be written */
          234  +  int nRem = nData;       /* Number of bytes yet to be written */
          235  +  int nRetry = 0;         /* Number of retrys */
   124    236   
   125         -  offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
   126         -  if( offset!=iOff ){
   127         -    rc = LSM_IOERR_BKPT;
   128         -  }else{
   129         -    ssize_t prc = write(p->fd, pData, (size_t)nData);
   130         -    if( prc<0 ) rc = LSM_IOERR_BKPT;
          237  +  memset(&overlapped, 0, sizeof(OVERLAPPED));
          238  +  overlapped.Offset = (LONG)(iOff & 0xffffffff);
          239  +  overlapped.OffsetHigh = (LONG)((iOff>>32) & 0x7fffffff);
          240  +  while( nRem>0 ){
          241  +    DWORD nWrite = 0; /* Bytes written using WriteFile */
          242  +    if( !WriteFile(pWin32File->hFile, aRem, nRem, &nWrite, &overlapped) ){
          243  +      if( win32RetryIoerr(pWin32File->pEnv, &nRetry) ) continue;
          244  +      break;
          245  +    }
          246  +    assert( nWrite==0 || nWrite<=(DWORD)nRem );
          247  +    if( nWrite==0 || nWrite>(DWORD)nRem ){
          248  +      break;
          249  +    }
          250  +    iOff += nWrite;
          251  +    overlapped.Offset = (LONG)(iOff & 0xffffffff);
          252  +    overlapped.OffsetHigh = (LONG)((iOff>>32) & 0x7fffffff);
          253  +    aRem += nWrite;
          254  +    nRem -= nWrite;
   131    255     }
   132         -
   133         -  return rc;
          256  +  if( nRem!=0 ) return LSM_IOERR_BKPT;
          257  +  return LSM_OK;
   134    258   }
   135    259   
   136    260   static int lsmWin32OsTruncate(
   137         -  lsm_file *pFile,                /* File to write to */
   138         -  lsm_i64 nSize                   /* Size to truncate file to */
          261  +  lsm_file *pFile, /* File to write to */
          262  +  lsm_i64 nSize    /* Size to truncate file to */
   139    263   ){
   140         -  Win32File *p = (Win32File *)pFile;
   141         -  int rc = LSM_OK;                /* Return code */
   142         -  int prc;                        /* Posix Return Code */
   143         -  struct stat sStat;              /* Result of fstat() invocation */
   144         -  
   145         -  prc = fstat(p->fd, &sStat);
   146         -  if( prc==0 && sStat.st_size>nSize ){
   147         -    prc = ftruncate(p->fd, (off_t)nSize);
          264  +  Win32File *pWin32File = (Win32File *)pFile;
          265  +  LARGE_INTEGER largeInteger; /* The new offset */
          266  +
          267  +  largeInteger.QuadPart = nSize;
          268  +  if( !SetFilePointerEx(pWin32File->hFile, largeInteger, 0, FILE_BEGIN) ){
          269  +    return LSM_IOERR_BKPT;
   148    270     }
   149         -  if( prc<0 ) rc = LSM_IOERR_BKPT;
   150         -
   151         -  return rc;
          271  +  if (!SetEndOfFile(pWin32File->hFile) ){
          272  +    return LSM_IOERR_BKPT;
          273  +  }
          274  +  return LSM_OK;
   152    275   }
   153    276   
   154    277   static int lsmWin32OsRead(
   155         -  lsm_file *pFile,                /* File to read from */
   156         -  lsm_i64 iOff,                   /* Offset to read from */
   157         -  void *pData,                    /* Read data into this buffer */
   158         -  int nData                       /* Bytes of data to read */
          278  +  lsm_file *pFile, /* File to read from */
          279  +  lsm_i64 iOff,    /* Offset to read from */
          280  +  void *pData,     /* Read data into this buffer */
          281  +  int nData        /* Bytes of data to read */
   159    282   ){
   160         -  int rc = LSM_OK;
   161         -  Win32File *p = (Win32File *)pFile;
   162         -  off_t offset;
          283  +  Win32File *pWin32File = (Win32File *)pFile;
          284  +  OVERLAPPED overlapped; /* The offset for ReadFile */
          285  +  DWORD nRead = 0;       /* Bytes read using ReadFile */
          286  +  int nRetry = 0;        /* Number of retrys */
   163    287   
   164         -  offset = lseek(p->fd, (off_t)iOff, SEEK_SET);
   165         -  if( offset!=iOff ){
   166         -    rc = LSM_IOERR_BKPT;
   167         -  }else{
   168         -    ssize_t prc = read(p->fd, pData, (size_t)nData);
   169         -    if( prc<0 ){ 
   170         -      rc = LSM_IOERR_BKPT;
   171         -    }else if( prc<nData ){
   172         -      memset(&((u8 *)pData)[prc], 0, nData - prc);
   173         -    }
   174         -
          288  +  memset(&overlapped, 0, sizeof(OVERLAPPED));
          289  +  overlapped.Offset = (LONG)(iOff & 0xffffffff);
          290  +  overlapped.OffsetHigh = (LONG)((iOff>>32) & 0x7fffffff);
          291  +  while( !ReadFile(pWin32File->hFile, pData, nData, &nRead, &overlapped) &&
          292  +         GetLastError()!=ERROR_HANDLE_EOF ){
          293  +    if( win32RetryIoerr(pWin32File->pEnv, &nRetry) ) continue;
          294  +    return LSM_IOERR_BKPT;
          295  +  }
          296  +  if( nRead<(DWORD)nData ){
          297  +    /* Unread parts of the buffer must be zero-filled */
          298  +    memset(&((char*)pData)[nRead], 0, nData - nRead);
   175    299     }
   176         -
   177         -  return rc;
          300  +  return LSM_OK;
   178    301   }
   179    302   
   180    303   static int lsmWin32OsSync(lsm_file *pFile){
   181    304     int rc = LSM_OK;
   182    305   
   183    306   #ifndef LSM_NO_SYNC
   184         -  Win32File *p = (Win32File *)pFile;
   185         -  int prc = 0;
          307  +  Win32File *pWin32File = (Win32File *)pFile;
   186    308   
   187         -  if( p->pMap ){
   188         -    prc = msync(p->pMap, p->nMap, MS_SYNC);
          309  +  if( pWin32File->pMap ){
          310  +    if( !FlushViewOfFile(pWin32File->pMap, 0) ){
          311  +      rc = LSM_IOERR_BKPT;
          312  +    }
          313  +  }
          314  +  if( rc==LSM_OK && !FlushFileBuffers(pWin32File->hFile) ){
          315  +    rc = LSM_IOERR_BKPT;
   189    316     }
   190         -  if( prc==0 ) prc = fdatasync(p->fd);
   191         -  if( prc<0 ) rc = LSM_IOERR_BKPT;
   192    317   #else
   193         -  (void)pFile;
   194    318   #endif
   195    319   
   196    320     return rc;
   197    321   }
   198    322   
   199    323   static int lsmWin32OsSectorSize(lsm_file *pFile){
   200    324     return 512;
   201    325   }
   202    326   
   203    327   static int lsmWin32OsRemap(
   204         -  lsm_file *pFile, 
   205         -  lsm_i64 iMin, 
          328  +  lsm_file *pFile,
          329  +  lsm_i64 iMin,
   206    330     void **ppOut,
   207    331     lsm_i64 *pnOut
   208    332   ){
   209         -  off_t iSz;
   210         -  int prc;
   211         -  Win32File *p = (Win32File *)pFile;
   212         -  struct stat buf;
   213         -
   214         -  /* If the file is between 0 and 2MB in size, extend it in chunks of 256K.
   215         -  ** Thereafter, in chunks of 1MB at a time.  */
   216         -  const int aIncrSz[] = {256*1024, 1024*1024};
   217         -  int nIncrSz = aIncrSz[iMin>(2*1024*1024)];
   218         -
   219         -  if( p->pMap ){
   220         -    munmap(p->pMap, p->nMap);
   221         -    *ppOut = p->pMap = 0;
   222         -    *pnOut = p->nMap = 0;
   223         -  }
   224         -
   225         -  if( iMin>=0 ){
   226         -    memset(&buf, 0, sizeof(buf));
   227         -    prc = fstat(p->fd, &buf);
   228         -    if( prc!=0 ) return LSM_IOERR_BKPT;
   229         -    iSz = buf.st_size;
   230         -    if( iSz<iMin ){
   231         -      iSz = ((iMin + nIncrSz-1) / nIncrSz) * nIncrSz;
   232         -      prc = ftruncate(p->fd, iSz);
   233         -      if( prc!=0 ) return LSM_IOERR_BKPT;
   234         -    }
   235         -
   236         -    p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
   237         -    p->nMap = iSz;
   238         -  }
   239         -
   240         -  *ppOut = p->pMap;
   241         -  *pnOut = p->nMap;
   242         -  return LSM_OK;
          333  +  return LSM_ERROR;
   243    334   }
   244    335   
   245    336   static int lsmWin32OsFullpath(
   246    337     lsm_env *pEnv,
   247    338     const char *zName,
   248    339     char *zOut,
   249    340     int *pnOut
   250    341   ){
   251         -  int nBuf = *pnOut;
   252         -  int nReq;
   253         -
   254         -  if( zName[0]!='/' ){
   255         -    char *z;
   256         -    char *zTmp;
   257         -    int nTmp = 512;
   258         -    zTmp = lsmMalloc(pEnv, nTmp);
   259         -    while( zTmp ){
   260         -      z = getcwd(zTmp, nTmp);
   261         -      if( z || errno!=ERANGE ) break;
   262         -      nTmp = nTmp*2;
   263         -      zTmp = lsmReallocOrFree(pEnv, zTmp, nTmp);
   264         -    }
   265         -    if( zTmp==0 ) return LSM_NOMEM_BKPT;
   266         -    if( z==0 ) return LSM_IOERR_BKPT;
   267         -    assert( z==zTmp );
   268         -
   269         -    nTmp = strlen(zTmp);
   270         -    nReq = nTmp + 1 + strlen(zName) + 1;
   271         -    if( nReq<=nBuf ){
   272         -      memcpy(zOut, zTmp, nTmp);
   273         -      zOut[nTmp] = '/';
   274         -      memcpy(&zOut[nTmp+1], zName, strlen(zName)+1);
   275         -    }
   276         -    lsmFree(pEnv, zTmp);
   277         -  }else{
   278         -    nReq = strlen(zName)+1;
   279         -    if( nReq<=nBuf ){
   280         -      memcpy(zOut, zName, strlen(zName)+1);
   281         -    }
   282         -  }
   283         -
   284         -  *pnOut = nReq;
   285         -  return LSM_OK;
          342  +  return LSM_ERROR;
   286    343   }
   287    344   
   288    345   static int lsmWin32OsFileid(
   289         -  lsm_file *pFile, 
          346  +  lsm_file *pFile,
   290    347     void *pBuf,
   291    348     int *pnBuf
   292    349   ){
   293         -  int prc;
   294    350     int nBuf;
   295    351     int nReq;
   296         -  Win32File *p = (Win32File *)pFile;
   297         -  struct stat buf;
          352  +  u8 *pBuf2 = (u8 *)pBuf;
          353  +  Win32File *pWin32File = (Win32File *)pFile;
          354  +  BY_HANDLE_FILE_INFORMATION fileInfo;
   298    355   
   299    356     nBuf = *pnBuf;
   300         -  nReq = (sizeof(buf.st_dev) + sizeof(buf.st_ino));
          357  +  nReq = (sizeof(fileInfo.dwVolumeSerialNumber) +
          358  +          sizeof(fileInfo.nFileIndexHigh) +
          359  +          sizeof(fileInfo.nFileIndexLow));
   301    360     *pnBuf = nReq;
   302    361     if( nReq>nBuf ) return LSM_OK;
   303         -
   304         -  memset(&buf, 0, sizeof(buf));
   305         -  prc = fstat(p->fd, &buf);
   306         -  if( prc!=0 ) return LSM_IOERR_BKPT;
   307         -
   308         -  memcpy(pBuf, &buf.st_dev, sizeof(buf.st_dev));
   309         -  memcpy(&(((u8 *)pBuf)[sizeof(buf.st_dev)]), &buf.st_ino, sizeof(buf.st_ino));
          362  +  memset(&fileInfo, 0, sizeof(BY_HANDLE_FILE_INFORMATION));
          363  +  if( !GetFileInformationByHandle(pWin32File->hFile, &fileInfo) ){
          364  +    return LSM_IOERR_BKPT;
          365  +  }
          366  +  nReq = sizeof(fileInfo.dwVolumeSerialNumber);
          367  +  memcpy(pBuf2, &fileInfo.dwVolumeSerialNumber, nReq);
          368  +  pBuf2 += nReq;
          369  +  nReq = sizeof(fileInfo.nFileIndexHigh);
          370  +  memcpy(pBuf, &fileInfo.nFileIndexHigh, nReq);
          371  +  pBuf2 += nReq;
          372  +  nReq = sizeof(fileInfo.nFileIndexLow);
          373  +  memcpy(pBuf2, &fileInfo.nFileIndexLow, nReq);
   310    374     return LSM_OK;
   311    375   }
   312    376   
   313    377   static int lsmWin32OsUnlink(lsm_env *pEnv, const char *zFile){
   314         -  int prc = unlink(zFile);
   315         -  return prc ? LSM_IOERR_BKPT : LSM_OK;
          378  +  return LSM_ERROR;
   316    379   }
   317    380   
   318    381   int lsmWin32OsLock(lsm_file *pFile, int iLock, int eType){
   319         -  int rc = LSM_OK;
   320         -  Win32File *p = (Win32File *)pFile;
   321         -  static const short aType[3] = { F_UNLCK, F_RDLCK, F_WRLCK };
   322         -  struct flock lock;
   323         -
   324         -  assert( aType[LSM_LOCK_UNLOCK]==F_UNLCK );
   325         -  assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
   326         -  assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
   327         -  assert( eType>=0 && eType<array_size(aType) );
   328         -  assert( iLock>0 && iLock<=32 );
   329         -
   330         -  memset(&lock, 0, sizeof(lock));
   331         -  lock.l_whence = SEEK_SET;
   332         -  lock.l_len = 1;
   333         -  lock.l_type = aType[eType];
   334         -  lock.l_start = (4096-iLock);
   335         -
   336         -  if( fcntl(p->fd, F_SETLK, &lock) ){
   337         -    int e = errno;
   338         -    if( e==EACCES || e==EAGAIN ){
   339         -      rc = LSM_BUSY;
   340         -    }else{
   341         -      rc = LSM_IOERR_BKPT;
   342         -    }
   343         -  }
   344         -
   345         -  return rc;
          382  +  return LSM_ERROR;
   346    383   }
   347    384   
   348    385   int lsmWin32OsTestLock(lsm_file *pFile, int iLock, int nLock, int eType){
   349         -  int rc = LSM_OK;
   350         -  Win32File *p = (Win32File *)pFile;
   351         -  static const short aType[3] = { 0, F_RDLCK, F_WRLCK };
   352         -  struct flock lock;
   353         -
   354         -  assert( eType==LSM_LOCK_SHARED || eType==LSM_LOCK_EXCL );
   355         -  assert( aType[LSM_LOCK_SHARED]==F_RDLCK );
   356         -  assert( aType[LSM_LOCK_EXCL]==F_WRLCK );
   357         -  assert( eType>=0 && eType<array_size(aType) );
   358         -  assert( iLock>0 && iLock<=32 );
   359         -
   360         -  memset(&lock, 0, sizeof(lock));
   361         -  lock.l_whence = SEEK_SET;
   362         -  lock.l_len = nLock;
   363         -  lock.l_type = aType[eType];
   364         -  lock.l_start = (4096-iLock);
   365         -
   366         -  if( fcntl(p->fd, F_GETLK, &lock) ){
   367         -    rc = LSM_IOERR_BKPT;
   368         -  }else if( lock.l_type!=F_UNLCK ){
   369         -    rc = LSM_BUSY;
          386  +  return LSM_ERROR;
          387  +}
          388  +
          389  +int lsmWin32OsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
          390  +  return LSM_ERROR;
          391  +}
          392  +
          393  +void lsmWin32OsShmBarrier(void){
          394  +  MemoryBarrier();
          395  +}
          396  +
          397  +int lsmWin32OsShmUnmap(lsm_file *pFile, int bDelete){
          398  +  return LSM_ERROR;
          399  +}
          400  +
          401  +#define MX_CLOSE_ATTEMPT 3
          402  +static int lsmWin32OsClose(lsm_file *pFile){
          403  +  int rc;
          404  +  int nRetry = 0;
          405  +  Win32File *pWin32File = (Win32File *)pFile;
          406  +  lsmWin32OsShmUnmap(pFile, 0);
          407  +  if( pWin32File->pMap ){
          408  +    UnmapViewOfFile(pWin32File->pMap);
          409  +    pWin32File->pMap = 0;
          410  +  }
          411  +  if( pWin32File->hMap!=NULL ){
          412  +    CloseHandle(pWin32File->hMap);
          413  +    pWin32File->hMap = NULL;
   370    414     }
   371         -
          415  +  do{
          416  +    rc = CloseHandle(pWin32File->hFile);
          417  +    if( rc ){
          418  +      rc = LSM_OK;
          419  +      break;
          420  +    }
          421  +    if( ++nRetry>=MX_CLOSE_ATTEMPT ){
          422  +      rc = LSM_IOERR_BKPT;
          423  +      break;
          424  +    }
          425  +  }while( 1 );
          426  +  lsmFree(pWin32File->pEnv, pWin32File->apShm);
          427  +  lsmFree(pWin32File->pEnv, pWin32File);
   372    428     return rc;
   373    429   }
   374    430   
   375         -int lsmWin32OsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
   376         -  Win32File *p = (Win32File *)pFile;
   377         -
   378         -  *ppShm = 0;
   379         -  assert( sz==LSM_SHM_CHUNK_SIZE );
   380         -  if( iChunk>=p->nShm ){
   381         -    int i;
   382         -    void **apNew;
   383         -    int nNew = iChunk+1;
   384         -    off_t nReq = nNew * LSM_SHM_CHUNK_SIZE;
   385         -    struct stat sStat;
   386         -
   387         -    /* If the shared-memory file has not been opened, open it now. */
   388         -    if( p->shmfd<=0 ){
   389         -      char *zShm = win32ShmFile(p);
   390         -      if( !zShm ) return LSM_NOMEM_BKPT;
   391         -      p->shmfd = open(zShm, O_RDWR|O_CREAT, 0644);
   392         -      lsmFree(p->pEnv, zShm);
   393         -      if( p->shmfd<0 ){ 
   394         -        return LSM_IOERR_BKPT;
   395         -      }
   396         -    }
   397         -
   398         -    /* If the shared-memory file is not large enough to contain the 
   399         -    ** requested chunk, cause it to grow.  */
   400         -    if( fstat(p->shmfd, &sStat) ){
   401         -      return LSM_IOERR_BKPT;
   402         -    }
   403         -    if( sStat.st_size<nReq ){
   404         -      if( ftruncate(p->shmfd, nReq) ){
   405         -        return LSM_IOERR_BKPT;
   406         -      }
   407         -    }
   408         -
   409         -    apNew = (void **)lsmRealloc(p->pEnv, p->apShm, sizeof(void *) * nNew);
   410         -    if( !apNew ) return LSM_NOMEM_BKPT;
   411         -    for(i=p->nShm; i<nNew; i++){
   412         -      apNew[i] = 0;
   413         -    }
   414         -    p->apShm = apNew;
   415         -    p->nShm = nNew;
   416         -  }
   417         -
   418         -  if( p->apShm[iChunk]==0 ){
   419         -    p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE, 
   420         -        PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
   421         -    );
   422         -    if( p->apShm[iChunk]==0 ) return LSM_IOERR_BKPT;
   423         -  }
   424         -
   425         -  *ppShm = p->apShm[iChunk];
   426         -  return LSM_OK;
   427         -}
   428         -
   429         -void lsmWin32OsShmBarrier(void){
   430         -}
   431         -
   432         -int lsmWin32OsShmUnmap(lsm_file *pFile, int bDelete){
   433         -  Win32File *p = (Win32File *)pFile;
   434         -  if( p->shmfd>0 ){
   435         -    int i;
   436         -    for(i=0; i<p->nShm; i++){
   437         -      if( p->apShm[i] ){
   438         -        munmap(p->apShm[i], LSM_SHM_CHUNK_SIZE);
   439         -        p->apShm[i] = 0;
   440         -      }
   441         -    }
   442         -    close(p->shmfd);
   443         -    p->shmfd = 0;
   444         -    if( bDelete ){
   445         -      char *zShm = win32ShmFile(p);
   446         -      if( zShm ) unlink(zShm);
   447         -      lsmFree(p->pEnv, zShm);
   448         -    }
   449         -  }
   450         -  return LSM_OK;
   451         -}
   452         -
   453         -
   454         -static int lsmWin32OsClose(lsm_file *pFile){
   455         -  Win32File *p = (Win32File *)pFile;
   456         -  lsmWin32OsShmUnmap(pFile, 0);
   457         -  if( p->pMap ) munmap(p->pMap, p->nMap);
   458         -  close(p->fd);
   459         -  lsm_free(p->pEnv, p->apShm);
   460         -  lsm_free(p->pEnv, p);
   461         -  return LSM_OK;
   462         -}
   463         -
   464    431   static int lsmWin32OsSleep(lsm_env *pEnv, int us){
   465         -  usleep(us);
          432  +  unused_parameter(pEnv);
          433  +  Sleep((us + 999) / 1000);
   466    434     return LSM_OK;
   467    435   }
   468    436   
   469    437   /****************************************************************************
   470    438   ** Memory allocation routines.
   471    439   */
   472         -#define BLOCK_HDR_SIZE ROUND8( sizeof(size_t) )
   473    440   
   474    441   static void *lsmWin32OsMalloc(lsm_env *pEnv, size_t N){
   475         -  unsigned char * m;
   476         -  N += BLOCK_HDR_SIZE;
   477         -  m = (unsigned char *)malloc(N);
   478         -  *((size_t*)m) = N;
   479         -  return m + BLOCK_HDR_SIZE;
          442  +  return HeapAlloc(GetProcessHeap(), 0, (SIZE_T)N);
   480    443   }
   481    444   
   482    445   static void lsmWin32OsFree(lsm_env *pEnv, void *p){
   483         -  if(p){
   484         -    free( ((unsigned char *)p) - BLOCK_HDR_SIZE );
          446  +  if( p ){
          447  +    HeapFree(GetProcessHeap(), 0, p);
   485    448     }
   486    449   }
   487    450   
   488    451   static void *lsmWin32OsRealloc(lsm_env *pEnv, void *p, size_t N){
   489         -  unsigned char * m = (unsigned char *)p;
   490         -  if(1>N){
   491         -    lsmWin32OsFree( pEnv, p );
          452  +  unsigned char *m = (unsigned char *)p;
          453  +  if( 1>N ){
          454  +    lsmWin32OsFree(pEnv, p);
   492    455       return NULL;
   493         -  }else if(NULL==p){
          456  +  }else if( NULL==p ){
   494    457       return lsmWin32OsMalloc(pEnv, N);
   495    458     }else{
   496         -    void * re = NULL;
   497         -    m -= BLOCK_HDR_SIZE;
   498    459   #if 0 /* arguable: don't shrink */
   499         -    size_t * sz = (size_t*)m;
   500         -    if(*sz >= (size_t)N){
          460  +    SIZE_T sz = HeapSize(GetProcessHeap(), 0, m);
          461  +    if( sz>=(SIZE_T)N ){
   501    462         return p;
   502    463       }
   503    464   #endif
   504         -    re = realloc( m, N + BLOCK_HDR_SIZE );
   505         -    if(re){
   506         -      m = (unsigned char *)re;
   507         -      *((size_t*)m) = N;
   508         -      return m + BLOCK_HDR_SIZE;
   509         -    }else{
   510         -      return NULL;
   511         -    }
          465  +    return HeapReAlloc(GetProcessHeap(), 0, m, N);
   512    466     }
   513    467   }
   514    468   
   515    469   static size_t lsmWin32OsMSize(lsm_env *pEnv, void *p){
   516         -  unsigned char * m = (unsigned char *)p;
   517         -  return *((size_t*)(m-BLOCK_HDR_SIZE));
          470  +  return (size_t)HeapSize(GetProcessHeap(), 0, p);
   518    471   }
   519         -#undef BLOCK_HDR_SIZE
   520    472   
   521    473   
   522         -#ifdef LSM_MUTEX_WIN32 
          474  +#ifdef LSM_MUTEX_WIN32
   523    475   /*************************************************************************
   524         -** Mutex methods for pthreads based systems.  If LSM_MUTEX_WIN32 is
   525         -** missing then a no-op implementation of mutexes found below will be 
          476  +** Mutex methods for Win32 based systems.  If LSM_MUTEX_WIN32 is
          477  +** missing then a no-op implementation of mutexes found below will be
   526    478   ** used instead.
   527    479   */
   528         -#include <pthread.h>
          480  +#include "windows.h"
   529    481   
   530         -typedef struct PthreadMutex PthreadMutex;
   531         -struct PthreadMutex {
          482  +typedef struct Win32Mutex Win32Mutex;
          483  +struct Win32Mutex {
   532    484     lsm_env *pEnv;
   533         -  pthread_mutex_t mutex;
          485  +  CRITICAL_SECTION mutex;
   534    486   #ifdef LSM_DEBUG
   535         -  pthread_t owner;
          487  +  DWORD owner;
   536    488   #endif
   537    489   };
          490  +
          491  +#ifndef WIN32_MUTEX_INITIALIZER
          492  +# define WIN32_MUTEX_INITIALIZER { 0 }
          493  +#endif
   538    494   
   539    495   #ifdef LSM_DEBUG
   540         -# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER, 0 }
          496  +# define LSM_WIN32_STATIC_MUTEX { 0, WIN32_MUTEX_INITIALIZER, 0 }
   541    497   #else
   542         -# define LSM_PTHREAD_STATIC_MUTEX { 0, PTHREAD_MUTEX_INITIALIZER }
          498  +# define LSM_WIN32_STATIC_MUTEX { 0, WIN32_MUTEX_INITIALIZER }
   543    499   #endif
   544    500   
   545    501   static int lsmWin32OsMutexStatic(
   546    502     lsm_env *pEnv,
   547    503     int iMutex,
   548    504     lsm_mutex **ppStatic
   549    505   ){
   550         -  static PthreadMutex sMutex[2] = {
   551         -    LSM_PTHREAD_STATIC_MUTEX,
   552         -    LSM_PTHREAD_STATIC_MUTEX
          506  +  static volatile LONG initialized = 0;
          507  +  static Win32Mutex sMutex[2] = {
          508  +    LSM_WIN32_STATIC_MUTEX,
          509  +    LSM_WIN32_STATIC_MUTEX
   553    510     };
   554    511   
   555    512     assert( iMutex==LSM_MUTEX_GLOBAL || iMutex==LSM_MUTEX_HEAP );
   556    513     assert( LSM_MUTEX_GLOBAL==1 && LSM_MUTEX_HEAP==2 );
   557    514   
          515  +  if( InterlockedCompareExchange(&initialized, 1, 0)==0 ){
          516  +    int i;
          517  +    for(i=0; i<array_size(sMutex); i++){
          518  +      InitializeCriticalSection(&sMutex[i].mutex);
          519  +    }
          520  +  }
   558    521     *ppStatic = (lsm_mutex *)&sMutex[iMutex-1];
   559    522     return LSM_OK;
   560    523   }
   561    524   
   562    525   static int lsmWin32OsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
   563         -  PthreadMutex *pMutex;           /* Pointer to new mutex */
   564         -  pthread_mutexattr_t attr;       /* Attributes object */
          526  +  Win32Mutex *pMutex;           /* Pointer to new mutex */
   565    527   
   566         -  pMutex = (PthreadMutex *)lsmMallocZero(pEnv, sizeof(PthreadMutex));
          528  +  pMutex = (Win32Mutex *)lsmMallocZero(pEnv, sizeof(Win32Mutex));
   567    529     if( !pMutex ) return LSM_NOMEM_BKPT;
   568    530   
   569    531     pMutex->pEnv = pEnv;
   570         -  pthread_mutexattr_init(&attr);
   571         -  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
   572         -  pthread_mutex_init(&pMutex->mutex, &attr);
   573         -  pthread_mutexattr_destroy(&attr);
          532  +  InitializeCriticalSection(&pMutex->mutex);
   574    533   
   575    534     *ppNew = (lsm_mutex *)pMutex;
   576    535     return LSM_OK;
   577    536   }
   578    537   
   579    538   static void lsmWin32OsMutexDel(lsm_mutex *p){
   580         -  PthreadMutex *pMutex = (PthreadMutex *)p;
   581         -  pthread_mutex_destroy(&pMutex->mutex);
          539  +  Win32Mutex *pMutex = (Win32Mutex *)p;
          540  +  DeleteCriticalSection(&pMutex->mutex);
   582    541     lsmFree(pMutex->pEnv, pMutex);
   583    542   }
   584    543   
   585    544   static void lsmWin32OsMutexEnter(lsm_mutex *p){
   586         -  PthreadMutex *pMutex = (PthreadMutex *)p;
   587         -  pthread_mutex_lock(&pMutex->mutex);
          545  +  Win32Mutex *pMutex = (Win32Mutex *)p;
          546  +  EnterCriticalSection(&pMutex->mutex);
   588    547   
   589    548   #ifdef LSM_DEBUG
   590         -  assert( !pthread_equal(pMutex->owner, pthread_self()) );
   591         -  pMutex->owner = pthread_self();
   592         -  assert( pthread_equal(pMutex->owner, pthread_self()) );
          549  +  assert( pMutex->owner!=GetCurrentThreadId() );
          550  +  pMutex->owner = GetCurrentThreadId();
          551  +  assert( pMutex->owner==GetCurrentThreadId() );
   593    552   #endif
   594    553   }
   595    554   
   596    555   static int lsmWin32OsMutexTry(lsm_mutex *p){
   597         -  int ret;
   598         -  PthreadMutex *pMutex = (PthreadMutex *)p;
   599         -  ret = pthread_mutex_trylock(&pMutex->mutex);
          556  +  BOOL bRet;
          557  +  Win32Mutex *pMutex = (Win32Mutex *)p;
          558  +  bRet = TryEnterCriticalSection(&pMutex->mutex);
   600    559   #ifdef LSM_DEBUG
   601         -  if( ret==0 ){
   602         -    assert( !pthread_equal(pMutex->owner, pthread_self()) );
   603         -    pMutex->owner = pthread_self();
   604         -    assert( pthread_equal(pMutex->owner, pthread_self()) );
          560  +  if( bRet ){
          561  +    assert( pMutex->owner!=GetCurrentThreadId() );
          562  +    pMutex->owner = GetCurrentThreadId();
          563  +    assert( pMutex->owner==GetCurrentThreadId() );
   605    564     }
   606    565   #endif
   607         -  return ret;
          566  +  return !bRet;
   608    567   }
   609    568   
   610    569   static void lsmWin32OsMutexLeave(lsm_mutex *p){
   611         -  PthreadMutex *pMutex = (PthreadMutex *)p;
          570  +  Win32Mutex *pMutex = (Win32Mutex *)p;
   612    571   #ifdef LSM_DEBUG
   613         -  assert( pthread_equal(pMutex->owner, pthread_self()) );
          572  +  assert( pMutex->owner==GetCurrentThreadId() );
   614    573     pMutex->owner = 0;
   615         -  assert( !pthread_equal(pMutex->owner, pthread_self()) );
          574  +  assert( pMutex->owner!=GetCurrentThreadId() );
   616    575   #endif
   617         -  pthread_mutex_unlock(&pMutex->mutex);
          576  +  LeaveCriticalSection(&pMutex->mutex);
   618    577   }
   619    578   
   620    579   #ifdef LSM_DEBUG
   621    580   static int lsmWin32OsMutexHeld(lsm_mutex *p){
   622         -  PthreadMutex *pMutex = (PthreadMutex *)p;
   623         -  return pMutex ? pthread_equal(pMutex->owner, pthread_self()) : 1;
          581  +  Win32Mutex *pMutex = (Win32Mutex *)p;
          582  +  return pMutex ? pMutex->owner==GetCurrentThreadId() : 1;
   624    583   }
   625    584   static int lsmWin32OsMutexNotHeld(lsm_mutex *p){
   626         -  PthreadMutex *pMutex = (PthreadMutex *)p;
   627         -  return pMutex ? !pthread_equal(pMutex->owner, pthread_self()) : 1;
          585  +  Win32Mutex *pMutex = (Win32Mutex *)p;
          586  +  return pMutex ? pMutex->owner!=GetCurrentThreadId() : 1;
   628    587   }
   629    588   #endif
   630    589   /*
   631    590   ** End of pthreads mutex implementation.
   632    591   *************************************************************************/
   633    592   #else
   634    593   /*************************************************************************
................................................................................
   657    616   static int lsmWin32OsMutexNew(lsm_env *pEnv, lsm_mutex **ppNew){
   658    617     NoopMutex *p;
   659    618     p = (NoopMutex *)lsmMallocZero(pEnv, sizeof(NoopMutex));
   660    619     if( p ) p->pEnv = pEnv;
   661    620     *ppNew = (lsm_mutex *)p;
   662    621     return (p ? LSM_OK : LSM_NOMEM_BKPT);
   663    622   }
   664         -static void lsmWin32OsMutexDel(lsm_mutex *pMutex)  { 
          623  +static void lsmWin32OsMutexDel(lsm_mutex *pMutex)  {
   665    624     NoopMutex *p = (NoopMutex *)pMutex;
   666    625     assert( p->bStatic==0 && p->pEnv );
   667    626     lsmFree(p->pEnv, p);
   668    627   }
   669         -static void lsmWin32OsMutexEnter(lsm_mutex *pMutex){ 
          628  +static void lsmWin32OsMutexEnter(lsm_mutex *pMutex){
   670    629     NoopMutex *p = (NoopMutex *)pMutex;
   671    630     assert( p->bHeld==0 );
   672    631     p->bHeld = 1;
   673    632   }
   674    633   static int lsmWin32OsMutexTry(lsm_mutex *pMutex){
   675    634     NoopMutex *p = (NoopMutex *)pMutex;
   676    635     assert( p->bHeld==0 );
   677    636     p->bHeld = 1;
   678    637     return 0;
   679    638   }
   680         -static void lsmWin32OsMutexLeave(lsm_mutex *pMutex){ 
          639  +static void lsmWin32OsMutexLeave(lsm_mutex *pMutex){
   681    640     NoopMutex *p = (NoopMutex *)pMutex;
   682    641     assert( p->bHeld==1 );
   683    642     p->bHeld = 0;
   684    643   }
   685    644   #ifdef LSM_DEBUG
   686         -static int lsmWin32OsMutexHeld(lsm_mutex *pMutex){ 
          645  +static int lsmWin32OsMutexHeld(lsm_mutex *pMutex){
   687    646     NoopMutex *p = (NoopMutex *)pMutex;
   688    647     return p ? p->bHeld : 1;
   689    648   }
   690         -static int lsmWin32OsMutexNotHeld(lsm_mutex *pMutex){ 
          649  +static int lsmWin32OsMutexNotHeld(lsm_mutex *pMutex){
   691    650     NoopMutex *p = (NoopMutex *)pMutex;
   692    651     return p ? !p->bHeld : 1;
   693    652   }
   694    653   #endif
   695    654   /***************************************************************************/
   696    655   #endif /* else LSM_MUTEX_NONE */
   697    656