From: drh Date: Wed, 1 Sep 2010 14:35:48 +0000 (+0000) Subject: Add the sqlite3_quota_dump test command. Add a destructor argument on X-Git-Tag: experimental~87^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ef9659babd225394119c8c890940f3974bd071b4;p=thirdparty%2Fsqlite.git Add the sqlite3_quota_dump test command. Add a destructor argument on the sqlite3_quota_set() interface. FossilOrigin-Name: 7a624b5ae2abff21bcbbb34af88d1c7656f3b729 --- diff --git a/manifest b/manifest index f7d1163f36..ebafdadb9d 100644 --- a/manifest +++ b/manifest @@ -1,8 +1,8 @@ -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 -C Clean\sup\scomments\sin\sthe\stest_quota.c\ssource\sfile. -D 2010-09-01T13:09:57 +C Add\sthe\ssqlite3_quota_dump\stest\scommand.\s\sAdd\sa\sdestructor\sargument\son\nthe\ssqlite3_quota_set()\sinterface. +D 2010-09-01T14:35:49 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in c599a15d268b1db2aeadea19df2adc3bf2eb6bee F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -211,7 +211,7 @@ F src/test_mutex.c ce06b59aca168cd8c520b77159a24352a7469bd3 F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec F src/test_osinst.c f408c6a181f2fb04c56273afd5c3e1e82f60392c F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8 -F src/test_quota.c e542d96d5e0ad7bbc064ab9912da3d8ed65cbe28 +F src/test_quota.c 92015bbb781f58a7073d03a4faf9981e46d679c4 F src/test_rtree.c e957a603a98871dcf005c1e96ae791cfe74eb7f6 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0 F src/test_server.c bbba05c144b5fc4b52ff650a4328027b3fa5fcc6 @@ -565,7 +565,7 @@ F test/printf.test 05970cde31b1a9f54bd75af60597be75a5c54fea F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 -F test/quota.test 0026c53f3ad78094f478c5e7048fb63602d59ee7 +F test/quota.test e6ea65a69ab79e77a9945d97004204fd6d8c3d97 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a @@ -856,14 +856,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P f5d263803084107389c5541face8d536b62fffe3 -R 35c143fcc0c1d935b095e49fe0b10b28 +P c1eec7dba698e5bad0870cb80079203f0fb89514 +R 5ccdd6b5ff8c4a7fd8c3537f33664271 U drh -Z 22044fa4707460c35e1dd2a52d813a99 +Z 37a3d6817393597a2d599801ebf7d8b4 -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) -iD8DBQFMflCroxKgR168RlERAupSAJ41VgmVbutErFMPzEt158JfEp4N/gCeLiry -ne2YPJhXeQQSv7tL27HzCOk= -=nNgv +iD8DBQFMfmTIoxKgR168RlERAkXOAJ9rg479NHW8icHIeLtH5Tt3WleCsQCfVywb +rV5uQ2LKNw+EzD5POJ3VPYQ= +=vORW -----END PGP SIGNATURE----- diff --git a/manifest.uuid b/manifest.uuid index 63e92c447c..e1c19f426f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c1eec7dba698e5bad0870cb80079203f0fb89514 \ No newline at end of file +7a624b5ae2abff21bcbbb34af88d1c7656f3b729 \ No newline at end of file diff --git a/src/test_quota.c b/src/test_quota.c index 61a8f6e8be..1e372ca9cc 100644 --- a/src/test_quota.c +++ b/src/test_quota.c @@ -35,7 +35,7 @@ /* Forward declaration of all object types */ typedef struct quotaGroup quotaGroup; -typedef struct quotaOpen quotaOpen; +typedef struct quotaConn quotaConn; typedef struct quotaFile quotaFile; /* @@ -63,6 +63,7 @@ struct quotaGroup { void *pArg /* Client data */ ); void *pArg; /* Third argument to the xCallback() */ + void (*xDestroy)(void*); /* Optional destructor for pArg */ quotaGroup *pNext, **ppPrev; /* Doubly linked list of all quota objects */ quotaFile *pFile; /* Files within this group */ }; @@ -89,7 +90,7 @@ struct quotaFile { ** subclass of sqlite3_file. The sqlite3_file object for the underlying ** VFS is appended to this structure. */ -struct quotaOpen { +struct quotaConn { sqlite3_file base; /* Base class - must be first */ quotaFile *pFile; /* The underlying file */ /* The underlying VFS sqlite3_file is appended to this object */ @@ -157,6 +158,7 @@ static void quotaGroupDeref(quotaGroup *p){ if( p->pFile==0 && p->iLimit==0 ){ if( p->pNext ) p->pNext->ppPrev = p->ppPrev; if( p->ppPrev ) *p->ppPrev = p->pNext; + if( p->xDestroy ) p->xDestroy(p->pArg); sqlite3_free(p); } } @@ -243,7 +245,7 @@ static int strglob(const char *zGlob, const char *z){ /* Find a quotaGroup given the filename. ** -** Return a pointer to the quotaOpen object. Return NULL if not found. +** Return a pointer to the quotaGroup object. Return NULL if not found. */ static quotaGroup *quotaGroupFind(const char *zFilename){ quotaGroup *p; @@ -251,11 +253,11 @@ static quotaGroup *quotaGroupFind(const char *zFilename){ return p; } -/* Translate an sqlite3_file* that is really a quotaOpen* into +/* Translate an sqlite3_file* that is really a quotaConn* into ** the sqlite3_file* for the underlying original VFS. */ -static sqlite3_file *quotaSubOpen(sqlite3_file *pOpen){ - quotaOpen *p = (quotaOpen*)pOpen; +static sqlite3_file *quotaSubOpen(sqlite3_file *pConn){ + quotaConn *p = (quotaConn*)pConn; return (sqlite3_file*)&p[1]; } @@ -267,15 +269,15 @@ static sqlite3_file *quotaSubOpen(sqlite3_file *pOpen){ ** simply links the new file into the appropriate quota group if it is a ** file that needs to be tracked. */ -static int quotaxOpen( +static int quotaOpen( sqlite3_vfs *pVfs, /* The quota VFS */ const char *zName, /* Name of file to be opened */ - sqlite3_file *pOpen, /* Fill in this file descriptor */ + sqlite3_file *pConn, /* Fill in this file descriptor */ int flags, /* Flags to control the opening */ int *pOutFlags /* Flags showing results of opening */ ){ int rc; /* Result code */ - quotaOpen *pQuotaOpen; /* The new quota file descriptor */ + quotaConn *pQuotaOpen; /* The new quota file descriptor */ quotaFile *pFile; /* Corresponding quotaFile obj */ quotaGroup *pGroup; /* The group file belongs to */ sqlite3_file *pSubOpen; /* Real file descriptor */ @@ -285,7 +287,7 @@ static int quotaxOpen( ** normal xOpen method. */ if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_WAL))==0 ){ - return pOrigVfs->xOpen(pOrigVfs, zName, pOpen, flags, pOutFlags); + return pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags); } /* If the name of the file does not match any quota group, then @@ -294,12 +296,12 @@ static int quotaxOpen( quotaEnter(); pGroup = quotaGroupFind(zName); if( pGroup==0 ){ - rc = pOrigVfs->xOpen(pOrigVfs, zName, pOpen, flags, pOutFlags); + rc = pOrigVfs->xOpen(pOrigVfs, zName, pConn, flags, pOutFlags); }else{ /* If we get to this point, it means the file needs to be quota tracked. */ - pQuotaOpen = (quotaOpen*)pOpen; - pSubOpen = quotaSubOpen(pOpen); + pQuotaOpen = (quotaConn*)pConn; + pSubOpen = quotaSubOpen(pConn); rc = pOrigVfs->xOpen(pOrigVfs, zName, pSubOpen, flags, pOutFlags); if( rc==SQLITE_OK ){ for(pFile=pGroup->pFile; pFile && strcmp(pFile->zFilename, zName); @@ -337,12 +339,13 @@ static int quotaxOpen( /************************ I/O Method Wrappers *******************************/ /* xClose requests get passed through to the original VFS. But we -** also have to unlink the quotaOpen from the quotaGroup. +** also have to unlink the quotaConn from the quotaFile and quotaGroup. +** The quotaFile and/or quotaGroup are freed if they are no longer in use. */ -static int quotaClose(sqlite3_file *pOpen){ - quotaOpen *p = (quotaOpen*)pOpen; +static int quotaClose(sqlite3_file *pConn){ + quotaConn *p = (quotaConn*)pConn; quotaFile *pFile = p->pFile; - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); + sqlite3_file *pSubOpen = quotaSubOpen(pConn); int rc; rc = pSubOpen->pMethods->xClose(pSubOpen); quotaEnter(); @@ -363,12 +366,12 @@ static int quotaClose(sqlite3_file *pOpen){ ** further processing. */ static int quotaRead( - sqlite3_file *pOpen, + sqlite3_file *pConn, void *pBuf, int iAmt, sqlite3_int64 iOfst ){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xRead(pSubOpen, pBuf, iAmt, iOfst); } @@ -377,13 +380,13 @@ static int quotaRead( ** original VFS. */ static int quotaWrite( - sqlite3_file *pOpen, + sqlite3_file *pConn, const void *pBuf, int iAmt, sqlite3_int64 iOfst ){ - quotaOpen *p = (quotaOpen*)pOpen; - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); + quotaConn *p = (quotaConn*)pConn; + sqlite3_file *pSubOpen = quotaSubOpen(pConn); sqlite3_int64 iEnd = iOfst+iAmt; quotaGroup *pGroup; quotaFile *pFile = p->pFile; @@ -413,9 +416,9 @@ static int quotaWrite( /* Pass xTruncate requests thru to the original VFS. If the ** success, update the file size. */ -static int quotaTruncate(sqlite3_file *pOpen, sqlite3_int64 size){ - quotaOpen *p = (quotaOpen*)pOpen; - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaTruncate(sqlite3_file *pConn, sqlite3_int64 size){ + quotaConn *p = (quotaConn*)pConn; + sqlite3_file *pSubOpen = quotaSubOpen(pConn); int rc = pSubOpen->pMethods->xTruncate(pSubOpen, size); quotaFile *pFile = p->pFile; quotaGroup *pGroup; @@ -432,17 +435,17 @@ static int quotaTruncate(sqlite3_file *pOpen, sqlite3_int64 size){ /* Pass xSync requests through to the original VFS without change */ -static int quotaSync(sqlite3_file *pOpen, int flags){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaSync(sqlite3_file *pConn, int flags){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xSync(pSubOpen, flags); } /* Pass xFileSize requests through to the original VFS but then ** update the quotaGroup with the new size before returning. */ -static int quotaFileSize(sqlite3_file *pOpen, sqlite3_int64 *pSize){ - quotaOpen *p = (quotaOpen*)pOpen; - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaFileSize(sqlite3_file *pConn, sqlite3_int64 *pSize){ + quotaConn *p = (quotaConn*)pConn; + sqlite3_file *pSubOpen = quotaSubOpen(pConn); quotaFile *pFile = p->pFile; quotaGroup *pGroup; sqlite3_int64 sz; @@ -463,82 +466,82 @@ static int quotaFileSize(sqlite3_file *pOpen, sqlite3_int64 *pSize){ /* Pass xLock requests through to the original VFS unchanged. */ -static int quotaLock(sqlite3_file *pOpen, int lock){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaLock(sqlite3_file *pConn, int lock){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xLock(pSubOpen, lock); } /* Pass xUnlock requests through to the original VFS unchanged. */ -static int quotaUnlock(sqlite3_file *pOpen, int lock){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaUnlock(sqlite3_file *pConn, int lock){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xUnlock(pSubOpen, lock); } /* Pass xCheckReservedLock requests through to the original VFS unchanged. */ -static int quotaCheckReservedLock(sqlite3_file *pOpen, int *pResOut){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaCheckReservedLock(sqlite3_file *pConn, int *pResOut){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xCheckReservedLock(pSubOpen, pResOut); } /* Pass xFileControl requests through to the original VFS unchanged. */ -static int quotaOpenControl(sqlite3_file *pOpen, int op, void *pArg){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaFileControl(sqlite3_file *pConn, int op, void *pArg){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xFileControl(pSubOpen, op, pArg); } /* Pass xSectorSize requests through to the original VFS unchanged. */ -static int quotaSectorSize(sqlite3_file *pOpen){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaSectorSize(sqlite3_file *pConn){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xSectorSize(pSubOpen); } /* Pass xDeviceCharacteristics requests through to the original VFS unchanged. */ -static int quotaDeviceCharacteristics(sqlite3_file *pOpen){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaDeviceCharacteristics(sqlite3_file *pConn){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xDeviceCharacteristics(pSubOpen); } /* Pass xShmMap requests through to the original VFS unchanged. */ static int quotaShmMap( - sqlite3_file *pOpen, /* Handle open on database file */ + sqlite3_file *pConn, /* Handle open on database file */ int iRegion, /* Region to retrieve */ int szRegion, /* Size of regions */ int bExtend, /* True to extend file if necessary */ void volatile **pp /* OUT: Mapped memory */ ){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xShmMap(pSubOpen, iRegion, szRegion, bExtend, pp); } /* Pass xShmLock requests through to the original VFS unchanged. */ static int quotaShmLock( - sqlite3_file *pOpen, /* Database file holding the shared memory */ + sqlite3_file *pConn, /* Database file holding the shared memory */ int ofst, /* First lock to acquire or release */ int n, /* Number of locks to acquire or release */ int flags /* What to do with the lock */ ){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xShmLock(pSubOpen, ofst, n, flags); } /* Pass xShmBarrier requests through to the original VFS unchanged. */ -static void quotaShmBarrier(sqlite3_file *pOpen){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static void quotaShmBarrier(sqlite3_file *pConn){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); pSubOpen->pMethods->xShmBarrier(pSubOpen); } /* Pass xShmUnmap requests through to the original VFS unchanged. */ -static int quotaShmUnmap(sqlite3_file *pOpen, int deleteFlag){ - sqlite3_file *pSubOpen = quotaSubOpen(pOpen); +static int quotaShmUnmap(sqlite3_file *pConn, int deleteFlag){ + sqlite3_file *pSubOpen = quotaSubOpen(pConn); return pSubOpen->pMethods->xShmUnmap(pSubOpen, deleteFlag); } @@ -567,8 +570,8 @@ int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){ gQuota.isInitialized = 1; gQuota.pOrigVfs = pOrigVfs; gQuota.sThisVfs = *pOrigVfs; - gQuota.sThisVfs.xOpen = quotaxOpen; - gQuota.sThisVfs.szOsFile += sizeof(quotaOpen); + gQuota.sThisVfs.xOpen = quotaOpen; + gQuota.sThisVfs.szOsFile += sizeof(quotaConn); gQuota.sThisVfs.zName = "quota"; gQuota.sIoMethodsV1.iVersion = 1; gQuota.sIoMethodsV1.xClose = quotaClose; @@ -580,7 +583,7 @@ int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){ gQuota.sIoMethodsV1.xLock = quotaLock; gQuota.sIoMethodsV1.xUnlock = quotaUnlock; gQuota.sIoMethodsV1.xCheckReservedLock = quotaCheckReservedLock; - gQuota.sIoMethodsV1.xFileControl = quotaOpenControl; + gQuota.sIoMethodsV1.xFileControl = quotaFileControl; gQuota.sIoMethodsV1.xSectorSize = quotaSectorSize; gQuota.sIoMethodsV1.xDeviceCharacteristics = quotaDeviceCharacteristics; gQuota.sIoMethodsV2 = gQuota.sIoMethodsV1; @@ -649,7 +652,8 @@ int sqlite3_quota_set( sqlite3_int64 iSize, /* Total size of all files in the group */ void *pArg /* Client data */ ), - void *pArg /* client data passed thru to callback */ + void *pArg, /* client data passed thru to callback */ + void (*xDestroy)(void*) /* Optional destructor for pArg */ ){ quotaGroup *pGroup; quotaEnter(); @@ -674,7 +678,11 @@ int sqlite3_quota_set( } pGroup->iLimit = iLimit; pGroup->xCallback = xCallback; + if( pGroup->xDestroy && pGroup->pArg!=pArg ){ + pGroup->xDestroy(pGroup->pArg); + } pGroup->pArg = pArg; + pGroup->xDestroy = xDestroy; quotaGroupDeref(pGroup); quotaLeave(); return SQLITE_OK; @@ -685,16 +693,21 @@ int sqlite3_quota_set( #ifdef SQLITE_TEST #include +/* +** Argument passed to a TCL quota-over-limit callback. +*/ typedef struct TclQuotaCallback TclQuotaCallback; struct TclQuotaCallback { - Tcl_Interp *interp; - Tcl_Obj *pScript; - TclQuotaCallback *pNext; + Tcl_Interp *interp; /* Interpreter in which to run the script */ + Tcl_Obj *pScript; /* Script to be run */ }; -static TclQuotaCallback *pQuotaCallbackList = 0; extern const char *sqlite3TestErrorName(int); + +/* +** This is the callback from a quota-over-limit. +*/ static void tclQuotaCallback( const char *zFilename, /* Name of file whose size increases */ sqlite3_int64 *piLimit, /* IN/OUT: The current limit */ @@ -733,6 +746,17 @@ static void tclQuotaCallback( if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp); } +/* +** Destructor for a TCL quota-over-limit callback. +*/ +static void tclCallbackDestructor(void *pObj){ + TclQuotaCallback *p = (TclQuotaCallback*)pObj; + if( p ){ + Tcl_DecrRefCount(p->pScript); + ckfree((char *)p); + } +} + /* ** tclcmd: sqlite3_quota_initialize NAME MAKEDEFAULT */ @@ -782,19 +806,6 @@ static int test_quota_shutdown( rc = sqlite3_quota_shutdown(); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); - /* If the quota system was successfully shut down, delete all the quota - ** callback script objects in the global linked list. - */ - if( rc==SQLITE_OK ){ - TclQuotaCallback *p, *pNext; - for(p=pQuotaCallbackList; p; p=pNext){ - pNext = p->pNext; - Tcl_DecrRefCount(p->pScript); - ckfree((char *)p); - } - pQuotaCallbackList = 0; - } - return TCL_OK; } @@ -812,6 +823,7 @@ static int test_quota_set( Tcl_Obj *pScript; /* Tcl script to invoke to increase quota */ int rc; /* Value returned by quota_set() */ TclQuotaCallback *p; /* Callback object */ + int nScript; /* Length of callback script */ /* Process arguments */ if( objc!=4 ){ @@ -821,27 +833,68 @@ static int test_quota_set( zPattern = Tcl_GetString(objv[1]); if( Tcl_GetWideIntFromObj(interp, objv[2], &iLimit) ) return TCL_ERROR; pScript = objv[3]; + Tcl_GetStringFromObj(pScript, &nScript); - /* Allocate a TclQuotaCallback object */ - p = (TclQuotaCallback *)ckalloc(sizeof(TclQuotaCallback)); - memset(p, 0, sizeof(TclQuotaCallback)); - - /* Invoke sqlite3_quota_set() */ - rc = sqlite3_quota_set(zPattern, iLimit, tclQuotaCallback, (void *)p); - if( rc!=SQLITE_OK ){ - ckfree((char *)p); - }else{ - Tcl_IncrRefCount(pScript); + if( nScript>0 ){ + /* Allocate a TclQuotaCallback object */ + p = (TclQuotaCallback *)ckalloc(sizeof(TclQuotaCallback)); + memset(p, 0, sizeof(TclQuotaCallback)); p->interp = interp; + Tcl_IncrRefCount(pScript); p->pScript = pScript; - p->pNext = pQuotaCallbackList; - pQuotaCallbackList = p; + }else{ + p = 0; } + /* Invoke sqlite3_quota_set() */ + rc = sqlite3_quota_set(zPattern, iLimit, tclQuotaCallback, + (void*)p, tclCallbackDestructor); Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); return TCL_OK; } +/* +** tclcmd: sqlite3_quota_dump +*/ +static int test_quota_dump( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + Tcl_Obj *pResult; + Tcl_Obj *pGroupTerm; + Tcl_Obj *pFileTerm; + quotaGroup *pGroup; + quotaFile *pFile; + + pResult = Tcl_NewObj(); + quotaEnter(); + for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){ + pGroupTerm = Tcl_NewObj(); + Tcl_ListObjAppendElement(interp, pGroupTerm, + Tcl_NewStringObj(pGroup->zPattern, -1)); + Tcl_ListObjAppendElement(interp, pGroupTerm, + Tcl_NewWideIntObj(pGroup->iLimit)); + Tcl_ListObjAppendElement(interp, pGroupTerm, + Tcl_NewWideIntObj(pGroup->iSize)); + for(pFile=pGroup->pFile; pFile; pFile=pFile->pNext){ + pFileTerm = Tcl_NewObj(); + Tcl_ListObjAppendElement(interp, pFileTerm, + Tcl_NewStringObj(pFile->zFilename, -1)); + Tcl_ListObjAppendElement(interp, pFileTerm, + Tcl_NewWideIntObj(pFile->iSize)); + Tcl_ListObjAppendElement(interp, pFileTerm, + Tcl_NewWideIntObj(pFile->nRef)); + Tcl_ListObjAppendElement(interp, pGroupTerm, pFileTerm); + } + Tcl_ListObjAppendElement(interp, pResult, pGroupTerm); + } + quotaLeave(); + Tcl_SetObjResult(interp, pResult); + return TCL_OK; +} + /* ** This routine registers the custom TCL commands defined in this ** module. This should be the only procedure visible from outside @@ -855,6 +908,7 @@ int Sqlitequota_Init(Tcl_Interp *interp){ { "sqlite3_quota_initialize", test_quota_initialize }, { "sqlite3_quota_shutdown", test_quota_shutdown }, { "sqlite3_quota_set", test_quota_set }, + { "sqlite3_quota_dump", test_quota_dump }, }; int i; diff --git a/test/quota.test b/test/quota.test index 9288b5f8b8..2890fe0624 100644 --- a/test/quota.test +++ b/test/quota.test @@ -101,7 +101,7 @@ do_test quota-2.4.2 { } {1 {database or disk is full}} do_test quota-2.4.3 { set ::quota } {5120 6144} do_test quota-2.4.4 { file size test.db } {5120} -do_test quota-2.4.5 { +do_test quota-2.4.99 { db close sqlite3_quota_shutdown } {SQLITE_OK} @@ -139,12 +139,35 @@ do_test quota-3.1.3 { execsql { CREATE TABLE t2(a, b) } db2 set ::quota } {} +puts "quotas: [sqlite3_quota_dump]" do_test quota-3.X { catch { db close } catch { db2 close } - sqlite3_quota_shutdown -} {SQLITE_OK} -finish_test +} {0} + +#------------------------------------------------------------------------- +# Quotas are deleted when unused and when there limit is set to zero +# +# Return a list of all currently defined quotas. Each quota is identified +# by its pattern. +proc quota_list {} { + set allq {} + foreach q [sqlite3_quota_dump] { + lappend allq [lindex $q 0] + } + return [lsort $allq] +} +do_test quota-4.1 { + sqlite3_quota_set *test.db 0 {} + quota_list +} {} +do_test quota-4.2 { + sqlite3_quota_set *test.db 4096 {} + quota_list +} {*test.db} + +sqlite3_quota_shutdown +finish_test