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

📄 os.c

📁 sqlite数据库源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  int rc;  if( id->locked>0 || id->refNumRF == -1 ){    rc = SQLITE_OK;  }else{    int lk;    OSErr res;    int cnt = 5;    ParamBlockRec params;    sqliteRandomness(sizeof(lk), &lk);    lk = (lk & 0x7fffffff)%N_LOCKBYTE + 1;    memset(&params, 0, sizeof(params));    params.ioParam.ioRefNum = id->refNumRF;    params.ioParam.ioPosMode = fsFromStart;    params.ioParam.ioPosOffset = FIRST_LOCKBYTE;    params.ioParam.ioReqCount = 1;    while( cnt-->0 && (res = PBLockRangeSync(&params))!=noErr ){      UInt32 finalTicks;      Delay(1, &finalTicks); /* 1/60 sec */    }    if( res == noErr ){      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;      params.ioParam.ioReqCount = N_LOCKBYTE;      PBUnlockRangeSync(&params);      params.ioParam.ioPosOffset = FIRST_LOCKBYTE+lk;      params.ioParam.ioReqCount = 1;      res = PBLockRangeSync(&params);      params.ioParam.ioPosOffset = FIRST_LOCKBYTE;      params.ioParam.ioReqCount = 1;      PBUnlockRangeSync(&params);    }    if( res == noErr ){      id->locked = lk;      rc = SQLITE_OK;    }else{      rc = SQLITE_BUSY;    }  }  return rc;#endif}/*** Change the lock status to be an exclusive or write lock.  Return** SQLITE_OK on success and SQLITE_BUSY on a failure.  If this** library was compiled with large file support (LFS) but LFS is not** available on the host, then an SQLITE_NOLFS is returned.*/int sqliteOsWriteLock(OsFile *id){#if OS_UNIX  int rc;  sqliteOsEnterMutex();  if( id->pLock->cnt==0 || (id->pLock->cnt==1 && id->locked==1) ){    struct flock lock;    int s;    lock.l_type = F_WRLCK;    lock.l_whence = SEEK_SET;    lock.l_start = lock.l_len = 0L;    s = fcntl(id->fd, F_SETLK, &lock);    if( s!=0 ){      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;    }else{      rc = SQLITE_OK;      if( !id->locked ){        id->pOpen->nLock++;        id->locked = 1;      }      id->pLock->cnt = -1;    }  }else{    rc = SQLITE_BUSY;  }  sqliteOsLeaveMutex();  return rc;#endif#if OS_WIN  int rc;  if( id->locked<0 ){    rc = SQLITE_OK;  }else{    int res;    int cnt = 100;    while( cnt-->0 && (res = LockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0))==0 ){      Sleep(1);    }    if( res ){      if( id->locked>0 ){        if( isNT() ){          UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);        }else{          res = UnlockFile(id->h, FIRST_LOCKBYTE + id->locked, 0, 1, 0);        }      }      if( res ){        res = LockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);      }else{        res = 0;      }      UnlockFile(id->h, FIRST_LOCKBYTE, 0, 1, 0);    }    if( res ){      id->locked = -1;      rc = SQLITE_OK;    }else{      rc = SQLITE_BUSY;    }  }  return rc;#endif#if OS_MAC  int rc;  if( id->locked<0 || id->refNumRF == -1 ){    rc = SQLITE_OK;  }else{    OSErr res;    int cnt = 5;    ParamBlockRec params;    memset(&params, 0, sizeof(params));    params.ioParam.ioRefNum = id->refNumRF;    params.ioParam.ioPosMode = fsFromStart;    params.ioParam.ioPosOffset = FIRST_LOCKBYTE;    params.ioParam.ioReqCount = 1;    while( cnt-->0 && (res = PBLockRangeSync(&params))!=noErr ){      UInt32 finalTicks;      Delay(1, &finalTicks); /* 1/60 sec */    }    if( res == noErr ){      params.ioParam.ioPosOffset = FIRST_LOCKBYTE + id->locked;      params.ioParam.ioReqCount = 1;      if( id->locked==0             || PBUnlockRangeSync(&params)==noErr ){        params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;        params.ioParam.ioReqCount = N_LOCKBYTE;        res = PBLockRangeSync(&params);      }else{        res = afpRangeNotLocked;      }      params.ioParam.ioPosOffset = FIRST_LOCKBYTE;      params.ioParam.ioReqCount = 1;      PBUnlockRangeSync(&params);    }    if( res == noErr ){      id->locked = -1;      rc = SQLITE_OK;    }else{      rc = SQLITE_BUSY;    }  }  return rc;#endif}/*** Unlock the given file descriptor.  If the file descriptor was** not previously locked, then this routine is a no-op.  If this** library was compiled with large file support (LFS) but LFS is not** available on the host, then an SQLITE_NOLFS is returned.*/int sqliteOsUnlock(OsFile *id){#if OS_UNIX  int rc;  if( !id->locked ) return SQLITE_OK;  sqliteOsEnterMutex();  assert( id->pLock->cnt!=0 );  if( id->pLock->cnt>1 ){    id->pLock->cnt--;    rc = SQLITE_OK;  }else{    struct flock lock;    int s;    lock.l_type = F_UNLCK;    lock.l_whence = SEEK_SET;    lock.l_start = lock.l_len = 0L;    s = fcntl(id->fd, F_SETLK, &lock);    if( s!=0 ){      rc = (errno==EINVAL) ? SQLITE_NOLFS : SQLITE_BUSY;    }else{      rc = SQLITE_OK;      id->pLock->cnt = 0;    }  }  if( rc==SQLITE_OK ){    /* Decrement the count of locks against this same file.  When the    ** count reaches zero, close any other file descriptors whose close    ** was deferred because of outstanding locks.    */    struct openCnt *pOpen = id->pOpen;    pOpen->nLock--;    assert( pOpen->nLock>=0 );    if( pOpen->nLock==0 && pOpen->nPending>0 ){      int i;      for(i=0; i<pOpen->nPending; i++){        close(pOpen->aPending[i]);      }      sqliteFree(pOpen->aPending);      pOpen->nPending = 0;      pOpen->aPending = 0;    }  }  sqliteOsLeaveMutex();  id->locked = 0;  return rc;#endif#if OS_WIN  int rc;  if( id->locked==0 ){    rc = SQLITE_OK;  }else if( isNT() || id->locked<0 ){    UnlockFile(id->h, FIRST_LOCKBYTE+1, 0, N_LOCKBYTE, 0);    rc = SQLITE_OK;    id->locked = 0;  }else{    UnlockFile(id->h, FIRST_LOCKBYTE+id->locked, 0, 1, 0);    rc = SQLITE_OK;    id->locked = 0;  }  return rc;#endif#if OS_MAC  int rc;  ParamBlockRec params;  memset(&params, 0, sizeof(params));  params.ioParam.ioRefNum = id->refNumRF;  params.ioParam.ioPosMode = fsFromStart;  if( id->locked==0 || id->refNumRF == -1 ){    rc = SQLITE_OK;  }else if( id->locked<0 ){    params.ioParam.ioPosOffset = FIRST_LOCKBYTE+1;    params.ioParam.ioReqCount = N_LOCKBYTE;    PBUnlockRangeSync(&params);    rc = SQLITE_OK;    id->locked = 0;  }else{    params.ioParam.ioPosOffset = FIRST_LOCKBYTE+id->locked;    params.ioParam.ioReqCount = 1;    PBUnlockRangeSync(&params);    rc = SQLITE_OK;    id->locked = 0;  }  return rc;#endif}/*** 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 sqliteOsRandomSeed(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);#if OS_UNIX && !defined(SQLITE_TEST)  {    int pid;    time((time_t*)zBuf);    pid = getpid();    memcpy(&zBuf[sizeof(time_t)], &pid, sizeof(pid));  }#endif#if OS_WIN && !defined(SQLITE_TEST)  GetSystemTime((LPSYSTEMTIME)zBuf);#endif#if OS_MAC  {    int pid;    Microseconds((UnsignedWide*)zBuf);    pid = getpid();    memcpy(&zBuf[sizeof(UnsignedWide)], &pid, sizeof(pid));  }#endif  return SQLITE_OK;}/*** Sleep for a little while.  Return the amount of time slept.*/int sqliteOsSleep(int ms){#if OS_UNIX#if defined(HAVE_USLEEP) && HAVE_USLEEP  usleep(ms*1000);  return ms;#else  sleep((ms+999)/1000);  return 1000*((ms+999)/1000);#endif#endif#if OS_WIN  Sleep(ms);  return ms;#endif#if OS_MAC  UInt32 finalTicks;  UInt32 ticks = (((UInt32)ms+16)*3)/50;  /* 1/60 sec per tick */  Delay(ticks, &finalTicks);  return (int)((ticks*50)/3);#endif}/*** Static variables used for thread synchronization*/static int inMutex = 0;#ifdef SQLITE_UNIX_THREADS  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;#endif#ifdef SQLITE_W32_THREADS  static CRITICAL_SECTION cs;#endif#ifdef SQLITE_MACOS_MULTITASKING  static MPCriticalRegionID criticalRegion;#endif/*** The following pair of routine 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 sqliteOsEnterMutex(){#ifdef SQLITE_UNIX_THREADS  pthread_mutex_lock(&mutex);#endif#ifdef SQLITE_W32_THREADS  static int isInit = 0;  while( !isInit ){    static long lock = 0;    if( InterlockedIncrement(&lock)==1 ){      InitializeCriticalSection(&cs);      isInit = 1;    }else{      Sleep(1);    }  }  EnterCriticalSection(&cs);#endif#ifdef SQLITE_MACOS_MULTITASKING  static volatile int notInit = 1;  if( notInit ){    if( notInit == 2 ) /* as close as you can get to thread safe init */      MPYield();    else{      notInit = 2;      MPCreateCriticalRegion(&criticalRegion);      notInit = 0;    }  }  MPEnterCriticalRegion(criticalRegion, kDurationForever);#endif  assert( !inMutex );  inMutex = 1;}void sqliteOsLeaveMutex(){  assert( inMutex );  inMutex = 0;#ifdef SQLITE_UNIX_THREADS  pthread_mutex_unlock(&mutex);#endif#ifdef SQLITE_W32_THREADS  LeaveCriticalSection(&cs);#endif#ifdef SQLITE_MACOS_MULTITASKING  MPExitCriticalRegion(criticalRegion);#endif}/*** 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 *sqliteOsFullPathname(const char *zRelative){#if OS_UNIX  char *zFull = 0;  if( zRelative[0]=='/' ){    sqliteSetString(&zFull, zRelative, (char*)0);  }else{    char zBuf[5000];    sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), "/", zRelative,                    (char*)0);  }  return zFull;#endif#if OS_WIN  char *zNotUsed;  char *zFull;  int nByte;  nByte = GetFullPathName(zRelative, 0, 0, &zNotUsed) + 1;  zFull = sqliteMalloc( nByte );  if( zFull==0 ) return 0;  GetFullPathName(zRelative, nByte, zFull, &zNotUsed);  return zFull;#endif#if OS_MAC  char *zFull = 0;  if( zRelative[0]==':' ){    char zBuf[_MAX_PATH+1];    sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), &(zRelative[1]),                    (char*)0);  }else{    if( strchr(zRelative, ':') ){      sqliteSetString(&zFull, zRelative, (char*)0);    }else{    char zBuf[_MAX_PATH+1];      sqliteSetString(&zFull, getcwd(zBuf, sizeof(zBuf)), zRelative, (char*)0);    }  }  return zFull;#endif}/*** The following variable, if set to a non-zero value, becomes the result** returned from sqliteOsCurrentTime().  This is used for testing.*/#ifdef SQLITE_TESTint sqlite_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 sqliteOsCurrentTime(double *prNow){#if OS_UNIX  time_t t;  time(&t);  *prNow = t/86400.0 + 2440587.5;#endif#if OS_WIN  FILETIME ft;  /* FILETIME structure is a 64-bit value representing the number of      100-nanosecond intervals since January 1, 1601 (= JD 2305813.5).   */  double now;  GetSystemTimeAsFileTime( &ft );  now = ((double)ft.dwHighDateTime) * 4294967296.0;   *prNow = (now + ft.dwLowDateTime)/864000000000.0 + 2305813.5;#endif#ifdef SQLITE_TEST  if( sqlite_current_time ){    *prNow = sqlite_current_time/86400.0 + 2440587.5;  }#endif  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -