📄 os_os2.c
字号:
** the PENDING_LOCK byte is temporary. */ newLocktype = pFile->locktype; if( pFile->locktype==NO_LOCK || (locktype==EXCLUSIVE_LOCK && pFile->locktype==RESERVED_LOCK) ){ int cnt = 3; LockArea.lOffset = PENDING_BYTE; LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; while( cnt-->0 && (res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L) )!=NO_ERROR ){ /* Try 3 times to get the pending lock. The pending lock might be ** held by another reader process who will release it momentarily. */ TRACE2( "could not get a PENDING lock. cnt=%d\n", cnt ); DosSleep(1); } gotPendingLock = res; } /* Acquire a shared lock */ if( locktype==SHARED_LOCK && res ){ assert( pFile->locktype==NO_LOCK ); res = getReadLock(pFile); if( res == NO_ERROR ){ newLocktype = SHARED_LOCK; } } /* Acquire a RESERVED lock */ if( locktype==RESERVED_LOCK && res ){ assert( pFile->locktype==SHARED_LOCK ); LockArea.lOffset = RESERVED_BYTE; LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); if( res == NO_ERROR ){ newLocktype = RESERVED_LOCK; } } /* Acquire a PENDING lock */ if( locktype==EXCLUSIVE_LOCK && res ){ newLocktype = PENDING_LOCK; gotPendingLock = 0; } /* Acquire an EXCLUSIVE lock */ if( locktype==EXCLUSIVE_LOCK && res ){ assert( pFile->locktype>=SHARED_LOCK ); res = unlockReadLock(pFile); TRACE2( "unreadlock = %d\n", res ); LockArea.lOffset = SHARED_FIRST; LockArea.lRange = SHARED_SIZE; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; res = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); if( res == NO_ERROR ){ newLocktype = EXCLUSIVE_LOCK; }else{ TRACE2( "error-code = %d\n", res ); } } /* If we are holding a PENDING lock that ought to be released, then ** release it now. */ if( gotPendingLock && locktype==SHARED_LOCK ){ LockArea.lOffset = 0L; LockArea.lRange = 0L; UnlockArea.lOffset = PENDING_BYTE; UnlockArea.lRange = 1L; DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); } /* Update the state of the lock has held in the file descriptor then ** return the appropriate result code. */ if( res == NO_ERROR ){ rc = SQLITE_OK; }else{ TRACE4( "LOCK FAILED %d trying for %d but got %d\n", pFile->h, locktype, newLocktype ); rc = SQLITE_BUSY; } pFile->locktype = newLocktype; return rc;}/*** This routine checks if there is a RESERVED lock held on the specified** file by this or any other process. If such a lock is held, return** non-zero, otherwise zero.*/int os2CheckReservedLock( OsFile *id ){ APIRET rc = NO_ERROR; os2File *pFile = (os2File*)id; assert( pFile!=0 ); if( pFile->locktype>=RESERVED_LOCK ){ rc = 1; TRACE3( "TEST WR-LOCK %d %d (local)\n", pFile->h, rc ); }else{ FILELOCK LockArea, UnlockArea; memset(&LockArea, 0, sizeof(LockArea)); memset(&UnlockArea, 0, sizeof(UnlockArea)); LockArea.lOffset = RESERVED_BYTE; LockArea.lRange = 1L; UnlockArea.lOffset = 0L; UnlockArea.lRange = 0L; rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); if( rc == NO_ERROR ){ LockArea.lOffset = 0L; LockArea.lRange = 0L; UnlockArea.lOffset = RESERVED_BYTE; UnlockArea.lRange = 1L; rc = DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); } TRACE3( "TEST WR-LOCK %d %d (remote)\n", pFile->h, rc ); } return rc;}/*** Lower the locking level on file descriptor id to locktype. locktype** must be either NO_LOCK or SHARED_LOCK.**** If the locking level of the file descriptor is already at or below** the requested locking level, this routine is a no-op.**** It is not possible for this routine to fail if the second argument** is NO_LOCK. If the second argument is SHARED_LOCK then this routine** might return SQLITE_IOERR;*/int os2Unlock( OsFile *id, int locktype ){ int type; APIRET rc = SQLITE_OK; os2File *pFile = (os2File*)id; FILELOCK LockArea, UnlockArea; memset(&LockArea, 0, sizeof(LockArea)); memset(&UnlockArea, 0, sizeof(UnlockArea)); assert( pFile!=0 ); assert( locktype<=SHARED_LOCK ); TRACE4( "UNLOCK %d to %d was %d\n", pFile->h, locktype, pFile->locktype ); type = pFile->locktype; if( type>=EXCLUSIVE_LOCK ){ LockArea.lOffset = 0L; LockArea.lRange = 0L; UnlockArea.lOffset = SHARED_FIRST; UnlockArea.lRange = SHARED_SIZE; DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); if( locktype==SHARED_LOCK && getReadLock(pFile) != NO_ERROR ){ /* This should never happen. We should always be able to ** reacquire the read lock */ rc = SQLITE_IOERR; } } if( type>=RESERVED_LOCK ){ LockArea.lOffset = 0L; LockArea.lRange = 0L; UnlockArea.lOffset = RESERVED_BYTE; UnlockArea.lRange = 1L; DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); } if( locktype==NO_LOCK && type>=SHARED_LOCK ){ unlockReadLock(pFile); } if( type>=PENDING_LOCK ){ LockArea.lOffset = 0L; LockArea.lRange = 0L; UnlockArea.lOffset = PENDING_BYTE; UnlockArea.lRange = 1L; DosSetFileLocks( pFile->h, &UnlockArea, &LockArea, 2000L, 1L ); } pFile->locktype = locktype; return rc;}/*** Turn a relative pathname into a full pathname. Return a pointer** to the full pathname stored in space obtained from sqliteMalloc().** The calling function is responsible for freeing this space once it** is no longer needed.*/char *sqlite3Os2FullPathname( const char *zRelative ){ char *zFull = 0; if( strchr(zRelative, ':') ){ sqlite3SetString( &zFull, zRelative, (char*)0 ); }else{ char zBuff[SQLITE_TEMPNAME_SIZE - 2] = {0}; char zDrive[1] = {0}; ULONG cbzFullLen = SQLITE_TEMPNAME_SIZE; ULONG ulDriveNum = 0; ULONG ulDriveMap = 0; DosQueryCurrentDisk( &ulDriveNum, &ulDriveMap ); DosQueryCurrentDir( 0L, zBuff, &cbzFullLen ); zFull = sqliteMalloc( cbzFullLen ); sprintf( zDrive, "%c", (char)('A' + ulDriveNum - 1) ); sqlite3SetString( &zFull, zDrive, ":\\", zBuff, "\\", zRelative, (char*)0 ); } return zFull;}/*** The fullSync option is meaningless on os2, or correct me if I'm wrong. This is a no-op.** From os_unix.c: Change the value of the fullsync flag in the given file descriptor.** From os_unix.c: ((unixFile*)id)->fullSync = v;*/static void os2SetFullSync( OsFile *id, int v ){ return;}/*** Return the underlying file handle for an OsFile*/static int os2FileHandle( OsFile *id ){ return (int)((os2File*)id)->h;}/*** Return an integer that indices the type of lock currently held** by this handle. (Used for testing and analysis only.)*/static int os2LockState( OsFile *id ){ return ((os2File*)id)->locktype;}/*** This vector defines all the methods that can operate on an OsFile** for os2.*/static const IoMethod sqlite3Os2IoMethod = { os2Close, os2OpenDirectory, os2Read, os2Write, os2Seek, os2Truncate, os2Sync, os2SetFullSync, os2FileHandle, os2FileSize, os2Lock, os2Unlock, os2LockState, os2CheckReservedLock,};/*** Allocate memory for an OsFile. Initialize the new OsFile** to the value given in pInit and return a pointer to the new** OsFile. If we run out of memory, close the file and return NULL.*/int allocateOs2File( os2File *pInit, OsFile **pld ){ os2File *pNew; pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ){ DosClose( pInit->h ); *pld = 0; return SQLITE_NOMEM; }else{ *pNew = *pInit; pNew->pMethod = &sqlite3Os2IoMethod; pNew->locktype = NO_LOCK; *pld = (OsFile*)pNew; OpenCounter(+1); return SQLITE_OK; }}#endif /* SQLITE_OMIT_DISKIO *//***************************************************************************** Everything above deals with file I/O. Everything that follows deals** with other miscellanous aspects of the operating system interface****************************************************************************//*** Get information to seed the random number generator. The seed** is written into the buffer zBuf[256]. The calling function must** supply a sufficiently large buffer.*/int sqlite3Os2RandomSeed( char *zBuf ){ /* We have to initialize zBuf to prevent valgrind from reporting ** errors. The reports issued by valgrind are incorrect - we would ** prefer that the randomness be increased by making use of the ** uninitialized space in zBuf - but valgrind errors tend to worry ** some users. Rather than argue, it seems easier just to initialize ** the whole array and silence valgrind, even if that means less randomness ** in the random seed. ** ** When testing, initializing zBuf[] to zero is all we do. That means ** that we always use the same random number sequence. This makes the ** tests repeatable. */ memset( zBuf, 0, 256 ); DosGetDateTime( (PDATETIME)zBuf ); return SQLITE_OK;}/*** Sleep for a little while. Return the amount of time slept.*/int sqlite3Os2Sleep( int ms ){ DosSleep( ms ); return ms;}/*** Static variables used for thread synchronization*/static int inMutex = 0;#ifdef SQLITE_OS2_THREADSstatic ULONG mutexOwner;#endif/*** The following pair of routines implement mutual exclusion for** multi-threaded processes. Only a single thread is allowed to** executed code that is surrounded by EnterMutex() and LeaveMutex().**** SQLite uses only a single Mutex. There is not much critical** code and what little there is executes quickly and without blocking.*/void sqlite3Os2EnterMutex(){ PTIB ptib;#ifdef SQLITE_OS2_THREADS DosEnterCritSec(); DosGetInfoBlocks( &ptib, NULL ); mutexOwner = ptib->tib_ptib2->tib2_ultid;#endif assert( !inMutex ); inMutex = 1;}void sqlite3Os2LeaveMutex(){ PTIB ptib; assert( inMutex ); inMutex = 0;#ifdef SQLITE_OS2_THREADS DosGetInfoBlocks( &ptib, NULL ); assert( mutexOwner == ptib->tib_ptib2->tib2_ultid ); DosExitCritSec();#endif}/*** Return TRUE if the mutex is currently held.**** If the thisThreadOnly parameter is true, return true if and only if the** calling thread holds the mutex. If the parameter is false, return** true if any thread holds the mutex.*/int sqlite3Os2InMutex( int thisThreadOnly ){#ifdef SQLITE_OS2_THREADS PTIB ptib; DosGetInfoBlocks( &ptib, NULL ); return inMutex>0 && (thisThreadOnly==0 || mutexOwner==ptib->tib_ptib2->tib2_ultid);#else return inMutex>0;#endif}/*** The following variable, if set to a non-zero value, becomes the result** returned from sqlite3OsCurrentTime(). This is used for testing.*/#ifdef SQLITE_TESTint sqlite3_current_time = 0;#endif/*** Find the current time (in Universal Coordinated Time). Write the** current time and date as a Julian Day number into *prNow and** return 0. Return 1 if the time and date cannot be found.*/int sqlite3Os2CurrentTime( double *prNow ){ double now; USHORT second, minute, hour, day, month, year; DATETIME dt; DosGetDateTime( &dt ); second = (USHORT)dt.seconds; minute = (USHORT)dt.minutes + dt.timezone; hour = (USHORT)dt.hours; day = (USHORT)dt.day; month = (USHORT)dt.month; year = (USHORT)dt.year; /* Calculations from http://www.astro.keele.ac.uk/~rno/Astronomy/hjd.html http://www.astro.keele.ac.uk/~rno/Astronomy/hjd-0.1.c */ /* Calculate the Julian days */ now = day - 32076 + 1461*(year + 4800 + (month - 14)/12)/4 + 367*(month - 2 - (month - 14)/12*12)/12 - 3*((year + 4900 + (month - 14)/12)/100)/4; /* Add the fractional hours, mins and seconds */ now += (hour + 12.0)/24.0; now += minute/1440.0; now += second/86400.0; *prNow = now;#ifdef SQLITE_TEST if( sqlite3_current_time ){ *prNow = sqlite3_current_time/86400.0 + 2440587.5; }#endif return 0;}/*** Remember the number of thread-specific-data blocks allocated.** Use this to verify that we are not leaking thread-specific-data.** Ticket #1601*/#ifdef SQLITE_TESTint sqlite3_tsd_count = 0;# define TSD_COUNTER_INCR InterlockedIncrement( &sqlite3_tsd_count )# define TSD_COUNTER_DECR InterlockedDecrement( &sqlite3_tsd_count )#else# define TSD_COUNTER_INCR /* no-op */# define TSD_COUNTER_DECR /* no-op */#endif/*** If called with allocateFlag>1, then return a pointer to thread** specific data for the current thread. Allocate and zero the** thread-specific data if it does not already exist necessary.**** If called with allocateFlag==0, then check the current thread** specific data. Return it if it exists. If it does not exist,** then return NULL.**** If called with allocateFlag<0, check to see if the thread specific** data is allocated and is all zero. If it is then deallocate it.** Return a pointer to the thread specific data or NULL if it is** unallocated or gets deallocated.*/ThreadData *sqlite3Os2ThreadSpecificData( int allocateFlag ){ static ThreadData **s_ppTsd = NULL; static const ThreadData zeroData = {0, 0, 0}; ThreadData *pTsd; if( !s_ppTsd ){ sqlite3OsEnterMutex(); if( !s_ppTsd ){ PULONG pul; APIRET rc = DosAllocThreadLocalMemory(1, &pul); if( rc != NO_ERROR ){ sqlite3OsLeaveMutex(); return 0; } s_ppTsd = (ThreadData **)pul; } sqlite3OsLeaveMutex(); } pTsd = *s_ppTsd; if( allocateFlag>0 ){ if( !pTsd ){ pTsd = sqlite3OsMalloc( sizeof(zeroData) ); if( pTsd ){ *pTsd = zeroData; *s_ppTsd = pTsd; TSD_COUNTER_INCR; } } }else if( pTsd!=0 && allocateFlag<0 && memcmp( pTsd, &zeroData, sizeof(ThreadData) )==0 ){ sqlite3OsFree(pTsd); *s_ppTsd = NULL; TSD_COUNTER_DECR; pTsd = 0; } return pTsd;}#endif /* OS_OS2 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -