/ Check-in [dc46156a]
Login

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

Overview
Comment:Updates to the OS/2 implementation from Rich Walsh.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: dc46156a2237701679433779b871844f4f2abe4b
User & Date: drh 2011-03-09 11:04:07
Context
2011-03-09
21:02
Omit unnecessary OP_Next and OP_Prev operators when uniqueness constraints guarantee that the code will only make one pass through the loop. check-in: f000c9b2 user: drh tags: trunk
11:04
Updates to the OS/2 implementation from Rich Walsh. check-in: dc46156a user: drh tags: trunk
2011-03-08
16:39
Merge the syscall-override changes into trunk. check-in: 36d79e6f user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/mutex_os2.c.

    27     27   /*
    28     28   ** The mutex object
    29     29   ** Each recursive mutex is an instance of the following structure.
    30     30   */
    31     31   struct sqlite3_mutex {
    32     32     HMTX mutex;       /* Mutex controlling the lock */
    33     33     int  id;          /* Mutex type */
    34         -  int  nRef;        /* Number of references */
    35         -  TID  owner;       /* Thread holding this mutex */
           34  +#ifdef SQLITE_DEBUG
           35  + int   trace;       /* True to trace changes */
           36  +#endif
    36     37   };
    37     38   
    38         -#define OS2_MUTEX_INITIALIZER   0,0,0,0
           39  +#ifdef SQLITE_DEBUG
           40  +#define SQLITE3_MUTEX_INITIALIZER { 0, 0, 0 }
           41  +#else
           42  +#define SQLITE3_MUTEX_INITIALIZER { 0, 0 }
           43  +#endif
    39     44   
    40     45   /*
    41     46   ** Initialize and deinitialize the mutex subsystem.
    42     47   */
    43     48   static int os2MutexInit(void){ return SQLITE_OK; }
    44     49   static int os2MutexEnd(void){ return SQLITE_OK; }
    45     50   
................................................................................
    47     52   ** The sqlite3_mutex_alloc() routine allocates a new
    48     53   ** mutex and returns a pointer to it.  If it returns NULL
    49     54   ** that means that a mutex could not be allocated. 
    50     55   ** SQLite will unwind its stack and return an error.  The argument
    51     56   ** to sqlite3_mutex_alloc() is one of these integer constants:
    52     57   **
    53     58   ** <ul>
    54         -** <li>  SQLITE_MUTEX_FAST               0
    55         -** <li>  SQLITE_MUTEX_RECURSIVE          1
    56         -** <li>  SQLITE_MUTEX_STATIC_MASTER      2
    57         -** <li>  SQLITE_MUTEX_STATIC_MEM         3
    58         -** <li>  SQLITE_MUTEX_STATIC_PRNG        4
           59  +** <li>  SQLITE_MUTEX_FAST
           60  +** <li>  SQLITE_MUTEX_RECURSIVE
           61  +** <li>  SQLITE_MUTEX_STATIC_MASTER
           62  +** <li>  SQLITE_MUTEX_STATIC_MEM
           63  +** <li>  SQLITE_MUTEX_STATIC_MEM2
           64  +** <li>  SQLITE_MUTEX_STATIC_PRNG
           65  +** <li>  SQLITE_MUTEX_STATIC_LRU
           66  +** <li>  SQLITE_MUTEX_STATIC_LRU2
    59     67   ** </ul>
    60     68   **
    61     69   ** The first two constants cause sqlite3_mutex_alloc() to create
    62     70   ** a new mutex.  The new mutex is recursive when SQLITE_MUTEX_RECURSIVE
    63     71   ** is used but not necessarily so when SQLITE_MUTEX_FAST is used.
    64     72   ** The mutex implementation does not need to make a distinction
    65     73   ** between SQLITE_MUTEX_RECURSIVE and SQLITE_MUTEX_FAST if it does
    66     74   ** not want to.  But SQLite will only request a recursive mutex in
    67     75   ** cases where it really needs one.  If a faster non-recursive mutex
    68     76   ** implementation is available on the host platform, the mutex subsystem
    69     77   ** might return such a mutex in response to SQLITE_MUTEX_FAST.
    70     78   **
    71     79   ** The other allowed parameters to sqlite3_mutex_alloc() each return
    72         -** a pointer to a static preexisting mutex.  Three static mutexes are
           80  +** a pointer to a static preexisting mutex.  Six static mutexes are
    73     81   ** used by the current version of SQLite.  Future versions of SQLite
    74     82   ** may add additional static mutexes.  Static mutexes are for internal
    75     83   ** use by SQLite only.  Applications that use SQLite mutexes should
    76     84   ** use only the dynamic mutexes returned by SQLITE_MUTEX_FAST or
    77     85   ** SQLITE_MUTEX_RECURSIVE.
    78     86   **
    79     87   ** Note that if one of the dynamic mutex parameters (SQLITE_MUTEX_FAST
................................................................................
    95    103             p = NULL;
    96    104           }
    97    105         }
    98    106         break;
    99    107       }
   100    108       default: {
   101    109         static volatile int isInit = 0;
   102         -      static sqlite3_mutex staticMutexes[] = {
   103         -        { OS2_MUTEX_INITIALIZER, },
   104         -        { OS2_MUTEX_INITIALIZER, },
   105         -        { OS2_MUTEX_INITIALIZER, },
   106         -        { OS2_MUTEX_INITIALIZER, },
   107         -        { OS2_MUTEX_INITIALIZER, },
   108         -        { OS2_MUTEX_INITIALIZER, },
          110  +      static sqlite3_mutex staticMutexes[6] = {
          111  +        SQLITE3_MUTEX_INITIALIZER,
          112  +        SQLITE3_MUTEX_INITIALIZER,
          113  +        SQLITE3_MUTEX_INITIALIZER,
          114  +        SQLITE3_MUTEX_INITIALIZER,
          115  +        SQLITE3_MUTEX_INITIALIZER,
          116  +        SQLITE3_MUTEX_INITIALIZER,
   109    117         };
   110    118         if ( !isInit ){
   111    119           APIRET rc;
   112    120           PTIB ptib;
   113    121           PPIB ppib;
   114    122           HMTX mutex;
   115    123           char name[32];
................................................................................
   147    155   
   148    156   
   149    157   /*
   150    158   ** This routine deallocates a previously allocated mutex.
   151    159   ** SQLite is careful to deallocate every mutex that it allocates.
   152    160   */
   153    161   static void os2MutexFree(sqlite3_mutex *p){
   154         -  if( p==0 ) return;
   155         -  assert( p->nRef==0 );
          162  +#ifdef SQLITE_DEBUG
          163  +  TID tid;
          164  +  PID pid;
          165  +  ULONG ulCount;
          166  +  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
          167  +  assert( ulCount==0 );
   156    168     assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
          169  +#endif
   157    170     DosCloseMutexSem( p->mutex );
   158    171     sqlite3_free( p );
   159    172   }
   160    173   
   161    174   #ifdef SQLITE_DEBUG
   162    175   /*
   163    176   ** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
................................................................................
   164    177   ** intended for use inside assert() statements.
   165    178   */
   166    179   static int os2MutexHeld(sqlite3_mutex *p){
   167    180     TID tid;
   168    181     PID pid;
   169    182     ULONG ulCount;
   170    183     PTIB ptib;
   171         -  if( p!=0 ) {
   172         -    DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
   173         -  } else {
   174         -    DosGetInfoBlocks(&ptib, NULL);
   175         -    tid = ptib->tib_ptib2->tib2_ultid;
   176         -  }
   177         -  return p==0 || (p->nRef!=0 && p->owner==tid);
          184  +  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
          185  +  if( ulCount==0 || ( ulCount>1 && p->id!=SQLITE_MUTEX_RECURSIVE ) )
          186  +    return 0;
          187  +  DosGetInfoBlocks(&ptib, NULL);
          188  +  return tid==ptib->tib_ptib2->tib2_ultid;
   178    189   }
   179    190   static int os2MutexNotheld(sqlite3_mutex *p){
   180    191     TID tid;
   181    192     PID pid;
   182    193     ULONG ulCount;
   183    194     PTIB ptib;
   184         -  if( p!= 0 ) {
   185         -    DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
   186         -  } else {
   187         -    DosGetInfoBlocks(&ptib, NULL);
   188         -    tid = ptib->tib_ptib2->tib2_ultid;
   189         -  }
   190         -  return p==0 || p->nRef==0 || p->owner!=tid;
          195  +  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
          196  +  if( ulCount==0 )
          197  +    return 1;
          198  +  DosGetInfoBlocks(&ptib, NULL);
          199  +  return tid!=ptib->tib_ptib2->tib2_ultid;
          200  +}
          201  +static void os2MutexTrace(sqlite3_mutex *p, char *pAction){
          202  +  TID   tid;
          203  +  PID   pid;
          204  +  ULONG ulCount;
          205  +  DosQueryMutexSem(p->mutex, &pid, &tid, &ulCount);
          206  +  printf("%s mutex %p (%d) with nRef=%ld\n", pAction, (void*)p, p->trace, ulCount);
   191    207   }
   192    208   #endif
   193    209   
   194    210   /*
   195    211   ** The sqlite3_mutex_enter() and sqlite3_mutex_try() routines attempt
   196    212   ** to enter a mutex.  If another thread is already within the mutex,
   197    213   ** sqlite3_mutex_enter() will block and sqlite3_mutex_try() will return
................................................................................
   199    215   ** upon successful entry.  Mutexes created using SQLITE_MUTEX_RECURSIVE can
   200    216   ** be entered multiple times by the same thread.  In such cases the,
   201    217   ** mutex must be exited an equal number of times before another thread
   202    218   ** can enter.  If the same thread tries to enter any other kind of mutex
   203    219   ** more than once, the behavior is undefined.
   204    220   */
   205    221   static void os2MutexEnter(sqlite3_mutex *p){
   206         -  TID tid;
   207         -  PID holder1;
   208         -  ULONG holder2;
   209         -  if( p==0 ) return;
   210    222     assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
   211    223     DosRequestMutexSem(p->mutex, SEM_INDEFINITE_WAIT);
   212         -  DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
   213         -  p->owner = tid;
   214         -  p->nRef++;
          224  +#ifdef SQLITE_DEBUG
          225  +  if( p->trace ) os2MutexTrace(p, "enter");
          226  +#endif
   215    227   }
   216    228   static int os2MutexTry(sqlite3_mutex *p){
   217         -  int rc;
   218         -  TID tid;
   219         -  PID holder1;
   220         -  ULONG holder2;
   221         -  if( p==0 ) return SQLITE_OK;
          229  +  int rc = SQLITE_BUSY;
   222    230     assert( p->id==SQLITE_MUTEX_RECURSIVE || os2MutexNotheld(p) );
   223         -  if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR) {
   224         -    DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
   225         -    p->owner = tid;
   226         -    p->nRef++;
          231  +  if( DosRequestMutexSem(p->mutex, SEM_IMMEDIATE_RETURN) == NO_ERROR ) {
   227    232       rc = SQLITE_OK;
   228         -  } else {
   229         -    rc = SQLITE_BUSY;
          233  +#ifdef SQLITE_DEBUG
          234  +    if( p->trace ) os2MutexTrace(p, "try");
          235  +#endif
   230    236     }
   231         -
   232    237     return rc;
   233    238   }
   234    239   
   235    240   /*
   236    241   ** The sqlite3_mutex_leave() routine exits a mutex that was
   237    242   ** previously entered by the same thread.  The behavior
   238    243   ** is undefined if the mutex is not currently entered or
   239    244   ** is not currently allocated.  SQLite will never do either.
   240    245   */
   241    246   static void os2MutexLeave(sqlite3_mutex *p){
   242         -  TID tid;
   243         -  PID holder1;
   244         -  ULONG holder2;
   245         -  if( p==0 ) return;
   246         -  assert( p->nRef>0 );
   247         -  DosQueryMutexSem(p->mutex, &holder1, &tid, &holder2);
   248         -  assert( p->owner==tid );
   249         -  p->nRef--;
   250         -  assert( p->nRef==0 || p->id==SQLITE_MUTEX_RECURSIVE );
          247  +  assert( os2MutexHeld(p) );
   251    248     DosReleaseMutexSem(p->mutex);
          249  +#ifdef SQLITE_DEBUG
          250  +  if( p->trace ) os2MutexTrace(p, "leave");
          251  +#endif
   252    252   }
   253    253   
   254         -sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
          254  +SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
   255    255     static const sqlite3_mutex_methods sMutex = {
   256    256       os2MutexInit,
   257    257       os2MutexEnd,
   258    258       os2MutexAlloc,
   259    259       os2MutexFree,
   260    260       os2MutexEnter,
   261    261       os2MutexTry,
   262    262       os2MutexLeave,
   263    263   #ifdef SQLITE_DEBUG
   264    264       os2MutexHeld,
   265    265       os2MutexNotheld
          266  +#else
          267  +    0,
          268  +    0
   266    269   #endif
   267    270     };
   268    271   
   269    272     return &sMutex;
   270    273   }
   271    274   #endif /* SQLITE_MUTEX_OS2 */

Changes to src/os_os2.c.

   642    642   }
   643    643   
   644    644   /*
   645    645   ** This vector defines all the methods that can operate on an
   646    646   ** sqlite3_file for os2.
   647    647   */
   648    648   static const sqlite3_io_methods os2IoMethod = {
   649         -  1,                        /* iVersion */
   650         -  os2Close,
   651         -  os2Read,
   652         -  os2Write,
   653         -  os2Truncate,
   654         -  os2Sync,
   655         -  os2FileSize,
   656         -  os2Lock,
   657         -  os2Unlock,
   658         -  os2CheckReservedLock,
   659         -  os2FileControl,
   660         -  os2SectorSize,
   661         -  os2DeviceCharacteristics
          649  +  1,                              /* iVersion */
          650  +  os2Close,                       /* xClose */
          651  +  os2Read,                        /* xRead */
          652  +  os2Write,                       /* xWrite */
          653  +  os2Truncate,                    /* xTruncate */
          654  +  os2Sync,                        /* xSync */
          655  +  os2FileSize,                    /* xFileSize */
          656  +  os2Lock,                        /* xLock */
          657  +  os2Unlock,                      /* xUnlock */
          658  +  os2CheckReservedLock,           /* xCheckReservedLock */
          659  +  os2FileControl,                 /* xFileControl */
          660  +  os2SectorSize,                  /* xSectorSize */
          661  +  os2DeviceCharacteristics,       /* xDeviceCharacteristics */
          662  +  0,                              /* xShmMap */
          663  +  0,                              /* xShmLock */
          664  +  0,                              /* xShmBarrier */
          665  +  0                               /* xShmUnmap */
   662    666   };
   663    667   
   664    668   /***************************************************************************
   665    669   ** Here ends the I/O methods that form the sqlite3_io_methods object.
   666    670   **
   667    671   ** The next block of code implements the VFS methods.
   668    672   ****************************************************************************/
................................................................................
   746    750   
   747    751   
   748    752   /*
   749    753   ** Open a file.
   750    754   */
   751    755   static int os2Open(
   752    756     sqlite3_vfs *pVfs,            /* Not used */
   753         -  const char *zName,            /* Name of the file */
          757  +  const char *zName,            /* Name of the file (UTF-8) */
   754    758     sqlite3_file *id,             /* Write the SQLite file handle here */
   755    759     int flags,                    /* Open mode flags */
   756    760     int *pOutFlags                /* Status return flags */
   757    761   ){
   758    762     HFILE h;
   759         -  ULONG ulFileAttribute = FILE_NORMAL;
   760    763     ULONG ulOpenFlags = 0;
   761    764     ULONG ulOpenMode = 0;
          765  +  ULONG ulAction = 0;
          766  +  ULONG rc;
   762    767     os2File *pFile = (os2File*)id;
   763         -  APIRET rc = NO_ERROR;
   764         -  ULONG ulAction;
          768  +  const char *zUtf8Name = zName;
   765    769     char *zNameCp;
   766         -  char zTmpname[CCHMAXPATH+1];    /* Buffer to hold name of temp file */
          770  +  char  zTmpname[CCHMAXPATH];
          771  +
          772  +  int isExclusive  = (flags & SQLITE_OPEN_EXCLUSIVE);
          773  +  int isDelete     = (flags & SQLITE_OPEN_DELETEONCLOSE);
          774  +  int isCreate     = (flags & SQLITE_OPEN_CREATE);
          775  +  int isReadWrite  = (flags & SQLITE_OPEN_READWRITE);
          776  +#ifndef NDEBUG
          777  +  int isReadonly   = (flags & SQLITE_OPEN_READONLY);
          778  +  int eType        = (flags & 0xFFFFFF00);
          779  +  int isOpenJournal = (isCreate && (
          780  +        eType==SQLITE_OPEN_MASTER_JOURNAL 
          781  +     || eType==SQLITE_OPEN_MAIN_JOURNAL 
          782  +     || eType==SQLITE_OPEN_WAL
          783  +  ));
          784  +#endif
          785  +
          786  +  UNUSED_PARAMETER(pVfs);
          787  +  assert( id!=0 );
          788  +
          789  +  /* Check the following statements are true: 
          790  +  **
          791  +  **   (a) Exactly one of the READWRITE and READONLY flags must be set, and 
          792  +  **   (b) if CREATE is set, then READWRITE must also be set, and
          793  +  **   (c) if EXCLUSIVE is set, then CREATE must also be set.
          794  +  **   (d) if DELETEONCLOSE is set, then CREATE must also be set.
          795  +  */
          796  +  assert((isReadonly==0 || isReadWrite==0) && (isReadWrite || isReadonly));
          797  +  assert(isCreate==0 || isReadWrite);
          798  +  assert(isExclusive==0 || isCreate);
          799  +  assert(isDelete==0 || isCreate);
          800  +
          801  +  /* The main DB, main journal, WAL file and master journal are never 
          802  +  ** automatically deleted. Nor are they ever temporary files.  */
          803  +  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
          804  +  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
          805  +  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
          806  +  assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
          807  +
          808  +  /* Assert that the upper layer has set one of the "file-type" flags. */
          809  +  assert( eType==SQLITE_OPEN_MAIN_DB      || eType==SQLITE_OPEN_TEMP_DB 
          810  +       || eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL 
          811  +       || eType==SQLITE_OPEN_SUBJOURNAL   || eType==SQLITE_OPEN_MASTER_JOURNAL 
          812  +       || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
          813  +  );
          814  +
          815  +  memset( pFile, 0, sizeof(*pFile) );
          816  +  pFile->pMethod = &os2IoMethod;
   767    817   
   768    818     /* If the second argument to this function is NULL, generate a 
   769    819     ** temporary file name to use 
   770    820     */
   771         -  if( !zName ){
   772         -    int rc = getTempname(CCHMAXPATH+1, zTmpname);
          821  +  if( !zUtf8Name ){
          822  +    assert(isDelete && !isOpenJournal);
          823  +    rc = getTempname(CCHMAXPATH, zTmpname);
   773    824       if( rc!=SQLITE_OK ){
   774    825         return rc;
   775    826       }
   776         -    zName = zTmpname;
          827  +    zUtf8Name = zTmpname;
   777    828     }
   778    829   
   779         -
   780         -  memset( pFile, 0, sizeof(*pFile) );
   781         -
   782         -  OSTRACE(( "OPEN want %d\n", flags ));
   783         -
   784         -  if( flags & SQLITE_OPEN_READWRITE ){
          830  +  if( isReadWrite ){
   785    831       ulOpenMode |= OPEN_ACCESS_READWRITE;
   786         -    OSTRACE(( "OPEN read/write\n" ));
   787    832     }else{
   788    833       ulOpenMode |= OPEN_ACCESS_READONLY;
   789         -    OSTRACE(( "OPEN read only\n" ));
   790    834     }
   791    835   
   792         -  if( flags & SQLITE_OPEN_CREATE ){
   793         -    ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
   794         -    OSTRACE(( "OPEN open new/create\n" ));
   795         -  }else{
   796         -    ulOpenFlags |= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
   797         -    OSTRACE(( "OPEN open existing\n" ));
   798         -  }
   799         -
   800         -  if( flags & SQLITE_OPEN_MAIN_DB ){
   801         -    ulOpenMode |= OPEN_SHARE_DENYNONE;
   802         -    OSTRACE(( "OPEN share read/write\n" ));
   803         -  }else{
   804         -    ulOpenMode |= OPEN_SHARE_DENYWRITE;
   805         -    OSTRACE(( "OPEN share read only\n" ));
   806         -  }
   807         -
   808         -  if( flags & SQLITE_OPEN_DELETEONCLOSE ){
   809         -    char pathUtf8[CCHMAXPATH];
   810         -#ifdef NDEBUG /* when debugging we want to make sure it is deleted */
   811         -    ulFileAttribute = FILE_HIDDEN;
   812         -#endif
   813         -    os2FullPathname( pVfs, zName, CCHMAXPATH, pathUtf8 );
   814         -    pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
   815         -    OSTRACE(( "OPEN hidden/delete on close file attributes\n" ));
   816         -  }else{
   817         -    pFile->pathToDel = NULL;
   818         -    OSTRACE(( "OPEN normal file attribute\n" ));
   819         -  }
   820         -
   821         -  /* always open in random access mode for possibly better speed */
          836  +  /* Open in random access mode for possibly better speed.  Allow full
          837  +  ** sharing because file locks will provide exclusive access when needed.
          838  +  */
   822    839     ulOpenMode |= OPEN_FLAGS_RANDOM;
   823    840     ulOpenMode |= OPEN_FLAGS_FAIL_ON_ERROR;
   824    841     ulOpenMode |= OPEN_FLAGS_NOINHERIT;
          842  +  ulOpenMode |= OPEN_SHARE_DENYNONE;
   825    843   
   826         -  zNameCp = convertUtf8PathToCp( zName );
          844  +  /* SQLITE_OPEN_EXCLUSIVE is used to make sure that a new file is 
          845  +  ** created. SQLite doesn't use it to indicate "exclusive access" 
          846  +  ** as it is usually understood.
          847  +  */
          848  +  if( isExclusive ){
          849  +    /* Creates a new file, only if it does not already exist. */
          850  +    /* If the file exists, it fails. */
          851  +    ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
          852  +  }else if( isCreate ){
          853  +    /* Open existing file, or create if it doesn't exist */
          854  +    ulOpenFlags |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
          855  +  }else{
          856  +    /* Opens a file, only if it exists. */
          857  +    ulOpenFlags |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
          858  +  }
          859  +
          860  +  /* For DELETEONCLOSE, save a pointer to the converted filename */
          861  +  if( isDelete ){
          862  +    char pathUtf8[CCHMAXPATH];
          863  +    os2FullPathname( pVfs, zUtf8Name, CCHMAXPATH, pathUtf8 );
          864  +    pFile->pathToDel = convertUtf8PathToCp( pathUtf8 );
          865  +  }
          866  +
          867  +  zNameCp = convertUtf8PathToCp( zUtf8Name );
   827    868     rc = DosOpen( (PSZ)zNameCp,
   828    869                   &h,
   829    870                   &ulAction,
   830    871                   0L,
   831         -                ulFileAttribute,
          872  +                FILE_NORMAL,
   832    873                   ulOpenFlags,
   833    874                   ulOpenMode,
   834    875                   (PEAOP2)NULL );
   835    876     free( zNameCp );
          877  +
   836    878     if( rc != NO_ERROR ){
   837         -    OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulAttr=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
   838         -              rc, zName, ulAction, ulFileAttribute, ulOpenFlags, ulOpenMode ));
          879  +    OSTRACE(( "OPEN Invalid handle rc=%d: zName=%s, ulAction=%#lx, ulFlags=%#lx, ulMode=%#lx\n",
          880  +              rc, zUtf8Name, ulAction, ulOpenFlags, ulOpenMode ));
   839    881       if( pFile->pathToDel )
   840    882         free( pFile->pathToDel );
   841    883       pFile->pathToDel = NULL;
   842         -    if( flags & SQLITE_OPEN_READWRITE ){
   843         -      OSTRACE(( "OPEN %d Invalid handle\n",
   844         -                ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE) ));
          884  +
          885  +    if( isReadWrite ){
   845    886         return os2Open( pVfs, zName, id,
   846         -                      ((flags | SQLITE_OPEN_READONLY) & ~SQLITE_OPEN_READWRITE),
          887  +                      ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
   847    888                         pOutFlags );
   848    889       }else{
   849    890         return SQLITE_CANTOPEN;
   850    891       }
   851    892     }
   852    893   
   853    894     if( pOutFlags ){
   854         -    *pOutFlags = flags & SQLITE_OPEN_READWRITE ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
          895  +    *pOutFlags = isReadWrite ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
   855    896     }
   856    897   
   857         -  pFile->pMethod = &os2IoMethod;
   858    898     pFile->h = h;
   859    899     OpenCounter(+1);
   860    900     OSTRACE(( "OPEN %d pOutFlags=%d\n", pFile->h, pOutFlags ));
   861    901     return SQLITE_OK;
   862    902   }
   863    903   
   864    904   /*
................................................................................
   865    905   ** Delete the named file.
   866    906   */
   867    907   static int os2Delete(
   868    908     sqlite3_vfs *pVfs,                     /* Not used on os2 */
   869    909     const char *zFilename,                 /* Name of file to delete */
   870    910     int syncDir                            /* Not used on os2 */
   871    911   ){
   872         -  APIRET rc = NO_ERROR;
   873         -  char *zFilenameCp = convertUtf8PathToCp( zFilename );
          912  +  APIRET rc;
          913  +  char *zFilenameCp;
   874    914     SimulateIOError( return SQLITE_IOERR_DELETE );
          915  +  zFilenameCp = convertUtf8PathToCp( zFilename );
   875    916     rc = DosDelete( (PSZ)zFilenameCp );
   876    917     free( zFilenameCp );
   877    918     OSTRACE(( "DELETE \"%s\"\n", zFilename ));
   878         -  return rc == NO_ERROR ? SQLITE_OK : SQLITE_IOERR_DELETE;
          919  +  return (rc == NO_ERROR ||
          920  +          rc == ERROR_FILE_NOT_FOUND ||
          921  +          rc == ERROR_PATH_NOT_FOUND ) ? SQLITE_OK : SQLITE_IOERR_DELETE;
   879    922   }
   880    923   
   881    924   /*
   882    925   ** Check the existance and status of a file.
   883    926   */
   884    927   static int os2Access(
   885    928     sqlite3_vfs *pVfs,        /* Not used on os2 */
................................................................................
   936    979   /*
   937    980   ** A no-op since the error code is returned on the DosLoadModule call.
   938    981   ** os2Dlopen returns zero if DosLoadModule is not successful.
   939    982   */
   940    983   static void os2DlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
   941    984   /* no-op */
   942    985   }
   943         -static void *os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol){
          986  +static void (*os2DlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
   944    987     PFN pfn;
   945    988     APIRET rc;
   946    989     rc = DosQueryProcAddr((HMODULE)pHandle, 0L, zSymbol, &pfn);
   947    990     if( rc != NO_ERROR ){
   948    991       /* if the symbol itself was not found, search again for the same
   949    992        * symbol with an extra underscore, that might be needed depending
   950    993        * on the calling convention */
   951    994       char _zSymbol[256] = "_";
   952    995       strncat(_zSymbol, zSymbol, 255);
   953    996       rc = DosQueryProcAddr((HMODULE)pHandle, 0L, _zSymbol, &pfn);
   954    997     }
   955         -  return rc != NO_ERROR ? 0 : (void*)pfn;
          998  +  return rc != NO_ERROR ? 0 : (void(*)(void))pfn;
   956    999   }
   957   1000   static void os2DlClose(sqlite3_vfs *pVfs, void *pHandle){
   958   1001     DosFreeModule((HMODULE)pHandle);
   959   1002   }
   960   1003   #else /* if SQLITE_OMIT_LOAD_EXTENSION is defined: */
   961   1004     #define os2DlOpen 0
   962   1005     #define os2DlError 0
................................................................................
  1052   1095   ** Find the current time (in Universal Coordinated Time).  Write the
  1053   1096   ** current time and date as a Julian Day number into *prNow and
  1054   1097   ** return 0.  Return 1 if the time and date cannot be found.
  1055   1098   */
  1056   1099   int os2CurrentTime( sqlite3_vfs *pVfs, double *prNow ){
  1057   1100     double now;
  1058   1101     SHORT minute; /* needs to be able to cope with negative timezone offset */
  1059         -  USHORT second, hour,
         1102  +  USHORT hundredths, second, hour,
  1060   1103            day, month, year;
  1061   1104     DATETIME dt;
  1062   1105     DosGetDateTime( &dt );
         1106  +  hundredths = (USHORT)dt.hundredths;
  1063   1107     second = (USHORT)dt.seconds;
  1064   1108     minute = (SHORT)dt.minutes + dt.timezone;
  1065   1109     hour = (USHORT)dt.hours;
  1066   1110     day = (USHORT)dt.day;
  1067   1111     month = (USHORT)dt.month;
  1068   1112     year = (USHORT)dt.year;
  1069   1113   
................................................................................
  1075   1119       367*(month - 2 - (month - 14)/12*12)/12 -
  1076   1120       3*((year + 4900 + (month - 14)/12)/100)/4;
  1077   1121   
  1078   1122     /* Add the fractional hours, mins and seconds */
  1079   1123     now += (hour + 12.0)/24.0;
  1080   1124     now += minute/1440.0;
  1081   1125     now += second/86400.0;
         1126  +  now += hundredths/8640000.0;
  1082   1127     *prNow = now;
  1083   1128   #ifdef SQLITE_TEST
  1084   1129     if( sqlite3_current_time ){
  1085   1130       *prNow = sqlite3_current_time/86400.0 + 2440587.5;
  1086   1131     }
  1087   1132   #endif
  1088   1133     return 0;
  1089   1134   }
         1135  +
         1136  +/*
         1137  +** Find the current time (in Universal Coordinated Time).  Write into *piNow
         1138  +** the current time and date as a Julian Day number times 86_400_000.  In
         1139  +** other words, write into *piNow the number of milliseconds since the Julian
         1140  +** epoch of noon in Greenwich on November 24, 4714 B.C according to the
         1141  +** proleptic Gregorian calendar.
         1142  +**
         1143  +** On success, return 0.  Return 1 if the time and date cannot be found.
         1144  +*/
         1145  +static int os2CurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
         1146  +  double now;
         1147  +  os2CurrentTime(pVfs, &now);
         1148  +  *piNow = now * 86400000;
         1149  +  return 0;
         1150  +}
  1090   1151   
  1091   1152   static int os2GetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
  1092   1153     return 0;
  1093   1154   }
  1094   1155   
  1095   1156   /*
  1096   1157   ** Initialize and deinitialize the operating system interface.
  1097   1158   */
  1098   1159   int sqlite3_os_init(void){
  1099   1160     static sqlite3_vfs os2Vfs = {
  1100         -    1,                 /* iVersion */
         1161  +    3,                 /* iVersion */
  1101   1162       sizeof(os2File),   /* szOsFile */
  1102   1163       CCHMAXPATH,        /* mxPathname */
  1103   1164       0,                 /* pNext */
  1104   1165       "os2",             /* zName */
  1105   1166       0,                 /* pAppData */
  1106   1167   
  1107   1168       os2Open,           /* xOpen */
................................................................................
  1112   1173       os2DlError,        /* xDlError */
  1113   1174       os2DlSym,          /* xDlSym */
  1114   1175       os2DlClose,        /* xDlClose */
  1115   1176       os2Randomness,     /* xRandomness */
  1116   1177       os2Sleep,          /* xSleep */
  1117   1178       os2CurrentTime,    /* xCurrentTime */
  1118   1179       os2GetLastError,   /* xGetLastError */
         1180  +    os2CurrentTimeInt64 /* xCurrentTimeInt64 */
         1181  +    0,                 /* xSetSystemCall */
         1182  +    0,                 /* xGetSystemCall */
         1183  +    0,                 /* xNextSystemCall */
  1119   1184     };
  1120   1185     sqlite3_vfs_register(&os2Vfs, 1);
  1121   1186     initUconvObjects();
  1122   1187     return SQLITE_OK;
  1123   1188   }
  1124   1189   int sqlite3_os_end(void){
  1125   1190     freeUconvObjects();
  1126   1191     return SQLITE_OK;
  1127   1192   }
  1128   1193   
  1129   1194   #endif /* SQLITE_OS_OS2 */