⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_os2.c

📁 一个小型嵌入式数据库SQLite的源码,C语言
💻 C
📖 第 1 页 / 共 2 页
字号:
  ** 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 + -