]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Changes to test_quota.c to make quota groups persistent even after files
authordrh <drh@noemail.net>
Wed, 24 Aug 2011 01:25:55 +0000 (01:25 +0000)
committerdrh <drh@noemail.net>
Wed, 24 Aug 2011 01:25:55 +0000 (01:25 +0000)
are closed.  Files remain a part of the quota group until they are
deleted.

FossilOrigin-Name: 04111ce980df9692b7fe65a36105e7de9627a3bb

manifest
manifest.uuid
src/test_quota.c
test/quota.test

index 6323eabd4367155b6828950eb95373eb613c5e08..16af0d39eff6ac9f8dae3e5acd9f3c4e9f060396 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Simplifications\sto\sthe\sSQLITE_PAGECACHE_BLOCKALLOC\slogic.\s\sReduce\sthe\snumber\nof\sdifficult-to-reach\sbranches.
-D 2011-08-23T23:41:40.811
+C Changes\sto\stest_quota.c\sto\smake\squota\sgroups\spersistent\seven\safter\sfiles\nare\sclosed.\s\sFiles\sremain\sa\spart\sof\sthe\squota\sgroup\suntil\sthey\sare\ndeleted.
+D 2011-08-24T01:25:55.043
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 8c930e7b493d59099ea1304bd0f2aed152eb3315
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -219,7 +219,7 @@ F src/test_mutex.c a6bd7b9cf6e19d989e31392b06ac8d189f0d573e
 F src/test_onefile.c 40cf9e212a377a6511469384a64b01e6e34b2eec
 F src/test_osinst.c 62b0b8ef21ce754cc94e17bb42377ed8795dba32
 F src/test_pcache.c 7bf828972ac0d2403f5cfa4cd14da41f8ebe73d8
-F src/test_quota.c cc4f67e12558a252ea4a11720be268348f4b1595
+F src/test_quota.c e3a72c73bae28470ebece837b73d960f5a252878
 F src/test_rtree.c 30c981837445a4e187ee850a49c4760d9642f7c3
 F src/test_schema.c 8c06ef9ddb240c7a0fcd31bc221a6a2aade58bf0
 F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
@@ -626,7 +626,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 9535e220ad10ac1cdc49e246a53f080056f41141
+F test/quota.test dd8f0e0eb77bc206c1ad1b1494f4fe2fe6985183
 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
 F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a
@@ -961,7 +961,7 @@ F tool/symbols.sh caaf6ccc7300fd43353318b44524853e222557d5
 F tool/tostr.awk 11760e1b94a5d3dcd42378f3cc18544c06cfa576
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
 F tool/warnings.sh 2ebae31e1eb352696f3c2f7706a34c084b28c262
-P 880b51150aaed804005f5062b4dd2fa0ffafa147
-R 690091bd4eec428f02b835dd5a4096b1
+P d5d835fe8352cb2009133246d4ed1cd310803f75
+R 2328973d91120b14c5ab36809b3bc4cb
 U drh
-Z a67c28a746ea7a9568474b8f0d071914
+Z 9f91d97e63ce42debeb18d7ad0c4d84a
index 32875c869f54f9286f89b16eda4a1d1a5adef584..a8d9586f0bc6ce2e6de33644db1aa9d75743db54 100644 (file)
@@ -1 +1 @@
-d5d835fe8352cb2009133246d4ed1cd310803f75
\ No newline at end of file
+04111ce980df9692b7fe65a36105e7de9627a3bb
\ No newline at end of file
index 9b0e4a9ddce2ec3457ab346be13dae56085e3382..faf40955592200717f7baca115148ce6033213ba 100644 (file)
@@ -95,6 +95,7 @@ struct quotaFile {
   quotaGroup *pGroup;             /* Quota group to which this file belongs */
   sqlite3_int64 iSize;            /* Current size of this file */
   int nRef;                       /* Number of times this file is open */
+  int deleteOnClose;              /* True to delete this file when it closes */
   quotaFile *pNext, **ppPrev;     /* Linked list of files in the same group */
 };
 
@@ -164,12 +165,45 @@ static struct {
 static void quotaEnter(void){ sqlite3_mutex_enter(gQuota.pMutex); }
 static void quotaLeave(void){ sqlite3_mutex_leave(gQuota.pMutex); }
 
+/* Count the number of open files in a quotaGroup 
+*/
+static int quotaGroupOpenFileCount(quotaGroup *pGroup){
+  int N = 0;
+  quotaFile *pFile = pGroup->pFiles;
+  while( pFile ){
+    if( pFile->nRef ) N++;
+    pFile = pFile->pNext;
+  }
+  return N;
+}
+
+/* Remove a file from a quota group.
+*/
+static void quotaRemoveFile(quotaFile *pFile){
+  quotaGroup *pGroup = pFile->pGroup;
+  pGroup->iSize -= pFile->iSize;
+  *pFile->ppPrev = pFile->pNext;
+  if( pFile->pNext ) pFile->pNext->ppPrev = pFile->ppPrev;
+  sqlite3_free(pFile);
+}
+
+/* Remove all files from a quota group.  It is always the case that
+** all files will be closed when this routine is called.
+*/
+static void quotaRemoveAllFiles(quotaGroup *pGroup){
+  while( pGroup->pFiles ){
+    assert( pGroup->pFiles->nRef==0 );
+    quotaRemoveFile(pGroup->pFiles);
+  }
+}
+
 
 /* If the reference count and threshold for a quotaGroup are both
 ** zero, then destroy the quotaGroup.
 */
 static void quotaGroupDeref(quotaGroup *pGroup){
-  if( pGroup->pFiles==0 && pGroup->iLimit==0 ){
+  if( pGroup->iLimit==0 && quotaGroupOpenFileCount(pGroup)==0 ){
+    quotaRemoveAllFiles(pGroup);
     *pGroup->ppPrev = pGroup->pNext;
     if( pGroup->pNext ) pGroup->pNext->ppPrev = pGroup->ppPrev;
     if( pGroup->xDestroy ) pGroup->xDestroy(pGroup->pArg);
@@ -276,6 +310,17 @@ static sqlite3_file *quotaSubOpen(sqlite3_file *pConn){
   return (sqlite3_file*)&p[1];
 }
 
+/* Find a file in a quota group and return a pointer to that file.
+** Return NULL if the file is not in the group.
+*/
+static quotaFile *quotaFindFile(quotaGroup *pGroup, const char *zName){
+  quotaFile *pFile = pGroup->pFiles;
+  while( pFile && strcmp(pFile->zFilename, zName)!=0 ){
+    pFile = pFile->pNext;
+  }
+  return pFile;
+}
+
 /************************* VFS Method Wrappers *****************************/
 /*
 ** This is the xOpen method used for the "quota" VFS.
@@ -319,8 +364,7 @@ static int quotaOpen(
     pSubOpen = quotaSubOpen(pConn);
     rc = pOrigVfs->xOpen(pOrigVfs, zName, pSubOpen, flags, pOutFlags);
     if( rc==SQLITE_OK ){
-      for(pFile=pGroup->pFiles; pFile && strcmp(pFile->zFilename, zName);
-          pFile=pFile->pNext){}
+      pFile = quotaFindFile(pGroup, zName);
       if( pFile==0 ){
         int nName = strlen(zName);
         pFile = (quotaFile *)sqlite3_malloc( sizeof(*pFile) + nName + 1 );
@@ -337,6 +381,7 @@ static int quotaOpen(
         pFile->ppPrev = &pGroup->pFiles;
         pGroup->pFiles = pFile;
         pFile->pGroup = pGroup;
+        pFile->deleteOnClose = (flags & SQLITE_OPEN_DELETEONCLOSE)!=0;
       }
       pFile->nRef++;
       pQuotaOpen->pFile = pFile;
@@ -351,6 +396,49 @@ static int quotaOpen(
   return rc;
 }
 
+/*
+** This is the xDelete method used for the "quota" VFS.
+**
+** If the file being deleted is part of the quota group, then reduce
+** the size of the quota group accordingly.  And remove the file from
+** the set of files in the quota group.
+*/
+static int quotaDelete(
+  sqlite3_vfs *pVfs,          /* The quota VFS */
+  const char *zName,          /* Name of file to be deleted */
+  int syncDir                 /* Do a directory sync after deleting */
+){
+  int rc;                                    /* Result code */         
+  quotaFile *pFile;                          /* Files in the quota */
+  quotaGroup *pGroup;                        /* The group file belongs to */
+  sqlite3_vfs *pOrigVfs = gQuota.pOrigVfs;   /* Real VFS */
+
+  /* Do the actual file delete */
+  rc = pOrigVfs->xDelete(pOrigVfs, zName, syncDir);
+
+  /* If the file just deleted is a member of a quota group, then remove
+  ** it from that quota group.
+  */
+  if( rc==SQLITE_OK ){
+    quotaEnter();
+    pGroup = quotaGroupFind(zName);
+    if( pGroup ){
+      pFile = quotaFindFile(pGroup, zName);
+      if( pFile ){
+        if( pFile->nRef ){
+          pFile->deleteOnClose = 1;
+        }else{
+          quotaRemoveFile(pFile);
+          quotaGroupDeref(pGroup);
+        }
+      }
+    }
+    quotaLeave();
+  }
+  return rc;
+}
+
+
 /************************ I/O Method Wrappers *******************************/
 
 /* xClose requests get passed through to the original VFS.  But we
@@ -367,11 +455,8 @@ static int quotaClose(sqlite3_file *pConn){
   pFile->nRef--;
   if( pFile->nRef==0 ){
     quotaGroup *pGroup = pFile->pGroup;
-    pGroup->iSize -= pFile->iSize;
-    if( pFile->pNext ) pFile->pNext->ppPrev = pFile->ppPrev;
-    *pFile->ppPrev = pFile->pNext;
+    if( pFile->deleteOnClose ) quotaRemoveFile(pFile);
     quotaGroupDeref(pGroup);
-    sqlite3_free(pFile);
   }
   quotaLeave();
   return rc;
@@ -586,6 +671,7 @@ int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){
   gQuota.pOrigVfs = pOrigVfs;
   gQuota.sThisVfs = *pOrigVfs;
   gQuota.sThisVfs.xOpen = quotaOpen;
+  gQuota.sThisVfs.xDelete = quotaDelete;
   gQuota.sThisVfs.szOsFile += sizeof(quotaConn);
   gQuota.sThisVfs.zName = "quota";
   gQuota.sIoMethodsV1.iVersion = 1;
@@ -617,19 +703,20 @@ int sqlite3_quota_initialize(const char *zOrigVfsName, int makeDefault){
 ** All SQLite database connections must be closed before calling this
 ** routine.
 **
-** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly one while
+** THIS ROUTINE IS NOT THREADSAFE.  Call this routine exactly once while
 ** shutting down in order to free all remaining quota groups.
 */
 int sqlite3_quota_shutdown(void){
   quotaGroup *pGroup;
   if( gQuota.isInitialized==0 ) return SQLITE_MISUSE;
   for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){
-    if( pGroup->pFiles ) return SQLITE_MISUSE;
+    if( quotaGroupOpenFileCount(pGroup)>0 ) return SQLITE_MISUSE;
   }
   while( gQuota.pGroup ){
     pGroup = gQuota.pGroup;
     gQuota.pGroup = pGroup->pNext;
     pGroup->iLimit = 0;
+    assert( quotaGroupOpenFileCount(pGroup)==0 );
     quotaGroupDeref(pGroup);
   }
   gQuota.isInitialized = 0;
@@ -917,6 +1004,8 @@ static int test_quota_dump(
             Tcl_NewWideIntObj(pFile->iSize));
       Tcl_ListObjAppendElement(interp, pFileTerm,
             Tcl_NewWideIntObj(pFile->nRef));
+      Tcl_ListObjAppendElement(interp, pFileTerm,
+            Tcl_NewWideIntObj(pFile->deleteOnClose));
       Tcl_ListObjAppendElement(interp, pGroupTerm, pFileTerm);
     }
     Tcl_ListObjAppendElement(interp, pResult, pGroupTerm);
index 55eca2d538852b1a259efa11ed155a9ea1c40466..469bc49016f695bb637d59c51efedd0f6ae4e555 100644 (file)
@@ -223,7 +223,7 @@ do_test quota-3.2.X {
 } {SQLITE_OK}
 
 #-------------------------------------------------------------------------
-# Quotas are deleted when unused and when there limit is set to zero
+# Quotas are deleted when unused and when their limit is set to zero
 #
 
 # Return a list of all currently defined quotas.  Each quota is identified
@@ -330,10 +330,39 @@ do_test quota-4.3.1 {
 } {}
 
 do_test quota-4.4.1 {
+  set ::quota {}
+  sqlite3_quota_set */quota-test-A?.db 10000 quota_callback
+  file delete -force ./quota-test-A1.db ./quota-test-A2.db
+  sqlite3 db ./quota-test-A1.db
+  db eval {
+     CREATE TABLE t1(x);
+     INSERT INTO t1 VALUES(randomblob(5000));
+  }
+  quota_list
+} {*/quota-test-A?.db}
+do_test quota-4.4.2 {
+  expr {$::quota==""}
+} {1}
+do_test quota-4.4.3 {
+  db close
+  sqlite3 db ./quota-test-A2.db
+  db eval {
+     CREATE TABLE t1(x);
+     INSERT INTO t1 VALUES(randomblob(5000));
+  }
+  quota_list
+} {*/quota-test-A?.db}
+do_test quota-4.4.4 {
+  expr {$::quota!=""}
+} {1}
+
+
+do_test quota-4.9.1 {
+  db close
   sqlite3_quota_set A 1000 quota_callback
   sqlite3_quota_shutdown
 } {SQLITE_OK}
-do_test quota-4.4.2 {
+do_test quota-4.9.2 {
   quota_list
 } {}