mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-12 13:01:09 +03:00
Modify test_async.c to avoid using internal SQLite APIs. There are still some comments that need updating. (CVS 5698)
FossilOrigin-Name: 1d4fcaafd058bf1b726378e9ec308ecd8130fe1b
This commit is contained in:
12
manifest
12
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Check\sif\serror\scode\sENOTSUP\sis\ssupported\sbefore\susing\sit.\sTicket\s#3375.\s(CVS\s5697)
|
C Modify\stest_async.c\sto\savoid\susing\sinternal\sSQLite\sAPIs.\sThere\sare\sstill\ssome\scomments\sthat\sneed\supdating.\s(CVS\s5698)
|
||||||
D 2008-09-15T04:20:32
|
D 2008-09-15T14:08:04
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in d15a7ebfe5e057a72a49805ffb302dbb601c8329
|
F Makefile.in d15a7ebfe5e057a72a49805ffb302dbb601c8329
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -165,7 +165,7 @@ F src/test6.c 0a0304a69cfa4962a429d084c6d451ff9e4fb572
|
|||||||
F src/test7.c 475b1fa7e3275408b40a3cbdc9508cbdc41ffa02
|
F src/test7.c 475b1fa7e3275408b40a3cbdc9508cbdc41ffa02
|
||||||
F src/test8.c 3637439424d0d21ff2dcf9b015c30fcc1e7bcb24
|
F src/test8.c 3637439424d0d21ff2dcf9b015c30fcc1e7bcb24
|
||||||
F src/test9.c 904ebe0ed1472d6bad17a81e2ecbfc20017dc237
|
F src/test9.c 904ebe0ed1472d6bad17a81e2ecbfc20017dc237
|
||||||
F src/test_async.c da9f58f49faccd3a26ba89f58de125862351b6e2
|
F src/test_async.c 2f644e5c4ee4ecc568234a22b98d992deda6006e
|
||||||
F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad
|
F src/test_autoext.c f53b0cdf7bf5f08100009572a5d65cdb540bd0ad
|
||||||
F src/test_btree.c 8d5b835054f1dd15992e09864a8bc04386bab701
|
F src/test_btree.c 8d5b835054f1dd15992e09864a8bc04386bab701
|
||||||
F src/test_config.c b2681a8e1b570f0c3686c934d6ef6112921af05d
|
F src/test_config.c b2681a8e1b570f0c3686c934d6ef6112921af05d
|
||||||
@@ -635,7 +635,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
|||||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||||
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
P ced6bbd228b4a324ddb9c5ff15fd027811c8806a
|
P c32cb106c5d68e98f51f1eaf9ae0e2a3c36d00d6
|
||||||
R 4d23aa13f9709d8ea8e494bd8ecff601
|
R 81c8df88182aeac4375b62d10daf76ae
|
||||||
U danielk1977
|
U danielk1977
|
||||||
Z 15f69e2058d6662c1b75f3319378d24f
|
Z 598fdfba976b3753bad5428908262014
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
c32cb106c5d68e98f51f1eaf9ae0e2a3c36d00d6
|
1d4fcaafd058bf1b726378e9ec308ecd8130fe1b
|
||||||
206
src/test_async.c
206
src/test_async.c
@@ -10,7 +10,7 @@
|
|||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
**
|
**
|
||||||
** $Id: test_async.c,v 1.45 2008/06/26 10:41:19 danielk1977 Exp $
|
** $Id: test_async.c,v 1.46 2008/09/15 14:08:04 danielk1977 Exp $
|
||||||
**
|
**
|
||||||
** This file contains an example implementation of an asynchronous IO
|
** This file contains an example implementation of an asynchronous IO
|
||||||
** backend for SQLite.
|
** backend for SQLite.
|
||||||
@@ -109,7 +109,9 @@
|
|||||||
#define ENABLE_FILE_LOCKING
|
#define ENABLE_FILE_LOCKING
|
||||||
|
|
||||||
#ifndef SQLITE_AMALGAMATION
|
#ifndef SQLITE_AMALGAMATION
|
||||||
# include "sqliteInt.h"
|
# include "sqlite3.h"
|
||||||
|
# include <assert.h>
|
||||||
|
# include <string.h>
|
||||||
#endif
|
#endif
|
||||||
#include <tcl.h>
|
#include <tcl.h>
|
||||||
|
|
||||||
@@ -274,7 +276,7 @@ static struct TestAsyncStaticData {
|
|||||||
pthread_cond_t emptySignal; /* Notify when the write queue is empty */
|
pthread_cond_t emptySignal; /* Notify when the write queue is empty */
|
||||||
AsyncWrite *pQueueFirst; /* Next write operation to be processed */
|
AsyncWrite *pQueueFirst; /* Next write operation to be processed */
|
||||||
AsyncWrite *pQueueLast; /* Last write operation on the list */
|
AsyncWrite *pQueueLast; /* Last write operation on the list */
|
||||||
Hash aLock; /* Files locked */
|
AsyncLock *pLock; /* Linked list of all AsyncLock structures */
|
||||||
volatile int ioDelay; /* Extra delay between write operations */
|
volatile int ioDelay; /* Extra delay between write operations */
|
||||||
volatile int writerHaltWhenIdle; /* Writer thread halts when queue empty */
|
volatile int writerHaltWhenIdle; /* Writer thread halts when queue empty */
|
||||||
volatile int writerHaltNow; /* Writer thread halts after next op */
|
volatile int writerHaltNow; /* Writer thread halts after next op */
|
||||||
@@ -350,7 +352,7 @@ static const char *azOpcodeName[] = {
|
|||||||
struct AsyncWrite {
|
struct AsyncWrite {
|
||||||
AsyncFileData *pFileData; /* File to write data to or sync */
|
AsyncFileData *pFileData; /* File to write data to or sync */
|
||||||
int op; /* One of ASYNC_xxx etc. */
|
int op; /* One of ASYNC_xxx etc. */
|
||||||
i64 iOffset; /* See above */
|
sqlite_int64 iOffset; /* See above */
|
||||||
int nByte; /* See above */
|
int nByte; /* See above */
|
||||||
char *zBuf; /* Data to write to file (or NULL if op!=ASYNC_WRITE) */
|
char *zBuf; /* Data to write to file (or NULL if op!=ASYNC_WRITE) */
|
||||||
AsyncWrite *pNext; /* Next write operation (to any file) */
|
AsyncWrite *pNext; /* Next write operation (to any file) */
|
||||||
@@ -376,9 +378,12 @@ struct AsyncWrite {
|
|||||||
** the implementation of database locking used by this backend.
|
** the implementation of database locking used by this backend.
|
||||||
*/
|
*/
|
||||||
struct AsyncLock {
|
struct AsyncLock {
|
||||||
|
char *zFile;
|
||||||
|
int nFile;
|
||||||
sqlite3_file *pFile;
|
sqlite3_file *pFile;
|
||||||
int eLock;
|
int eLock;
|
||||||
AsyncFileLock *pList;
|
AsyncFileLock *pList;
|
||||||
|
AsyncLock *pNext; /* Next in linked list headed by async.pLock */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -412,7 +417,8 @@ struct AsyncFileData {
|
|||||||
int nName; /* Number of characters in zName */
|
int nName; /* Number of characters in zName */
|
||||||
sqlite3_file *pBaseRead; /* Read handle to the underlying Os file */
|
sqlite3_file *pBaseRead; /* Read handle to the underlying Os file */
|
||||||
sqlite3_file *pBaseWrite; /* Write handle to the underlying Os file */
|
sqlite3_file *pBaseWrite; /* Write handle to the underlying Os file */
|
||||||
AsyncFileLock lock;
|
AsyncFileLock lock; /* Lock state for this handle */
|
||||||
|
AsyncLock *pLock; /* AsyncLock object for this file system entry */
|
||||||
AsyncWrite close;
|
AsyncWrite close;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -631,7 +637,7 @@ static void incrOpenFileCount(){
|
|||||||
static int addNewAsyncWrite(
|
static int addNewAsyncWrite(
|
||||||
AsyncFileData *pFileData,
|
AsyncFileData *pFileData,
|
||||||
int op,
|
int op,
|
||||||
i64 iOffset,
|
sqlite3_int64 iOffset,
|
||||||
int nByte,
|
int nByte,
|
||||||
const char *zByte
|
const char *zByte
|
||||||
){
|
){
|
||||||
@@ -686,7 +692,12 @@ static int asyncClose(sqlite3_file *pFile){
|
|||||||
** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be
|
** the global AsyncWrite list. Either SQLITE_OK or SQLITE_NOMEM may be
|
||||||
** returned.
|
** returned.
|
||||||
*/
|
*/
|
||||||
static int asyncWrite(sqlite3_file *pFile, const void *pBuf, int amt, i64 iOff){
|
static int asyncWrite(
|
||||||
|
sqlite3_file *pFile,
|
||||||
|
const void *pBuf,
|
||||||
|
int amt,
|
||||||
|
sqlite3_int64 iOff
|
||||||
|
){
|
||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
return addNewAsyncWrite(p, ASYNC_WRITE, iOff, amt, pBuf);
|
return addNewAsyncWrite(p, ASYNC_WRITE, iOff, amt, pBuf);
|
||||||
}
|
}
|
||||||
@@ -698,10 +709,15 @@ static int asyncWrite(sqlite3_file *pFile, const void *pBuf, int amt, i64 iOff){
|
|||||||
**
|
**
|
||||||
** This method holds the mutex from start to finish.
|
** This method holds the mutex from start to finish.
|
||||||
*/
|
*/
|
||||||
static int asyncRead(sqlite3_file *pFile, void *zOut, int iAmt, i64 iOffset){
|
static int asyncRead(
|
||||||
|
sqlite3_file *pFile,
|
||||||
|
void *zOut,
|
||||||
|
int iAmt,
|
||||||
|
sqlite3_int64 iOffset
|
||||||
|
){
|
||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
i64 filesize;
|
sqlite3_int64 filesize;
|
||||||
int nRead;
|
int nRead;
|
||||||
sqlite3_file *pBase = p->pBaseRead;
|
sqlite3_file *pBase = p->pBaseRead;
|
||||||
|
|
||||||
@@ -717,13 +733,13 @@ static int asyncRead(sqlite3_file *pFile, void *zOut, int iAmt, i64 iOffset){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( pBase->pMethods ){
|
if( pBase->pMethods ){
|
||||||
rc = sqlite3OsFileSize(pBase, &filesize);
|
rc = pBase->pMethods->xFileSize(pBase, &filesize);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
goto asyncread_out;
|
goto asyncread_out;
|
||||||
}
|
}
|
||||||
nRead = MIN(filesize - iOffset, iAmt);
|
nRead = MIN(filesize - iOffset, iAmt);
|
||||||
if( nRead>0 ){
|
if( nRead>0 ){
|
||||||
rc = sqlite3OsRead(pBase, zOut, nRead, iOffset);
|
rc = pBase->pMethods->xRead(pBase, zOut, nRead, iOffset);
|
||||||
ASYNC_TRACE(("READ %s %d bytes at %d\n", p->zName, nRead, iOffset));
|
ASYNC_TRACE(("READ %s %d bytes at %d\n", p->zName, nRead, iOffset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -733,7 +749,10 @@ static int asyncRead(sqlite3_file *pFile, void *zOut, int iAmt, i64 iOffset){
|
|||||||
char *zName = p->zName;
|
char *zName = p->zName;
|
||||||
|
|
||||||
for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
|
for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
|
||||||
if( pWrite->op==ASYNC_WRITE && pWrite->pFileData->zName==zName ){
|
if( pWrite->op==ASYNC_WRITE && (
|
||||||
|
(pWrite->pFileData==p) ||
|
||||||
|
(zName && pWrite->pFileData->zName==zName)
|
||||||
|
)){
|
||||||
int iBeginOut = (pWrite->iOffset-iOffset);
|
int iBeginOut = (pWrite->iOffset-iOffset);
|
||||||
int iBeginIn = -iBeginOut;
|
int iBeginIn = -iBeginOut;
|
||||||
int nCopy;
|
int nCopy;
|
||||||
@@ -759,7 +778,7 @@ asyncread_out:
|
|||||||
** Truncate the file to nByte bytes in length. This just adds an entry to
|
** Truncate the file to nByte bytes in length. This just adds an entry to
|
||||||
** the write-op list, no IO actually takes place.
|
** the write-op list, no IO actually takes place.
|
||||||
*/
|
*/
|
||||||
static int asyncTruncate(sqlite3_file *pFile, i64 nByte){
|
static int asyncTruncate(sqlite3_file *pFile, sqlite3_int64 nByte){
|
||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
return addNewAsyncWrite(p, ASYNC_TRUNCATE, nByte, 0, 0);
|
return addNewAsyncWrite(p, ASYNC_TRUNCATE, nByte, 0, 0);
|
||||||
}
|
}
|
||||||
@@ -780,10 +799,10 @@ static int asyncSync(sqlite3_file *pFile, int flags){
|
|||||||
**
|
**
|
||||||
** This method holds the mutex from start to finish.
|
** This method holds the mutex from start to finish.
|
||||||
*/
|
*/
|
||||||
int asyncFileSize(sqlite3_file *pFile, i64 *piSize){
|
int asyncFileSize(sqlite3_file *pFile, sqlite3_int64 *piSize){
|
||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
i64 s = 0;
|
sqlite3_int64 s = 0;
|
||||||
sqlite3_file *pBase;
|
sqlite3_file *pBase;
|
||||||
|
|
||||||
pthread_mutex_lock(&async.queueMutex);
|
pthread_mutex_lock(&async.queueMutex);
|
||||||
@@ -795,18 +814,24 @@ int asyncFileSize(sqlite3_file *pFile, i64 *piSize){
|
|||||||
*/
|
*/
|
||||||
pBase = p->pBaseRead;
|
pBase = p->pBaseRead;
|
||||||
if( pBase->pMethods ){
|
if( pBase->pMethods ){
|
||||||
rc = sqlite3OsFileSize(pBase, &s);
|
rc = pBase->pMethods->xFileSize(pBase, &s);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
AsyncWrite *pWrite;
|
AsyncWrite *pWrite;
|
||||||
for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
|
for(pWrite=async.pQueueFirst; pWrite; pWrite = pWrite->pNext){
|
||||||
if( pWrite->op==ASYNC_DELETE && strcmp(p->zName, pWrite->zBuf)==0 ){
|
if( pWrite->op==ASYNC_DELETE
|
||||||
|
&& p->zName
|
||||||
|
&& strcmp(p->zName, pWrite->zBuf)==0
|
||||||
|
){
|
||||||
s = 0;
|
s = 0;
|
||||||
}else if( pWrite->pFileData && pWrite->pFileData->zName==p->zName){
|
}else if( pWrite->pFileData && (
|
||||||
|
(pWrite->pFileData==p)
|
||||||
|
|| (p->zName && pWrite->pFileData->zName==p->zName)
|
||||||
|
)){
|
||||||
switch( pWrite->op ){
|
switch( pWrite->op ){
|
||||||
case ASYNC_WRITE:
|
case ASYNC_WRITE:
|
||||||
s = MAX(pWrite->iOffset + (i64)(pWrite->nByte), s);
|
s = MAX(pWrite->iOffset + (sqlite3_int64)(pWrite->nByte), s);
|
||||||
break;
|
break;
|
||||||
case ASYNC_TRUNCATE:
|
case ASYNC_TRUNCATE:
|
||||||
s = MIN(s, pWrite->iOffset);
|
s = MIN(s, pWrite->iOffset);
|
||||||
@@ -838,13 +863,13 @@ static int getFileLock(AsyncLock *pLock){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( eRequired>pLock->eLock ){
|
if( eRequired>pLock->eLock ){
|
||||||
rc = sqlite3OsLock(pLock->pFile, eRequired);
|
rc = pLock->pFile->pMethods->xLock(pLock->pFile, eRequired);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
pLock->eLock = eRequired;
|
pLock->eLock = eRequired;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( eRequired<pLock->eLock && eRequired<=SQLITE_LOCK_SHARED ){
|
else if( eRequired<pLock->eLock && eRequired<=SQLITE_LOCK_SHARED ){
|
||||||
rc = sqlite3OsUnlock(pLock->pFile, eRequired);
|
rc = pLock->pFile->pMethods->xUnlock(pLock->pFile, eRequired);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
pLock->eLock = eRequired;
|
pLock->eLock = eRequired;
|
||||||
}
|
}
|
||||||
@@ -854,6 +879,19 @@ static int getFileLock(AsyncLock *pLock){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Return the AsyncLock structure from the global async.pLock list
|
||||||
|
** associated with the file-system entry identified by path zName
|
||||||
|
** (a string of nName bytes). If no such structure exists, return 0.
|
||||||
|
*/
|
||||||
|
static AsyncLock *findLock(const char *zName, int nName){
|
||||||
|
AsyncLock *p = async.pLock;
|
||||||
|
while( p && (p->nFile!=nName || memcmp(p->zFile, zName, nName)) ){
|
||||||
|
p = p->pNext;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** The following two methods - asyncLock() and asyncUnlock() - are used
|
** The following two methods - asyncLock() and asyncUnlock() - are used
|
||||||
** to obtain and release locks on database files opened with the
|
** to obtain and release locks on database files opened with the
|
||||||
@@ -863,11 +901,11 @@ static int asyncLock(sqlite3_file *pFile, int eLock){
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
|
|
||||||
|
if( p->zName ){
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
if( p->lock.eLock<eLock ){
|
if( p->lock.eLock<eLock ){
|
||||||
AsyncLock *pLock;
|
AsyncLock *pLock = p->pLock;
|
||||||
AsyncFileLock *pIter;
|
AsyncFileLock *pIter;
|
||||||
pLock = (AsyncLock *)sqlite3HashFind(&async.aLock, p->zName, p->nName);
|
|
||||||
assert(pLock && pLock->pList);
|
assert(pLock && pLock->pList);
|
||||||
for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
|
for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
|
||||||
if( pIter!=&p->lock && (
|
if( pIter!=&p->lock && (
|
||||||
@@ -889,17 +927,22 @@ static int asyncLock(sqlite3_file *pFile, int eLock){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&async.lockMutex);
|
pthread_mutex_unlock(&async.lockMutex);
|
||||||
|
}
|
||||||
|
|
||||||
ASYNC_TRACE(("LOCK %d (%s) rc=%d\n", eLock, p->zName, rc));
|
ASYNC_TRACE(("LOCK %d (%s) rc=%d\n", eLock, p->zName, rc));
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
static int asyncUnlock(sqlite3_file *pFile, int eLock){
|
static int asyncUnlock(sqlite3_file *pFile, int eLock){
|
||||||
|
int rc = SQLITE_OK;
|
||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
|
if( p->zName ){
|
||||||
AsyncFileLock *pLock = &p->lock;
|
AsyncFileLock *pLock = &p->lock;
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
pLock->eLock = MIN(pLock->eLock, eLock);
|
pLock->eLock = MIN(pLock->eLock, eLock);
|
||||||
pthread_mutex_unlock(&async.lockMutex);
|
pthread_mutex_unlock(&async.lockMutex);
|
||||||
return addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0);
|
rc = addNewAsyncWrite(p, ASYNC_UNLOCK, 0, eLock, 0);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -909,12 +952,10 @@ static int asyncUnlock(sqlite3_file *pFile, int eLock){
|
|||||||
static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
AsyncFileLock *pIter;
|
AsyncFileLock *pIter;
|
||||||
AsyncLock *pLock;
|
|
||||||
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
AsyncFileData *p = ((AsyncFile *)pFile)->pData;
|
||||||
|
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
pLock = (AsyncLock *)sqlite3HashFind(&async.aLock, p->zName, p->nName);
|
for(pIter=p->pLock->pList; pIter; pIter=pIter->pNext){
|
||||||
for(pIter=pLock->pList; pIter; pIter=pIter->pNext){
|
|
||||||
if( pIter->eLock>=SQLITE_LOCK_RESERVED ){
|
if( pIter->eLock>=SQLITE_LOCK_RESERVED ){
|
||||||
ret = 1;
|
ret = 1;
|
||||||
}
|
}
|
||||||
@@ -927,7 +968,7 @@ static int asyncCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This is a no-op, as the asynchronous backend does not support locking.
|
** sqlite3_file_control() implementation.
|
||||||
*/
|
*/
|
||||||
static int asyncFileControl(sqlite3_file *id, int op, void *pArg){
|
static int asyncFileControl(sqlite3_file *id, int op, void *pArg){
|
||||||
switch( op ){
|
switch( op ){
|
||||||
@@ -954,11 +995,11 @@ static int asyncDeviceCharacteristics(sqlite3_file *pFile){
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int unlinkAsyncFile(AsyncFileData *pData){
|
static int unlinkAsyncFile(AsyncFileData *pData){
|
||||||
AsyncLock *pLock;
|
|
||||||
AsyncFileLock **ppIter;
|
AsyncFileLock **ppIter;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
|
|
||||||
pLock = sqlite3HashFind(&async.aLock, pData->zName, pData->nName);
|
if( pData->zName ){
|
||||||
|
AsyncLock *pLock = pData->pLock;
|
||||||
for(ppIter=&pLock->pList; *ppIter; ppIter=&((*ppIter)->pNext)){
|
for(ppIter=&pLock->pList; *ppIter; ppIter=&((*ppIter)->pNext)){
|
||||||
if( (*ppIter)==&pData->lock ){
|
if( (*ppIter)==&pData->lock ){
|
||||||
*ppIter = pData->lock.pNext;
|
*ppIter = pData->lock.pNext;
|
||||||
@@ -966,17 +1007,17 @@ static int unlinkAsyncFile(AsyncFileData *pData){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( !pLock->pList ){
|
if( !pLock->pList ){
|
||||||
|
AsyncLock **pp;
|
||||||
if( pLock->pFile ){
|
if( pLock->pFile ){
|
||||||
sqlite3OsClose(pLock->pFile);
|
pLock->pFile->pMethods->xClose(pLock->pFile);
|
||||||
}
|
}
|
||||||
|
for(pp=&async.pLock; *pp!=pLock; pp=&((*pp)->pNext));
|
||||||
|
*pp = pLock->pNext;
|
||||||
sqlite3_free(pLock);
|
sqlite3_free(pLock);
|
||||||
sqlite3HashInsert(&async.aLock, pData->zName, pData->nName, 0);
|
|
||||||
if( !sqliteHashFirst(&async.aLock) ){
|
|
||||||
sqlite3HashClear(&async.aLock);
|
|
||||||
}
|
|
||||||
}else{
|
}else{
|
||||||
rc = getFileLock(pLock);
|
rc = getFileLock(pLock);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -1009,7 +1050,7 @@ static int asyncOpen(
|
|||||||
|
|
||||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
|
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
|
||||||
AsyncFile *p = (AsyncFile *)pFile;
|
AsyncFile *p = (AsyncFile *)pFile;
|
||||||
int nName = strlen(zName)+1;
|
int nName = 0;
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
int nByte;
|
int nByte;
|
||||||
AsyncFileData *pData;
|
AsyncFileData *pData;
|
||||||
@@ -1017,6 +1058,11 @@ static int asyncOpen(
|
|||||||
char *z;
|
char *z;
|
||||||
int isExclusive = (flags&SQLITE_OPEN_EXCLUSIVE);
|
int isExclusive = (flags&SQLITE_OPEN_EXCLUSIVE);
|
||||||
|
|
||||||
|
/* If zName is NULL, then the upper layer is requesting an anonymous file */
|
||||||
|
if( zName ){
|
||||||
|
nName = strlen(zName)+1;
|
||||||
|
}
|
||||||
|
|
||||||
nByte = (
|
nByte = (
|
||||||
sizeof(AsyncFileData) + /* AsyncFileData structure */
|
sizeof(AsyncFileData) + /* AsyncFileData structure */
|
||||||
2 * pVfs->szOsFile + /* AsyncFileData.pBaseRead and pBaseWrite */
|
2 * pVfs->szOsFile + /* AsyncFileData.pBaseRead and pBaseWrite */
|
||||||
@@ -1032,44 +1078,48 @@ static int asyncOpen(
|
|||||||
pData->pBaseRead = (sqlite3_file*)z;
|
pData->pBaseRead = (sqlite3_file*)z;
|
||||||
z += pVfs->szOsFile;
|
z += pVfs->szOsFile;
|
||||||
pData->pBaseWrite = (sqlite3_file*)z;
|
pData->pBaseWrite = (sqlite3_file*)z;
|
||||||
|
pData->close.pFileData = pData;
|
||||||
|
pData->close.op = ASYNC_CLOSE;
|
||||||
|
|
||||||
|
if( zName ){
|
||||||
z += pVfs->szOsFile;
|
z += pVfs->szOsFile;
|
||||||
pData->zName = z;
|
pData->zName = z;
|
||||||
pData->nName = nName;
|
pData->nName = nName;
|
||||||
pData->close.pFileData = pData;
|
|
||||||
pData->close.op = ASYNC_CLOSE;
|
|
||||||
memcpy(pData->zName, zName, nName);
|
memcpy(pData->zName, zName, nName);
|
||||||
|
}
|
||||||
|
|
||||||
if( !isExclusive ){
|
if( !isExclusive ){
|
||||||
rc = sqlite3OsOpen(pVfs, zName, pData->pBaseRead, flags, pOutFlags);
|
rc = pVfs->xOpen(pVfs, zName, pData->pBaseRead, flags, pOutFlags);
|
||||||
if( rc==SQLITE_OK && ((*pOutFlags)&SQLITE_OPEN_READWRITE) ){
|
if( rc==SQLITE_OK && ((*pOutFlags)&SQLITE_OPEN_READWRITE) ){
|
||||||
rc = sqlite3OsOpen(pVfs, zName, pData->pBaseWrite, flags, 0);
|
rc = pVfs->xOpen(pVfs, zName, pData->pBaseWrite, flags, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( zName && rc==SQLITE_OK ){
|
||||||
pLock = sqlite3HashFind(&async.aLock, pData->zName, pData->nName);
|
pLock = findLock(pData->zName, pData->nName);
|
||||||
if( !pLock ){
|
if( !pLock ){
|
||||||
pLock = sqlite3MallocZero(pVfs->szOsFile + sizeof(AsyncLock));
|
int nByte = pVfs->szOsFile + sizeof(AsyncLock) + pData->nName + 1;
|
||||||
|
pLock = (AsyncLock *)sqlite3_malloc(nByte);
|
||||||
if( pLock ){
|
if( pLock ){
|
||||||
AsyncLock *pDelete;
|
memset(pLock, 0, nByte);
|
||||||
#ifdef ENABLE_FILE_LOCKING
|
#ifdef ENABLE_FILE_LOCKING
|
||||||
if( flags&SQLITE_OPEN_MAIN_DB ){
|
if( flags&SQLITE_OPEN_MAIN_DB ){
|
||||||
pLock->pFile = (sqlite3_file *)&pLock[1];
|
pLock->pFile = (sqlite3_file *)&pLock[1];
|
||||||
rc = sqlite3OsOpen(pVfs, zName, pLock->pFile, flags, 0);
|
rc = pVfs->xOpen(pVfs, zName, pLock->pFile, flags, 0);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
sqlite3_free(pLock);
|
sqlite3_free(pLock);
|
||||||
pLock = 0;
|
pLock = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
pDelete = sqlite3HashInsert(
|
if( pLock ){
|
||||||
&async.aLock, pData->zName, pData->nName, (void *)pLock
|
pLock->nFile = pData->nName;
|
||||||
);
|
pLock->zFile = &((char *)(&pLock[1]))[pVfs->szOsFile];
|
||||||
if( pDelete ){
|
memcpy(pLock->zFile, pData->zName, pLock->nFile);
|
||||||
rc = SQLITE_NOMEM;
|
pLock->pNext = async.pLock;
|
||||||
sqlite3_free(pLock);
|
async.pLock = pLock;
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
@@ -1078,21 +1128,24 @@ static int asyncOpen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
HashElem *pElem;
|
|
||||||
p->pMethod = &async_methods;
|
p->pMethod = &async_methods;
|
||||||
p->pData = pData;
|
p->pData = pData;
|
||||||
|
|
||||||
/* Link AsyncFileData.lock into the linked list of
|
/* Link AsyncFileData.lock into the linked list of
|
||||||
** AsyncFileLock structures for this file.
|
** AsyncFileLock structures for this file.
|
||||||
*/
|
*/
|
||||||
|
if( zName ){
|
||||||
pData->lock.pNext = pLock->pList;
|
pData->lock.pNext = pLock->pList;
|
||||||
pLock->pList = &pData->lock;
|
pLock->pList = &pData->lock;
|
||||||
|
pData->zName = pLock->zFile;
|
||||||
pElem = sqlite3HashFindElem(&async.aLock, pData->zName, pData->nName);
|
}
|
||||||
pData->zName = (char *)sqliteHashKey(pElem);
|
|
||||||
}else{
|
}else{
|
||||||
sqlite3OsClose(pData->pBaseRead);
|
if( pData->pBaseRead->pMethods ){
|
||||||
sqlite3OsClose(pData->pBaseWrite);
|
pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
|
||||||
|
}
|
||||||
|
if( pData->pBaseWrite->pMethods ){
|
||||||
|
pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
|
||||||
|
}
|
||||||
sqlite3_free(pData);
|
sqlite3_free(pData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1100,10 +1153,11 @@ static int asyncOpen(
|
|||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
incrOpenFileCount();
|
incrOpenFileCount();
|
||||||
|
pData->pLock = pLock;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc==SQLITE_OK && isExclusive ){
|
if( rc==SQLITE_OK && isExclusive ){
|
||||||
rc = addNewAsyncWrite(pData, ASYNC_OPENEXCLUSIVE, (i64)flags, 0, 0);
|
rc = addNewAsyncWrite(pData, ASYNC_OPENEXCLUSIVE, (sqlite3_int64)flags,0,0);
|
||||||
if( rc==SQLITE_OK ){
|
if( rc==SQLITE_OK ){
|
||||||
if( pOutFlags ) *pOutFlags = flags;
|
if( pOutFlags ) *pOutFlags = flags;
|
||||||
}else{
|
}else{
|
||||||
@@ -1145,12 +1199,13 @@ static int asyncAccess(
|
|||||||
);
|
);
|
||||||
|
|
||||||
pthread_mutex_lock(&async.queueMutex);
|
pthread_mutex_lock(&async.queueMutex);
|
||||||
rc = sqlite3OsAccess(pVfs, zName, flags, &ret);
|
rc = pVfs->xAccess(pVfs, zName, flags, &ret);
|
||||||
if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
|
if( rc==SQLITE_OK && flags==SQLITE_ACCESS_EXISTS ){
|
||||||
for(p=async.pQueueFirst; p; p = p->pNext){
|
for(p=async.pQueueFirst; p; p = p->pNext){
|
||||||
if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, zName) ){
|
if( p->op==ASYNC_DELETE && 0==strcmp(p->zBuf, zName) ){
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}else if( p->op==ASYNC_OPENEXCLUSIVE
|
}else if( p->op==ASYNC_OPENEXCLUSIVE
|
||||||
|
&& p->pFileData->zName
|
||||||
&& 0==strcmp(p->pFileData->zName, zName)
|
&& 0==strcmp(p->pFileData->zName, zName)
|
||||||
){
|
){
|
||||||
ret = 1;
|
ret = 1;
|
||||||
@@ -1178,7 +1233,7 @@ static int asyncFullPathname(
|
|||||||
){
|
){
|
||||||
int rc;
|
int rc;
|
||||||
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
|
sqlite3_vfs *pVfs = (sqlite3_vfs *)pAsyncVfs->pAppData;
|
||||||
rc = sqlite3OsFullPathname(pVfs, zPath, nPathOut, zPathOut);
|
rc = pVfs->xFullPathname(pVfs, zPath, nPathOut, zPathOut);
|
||||||
|
|
||||||
/* Because of the way intra-process file locking works, this backend
|
/* Because of the way intra-process file locking works, this backend
|
||||||
** needs to return a canonical path. The following block assumes the
|
** needs to return a canonical path. The following block assumes the
|
||||||
@@ -1286,14 +1341,9 @@ static sqlite3_vfs async_vfs = {
|
|||||||
static void asyncEnable(int enable){
|
static void asyncEnable(int enable){
|
||||||
if( enable ){
|
if( enable ){
|
||||||
if( !async_vfs.pAppData ){
|
if( !async_vfs.pAppData ){
|
||||||
static int hashTableInit = 0;
|
|
||||||
async_vfs.pAppData = (void *)sqlite3_vfs_find(0);
|
async_vfs.pAppData = (void *)sqlite3_vfs_find(0);
|
||||||
async_vfs.mxPathname = ((sqlite3_vfs *)async_vfs.pAppData)->mxPathname;
|
async_vfs.mxPathname = ((sqlite3_vfs *)async_vfs.pAppData)->mxPathname;
|
||||||
sqlite3_vfs_register(&async_vfs, 1);
|
sqlite3_vfs_register(&async_vfs, 1);
|
||||||
if( !hashTableInit ){
|
|
||||||
sqlite3HashInit(&async.aLock, SQLITE_HASH_BINARY, 1);
|
|
||||||
hashTableInit = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
if( async_vfs.pAppData ){
|
if( async_vfs.pAppData ){
|
||||||
@@ -1398,27 +1448,31 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
assert( pBase );
|
assert( pBase );
|
||||||
ASYNC_TRACE(("WRITE %s %d bytes at %d\n",
|
ASYNC_TRACE(("WRITE %s %d bytes at %d\n",
|
||||||
p->pFileData->zName, p->nByte, p->iOffset));
|
p->pFileData->zName, p->nByte, p->iOffset));
|
||||||
rc = sqlite3OsWrite(pBase, (void *)(p->zBuf), p->nByte, p->iOffset);
|
rc = pBase->pMethods->xWrite(pBase, (void *)(p->zBuf), p->nByte, p->iOffset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASYNC_SYNC:
|
case ASYNC_SYNC:
|
||||||
assert( pBase );
|
assert( pBase );
|
||||||
ASYNC_TRACE(("SYNC %s\n", p->pFileData->zName));
|
ASYNC_TRACE(("SYNC %s\n", p->pFileData->zName));
|
||||||
rc = sqlite3OsSync(pBase, p->nByte);
|
rc = pBase->pMethods->xSync(pBase, p->nByte);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASYNC_TRUNCATE:
|
case ASYNC_TRUNCATE:
|
||||||
assert( pBase );
|
assert( pBase );
|
||||||
ASYNC_TRACE(("TRUNCATE %s to %d bytes\n",
|
ASYNC_TRACE(("TRUNCATE %s to %d bytes\n",
|
||||||
p->pFileData->zName, p->iOffset));
|
p->pFileData->zName, p->iOffset));
|
||||||
rc = sqlite3OsTruncate(pBase, p->iOffset);
|
rc = pBase->pMethods->xTruncate(pBase, p->iOffset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASYNC_CLOSE: {
|
case ASYNC_CLOSE: {
|
||||||
AsyncFileData *pData = p->pFileData;
|
AsyncFileData *pData = p->pFileData;
|
||||||
ASYNC_TRACE(("CLOSE %s\n", p->pFileData->zName));
|
ASYNC_TRACE(("CLOSE %s\n", p->pFileData->zName));
|
||||||
sqlite3OsClose(pData->pBaseWrite);
|
if( pData->pBaseWrite->pMethods ){
|
||||||
sqlite3OsClose(pData->pBaseRead);
|
pData->pBaseWrite->pMethods->xClose(pData->pBaseWrite);
|
||||||
|
}
|
||||||
|
if( pData->pBaseRead->pMethods ){
|
||||||
|
pData->pBaseRead->pMethods->xClose(pData->pBaseRead);
|
||||||
|
}
|
||||||
|
|
||||||
/* Unlink AsyncFileData.lock from the linked list of AsyncFileLock
|
/* Unlink AsyncFileData.lock from the linked list of AsyncFileLock
|
||||||
** structures for this file. Obtain the async.lockMutex mutex
|
** structures for this file. Obtain the async.lockMutex mutex
|
||||||
@@ -1435,7 +1489,6 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
}
|
}
|
||||||
|
|
||||||
case ASYNC_UNLOCK: {
|
case ASYNC_UNLOCK: {
|
||||||
AsyncLock *pLock;
|
|
||||||
AsyncFileData *pData = p->pFileData;
|
AsyncFileData *pData = p->pFileData;
|
||||||
int eLock = p->nByte;
|
int eLock = p->nByte;
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
@@ -1443,15 +1496,14 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock)
|
pData->lock.eAsyncLock, MAX(pData->lock.eLock, eLock)
|
||||||
);
|
);
|
||||||
assert(pData->lock.eAsyncLock>=pData->lock.eLock);
|
assert(pData->lock.eAsyncLock>=pData->lock.eLock);
|
||||||
pLock = sqlite3HashFind(&async.aLock, pData->zName, pData->nName);
|
rc = getFileLock(pData->pLock);
|
||||||
rc = getFileLock(pLock);
|
|
||||||
pthread_mutex_unlock(&async.lockMutex);
|
pthread_mutex_unlock(&async.lockMutex);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ASYNC_DELETE:
|
case ASYNC_DELETE:
|
||||||
ASYNC_TRACE(("DELETE %s\n", p->zBuf));
|
ASYNC_TRACE(("DELETE %s\n", p->zBuf));
|
||||||
rc = sqlite3OsDelete(pVfs, p->zBuf, (int)p->iOffset);
|
rc = pVfs->xDelete(pVfs, p->zBuf, (int)p->iOffset);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASYNC_OPENEXCLUSIVE: {
|
case ASYNC_OPENEXCLUSIVE: {
|
||||||
@@ -1459,7 +1511,7 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
AsyncFileData *pData = p->pFileData;
|
AsyncFileData *pData = p->pFileData;
|
||||||
ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset));
|
ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset));
|
||||||
assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0);
|
assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0);
|
||||||
rc = sqlite3OsOpen(pVfs, pData->zName, pData->pBaseRead, flags, 0);
|
rc = pVfs->xOpen(pVfs, pData->zName, pData->pBaseRead, flags, 0);
|
||||||
assert( holdingMutex==0 );
|
assert( holdingMutex==0 );
|
||||||
pthread_mutex_lock(&async.queueMutex);
|
pthread_mutex_lock(&async.queueMutex);
|
||||||
holdingMutex = 1;
|
holdingMutex = 1;
|
||||||
@@ -1511,7 +1563,7 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
|
|
||||||
if( async.ioError && !async.pQueueFirst ){
|
if( async.ioError && !async.pQueueFirst ){
|
||||||
pthread_mutex_lock(&async.lockMutex);
|
pthread_mutex_lock(&async.lockMutex);
|
||||||
if( 0==sqliteHashFirst(&async.aLock) ){
|
if( 0==async.pLock ){
|
||||||
async.ioError = SQLITE_OK;
|
async.ioError = SQLITE_OK;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&async.lockMutex);
|
pthread_mutex_unlock(&async.lockMutex);
|
||||||
@@ -1524,7 +1576,7 @@ static void *asyncWriterThread(void *pIsStarted){
|
|||||||
pthread_mutex_unlock(&async.queueMutex);
|
pthread_mutex_unlock(&async.queueMutex);
|
||||||
holdingMutex = 0;
|
holdingMutex = 0;
|
||||||
if( async.ioDelay>0 ){
|
if( async.ioDelay>0 ){
|
||||||
sqlite3OsSleep(pVfs, async.ioDelay);
|
pVfs->xSleep(pVfs, async.ioDelay);
|
||||||
}else{
|
}else{
|
||||||
sched_yield();
|
sched_yield();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user