Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Changes so that test_async.c works with memory management turned on. (CVS 3093) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f4150c29df2774b4422d4296d913cdbc |
User & Date: | danielk1977 2006-02-14 10:48:39.000 |
Context
2006-02-14
| ||
13:25 | Add simple io error tests for test_async.c. (CVS 3094) (check-in: 528dfb7180 user: danielk1977 tags: trunk) | |
10:48 | Changes so that test_async.c works with memory management turned on. (CVS 3093) (check-in: f4150c29df user: danielk1977 tags: trunk) | |
2006-02-13
| ||
18:42 | Disable the /./ and /../ collapser logic in sqlite3OsFullPathname under Unix. (CVS 3092) (check-in: 111a426b3e user: drh tags: trunk) | |
Changes
Changes to src/hash.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the implementation of generic hash-tables ** used in SQLite. ** ** $Id: hash.c,v 1.18 2006/02/14 10:48:39 danielk1977 Exp $ */ #include "sqliteInt.h" #include <assert.h> /* Turn bulk memory into a hash table object by initializing the ** fields of the Hash structure. ** |
︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0; #endif pNew->copyKey = copyKey; pNew->first = 0; pNew->count = 0; pNew->htsize = 0; pNew->ht = 0; } /* Remove all entries from a hash table. Reclaim all memory. ** Call this routine to delete a hash table or to reset a hash table ** to the empty state. */ void sqlite3HashClear(Hash *pH){ HashElem *elem; /* For looping over all elements of the table */ assert( pH!=0 ); elem = pH->first; pH->first = 0; | > > | | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | if( keyClass==SQLITE_HASH_POINTER || keyClass==SQLITE_HASH_INT ) copyKey = 0; #endif pNew->copyKey = copyKey; pNew->first = 0; pNew->count = 0; pNew->htsize = 0; pNew->ht = 0; pNew->xMalloc = sqlite3MallocX; pNew->xFree = sqlite3FreeX; } /* Remove all entries from a hash table. Reclaim all memory. ** Call this routine to delete a hash table or to reset a hash table ** to the empty state. */ void sqlite3HashClear(Hash *pH){ HashElem *elem; /* For looping over all elements of the table */ assert( pH!=0 ); elem = pH->first; pH->first = 0; if( pH->ht ) pH->xFree(pH->ht); pH->ht = 0; pH->htsize = 0; while( elem ){ HashElem *next_elem = elem->next; if( pH->copyKey && elem->pKey ){ pH->xFree(elem->pKey); } pH->xFree(elem); elem = next_elem; } pH->count = 0; } #if 0 /* NOT USED */ /* |
︙ | ︙ | |||
218 219 220 221 222 223 224 | */ static void rehash(Hash *pH, int new_size){ struct _ht *new_ht; /* The new hash table */ HashElem *elem, *next_elem; /* For looping over existing elements */ int (*xHash)(const void*,int); /* The hash function */ assert( (new_size & (new_size-1))==0 ); | | | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | */ static void rehash(Hash *pH, int new_size){ struct _ht *new_ht; /* The new hash table */ HashElem *elem, *next_elem; /* For looping over existing elements */ int (*xHash)(const void*,int); /* The hash function */ assert( (new_size & (new_size-1))==0 ); new_ht = (struct _ht *)pH->xMalloc( new_size*sizeof(struct _ht) ); if( new_ht==0 ) return; if( pH->ht ) pH->xFree(pH->ht); pH->ht = new_ht; pH->htsize = new_size; xHash = hashFunction(pH->keyClass); for(elem=pH->first, pH->first=0; elem; elem = next_elem){ int h = (*xHash)(elem->pKey, elem->nKey) & (new_size-1); next_elem = elem->next; insertElement(pH, &new_ht[h], elem); |
︙ | ︙ | |||
286 287 288 289 290 291 292 | pEntry->chain = elem->next; } pEntry->count--; if( pEntry->count<=0 ){ pEntry->chain = 0; } if( pH->copyKey && elem->pKey ){ | | | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | pEntry->chain = elem->next; } pEntry->count--; if( pEntry->count<=0 ){ pEntry->chain = 0; } if( pH->copyKey && elem->pKey ){ pH->xFree(elem->pKey); } pH->xFree( elem ); pH->count--; if( pH->count<=0 ){ assert( pH->first==0 ); assert( pH->count==0 ); sqlite3HashClear(pH); } } |
︙ | ︙ | |||
354 355 356 357 358 359 360 | removeElementGivenHash(pH,elem,h); }else{ elem->data = data; } return old_data; } if( data==0 ) return 0; | | | | | | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | removeElementGivenHash(pH,elem,h); }else{ elem->data = data; } return old_data; } if( data==0 ) return 0; new_elem = (HashElem*)pH->xMalloc( sizeof(HashElem) ); if( new_elem==0 ) return data; if( pH->copyKey && pKey!=0 ){ new_elem->pKey = pH->xMalloc( nKey ); if( new_elem->pKey==0 ){ pH->xFree(new_elem); return data; } memcpy((void*)new_elem->pKey, pKey, nKey); }else{ new_elem->pKey = (void*)pKey; } new_elem->nKey = nKey; pH->count++; if( pH->htsize==0 ){ rehash(pH,8); if( pH->htsize==0 ){ pH->count = 0; pH->xFree(new_elem); return data; } } if( pH->count > pH->htsize ){ rehash(pH,pH->htsize*2); } assert( pH->htsize>0 ); assert( (pH->htsize & (pH->htsize-1))==0 ); h = hraw & (pH->htsize-1); insertElement(pH, &pH->ht[h], new_elem); new_elem->data = data; return 0; } |
Changes to src/hash.h.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This is the header file for the generic hash-table implemenation ** used in SQLite. ** ** $Id: hash.h,v 1.9 2006/02/14 10:48:39 danielk1977 Exp $ */ #ifndef _SQLITE_HASH_H_ #define _SQLITE_HASH_H_ /* Forward declarations of structures. */ typedef struct Hash Hash; typedef struct HashElem HashElem; |
︙ | ︙ | |||
30 31 32 33 34 35 36 37 38 39 40 41 42 43 | ** this structure opaque. */ struct Hash { char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */ char copyKey; /* True if copy of key made on insert */ int count; /* Number of entries in this table */ HashElem *first; /* The first element of the array */ int htsize; /* Number of buckets in the hash table */ struct _ht { /* the hash table */ int count; /* Number of entries with this hash */ HashElem *chain; /* Pointer to first entry with this hash */ } *ht; }; | > > | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | ** this structure opaque. */ struct Hash { char keyClass; /* SQLITE_HASH_INT, _POINTER, _STRING, _BINARY */ char copyKey; /* True if copy of key made on insert */ int count; /* Number of entries in this table */ HashElem *first; /* The first element of the array */ void *(*xMalloc)(int); /* malloc() function to use */ void (*xFree)(void *); /* free() function to use */ int htsize; /* Number of buckets in the hash table */ struct _ht { /* the hash table */ int count; /* Number of entries with this hash */ HashElem *chain; /* Pointer to first entry with this hash */ } *ht; }; |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
336 337 338 339 340 341 342 | }; /* ** These hash tables map inodes and file descriptors (really, lockKey and ** openKey structures) into lockInfo and openCnt structures. Access to ** these hash tables must be protected by a mutex. */ | | > | | | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | }; /* ** These hash tables map inodes and file descriptors (really, lockKey and ** openKey structures) into lockInfo and openCnt structures. Access to ** these hash tables must be protected by a mutex. */ static Hash lockHash = {SQLITE_HASH_BINARY, 0, 0, 0, sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0}; static Hash openHash = {SQLITE_HASH_BINARY, 0, 0, 0, sqlite3ThreadSafeMalloc, sqlite3ThreadSafeFree, 0, 0}; #ifdef SQLITE_UNIX_THREADS /* ** This variable records whether or not threads can override each others ** locks. ** ** 0: No. Threads cannot override each others locks. |
︙ | ︙ | |||
487 488 489 490 491 492 493 | ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ assert( sqlite3OsInMutex(1) ); pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); | | | | 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 | ** Release a lockInfo structure previously allocated by findLockInfo(). */ static void releaseLockInfo(struct lockInfo *pLock){ assert( sqlite3OsInMutex(1) ); pLock->nRef--; if( pLock->nRef==0 ){ sqlite3HashInsert(&lockHash, &pLock->key, sizeof(pLock->key), 0); sqlite3ThreadSafeFree(pLock); } } /* ** Release a openCnt structure previously allocated by findLockInfo(). */ static void releaseOpenCnt(struct openCnt *pOpen){ assert( sqlite3OsInMutex(1) ); pOpen->nRef--; if( pOpen->nRef==0 ){ sqlite3HashInsert(&openHash, &pOpen->key, sizeof(pOpen->key), 0); free(pOpen->aPending); sqlite3ThreadSafeFree(pOpen); } } /* ** Given a file descriptor, locate lockInfo and openCnt structures that ** describes that file descriptor. Create new ones if necessary. The ** return values might be uninitialized if an error occurs. |
︙ | ︙ | |||
541 542 543 544 545 546 547 | #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; | | | | | | 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | #endif memset(&key2, 0, sizeof(key2)); key2.dev = statbuf.st_dev; key2.ino = statbuf.st_ino; pLock = (struct lockInfo*)sqlite3HashFind(&lockHash, &key1, sizeof(key1)); if( pLock==0 ){ struct lockInfo *pOld; pLock = sqlite3ThreadSafeMalloc( sizeof(*pLock) ); if( pLock==0 ){ rc = 1; goto exit_findlockinfo; } pLock->key = key1; pLock->nRef = 1; pLock->cnt = 0; pLock->locktype = 0; pOld = sqlite3HashInsert(&lockHash, &pLock->key, sizeof(key1), pLock); if( pOld!=0 ){ assert( pOld==pLock ); sqlite3ThreadSafeFree(pLock); rc = 1; goto exit_findlockinfo; } }else{ pLock->nRef++; } *ppLock = pLock; if( ppOpen!=0 ){ pOpen = (struct openCnt*)sqlite3HashFind(&openHash, &key2, sizeof(key2)); if( pOpen==0 ){ struct openCnt *pOld; pOpen = sqlite3ThreadSafeMalloc( sizeof(*pOpen) ); if( pOpen==0 ){ releaseLockInfo(pLock); rc = 1; goto exit_findlockinfo; } pOpen->key = key2; pOpen->nRef = 1; pOpen->nLock = 0; pOpen->nPending = 0; pOpen->aPending = 0; pOld = sqlite3HashInsert(&openHash, &pOpen->key, sizeof(key2), pOpen); if( pOld!=0 ){ assert( pOld==pOpen ); sqlite3ThreadSafeFree(pOpen); releaseLockInfo(pLock); rc = 1; goto exit_findlockinfo; } }else{ pOpen->nRef++; } |
︙ | ︙ | |||
1522 1523 1524 1525 1526 1527 1528 | releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); sqlite3OsLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); | | | 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 | releaseLockInfo(id->pLock); releaseOpenCnt(id->pOpen); sqlite3OsLeaveMutex(); id->isOpen = 0; TRACE2("CLOSE %-3d\n", id->h); OpenCounter(-1); sqlite3ThreadSafeFree(id); *pId = 0; return SQLITE_OK; } /* ** Turn a relative pathname into a full pathname. Return a pointer ** to the full pathname stored in space obtained from sqliteMalloc(). |
︙ | ︙ | |||
1631 1632 1633 1634 1635 1636 1637 | */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pInit->dirfd = -1; pInit->fullSync = 0; pInit->locktype = 0; SET_THREADID(pInit); | | | 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 | */ static int allocateUnixFile(unixFile *pInit, OsFile **pId){ unixFile *pNew; pInit->dirfd = -1; pInit->fullSync = 0; pInit->locktype = 0; SET_THREADID(pInit); pNew = sqlite3ThreadSafeMalloc( sizeof(unixFile) ); if( pNew==0 ){ close(pInit->h); sqlite3OsEnterMutex(); releaseLockInfo(pInit->pLock); releaseOpenCnt(pInit->pOpen); sqlite3OsLeaveMutex(); *pId = 0; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.482 2006/02/14 10:48:39 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Extra interface definitions for those who need them */ |
︙ | ︙ | |||
263 264 265 266 267 268 269 | ** only. They only work if SQLITE_MEMDEBUG is defined. */ extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ extern int sqlite3_nFree; /* Number of sqliteFree() calls */ extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ | < | | | 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | ** only. They only work if SQLITE_MEMDEBUG is defined. */ extern int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */ extern int sqlite3_nFree; /* Number of sqliteFree() calls */ extern int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */ extern int sqlite3_iMallocReset; /* Set iMallocFail to this when it reaches 0 */ extern void *sqlite3_pFirst; /* Pointer to linked list of allocations */ extern int sqlite3_nMaxAlloc; /* High water mark of ThreadData.nAlloc */ extern int sqlite3_mallocDisallowed; /* assert() in sqlite3Malloc() if set */ extern int sqlite3_isFail; /* True if all malloc calls should fail */ extern const char *sqlite3_zFile; /* Filename to associate debug info with */ extern int sqlite3_iLine; /* Line number for debug info */ #define ENTER_MALLOC (sqlite3_zFile = __FILE__, sqlite3_iLine = __LINE__) #define sqliteMalloc(x) (ENTER_MALLOC, sqlite3Malloc(x,1)) #define sqliteMallocRaw(x) (ENTER_MALLOC, sqlite3MallocRaw(x,1)) #define sqliteRealloc(x,y) (ENTER_MALLOC, sqlite3Realloc(x,y)) #define sqliteStrDup(x) (ENTER_MALLOC, sqlite3StrDup(x)) #define sqliteStrNDup(x,y) (ENTER_MALLOC, sqlite3StrNDup(x,y)) #define sqliteReallocOrFree(x,y) (ENTER_MALLOC, sqlite3ReallocOrFree(x,y)) #else |
︙ | ︙ | |||
1479 1480 1481 1482 1483 1484 1485 | int sqlite3StrNICmp(const char *, const char *, int); int sqlite3HashNoCase(const char *, int); int sqlite3IsNumber(const char*, int*, u8); int sqlite3Compare(const char *, const char *); int sqlite3SortCompare(const char *, const char *); void sqlite3RealToSortable(double r, char *); | | | | 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 | int sqlite3StrNICmp(const char *, const char *, int); int sqlite3HashNoCase(const char *, int); int sqlite3IsNumber(const char*, int*, u8); int sqlite3Compare(const char *, const char *); int sqlite3SortCompare(const char *, const char *); void sqlite3RealToSortable(double r, char *); void *sqlite3Malloc(int,int); void *sqlite3MallocRaw(int,int); void sqlite3Free(void*); void *sqlite3Realloc(void*,int); char *sqlite3StrDup(const char*); char *sqlite3StrNDup(const char*, int); # define sqlite3CheckMemory(a,b) void sqlite3ReallocOrFree(void**,int); void sqlite3FreeX(void*); |
︙ | ︙ | |||
1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 | void sqlite3MallocAllow(void); int sqlite3TestMallocFail(void); #else #define sqlite3TestMallocFail() 0 #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #endif #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif | > > > > > > > > | 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 | void sqlite3MallocAllow(void); int sqlite3TestMallocFail(void); #else #define sqlite3TestMallocFail() 0 #define sqlite3MallocDisallow() #define sqlite3MallocAllow() #endif #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT void *sqlite3ThreadSafeMalloc(int); void sqlite3ThreadSafeFree(void *); #else #define sqlite3ThreadSafeMalloc sqlite3MallocX #define sqlite3ThreadSafeFree sqlite3FreeX #endif #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif |
Changes to src/test_async.c.
︙ | ︙ | |||
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | ** This method holds the mutex from start to finish. */ static int asyncRead(OsFile *id, void *obuf, int amt){ int rc = SQLITE_OK; i64 filesize; int nRead; AsyncFile *pFile = (AsyncFile *)id; /* If an I/O error has previously occurred on this file, then all ** subsequent operations fail. */ if( pFile->ioError!=SQLITE_OK ){ return pFile->ioError; } /* Grab the write queue mutex for the duration of the call */ pthread_mutex_lock(&async.queueMutex); | > > > > > | | | | | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 | ** This method holds the mutex from start to finish. */ static int asyncRead(OsFile *id, void *obuf, int amt){ int rc = SQLITE_OK; i64 filesize; int nRead; AsyncFile *pFile = (AsyncFile *)id; OsFile *pBase = pFile->pBaseRead; if( !pBase ){ pBase = pFile->pBaseWrite; } /* If an I/O error has previously occurred on this file, then all ** subsequent operations fail. */ if( pFile->ioError!=SQLITE_OK ){ return pFile->ioError; } /* Grab the write queue mutex for the duration of the call */ pthread_mutex_lock(&async.queueMutex); if( pBase ){ rc = sqlite3OsFileSize(pBase, &filesize); if( rc!=SQLITE_OK ){ goto asyncread_out; } rc = sqlite3OsSeek(pBase, pFile->iOffset); if( rc!=SQLITE_OK ){ goto asyncread_out; } nRead = MIN(filesize - pFile->iOffset, amt); if( nRead>0 ){ rc = sqlite3OsRead(pBase, obuf, nRead); TRACE(("READ %s %d bytes at %d\n", pFile->zName, nRead, pFile->iOffset)); } } if( rc==SQLITE_OK ){ AsyncWrite *p; i64 iOffset = pFile->iOffset; /* Current seek offset */ |
︙ | ︙ | |||
558 559 560 561 562 563 564 565 566 567 568 569 570 571 | /* Read the filesystem size from the base file. If pBaseRead is NULL, this ** means the file hasn't been opened yet. In this case all relevant data ** must be in the write-op queue anyway, so we can omit reading from the ** file-system. */ pBase = ((AsyncFile *)id)->pBaseRead; if( pBase ){ rc = sqlite3OsFileSize(pBase, &s); } if( rc==SQLITE_OK ){ AsyncWrite *p; for(p=async.pQueueFirst; p; p = p->pNext){ | > > > | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | /* Read the filesystem size from the base file. If pBaseRead is NULL, this ** means the file hasn't been opened yet. In this case all relevant data ** must be in the write-op queue anyway, so we can omit reading from the ** file-system. */ pBase = ((AsyncFile *)id)->pBaseRead; if( !pBase ){ pBase = ((AsyncFile *)id)->pBaseWrite; } if( pBase ){ rc = sqlite3OsFileSize(pBase, &s); } if( rc==SQLITE_OK ){ AsyncWrite *p; for(p=async.pQueueFirst; p; p = p->pNext){ |
︙ | ︙ | |||
798 799 800 801 802 803 804 805 | ** asynchronous IO features implemented in this file. ** ** This routine is not even remotely threadsafe. Do not call ** this routine while any SQLite database connections are open. */ static void asyncEnable(int enable){ if( enable && xOrigOpenReadWrite==0 ){ sqlite3HashInit(&async.aLock, SQLITE_HASH_BINARY, 1); | > < > > < > | 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | ** asynchronous IO features implemented in this file. ** ** This routine is not even remotely threadsafe. Do not call ** this routine while any SQLite database connections are open. */ static void asyncEnable(int enable){ if( enable && xOrigOpenReadWrite==0 ){ assert(sqlite3Os.xOpenReadWrite); sqlite3HashInit(&async.aLock, SQLITE_HASH_BINARY, 1); xOrigOpenReadWrite = sqlite3Os.xOpenReadWrite; xOrigOpenReadOnly = sqlite3Os.xOpenReadOnly; xOrigOpenExclusive = sqlite3Os.xOpenExclusive; xOrigDelete = sqlite3Os.xDelete; xOrigFileExists = sqlite3Os.xFileExists; xOrigSyncDirectory = sqlite3Os.xSyncDirectory; 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. ** |
︙ | ︙ | |||
943 944 945 946 947 948 949 | 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)); | | | | 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 | 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); |
︙ | ︙ | |||
975 976 977 978 979 980 981 982 983 984 985 986 | 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)); rc = xOrigOpenExclusive(p->zBuf, &pBase, delFlag); assert( holdingMutex==0 ); pthread_mutex_lock(&async.queueMutex); holdingMutex = 1; if( rc==SQLITE_OK ){ | > | | 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 | 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->pBaseWrite = pBase; } break; } default: assert(!"Illegal value for AsyncWrite.op"); } |
︙ | ︙ | |||
1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 | 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); | > | 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 | 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); |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Utility functions used throughout sqlite. ** ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** ** $Id: util.c,v 1.185 2006/02/14 10:48:39 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <stdarg.h> #include <ctype.h> /* |
︙ | ︙ | |||
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 | } #endif /* ** This is the test layer's wrapper around sqlite3OsMalloc(). */ static void * OSMALLOC(int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc); #endif assert( !sqlite3_mallocDisallowed ); if( !sqlite3TestMallocFail() ){ u32 *p; p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); assert(p); sqlite3_nMalloc++; applyGuards(p); linkAlloc(p); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } return 0; } static int OSSIZEOF(void *p){ if( p ){ u32 *pOs = (u32 *)getOsPointer(p); return sqlite3OsAllocationSize(pOs) - TESTALLOC_OVERHEAD; } return 0; } /* ** This is the test layer's wrapper around sqlite3OsFree(). The argument is a ** pointer to the space allocated for the application to use. */ static void OSFREE(void *pFree){ u32 *p = (u32 *)getOsPointer(pFree); /* p points to Os level allocation */ checkGuards(p); unlinkAlloc(p); memset(pFree, 0x55, OSSIZEOF(pFree)); sqlite3OsFree(p); sqlite3_nFree++; } /* ** This is the test layer's wrapper around sqlite3OsRealloc(). */ static void * OSREALLOC(void *pRealloc, int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT | > > > > > | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | } #endif /* ** This is the test layer's wrapper around sqlite3OsMalloc(). */ static void * OSMALLOC(int n){ sqlite3OsEnterMutex(); #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT sqlite3_nMaxAlloc = MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc); #endif assert( !sqlite3_mallocDisallowed ); if( !sqlite3TestMallocFail() ){ u32 *p; p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD); assert(p); sqlite3_nMalloc++; applyGuards(p); linkAlloc(p); sqlite3OsLeaveMutex(); return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]); } sqlite3OsLeaveMutex(); return 0; } static int OSSIZEOF(void *p){ if( p ){ u32 *pOs = (u32 *)getOsPointer(p); return sqlite3OsAllocationSize(pOs) - TESTALLOC_OVERHEAD; } return 0; } /* ** This is the test layer's wrapper around sqlite3OsFree(). The argument is a ** pointer to the space allocated for the application to use. */ static void OSFREE(void *pFree){ sqlite3OsEnterMutex(); u32 *p = (u32 *)getOsPointer(pFree); /* p points to Os level allocation */ checkGuards(p); unlinkAlloc(p); memset(pFree, 0x55, OSSIZEOF(pFree)); sqlite3OsFree(p); sqlite3_nFree++; sqlite3OsLeaveMutex(); } /* ** This is the test layer's wrapper around sqlite3OsRealloc(). */ static void * OSREALLOC(void *pRealloc, int n){ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT |
︙ | ︙ | |||
574 575 576 577 578 579 580 | #endif /* ** Allocate and return N bytes of uninitialised memory by calling ** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory ** by calling sqlite3_release_memory(). */ | | | | | | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 | #endif /* ** Allocate and return N bytes of uninitialised memory by calling ** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory ** by calling sqlite3_release_memory(). */ void *sqlite3MallocRaw(int n, int doMemManage){ void *p = 0; if( n>0 && !sqlite3MallocFailed() && (!doMemManage || enforceSoftLimit(n)) ){ while( (p = OSMALLOC(n))==0 && sqlite3_release_memory(n) ); if( !p ){ sqlite3FailedMalloc(); OSMALLOC_FAILED(); }else if( doMemManage ){ updateMemoryUsedCount(OSSIZEOF(p)); } } return p; } /* ** Resize the allocation at p to n bytes by calling sqlite3OsRealloc(). The ** pointer to the new allocation is returned. If the Realloc() call fails, ** attempt to free memory by calling sqlite3_release_memory(). */ void *sqlite3Realloc(void *p, int n){ if( sqlite3MallocFailed() ){ return 0; } if( !p ){ return sqlite3Malloc(n, 1); }else{ void *np = 0; #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT int origSize = OSSIZEOF(p); #endif if( enforceSoftLimit(n - origSize) ){ while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ); |
︙ | ︙ | |||
644 645 646 647 648 649 650 | /* ** sqlite3Malloc ** sqlite3ReallocOrFree ** ** These two are implemented as wrappers around sqlite3MallocRaw(), ** sqlite3Realloc() and sqlite3Free(). */ | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 | /* ** sqlite3Malloc ** sqlite3ReallocOrFree ** ** These two are implemented as wrappers around sqlite3MallocRaw(), ** sqlite3Realloc() and sqlite3Free(). */ void *sqlite3Malloc(int n, int doMemManage){ void *p = sqlite3MallocRaw(n, doMemManage); if( p ){ memset(p, 0, n); } return p; } void sqlite3ReallocOrFree(void **pp, int n){ void *p = sqlite3Realloc(*pp, n); if( !p ){ sqlite3FreeX(*pp); } *pp = p; } /* ** sqlite3ThreadSafeMalloc() and sqlite3ThreadSafeFree() are used in those ** rare scenarios where sqlite may allocate memory in one thread and free ** it in another. They are exactly the same as sqlite3Malloc() and ** sqlite3Free() except that: ** ** * The allocated memory is not included in any calculations with ** respect to the soft-heap-limit, and ** ** * sqlite3ThreadSafeMalloc() must be matched with ThreadSafeFree(), ** not sqlite3Free(). Calling sqlite3Free() on memory obtained from ** ThreadSafeMalloc() will cause an error somewhere down the line. */ #ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT void *sqlite3ThreadSafeMalloc(int n){ ENTER_MALLOC; return sqlite3Malloc(n, 0); } void sqlite3ThreadSafeFree(void *p){ ENTER_MALLOC; if( p ){ OSFREE(p); } } #endif /* ** Return the number of bytes allocated at location p. p must be either ** a NULL pointer (in which case 0 is returned) or a pointer returned by ** sqlite3Malloc(), sqlite3Realloc() or sqlite3ReallocOrFree(). ** ** The number of bytes allocated does not include any overhead inserted by |
︙ | ︙ | |||
685 686 687 688 689 690 691 | ** is because when memory debugging is turned on, these two functions are ** called via macros that record the current file and line number in the ** ThreadData structure. */ char *sqlite3StrDup(const char *z){ char *zNew; if( z==0 ) return 0; | | | | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | ** is because when memory debugging is turned on, these two functions are ** called via macros that record the current file and line number in the ** ThreadData structure. */ char *sqlite3StrDup(const char *z){ char *zNew; if( z==0 ) return 0; zNew = sqlite3MallocRaw(strlen(z)+1, 1); if( zNew ) strcpy(zNew, z); return zNew; } char *sqlite3StrNDup(const char *z, int n){ char *zNew; if( z==0 ) return 0; zNew = sqlite3MallocRaw(n+1, 1); if( zNew ){ memcpy(zNew, z, n); zNew[n] = 0; } return zNew; } |
︙ | ︙ |
Changes to test/async.test.
1 2 3 4 5 6 7 8 | # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # # $Id: async.test,v 1.6 2006/02/14 10:48:40 danielk1977 Exp $ if {[catch {sqlite3async_enable}]} { # The async logic is not built into this system return } |
︙ | ︙ | |||
27 28 29 30 31 32 33 | select3.test select4.test insert.test insert2.test insert3.test trans.test } | | | > | < | > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | select3.test select4.test insert.test insert2.test insert3.test trans.test } # set INCLUDE {select4.test} # Enable asynchronous IO. sqlite3async_enable 1 rename do_test really_do_test proc do_test {name args} { uplevel really_do_test async_io-$name $args sqlite3async_halt idle sqlite3async_start sqlite3async_wait } foreach testfile [lsort -dictionary [glob $testdir/*.test]] { set tail [file tail $testfile] if {[lsearch -exact $INCLUDE $tail]<0} continue source $testfile catch {db close} } # Flush the write-queue and disable asynchronous IO. This should ensure # all allocated memory is cleaned up. sqlite3async_halt idle sqlite3async_start sqlite3async_wait sqlite3async_enable 0 really_finish_test rename really_do_test do_test rename really_finish_test finish_test |
Changes to test/quick.test.
1 2 3 4 5 6 7 8 | # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file runs all tests. # # $Id: quick.test,v 1.43 2006/02/14 10:48:40 danielk1977 Exp $ proc lshift {lvar} { upvar $lvar l set ret [lindex $l 0] set l [lrange $l 1 end] return $ret } |
︙ | ︙ | |||
31 32 33 34 35 36 37 38 39 40 41 42 43 44 | rename finish_test really_finish_test proc finish_test {} {} set ISQUICK 1 set EXCLUDE { all.test async.test btree2.test btree3.test btree4.test btree5.test btree6.test corrupt.test crash.test | > | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | rename finish_test really_finish_test proc finish_test {} {} set ISQUICK 1 set EXCLUDE { all.test async.test async2.test btree2.test btree3.test btree4.test btree5.test btree6.test corrupt.test crash.test |
︙ | ︙ |