/ Check-in [b53ab71d]
Login

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

Overview
Comment:Minor coding fix in getting the windows platform version, when multithreading (CVS 761)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:b53ab71d074ada47ce22bd161f6aee24587302af
User & Date: mike 2002-10-17 09:01:32
Context
2002-10-19
20:13
Fix the URL for pointing to MinGW on the homepage. (CVS 762) check-in: 16aad98a user: drh tags: trunk
2002-10-17
09:01
Minor coding fix in getting the windows platform version, when multithreading (CVS 761) check-in: b53ab71d user: mike tags: trunk
00:38
fix for locking in Windows (CVS 760) check-in: 83add34f user: mike tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os.c.

86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
...
638
639
640
641
642
643
644
645
646


647
648
649
650
651
652
653
654

655


656
657
658
659
660
661
662
663
664
...
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
...
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
** point to the same locking structure.  The locking structure keeps
** a reference count (so we will know when to delete it) and a "cnt"
** field that tells us its internal lock status.  cnt==0 means the
** file is unlocked.  cnt==-1 means the file has an exclusive lock.
** cnt>0 means there are cnt shared locks on the file.
**
** Any attempt to lock or unlock a file first checks the locking
** structure.  The fcntl() system call is only invoked to set a 
** POSIX lock if the internal lock structure transitions between
** a locked and an unlocked state.
*/

/*
** An instance of the following structure serves as the key used
** to locate a particular lockInfo structure given its inode. 
*/
struct inodeKey {
  dev_t dev;   /* Device number */
  ino_t ino;   /* Inode number */
};

/*
................................................................................
*/
struct lockInfo {
  struct inodeKey key;  /* The lookup key */
  int cnt;              /* 0: unlocked.  -1: write lock.  1...: read lock. */
  int nRef;             /* Number of pointers to this structure */
};

/* 
** This hash table maps inodes (in the form of inodeKey structures) into
** pointers to lockInfo structures.
*/
static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };

/*
** Given a file descriptor, locate a lockInfo structure that describes
................................................................................
  int *pReadonly
){
#if OS_UNIX
  id->fd = open(zFilename, O_RDWR|O_CREAT, 0644);
  if( id->fd<0 ){
    id->fd = open(zFilename, O_RDONLY);
    if( id->fd<0 ){
      return SQLITE_CANTOPEN; 
    }
    *pReadonly = 1;
  }else{
    *pReadonly = 0;
  }
  sqliteOsEnterMutex();
  id->pLock = findLockInfo(id->fd);
................................................................................
  }
  return SQLITE_OK;
#endif
#if OS_WIN
  HANDLE h;
  int fileflags;
  if( delFlag ){
    fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS 
                     | FILE_FLAG_DELETE_ON_CLOSE;
  }else{
    fileflags = FILE_FLAG_RANDOM_ACCESS;
  }
  h = CreateFile(zFilename,
     GENERIC_READ | GENERIC_WRITE,
     0,
................................................................................
      int n = sqliteRandomByte() % sizeof(zChars);
      zBuf[j++] = zChars[n];
    }
    zBuf[j] = 0;
    if( !sqliteOsFileExists(zBuf) ) break;
  }
#endif
  return SQLITE_OK; 
}

/*
** Close a file
*/
int sqliteOsClose(OsFile *id){
#if OS_UNIX
................................................................................
#define MX_LOCKBYTE 0xFFF0

#if OS_WIN

// get the platform id to decide how to calculate the lock offset

int mkPlatformId(void){
 
 static long init=0;


 static int pid=VER_PLATFORM_WIN32_WINDOWS;
 OSVERSIONINFOA info;	
 
 if (!init) {
  if (InterlockedIncrement(&init)==1)
   {
    info.dwOSVersionInfoSize=sizeof(info);
   if (GetVersionEx(&info)) pid=info.dwPlatformId;

   }


  } 
 return pid;  
}

// locks and unlocks beyond eof. uses platformid to move the lock as far as possible.
int mklock(HANDLE h, WORD base, WORD size)
{
 if (mkPlatformId()==VER_PLATFORM_WIN32_WINDOWS)
  return LockFile(h,0xFFFF0000+base,0,size,0);
................................................................................
  return UnlockFile(h,0xFFFF0000+base,0,size,0);
 else
  return UnlockFile(h,base,0xFFFFFFFF,size,0);
}

//obtain the sync lock on a handle

void synclock(HANDLE h){ 
 while (!mklock(h,0,1)) Sleep(1);
}

void syncunlock(HANDLE h){ 
 mkunlock(h,0,1);
}

#endif

/*
** Change the status of the lock on the file "id" to be a readlock.
................................................................................
#if OS_WIN
  int rc;
  if( id->locked>0 ){
    rc = SQLITE_OK;
  }else{
    int lk = (sqliteRandomInteger() & 0x7ffffff)%MX_LOCKBYTE + 1;
    int res;
    
    synclock(id->h);
    if (id->locked<0) mkunlock(id->h,1,MX_LOCKBYTE); // release write lock if we have it
    res=mklock(id->h,lk,1);
    syncunlock(id->h);
    
    if( res ){
      id->locked = lk;
      rc = SQLITE_OK;
    }else{
      rc = SQLITE_BUSY;
    }
  }
................................................................................
#endif
#if OS_WIN
  int rc;
  if( id->locked<0 ){
    rc = SQLITE_OK;
  }else{
    int res;
    
    synclock(id->h);
    if (id->locked>0) mkunlock(id->h,id->locked,1); // release read lock
    res=mklock(id->h,1,MX_LOCKBYTE);
    syncunlock(id->h);
   
    if(res){
      id->locked = -1;
      rc = SQLITE_OK;
    }else{
      rc = SQLITE_BUSY;
    }
  }







|






|







 







|







 







|







 







|







 







|







 







|

>
>

|
|
|
|


|
>

>
>
|
|







 







|



|







 







|




|







 







|




|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
...
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
...
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
...
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
...
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
** point to the same locking structure.  The locking structure keeps
** a reference count (so we will know when to delete it) and a "cnt"
** field that tells us its internal lock status.  cnt==0 means the
** file is unlocked.  cnt==-1 means the file has an exclusive lock.
** cnt>0 means there are cnt shared locks on the file.
**
** Any attempt to lock or unlock a file first checks the locking
** structure.  The fcntl() system call is only invoked to set a
** POSIX lock if the internal lock structure transitions between
** a locked and an unlocked state.
*/

/*
** An instance of the following structure serves as the key used
** to locate a particular lockInfo structure given its inode.
*/
struct inodeKey {
  dev_t dev;   /* Device number */
  ino_t ino;   /* Inode number */
};

/*
................................................................................
*/
struct lockInfo {
  struct inodeKey key;  /* The lookup key */
  int cnt;              /* 0: unlocked.  -1: write lock.  1...: read lock. */
  int nRef;             /* Number of pointers to this structure */
};

/*
** This hash table maps inodes (in the form of inodeKey structures) into
** pointers to lockInfo structures.
*/
static Hash lockHash = { SQLITE_HASH_BINARY, 0, 0, 0, 0, 0 };

/*
** Given a file descriptor, locate a lockInfo structure that describes
................................................................................
  int *pReadonly
){
#if OS_UNIX
  id->fd = open(zFilename, O_RDWR|O_CREAT, 0644);
  if( id->fd<0 ){
    id->fd = open(zFilename, O_RDONLY);
    if( id->fd<0 ){
      return SQLITE_CANTOPEN;
    }
    *pReadonly = 1;
  }else{
    *pReadonly = 0;
  }
  sqliteOsEnterMutex();
  id->pLock = findLockInfo(id->fd);
................................................................................
  }
  return SQLITE_OK;
#endif
#if OS_WIN
  HANDLE h;
  int fileflags;
  if( delFlag ){
    fileflags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_RANDOM_ACCESS
                     | FILE_FLAG_DELETE_ON_CLOSE;
  }else{
    fileflags = FILE_FLAG_RANDOM_ACCESS;
  }
  h = CreateFile(zFilename,
     GENERIC_READ | GENERIC_WRITE,
     0,
................................................................................
      int n = sqliteRandomByte() % sizeof(zChars);
      zBuf[j++] = zChars[n];
    }
    zBuf[j] = 0;
    if( !sqliteOsFileExists(zBuf) ) break;
  }
#endif
  return SQLITE_OK;
}

/*
** Close a file
*/
int sqliteOsClose(OsFile *id){
#if OS_UNIX
................................................................................
#define MX_LOCKBYTE 0xFFF0

#if OS_WIN

// get the platform id to decide how to calculate the lock offset

int mkPlatformId(void){

 static long init=0;
 static long lock=0;

 static int pid=VER_PLATFORM_WIN32_WINDOWS;
 OSVERSIONINFOA info;

 while (!init) {
  if (InterlockedIncrement(&lock)==1)
   {
    info.dwOSVersionInfoSize=sizeof(info);
    if (GetVersionEx(&info)) pid=info.dwPlatformId;
    init=1;
   }
  else
   Sleep(1);
  }
 return pid;
}

// locks and unlocks beyond eof. uses platformid to move the lock as far as possible.
int mklock(HANDLE h, WORD base, WORD size)
{
 if (mkPlatformId()==VER_PLATFORM_WIN32_WINDOWS)
  return LockFile(h,0xFFFF0000+base,0,size,0);
................................................................................
  return UnlockFile(h,0xFFFF0000+base,0,size,0);
 else
  return UnlockFile(h,base,0xFFFFFFFF,size,0);
}

//obtain the sync lock on a handle

void synclock(HANDLE h){
 while (!mklock(h,0,1)) Sleep(1);
}

void syncunlock(HANDLE h){
 mkunlock(h,0,1);
}

#endif

/*
** Change the status of the lock on the file "id" to be a readlock.
................................................................................
#if OS_WIN
  int rc;
  if( id->locked>0 ){
    rc = SQLITE_OK;
  }else{
    int lk = (sqliteRandomInteger() & 0x7ffffff)%MX_LOCKBYTE + 1;
    int res;

    synclock(id->h);
    if (id->locked<0) mkunlock(id->h,1,MX_LOCKBYTE); // release write lock if we have it
    res=mklock(id->h,lk,1);
    syncunlock(id->h);

    if( res ){
      id->locked = lk;
      rc = SQLITE_OK;
    }else{
      rc = SQLITE_BUSY;
    }
  }
................................................................................
#endif
#if OS_WIN
  int rc;
  if( id->locked<0 ){
    rc = SQLITE_OK;
  }else{
    int res;

    synclock(id->h);
    if (id->locked>0) mkunlock(id->h,id->locked,1); // release read lock
    res=mklock(id->h,1,MX_LOCKBYTE);
    syncunlock(id->h);

    if(res){
      id->locked = -1;
      rc = SQLITE_OK;
    }else{
      rc = SQLITE_BUSY;
    }
  }