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

📄 test_async.c

📁 sqlite嵌入式数据库源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    sqlite3Os.xOpenReadWrite = asyncOpenReadWrite;    sqlite3Os.xOpenReadOnly = asyncOpenReadOnly;    sqlite3Os.xOpenExclusive = asyncOpenExclusive;    sqlite3Os.xDelete = asyncDelete;    sqlite3Os.xFileExists = asyncFileExists;    sqlite3Os.xSyncDirectory = asyncSyncDirectory;    assert(sqlite3Os.xOpenReadWrite);  }  if( !enable && xOrigOpenReadWrite!=0 ){    assert(sqlite3Os.xOpenReadWrite);    sqlite3HashClear(&async.aLock);    sqlite3Os.xOpenReadWrite = xOrigOpenReadWrite;    sqlite3Os.xOpenReadOnly = xOrigOpenReadOnly;    sqlite3Os.xOpenExclusive = xOrigOpenExclusive;    sqlite3Os.xDelete = xOrigDelete;    sqlite3Os.xFileExists = xOrigFileExists;    sqlite3Os.xSyncDirectory = xOrigSyncDirectory;    xOrigOpenReadWrite = 0;    xOrigOpenReadOnly = 0;    xOrigOpenExclusive = 0;    xOrigDelete = 0;    xOrigFileExists = 0;    xOrigSyncDirectory = 0;    assert(sqlite3Os.xOpenReadWrite);  }}/* ** This procedure runs in a separate thread, reading messages off of the** write queue and processing them one by one.  **** If async.writerHaltNow is true, then this procedure exits** after processing a single message.**** If async.writerHaltWhenIdle is true, then this procedure exits when** the write queue is empty.**** If both of the above variables are false, this procedure runs** indefinately, waiting for operations to be added to the write queue** and processing them in the order in which they arrive.**** An artifical delay of async.ioDelay milliseconds is inserted before** each write operation in order to simulate the effect of a slow disk.**** Only one instance of this procedure may be running at a time.*/static void *asyncWriterThread(void *NotUsed){  AsyncWrite *p = 0;  int rc = SQLITE_OK;  int holdingMutex = 0;  if( pthread_mutex_trylock(&async.writerMutex) ){    return 0;  }  while( async.writerHaltNow==0 ){    OsFile *pBase = 0;    if( !holdingMutex ){      pthread_mutex_lock(&async.queueMutex);    }    while( (p = async.pQueueFirst)==0 ){      pthread_cond_broadcast(&async.emptySignal);      if( async.writerHaltWhenIdle ){        pthread_mutex_unlock(&async.queueMutex);        break;      }else{        TRACE(("IDLE\n"));        pthread_cond_wait(&async.queueSignal, &async.queueMutex);        TRACE(("WAKEUP\n"));      }    }    if( p==0 ) break;    holdingMutex = 1;    /* Right now this thread is holding the mutex on the write-op queue.    ** Variable 'p' points to the first entry in the write-op queue. In    ** the general case, we hold on to the mutex for the entire body of    ** the loop.     **    ** However in the cases enumerated below, we relinquish the mutex,    ** perform the IO, and then re-request the mutex before removing 'p' from    ** the head of the write-op queue. The idea is to increase concurrency with    ** sqlite threads.    **    **     * An ASYNC_CLOSE operation.    **     * An ASYNC_OPENEXCLUSIVE operation. For this one, we relinquish     **       the mutex, call the underlying xOpenExclusive() function, then    **       re-aquire the mutex before seting the AsyncFile.pBaseRead     **       variable.    **     * ASYNC_SYNC and ASYNC_WRITE operations, if     **       SQLITE_ASYNC_TWO_FILEHANDLES was set at compile time and two    **       file-handles are open for the particular file being "synced".    */    if( async.ioError!=SQLITE_OK && p->op!=ASYNC_CLOSE ){      p->op = ASYNC_NOOP;    }    if( p->pFile ){      pBase = p->pFile->pBaseWrite;      if(         p->op==ASYNC_CLOSE ||         p->op==ASYNC_OPENEXCLUSIVE ||        (pBase && (p->op==ASYNC_SYNC || p->op==ASYNC_WRITE) )       ){        pthread_mutex_unlock(&async.queueMutex);        holdingMutex = 0;      }      if( !pBase ){        pBase = p->pFile->pBaseRead;      }    }    switch( p->op ){      case ASYNC_NOOP:        break;      case ASYNC_WRITE:        assert( pBase );        TRACE(("WRITE %s %d bytes at %d\n",                p->pFile->zName, p->nByte, p->iOffset));        rc = sqlite3OsSeek(pBase, p->iOffset);        if( rc==SQLITE_OK ){          rc = sqlite3OsWrite(pBase, (const void *)(p->zBuf), p->nByte);        }        break;      case ASYNC_SYNC:        assert( pBase );        TRACE(("SYNC %s\n", p->pFile->zName));        rc = sqlite3OsSync(pBase, p->nByte);        break;      case ASYNC_TRUNCATE:        assert( pBase );        TRACE(("TRUNCATE %s to %d bytes\n", p->pFile->zName, p->iOffset));        rc = sqlite3OsTruncate(pBase, p->iOffset);        break;      case ASYNC_CLOSE:        TRACE(("CLOSE %s\n", p->pFile->zName));        sqlite3OsClose(&p->pFile->pBaseWrite);        sqlite3OsClose(&p->pFile->pBaseRead);        sqlite3OsFree(p->pFile);        break;      case ASYNC_OPENDIRECTORY:        assert( pBase );        TRACE(("OPENDIR %s\n", p->zBuf));        sqlite3OsOpenDirectory(pBase, p->zBuf);        break;      case ASYNC_SETFULLSYNC:        assert( pBase );        TRACE(("SETFULLSYNC %s %d\n", p->pFile->zName, p->nByte));        sqlite3OsSetFullSync(pBase, p->nByte);        break;      case ASYNC_DELETE:        TRACE(("DELETE %s\n", p->zBuf));        rc = xOrigDelete(p->zBuf);        break;      case ASYNC_SYNCDIRECTORY:        TRACE(("SYNCDIR %s\n", p->zBuf));        rc = xOrigSyncDirectory(p->zBuf);        break;      case ASYNC_OPENEXCLUSIVE: {        AsyncFile *pFile = p->pFile;        int delFlag = ((p->iOffset)?1:0);        OsFile *pBase = 0;        TRACE(("OPEN %s delFlag=%d\n", p->zBuf, delFlag));        assert(pFile->pBaseRead==0 && pFile->pBaseWrite==0);        rc = xOrigOpenExclusive(p->zBuf, &pBase, delFlag);        assert( holdingMutex==0 );        pthread_mutex_lock(&async.queueMutex);        holdingMutex = 1;        if( rc==SQLITE_OK ){          pFile->pBaseRead = pBase;        }        break;      }      default: assert(!"Illegal value for AsyncWrite.op");    }    /* If we didn't hang on to the mutex during the IO op, obtain it now    ** so that the AsyncWrite structure can be safely removed from the     ** global write-op queue.    */    if( !holdingMutex ){      pthread_mutex_lock(&async.queueMutex);      holdingMutex = 1;    }    /* TRACE(("UNLINK %p\n", p)); */    if( p==async.pQueueLast ){      async.pQueueLast = 0;    }    async.pQueueFirst = p->pNext;    sqlite3OsFree(p);    assert( holdingMutex );    /* An IO error has occured. We cannot report the error back to the    ** connection that requested the I/O since the error happened     ** asynchronously.  The connection has already moved on.  There     ** really is nobody to report the error to.    **    ** The file for which the error occured may have been a database or    ** journal file. Regardless, none of the currently queued operations    ** associated with the same database should now be performed. Nor should    ** any subsequently requested IO on either a database or journal file     ** handle for the same database be accepted until the main database    ** file handle has been closed and reopened.    **    ** Furthermore, no further IO should be queued or performed on any file    ** handle associated with a database that may have been part of a     ** multi-file transaction that included the database associated with     ** the IO error (i.e. a database ATTACHed to the same handle at some     ** point in time).    */    if( rc!=SQLITE_OK ){      async.ioError = rc;    }    /* Drop the queue mutex before continuing to the next write operation    ** in order to give other threads a chance to work with the write queue.    */    if( !async.pQueueFirst || !async.ioError ){      sqlite3ApiExit(0, 0);      pthread_mutex_unlock(&async.queueMutex);      holdingMutex = 0;      if( async.ioDelay>0 ){        sqlite3OsSleep(async.ioDelay);      }else{        sched_yield();      }    }  }    pthread_mutex_unlock(&async.writerMutex);  return 0;}/**************************************************************************** The remaining code defines a Tcl interface for testing the asynchronous** IO implementation in this file.**** To adapt the code to a non-TCL environment, delete or comment out** the code that follows.*//*** sqlite3async_enable ?YES/NO?**** Enable or disable the asynchronous I/O backend.  This command is** not thread-safe.  Do not call it while any database connections** are open.*/static int testAsyncEnable(  void * clientData,  Tcl_Interp *interp,  int objc,  Tcl_Obj *CONST objv[]){  if( objc!=1 && objc!=2 ){    Tcl_WrongNumArgs(interp, 1, objv, "?YES/NO?");    return TCL_ERROR;  }  if( objc==1 ){    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(xOrigOpenReadWrite!=0));  }else{    int en;    if( Tcl_GetBooleanFromObj(interp, objv[1], &en) ) return TCL_ERROR;    asyncEnable(en);  }  return TCL_OK;}/*** sqlite3async_halt  "now"|"idle"|"never"**** Set the conditions at which the writer thread will halt.*/static int testAsyncHalt(  void * clientData,  Tcl_Interp *interp,  int objc,  Tcl_Obj *CONST objv[]){  const char *zCond;  if( objc!=2 ){    Tcl_WrongNumArgs(interp, 1, objv, "\"now\"|\"idle\"|\"never\"");    return TCL_ERROR;  }  zCond = Tcl_GetString(objv[1]);  if( strcmp(zCond, "now")==0 ){    async.writerHaltNow = 1;    pthread_cond_broadcast(&async.queueSignal);  }else if( strcmp(zCond, "idle")==0 ){    async.writerHaltWhenIdle = 1;    async.writerHaltNow = 0;    pthread_cond_broadcast(&async.queueSignal);  }else if( strcmp(zCond, "never")==0 ){    async.writerHaltWhenIdle = 0;    async.writerHaltNow = 0;  }else{    Tcl_AppendResult(interp,       "should be one of: \"now\", \"idle\", or \"never\"", (char*)0);    return TCL_ERROR;  }  return TCL_OK;}/*** sqlite3async_delay ?MS?**** Query or set the number of milliseconds of delay in the writer** thread after each write operation.  The default is 0.  By increasing** the memory delay we can simulate the effect of slow disk I/O.*/static int testAsyncDelay(  void * clientData,  Tcl_Interp *interp,  int objc,  Tcl_Obj *CONST objv[]){  if( objc!=1 && objc!=2 ){    Tcl_WrongNumArgs(interp, 1, objv, "?MS?");    return TCL_ERROR;  }  if( objc==1 ){    Tcl_SetObjResult(interp, Tcl_NewIntObj(async.ioDelay));  }else{    int ioDelay;    if( Tcl_GetIntFromObj(interp, objv[1], &ioDelay) ) return TCL_ERROR;    async.ioDelay = ioDelay;  }  return TCL_OK;}/*** sqlite3async_start**** Start a new writer thread.*/static int testAsyncStart(  void * clientData,  Tcl_Interp *interp,  int objc,  Tcl_Obj *CONST objv[]){  pthread_t x;  int rc;  rc = pthread_create(&x, 0, asyncWriterThread, 0);  if( rc ){    Tcl_AppendResult(interp, "failed to create the thread", 0);    return TCL_ERROR;  }  pthread_detach(x);  return TCL_OK;}/*** sqlite3async_wait**** Wait for the current writer thread to terminate.**** If the current writer thread is set to run forever then this** command would block forever.  To prevent that, an error is returned. */static int testAsyncWait(  void * clientData,  Tcl_Interp *interp,  int objc,  Tcl_Obj *CONST objv[]){  int cnt = 10;  if( async.writerHaltNow==0 && async.writerHaltWhenIdle==0 ){    Tcl_AppendResult(interp, "would block forever", (char*)0);    return TCL_ERROR;  }  while( cnt-- && !pthread_mutex_trylock(&async.writerMutex) ){    pthread_mutex_unlock(&async.writerMutex);    sched_yield();  }  if( cnt>=0 ){    TRACE(("WAIT\n"));    pthread_mutex_lock(&async.queueMutex);    pthread_cond_broadcast(&async.queueSignal);    pthread_mutex_unlock(&async.queueMutex);    pthread_mutex_lock(&async.writerMutex);    pthread_mutex_unlock(&async.writerMutex);  }else{    TRACE(("NO-WAIT\n"));  }  return TCL_OK;}#endif  /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) *//*** This routine registers the custom TCL commands defined in this** module.  This should be the only procedure visible from outside** of this module.*/int Sqlitetestasync_Init(Tcl_Interp *interp){#if OS_UNIX && THREADSAFE && defined(SQLITE_ENABLE_REDEF_IO)  Tcl_CreateObjCommand(interp,"sqlite3async_enable",testAsyncEnable,0,0);  Tcl_CreateObjCommand(interp,"sqlite3async_halt",testAsyncHalt,0,0);  Tcl_CreateObjCommand(interp,"sqlite3async_delay",testAsyncDelay,0,0);  Tcl_CreateObjCommand(interp,"sqlite3async_start",testAsyncStart,0,0);  Tcl_CreateObjCommand(interp,"sqlite3async_wait",testAsyncWait,0,0);  Tcl_LinkVar(interp, "sqlite3async_trace",      (char*)&sqlite3async_trace, TCL_LINK_INT);#endif  /* OS_UNIX and THREADSAFE and defined(SQLITE_ENABLE_REDEF_IO) */  return TCL_OK;}

⌨️ 快捷键说明

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