/ Check-in [c615c38c]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Hold the database mutex for the duration of an sqlite3changeset_apply() call. Also for the duration of all sqlite3session_xxx() calls.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: c615c38c3283e21c33550c093099a793761123a7
User & Date: dan 2011-03-18 18:03:14
Context
2011-03-19
02:37
Merge the fix to ticket [f7b4edece25c99485] into the sessions branch. check-in: 1b736ac2 user: drh tags: sessions
2011-03-18
18:03
Hold the database mutex for the duration of an sqlite3changeset_apply() call. Also for the duration of all sqlite3session_xxx() calls. check-in: c615c38c user: dan tags: sessions
16:47
Fixes for compiler warnings. Minor code cleanup. check-in: 9604d130 user: drh tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/session/sqlite3session.c.

   748    748     char const *zName,              /* Table name */
   749    749     sqlite3_int64 iKey1,            /* Rowid of row about to be deleted/updated */
   750    750     sqlite3_int64 iKey2             /* New rowid value (for a rowid UPDATE) */
   751    751   ){
   752    752     sqlite3_session *pSession;
   753    753     int nDb = strlen(zDb);
   754    754     int nName = strlen(zDb);
   755         - 
          755  +
          756  +  assert( sqlite3_mutex_held(db->mutex) );
          757  +
   756    758     for(pSession=(sqlite3_session *)pCtx; pSession; pSession=pSession->pNext){
   757    759       SessionTable *pTab;
   758    760   
   759    761       /* If this session is attached to a different database ("main", "temp" 
   760    762       ** etc.), or if it is not currently enabled, there is nothing to do. Skip 
   761    763       ** to the next session object attached to this database. */
   762    764       if( pSession->bEnable==0 ) continue;
................................................................................
   862    864   */
   863    865   int sqlite3session_attach(
   864    866     sqlite3_session *pSession,      /* Session object */
   865    867     const char *zName               /* Table name */
   866    868   ){
   867    869     SessionTable *pTab;             /* New table object (if required) */
   868    870     int nName;                      /* Number of bytes in string zName */
          871  +  int rc = SQLITE_OK;
          872  +
          873  +  sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
   869    874   
   870    875     /* First search for an existing entry. If one is found, this call is
   871    876     ** a no-op. Return early. */
   872    877     nName = strlen(zName);
   873    878     for(pTab=pSession->pTable; pTab; pTab=pTab->pNext){
   874         -    if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ){
   875         -      return SQLITE_OK;
          879  +    if( 0==sqlite3_strnicmp(pTab->zName, zName, nName+1) ) break;
          880  +  }
          881  +
          882  +  if( !pTab ){
          883  +    /* Allocate new SessionTable object. */
          884  +    pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
          885  +    if( !pTab ){
          886  +      rc = SQLITE_NOMEM;
          887  +    }else{
          888  +      /* Populate the new SessionTable object and link it into the list. */
          889  +      memset(pTab, 0, sizeof(SessionTable));
          890  +      pTab->zName = (char *)&pTab[1];
          891  +      memcpy(pTab->zName, zName, nName+1);
          892  +      pTab->pNext = pSession->pTable;
          893  +      pSession->pTable = pTab;
   876    894       }
   877    895     }
   878    896   
   879         -  /* Allocate new SessionTable object. */
   880         -  pTab = (SessionTable *)sqlite3_malloc(sizeof(SessionTable) + nName + 1);
   881         -  if( !pTab ) return SQLITE_NOMEM;
   882         -
   883         -  /* Populate the new SessionTable object and link it into the list. */
   884         -  memset(pTab, 0, sizeof(SessionTable));
   885         -  pTab->zName = (char *)&pTab[1];
   886         -  memcpy(pTab->zName, zName, nName+1);
   887         -  pTab->pNext = pSession->pTable;
   888         -  pSession->pTable = pTab;
   889         -
   890         -  return SQLITE_OK;
          897  +  sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
          898  +  return rc;
   891    899   }
   892    900   
   893    901   /*
   894    902   ** Ensure that there is room in the buffer to append nByte bytes of data.
   895    903   ** If not, use sqlite3_realloc() to grow the buffer so that there is.
   896    904   **
   897    905   ** If successful, return zero. Otherwise, if an OOM condition is encountered,
................................................................................
  1280   1288     int *pnChangeset,               /* OUT: Size of buffer at *ppChangeset */
  1281   1289     void **ppChangeset              /* OUT: Buffer containing changeset */
  1282   1290   ){
  1283   1291     sqlite3 *db = pSession->db;     /* Source database handle */
  1284   1292     SessionTable *pTab;             /* Used to iterate through attached tables */
  1285   1293     SessionBuffer buf = {0,0,0};    /* Buffer in which to accumlate changeset */
  1286   1294     int rc;                         /* Return code */
         1295  +
         1296  +  sqlite3_mutex_enter(sqlite3_db_mutex(db));
  1287   1297   
  1288   1298     /* Zero the output variables in case an error occurs. If this session
  1289   1299     ** object is already in the error state (sqlite3_session.rc != SQLITE_OK),
  1290   1300     ** this call will be a no-op.  */
  1291   1301     *pnChangeset = 0;
  1292   1302     *ppChangeset = 0;
  1293   1303     rc = pSession->rc;
................................................................................
  1353   1363   
  1354   1364     if( rc==SQLITE_OK ){
  1355   1365       *pnChangeset = buf.nBuf;
  1356   1366       *ppChangeset = buf.aBuf;
  1357   1367     }else{
  1358   1368       sqlite3_free(buf.aBuf);
  1359   1369     }
         1370  +
         1371  +  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  1360   1372     return rc;
  1361   1373   }
  1362   1374   
  1363   1375   /*
  1364   1376   ** Enable or disable the session object passed as the first argument.
  1365   1377   */
  1366   1378   int sqlite3session_enable(sqlite3_session *pSession, int bEnable){
         1379  +  int ret;
         1380  +  sqlite3_mutex_enter(sqlite3_db_mutex(pSession->db));
  1367   1381     if( bEnable>=0 ){
  1368   1382       pSession->bEnable = bEnable;
  1369   1383     }
  1370         -  return pSession->bEnable;
         1384  +  ret = pSession->bEnable;
         1385  +  sqlite3_mutex_leave(sqlite3_db_mutex(pSession->db));
         1386  +  return ret;
  1371   1387   }
  1372   1388   
  1373   1389   /*
  1374   1390   ** Create an iterator used to iterate through the contents of a changeset.
  1375   1391   */
  1376   1392   int sqlite3changeset_start(
  1377   1393     sqlite3_changeset_iter **pp,    /* OUT: Changeset iterator handle */
................................................................................
  2273   2289     const char *zTab = 0;           /* Name of current table */
  2274   2290     int nTab = 0;                   /* Result of strlen(zTab) */
  2275   2291     SessionApplyCtx sApply;         /* changeset_apply() context object */
  2276   2292   
  2277   2293     memset(&sApply, 0, sizeof(sApply));
  2278   2294     sqlite3changeset_start(&pIter, nChangeset, pChangeset);
  2279   2295   
         2296  +  sqlite3_mutex_enter(sqlite3_db_mutex(db));
  2280   2297     rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
  2281   2298     while( rc==SQLITE_OK && SQLITE_ROW==sqlite3changeset_next(pIter) ){
  2282   2299       int nCol;
  2283   2300       int op;
  2284   2301       int bReplace = 0;
  2285   2302       int bRetry = 0;
  2286   2303       const char *zNew;
................................................................................
  2362   2379     }
  2363   2380   
  2364   2381     sqlite3_finalize(sApply.pInsert);
  2365   2382     sqlite3_finalize(sApply.pDelete);
  2366   2383     sqlite3_finalize(sApply.pUpdate);
  2367   2384     sqlite3_finalize(sApply.pSelect);
  2368   2385     sqlite3_free(sApply.azCol);
         2386  +  sqlite3_mutex_leave(sqlite3_db_mutex(db));
  2369   2387     return rc;
  2370   2388   }
  2371   2389   
  2372   2390   #endif        /* #ifdef SQLITE_ENABLE_SESSION */

install-sh became a regular file.


test/progress.test became executable.


tool/mkopts.tcl became executable.