]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add the sqlite3session_memory_used() API to the sessions module. For querying the...
authordan <Dan Kennedy>
Wed, 23 Dec 2020 16:46:39 +0000 (16:46 +0000)
committerdan <Dan Kennedy>
Wed, 23 Dec 2020 16:46:39 +0000 (16:46 +0000)
FossilOrigin-Name: 823f75c2e448b649cbe9e174be21524ae3f580beedced65701ad49a2dcc5ee19

ext/session/sqlite3session.c
ext/session/sqlite3session.h
ext/session/test_session.c
manifest
manifest.uuid

index dae2604719411d586dc67f1a03bb39a0ce5e7e7c..2ee6b427e21a2f326da8493886ef2db5f1dde0a2 100644 (file)
@@ -48,6 +48,7 @@ struct sqlite3_session {
   int rc;                         /* Non-zero if an error has occurred */
   void *pFilterCtx;               /* First argument to pass to xTableFilter */
   int (*xTableFilter)(void *pCtx, const char *zTab);
+  i64 nMalloc;                    /* Number of bytes of data allocated */
   sqlite3_value *pZeroBlob;       /* Value containing X'' */
   sqlite3_session *pNext;         /* Next session object on same db. */
   SessionTable *pTable;           /* List of attached tables */
@@ -431,6 +432,26 @@ static int sessionSerializeValue(
   return SQLITE_OK;
 }
 
+/*
+** Allocate and return a pointer to a buffer nByte bytes in size. If
+** pSession is not NULL, increase the sqlite3_session.nMalloc variable
+** by the number of bytes allocated.
+*/
+static void *sessionMalloc64(sqlite3_session *pSession, i64 nByte){
+  void *pRet = sqlite3_malloc64(nByte);
+  if( pSession ) pSession->nMalloc += sqlite3_msize(pRet);
+  return pRet;
+}
+
+/*
+** Free buffer pFree, which must have been allocated by an earlier
+** call to sessionMalloc64(). If pSession is not NULL, decrease the
+** sqlite3_session.nMalloc counter by the number of bytes freed.
+*/
+static void sessionFree(sqlite3_session *pSession, void *pFree){
+  if( pSession ) pSession->nMalloc -= sqlite3_msize(pFree);
+  sqlite3_free(pFree);
+}
 
 /*
 ** This macro is used to calculate hash key values for data structures. In
@@ -898,13 +919,19 @@ static int sessionPreupdateEqual(
 ** Growing the hash table in this case is a performance optimization only,
 ** it is not required for correct operation.
 */
-static int sessionGrowHash(int bPatchset, SessionTable *pTab){
+static int sessionGrowHash(
+  sqlite3_session *pSession,      /* For memory accounting. May be NULL */
+  int bPatchset, 
+  SessionTable *pTab
+){
   if( pTab->nChange==0 || pTab->nEntry>=(pTab->nChange/2) ){
     int i;
     SessionChange **apNew;
     sqlite3_int64 nNew = 2*(sqlite3_int64)(pTab->nChange ? pTab->nChange : 128);
 
-    apNew = (SessionChange **)sqlite3_malloc64(sizeof(SessionChange *) * nNew);
+    apNew = (SessionChange**)sessionMalloc64(
+        pSession, sizeof(SessionChange*) * nNew
+    );
     if( apNew==0 ){
       if( pTab->nChange==0 ){
         return SQLITE_ERROR;
@@ -925,7 +952,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
       }
     }
 
-    sqlite3_free(pTab->apChange);
+    sessionFree(pSession, pTab->apChange);
     pTab->nChange = nNew;
     pTab->apChange = apNew;
   }
@@ -959,6 +986,7 @@ static int sessionGrowHash(int bPatchset, SessionTable *pTab){
 ** be freed using sqlite3_free() by the caller
 */
 static int sessionTableInfo(
+  sqlite3_session *pSession,      /* For memory accounting. May be NULL */
   sqlite3 *db,                    /* Database connection */
   const char *zDb,                /* Name of attached database (e.g. "main") */
   const char *zThis,              /* Table name */
@@ -1013,7 +1041,7 @@ static int sessionTableInfo(
 
   if( rc==SQLITE_OK ){
     nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1);
-    pAlloc = sqlite3_malloc64(nByte);
+    pAlloc = sessionMalloc64(pSession, nByte);
     if( pAlloc==0 ){
       rc = SQLITE_NOMEM;
     }
@@ -1056,7 +1084,7 @@ static int sessionTableInfo(
     *pabPK = 0;
     *pnCol = 0;
     if( pzTab ) *pzTab = 0;
-    sqlite3_free(azCol);
+    sessionFree(pSession, azCol);
   }
   sqlite3_finalize(pStmt);
   return rc;
@@ -1078,7 +1106,7 @@ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){
   if( pTab->nCol==0 ){
     u8 *abPK;
     assert( pTab->azCol==0 || pTab->abPK==0 );
-    pSession->rc = sessionTableInfo(pSession->db, pSession->zDb, 
+    pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, 
         pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK
     );
     if( pSession->rc==SQLITE_OK ){
@@ -1169,7 +1197,7 @@ static void sessionPreupdateOneChange(
   }
 
   /* Grow the hash table if required */
-  if( sessionGrowHash(0, pTab) ){
+  if( sessionGrowHash(pSession, 0, pTab) ){
     pSession->rc = SQLITE_NOMEM;
     return;
   }
@@ -1236,7 +1264,7 @@ static void sessionPreupdateOneChange(
       }
   
       /* Allocate the change object */
-      pChange = (SessionChange *)sqlite3_malloc64(nByte);
+      pChange = (SessionChange *)sessionMalloc64(pSession, nByte);
       if( !pChange ){
         rc = SQLITE_NOMEM;
         goto error_out;
@@ -1609,7 +1637,7 @@ int sqlite3session_diff(
       int nCol;                   /* Columns in zFrom.zTbl */
       u8 *abPK;
       const char **azCol = 0;
-      rc = sessionTableInfo(db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
+      rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK);
       if( rc==SQLITE_OK ){
         if( pTo->nCol!=nCol ){
           bMismatch = 1;
@@ -1707,7 +1735,7 @@ int sqlite3session_create(
 ** Free the list of table objects passed as the first argument. The contents
 ** of the changed-rows hash tables are also deleted.
 */
-static void sessionDeleteTable(SessionTable *pList){
+static void sessionDeleteTable(sqlite3_session *pSession, SessionTable *pList){
   SessionTable *pNext;
   SessionTable *pTab;
 
@@ -1719,12 +1747,12 @@ static void sessionDeleteTable(SessionTable *pList){
       SessionChange *pNextChange;
       for(p=pTab->apChange[i]; p; p=pNextChange){
         pNextChange = p->pNext;
-        sqlite3_free(p);
+        sessionFree(pSession, p);
       }
     }
-    sqlite3_free((char*)pTab->azCol);  /* cast works around VC++ bug */
-    sqlite3_free(pTab->apChange);
-    sqlite3_free(pTab);
+    sessionFree(pSession, (char*)pTab->azCol);  /* cast works around VC++ bug */
+    sessionFree(pSession, pTab->apChange);
+    sessionFree(pSession, pTab);
   }
 }
 
@@ -1752,9 +1780,11 @@ void sqlite3session_delete(sqlite3_session *pSession){
 
   /* Delete all attached table objects. And the contents of their 
   ** associated hash-tables. */
-  sessionDeleteTable(pSession->pTable);
+  sessionDeleteTable(pSession, pSession->pTable);
 
-  /* Free the session object itself. */
+  /* Assert that all allocations have been freed and then free the 
+  ** session object itself. */
+  assert( pSession->nMalloc==0 );
   sqlite3_free(pSession);
 }
 
@@ -1801,7 +1831,8 @@ int sqlite3session_attach(
 
     if( !pTab ){
       /* Allocate new SessionTable object. */
-      pTab = (SessionTable *)sqlite3_malloc64(sizeof(SessionTable) + nName + 1);
+      int nByte = sizeof(SessionTable) + nName + 1;
+      pTab = (SessionTable*)sessionMalloc64(pSession, nByte);
       if( !pTab ){
         rc = SQLITE_NOMEM;
       }else{
@@ -2398,7 +2429,7 @@ static int sessionGenerateChangeset(
       int nNoop;                  /* Size of buffer after writing tbl header */
 
       /* Check the table schema is still Ok. */
-      rc = sessionTableInfo(db, pSession->zDb, zName, &nCol, 0, &azCol, &abPK);
+      rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK);
       if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){
         rc = SQLITE_SCHEMA;
       }
@@ -2573,6 +2604,13 @@ int sqlite3session_isempty(sqlite3_session *pSession){
   return (ret==0);
 }
 
+/*
+** Return the amount of heap memory in use.
+*/
+sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession){
+  return pSession->nMalloc;
+}
+
 /*
 ** Do the work for either sqlite3changeset_start() or start_strm().
 */
@@ -4384,7 +4422,7 @@ static int sessionChangesetApply(
         int i;
 
         sqlite3changeset_pk(pIter, &abPK, 0);
-        rc = sessionTableInfo(
+        rc = sessionTableInfo(0, 
             db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK
         );
         if( rc!=SQLITE_OK ) break;
@@ -4863,7 +4901,7 @@ static int sessionChangesetToHash(
       }
     }
 
-    if( sessionGrowHash(pIter->bPatchset, pTab) ){
+    if( sessionGrowHash(0, pIter->bPatchset, pTab) ){
       rc = SQLITE_NOMEM;
       break;
     }
@@ -5049,7 +5087,7 @@ int sqlite3changegroup_output_strm(
 */
 void sqlite3changegroup_delete(sqlite3_changegroup *pGrp){
   if( pGrp ){
-    sessionDeleteTable(pGrp->pList);
+    sessionDeleteTable(0, pGrp->pList);
     sqlite3_free(pGrp);
   }
 }
@@ -5450,7 +5488,7 @@ int sqlite3rebaser_rebase_strm(
 */
 void sqlite3rebaser_delete(sqlite3_rebaser *p){
   if( p ){
-    sessionDeleteTable(p->grp.pList);
+    sessionDeleteTable(0, p->grp.pList);
     sqlite3_free(p);
   }
 }
index 1ed3b550f4372e51713dcab7f9f62058c52737b0..3785a77240c994cc99bab20994021cafc2263f07 100644 (file)
@@ -440,6 +440,14 @@ int sqlite3session_patchset(
 */
 int sqlite3session_isempty(sqlite3_session *pSession);
 
+/*
+** CAPI3REF: Query for the amount of heap memory used by a session object.
+**
+** This API returns the total amount of heap memory in bytes currently 
+** used by the session object passed as the only argument.
+*/
+sqlite3_int64 sqlite3session_memory_used(sqlite3_session *pSession);
+
 /*
 ** CAPI3REF: Create An Iterator To Traverse A Changeset 
 ** CONSTRUCTOR: sqlite3_changeset_iter
index 82f30979f5127dd6a2f6b29f8d8cb0e2898b6278..7f6cd0eb974752e99f20ce48972418a4c60affd2 100644 (file)
@@ -242,6 +242,7 @@ static int SQLITE_TCLAPI test_session_cmd(
     { "table_filter", 1, "SCRIPT",     }, /* 6 */
     { "patchset",     0, "",           }, /* 7 */
     { "diff",         2, "FROMDB TBL", }, /* 8 */
+    { "memory_used",  0, "",           }, /* 9 */
     { 0 }
   };
   int iSub;
@@ -347,6 +348,12 @@ static int SQLITE_TCLAPI test_session_cmd(
       }
       break;
     }
+
+    case 9: {      /* memory_used */
+      sqlite3_int64 nMalloc = sqlite3session_memory_used(pSession);
+      Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nMalloc));
+      break;
+    }
   }
 
   return TCL_OK;
index 45336da30c90af31a802f6366c6d3203e2ef8805..fddff0b8a5b154d95eaf2d3e932d0d9a1ebe6bdf 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sSQLITE_OMIT_WINDOWFUNC\sbuilds\sby\smoving\sdeclaration\sof\ssqlite3ExpandSubquery\sout\sof\s"ifndef\sSQLITE_OMIT_WINDOWFUNC"\sblock.
-D 2020-12-22T20:35:22.397
+C Add\sthe\ssqlite3session_memory_used()\sAPI\sto\sthe\ssessions\smodule.\sFor\squerying\sthe\samount\sof\sheap\smemory\scurrently\sbeing\sused\sby\sa\ssession\sobject.
+D 2020-12-23T16:46:39.915
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -453,9 +453,9 @@ F ext/session/sessioninvert.test 04075517a9497a80d39c495ba6b44f3982c7371129b89e2
 F ext/session/sessionrebase.test ccfa716b23bd1d3b03217ee58cfd90c78d4b99f53e6a9a2f05e82363b9142810
 F ext/session/sessionstat1.test 218d351cf9fcd6648f125a26b607b140310160184723c2666091b54450a68fb5
 F ext/session/sessionwor.test 67b5ab91d4f93ce65ff1f58240ac5ddf73f8670facc1ffa49cef56293d52818d
-F ext/session/sqlite3session.c 2c76b8c3a5d6dab736686f8a48833b8bdac0871ecc6f447f9839d28bd4a63d6c
-F ext/session/sqlite3session.h a2db5b72b938d12c727b4b4ec632254ca493670a9c0de597af3271a7f774fc57
-F ext/session/test_session.c 24286d958dc6f4ca4d7e710f09bc0fa9d50956a40dd99fd8223e7488024c71fe
+F ext/session/sqlite3session.c d2aaaf05241ac7d23a1b1eaa8b1f165c90f7ff0fe57ff1932a87c6b89b886117
+F ext/session/sqlite3session.h f53c99731882bf59c7362855cdeba176ce1fe8eeba089e38a8cce0172f8473aa
+F ext/session/test_session.c 93ca965112d2b4d9d669c9c0be6b1e52942a268796050a145612df1eee175ce0
 F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 7f00cded7dcaa5d47f54539b290a43d2e59f4b1eb5f447545fa865f002fc80cb
@@ -1894,7 +1894,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 907ddf86766ebdbe39bdc89543c1a7bbd65c710c9f3a3a4d796845b2c02b711b
-R dd30694e4f91ee91b88bcc802eb6d9cd
+P 9587fa8b29fc2f91d751a71b909f574014656f24d276b4974f47fcc18dbadcb8
+R 8a19a9976fc51c3ed2ff74d48489d86a
 U dan
-Z c8215834a8a499c013c16379be6fc471
+Z bb9f93711cbcff6309bc973aaedad8c7
index b931e07ba69d878e021cfe94ab40c57e77021ebc..541e80f31858831b551d54db589efaada543bce9 100644 (file)
@@ -1 +1 @@
-9587fa8b29fc2f91d751a71b909f574014656f24d276b4974f47fcc18dbadcb8
\ No newline at end of file
+823f75c2e448b649cbe9e174be21524ae3f580beedced65701ad49a2dcc5ee19
\ No newline at end of file