SQLite

Check-in [fb518b0ce4]
Login

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

Overview
Comment:Testing of the automatic TSD deallocation logic. The sqlite3_thread_cleanup() API is documented. This should close ticket #1601. (CVS 2920)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: fb518b0ce4ddd4aaca5cccf61e651f173e735119
User & Date: drh 2006-01-11 23:40:33.000
Context
2006-01-12
01:25
Improve performance by about 10% by avoiding excess calls to get the thread-specific data. (CVS 2921) (check-in: a8c74febec user: drh tags: trunk)
2006-01-11
23:40
Testing of the automatic TSD deallocation logic. The sqlite3_thread_cleanup() API is documented. This should close ticket #1601. (CVS 2920) (check-in: fb518b0ce4 user: drh tags: trunk)
21:41
Automatically deallocate thread-specific data when it is no longer being used. Ticket #1601. Also implemented the suggestion of ticket #1603. Memory management is now off by default at compile-time. The sqlite3_enable_memory_management() API has been removed. (CVS 2919) (check-in: 5d9c6aa964 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/os_unix.c.
1621
1622
1623
1624
1625
1626
1627





















1628
1629
1630
1631
1632
1633
1634

/*
** Return TRUE if we are currently within the mutex and FALSE if not.
*/
int sqlite3UnixInMutex(){
  return inMutex;
}






















/*
** If called with allocateFlag==1, then return a pointer to thread
** specific data for the current thread.  Allocate and zero the
** thread-specific data if it does not already exist necessary.
**
** If called with allocateFlag==0, then check the current thread







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655

/*
** Return TRUE if we are currently within the mutex and FALSE if not.
*/
int sqlite3UnixInMutex(){
  return inMutex;
}

/*
** Remember the number of thread-specific-data blocks allocated.
** Use this to verify that we are not leaking thread-specific-data.
** Ticket #1601
*/
#ifdef SQLITE_TEST
int sqlite3_tsd_count = 0;
# ifdef SQLITE_UNIX_THREADS
    static pthread_mutex_t tsd_counter_mutex = PTHREAD_MUTEX_INITIALIZER;
#   define TSD_COUNTER(N) \
             pthread_mutex_lock(&tsd_counter_mutex); \
             sqlite3_tsd_count += N; \
             pthread_mutex_unlock(&tsd_counter_mutex);
# else
#   define TSD_COUNTER(N)  sqlite3_tsd_count += N
# endif
#else
# define TSD_COUNTER(N)  /* no-op */
#endif


/*
** If called with allocateFlag==1, then return a pointer to thread
** specific data for the current thread.  Allocate and zero the
** thread-specific data if it does not already exist necessary.
**
** If called with allocateFlag==0, then check the current thread
1660
1661
1662
1663
1664
1665
1666

1667
1668
1669
1670
1671

1672
1673
1674
1675
1676
1677
1678
1679
1680
1681

1682
1683
1684
1685

1686
1687
1688
1689
1690
1691
1692
  pTsd = pthread_getspecific(key);
  if( allocateFlag ){
    if( pTsd==0 ){
      pTsd = sqlite3OsMalloc(sizeof(zeroData));
      if( pTsd ){
        *pTsd = zeroData;
        pthread_setspecific(key, pTsd);

      }
    }
  }else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
    sqlite3OsFree(pTsd);
    pthread_setspecific(key, 0);

    pTsd = 0;
  }
  return pTsd;
#else
  static ThreadData *pTsd = 0;
  if( allocateFlag ){
    if( pTsd==0 ){
      pTsd = sqlite3OsMalloc( sizeof(zeroData) );
      if( pTsd ){
        *pTsd = zeroData;

      }
    }
  }else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
    sqlite3OsFree(pTsd);

    pTsd = 0;
  }
  return pTsd;
#endif
}

/*







>





>










>




>







1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
  pTsd = pthread_getspecific(key);
  if( allocateFlag ){
    if( pTsd==0 ){
      pTsd = sqlite3OsMalloc(sizeof(zeroData));
      if( pTsd ){
        *pTsd = zeroData;
        pthread_setspecific(key, pTsd);
        TSD_COUNTER(+1);
      }
    }
  }else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
    sqlite3OsFree(pTsd);
    pthread_setspecific(key, 0);
    TSD_COUNTER(-1);
    pTsd = 0;
  }
  return pTsd;
#else
  static ThreadData *pTsd = 0;
  if( allocateFlag ){
    if( pTsd==0 ){
      pTsd = sqlite3OsMalloc( sizeof(zeroData) );
      if( pTsd ){
        *pTsd = zeroData;
        TSD_COUNTER(+1);
      }
    }
  }else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
    sqlite3OsFree(pTsd);
    TSD_COUNTER(-1);
    pTsd = 0;
  }
  return pTsd;
#endif
}

/*
Changes to src/os_win.c.
1143
1144
1145
1146
1147
1148
1149
















1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165

1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185

1186
1187
1188
1189
1190

1191
1192
1193
1194
1195
#ifdef SQLITE_TEST
  if( sqlite3_current_time ){
    *prNow = sqlite3_current_time/86400.0 + 2440587.5;
  }
#endif
  return 0;
}

















/*
** If called with allocateFlag==1, then return a pointer to thread
** specific data for the current thread.  Allocate and zero the
** thread-specific data if it does not already exist necessary.
**
** If called with allocateFlag==0, then check the current thread
** specific data.  If it exists and is all zeros, then deallocate it.
** Return a pointer to the thread specific data or NULL if it is
** unallocated.
*/
void *sqlite3WinThreadSpecificData(int allocateFlag){
  static void *pTsd = 0;
  static int key;
  static int keyInit = 0;
  static const ThreadData zeroData;


  if( !keyInit ){
    sqlite3OsEnterMutex();
    if( !keyInit ){
      key = TlsAlloc();
      if( key==0xffffffff ){
        sqlite3OsLeaveMutex();
        return 0;
      }
      keyInit = 1;
    }
    sqlite3OsLeaveMutex();
  }
  pTsd = TlsGetValue(key);
  if( allocateFlag ){
    if( !pTsd ){
      pTsd = sqlite3OsMalloc(nByte);
      if( pTsd ){
        *pTsd = zeroData;
        TlsSetValue(key, pTsd);

      }
    }
  }else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
    sqlite3OsFree(pTsd);
    TlsSetValue(key, 0);

    pTsd = 0;
  }
  return pTsd;
}
#endif /* OS_WIN */







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>











|
<



>
















|



>





>





1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177

1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
#ifdef SQLITE_TEST
  if( sqlite3_current_time ){
    *prNow = sqlite3_current_time/86400.0 + 2440587.5;
  }
#endif
  return 0;
}

/*
** Remember the number of thread-specific-data blocks allocated.
** Use this to verify that we are not leaking thread-specific-data.
** Ticket #1601
*/
#ifdef SQLITE_TEST
int sqlite3_tsd_count = 0;
# define TSD_COUNTER_INCR InterlockedIncrement(&sqlite3_tsd_count)
# define TSD_COUNTER_DECR InterlockedDecrement(&sqlite3_tsd_count)
#else
# define TSD_COUNTER_INCR  /* no-op */
# define TSD_COUNTER_DECR  /* no-op */
#endif



/*
** If called with allocateFlag==1, then return a pointer to thread
** specific data for the current thread.  Allocate and zero the
** thread-specific data if it does not already exist necessary.
**
** If called with allocateFlag==0, then check the current thread
** specific data.  If it exists and is all zeros, then deallocate it.
** Return a pointer to the thread specific data or NULL if it is
** unallocated.
*/
ThreadData *sqlite3WinThreadSpecificData(int allocateFlag){

  static int key;
  static int keyInit = 0;
  static const ThreadData zeroData;
  ThreadData *pTsd;

  if( !keyInit ){
    sqlite3OsEnterMutex();
    if( !keyInit ){
      key = TlsAlloc();
      if( key==0xffffffff ){
        sqlite3OsLeaveMutex();
        return 0;
      }
      keyInit = 1;
    }
    sqlite3OsLeaveMutex();
  }
  pTsd = TlsGetValue(key);
  if( allocateFlag ){
    if( !pTsd ){
      pTsd = sqlite3OsMalloc( sizeof(zeroData) );
      if( pTsd ){
        *pTsd = zeroData;
        TlsSetValue(key, pTsd);
        TSD_COUNTER_INCR;
      }
    }
  }else if( pTsd!=0 && memcmp(pTsd, &zeroData, sizeof(zeroData))==0 ){
    sqlite3OsFree(pTsd);
    TlsSetValue(key, 0);
    TSD_COUNTER_DECR;
    pTsd = 0;
  }
  return pTsd;
}
#endif /* OS_WIN */
Changes to src/server.c.
328
329
330
331
332
333
334

335
336
337
338
339
340
341
** on this procedure.  See the sqlite3_server_start() routine below
** for an example.  This procedure loops until g.serverHalt becomes
** true.
*/
void *sqlite3_server(void *NotUsed){
  sqlite3_enable_shared_cache(1);
  if( pthread_mutex_trylock(&g.serverMutex) ){

    return 0;  /* Another server is already running */
  }
  while( !g.serverHalt ){
    SqlMessage *pMsg;

    /* Remove the last message from the message queue.
    */







>







328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
** on this procedure.  See the sqlite3_server_start() routine below
** for an example.  This procedure loops until g.serverHalt becomes
** true.
*/
void *sqlite3_server(void *NotUsed){
  sqlite3_enable_shared_cache(1);
  if( pthread_mutex_trylock(&g.serverMutex) ){
    sqlite3_enable_shared_cache(0);
    return 0;  /* Another server is already running */
  }
  while( !g.serverHalt ){
    SqlMessage *pMsg;

    /* Remove the last message from the message queue.
    */
389
390
391
392
393
394
395

396
397
398
399
400
401
402
    /* Signal the client that the message has been processed.
    */
    pMsg->op = MSG_Done;
    pthread_mutex_unlock(&pMsg->clientMutex);
    pthread_cond_signal(&pMsg->clientWakeup);
  }
  pthread_mutex_unlock(&g.serverMutex);

  return 0;
}

/*
** Start a server thread if one is not already running.  If there
** is aleady a server thread running, the new thread will quickly
** die and this routine is effectively a no-op.







>







390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
    /* Signal the client that the message has been processed.
    */
    pMsg->op = MSG_Done;
    pthread_mutex_unlock(&pMsg->clientMutex);
    pthread_cond_signal(&pMsg->clientWakeup);
  }
  pthread_mutex_unlock(&g.serverMutex);
  sqlite3_thread_cleanup();
  return 0;
}

/*
** Start a server thread if one is not already running.  If there
** is aleady a server thread running, the new thread will quickly
** die and this routine is effectively a no-op.
Changes to src/test1.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.188 2006/01/11 21:41:22 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.189 2006/01/11 23:40:34 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

2996
2997
2998
2999
3000
3001
3002






















































3003
3004
3005
3006
3007
3008
3009
    if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
    sqlite3_soft_heap_limit(N);
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
#endif
  return TCL_OK;
}























































/*
** This routine sets entries in the global ::sqlite_options() array variable
** according to the compile-time configuration of the database.  Test
** procedures use this to determine when tests should be omitted.
*/
static void set_options(Tcl_Interp *interp){







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
    if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
    sqlite3_soft_heap_limit(N);
  }
  Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
#endif
  return TCL_OK;
}

/*
** Usage:   sqlite3_clear_tsd_memdebug
**
** Clear all of the MEMDEBUG information out of thread-specific data.
** This will allow it to be deallocated.
*/
static int test_clear_tsd_memdebug(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
#if defined(SQLITE_MEMDEBUG)
  ThreadData *pTd = sqlite3ThreadData();
  pTd->nMaxAlloc = 0;
  pTd->zFile = 0;
  pTd->iLine = 0;
#endif
  return TCL_OK;
}

/*
** Usage:   sqlite3_tsd_release
**
** Call sqlite3ReleaseThreadData.
*/
static int test_tsd_release(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
#if defined(SQLITE_MEMDEBUG)
  sqlite3ReleaseThreadData();
#endif
  return TCL_OK;
}

/*
** Usage:   sqlite3_thread_cleanup
**
** Call the sqlite3_thread_cleanup API.
*/
static int test_thread_cleanup(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3_thread_cleanup();
  return TCL_OK;
}


/*
** This routine sets entries in the global ::sqlite_options() array variable
** according to the compile-time configuration of the database.  Test
** procedures use this to determine when tests should be omitted.
*/
static void set_options(Tcl_Interp *interp){
3368
3369
3370
3371
3372
3373
3374
3375
3376



3377
3378
3379
3380
3381
3382
3383
     { "sqlite3_finalize",              test_finalize      ,0 },
     { "sqlite3_reset",                 test_reset         ,0 },
     { "sqlite3_expired",               test_expired       ,0 },
     { "sqlite3_transfer_bindings",     test_transfer_bind ,0 },
     { "sqlite3_changes",               test_changes       ,0 },
     { "sqlite3_step",                  test_step          ,0 },

     { "sqlite3_release_memory",        test_release_memory,  0},
     { "sqlite3_soft_heap_limit",       test_soft_heap_limit, 0},




     /* sqlite3_column_*() API */
     { "sqlite3_column_count",          test_column_count  ,0 },
     { "sqlite3_data_count",            test_data_count    ,0 },
     { "sqlite3_column_type",           test_column_type   ,0 },
     { "sqlite3_column_blob",           test_column_blob   ,0 },
     { "sqlite3_column_double",         test_column_double ,0 },







|
|
>
>
>







3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
     { "sqlite3_finalize",              test_finalize      ,0 },
     { "sqlite3_reset",                 test_reset         ,0 },
     { "sqlite3_expired",               test_expired       ,0 },
     { "sqlite3_transfer_bindings",     test_transfer_bind ,0 },
     { "sqlite3_changes",               test_changes       ,0 },
     { "sqlite3_step",                  test_step          ,0 },

     { "sqlite3_release_memory",        test_release_memory,     0},
     { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0},
     { "sqlite3_clear_tsd_memdebug",    test_clear_tsd_memdebug, 0},
     { "sqlite3_tsd_release",           test_tsd_release,        0},
     { "sqlite3_thread_cleanup",        test_thread_cleanup,     0},

     /* sqlite3_column_*() API */
     { "sqlite3_column_count",          test_column_count  ,0 },
     { "sqlite3_data_count",            test_data_count    ,0 },
     { "sqlite3_column_type",           test_column_type   ,0 },
     { "sqlite3_column_blob",           test_column_blob   ,0 },
     { "sqlite3_column_double",         test_column_double ,0 },
3425
3426
3427
3428
3429
3430
3431

3432
3433
3434
3435
3436
3437
3438
  extern int sqlite3_where_trace;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_memUsed;
  extern int sqlite3_malloc_id;
  extern int sqlite3_memMax;
  extern int sqlite3_like_count;

#if OS_WIN
  extern int sqlite3_os_type;
#endif
#ifdef SQLITE_DEBUG
  extern int sqlite3_vdbe_addop_trace;
#endif
#ifdef SQLITE_TEST







>







3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
  extern int sqlite3_where_trace;
  extern int sqlite3_sync_count, sqlite3_fullsync_count;
  extern int sqlite3_opentemp_count;
  extern int sqlite3_memUsed;
  extern int sqlite3_malloc_id;
  extern int sqlite3_memMax;
  extern int sqlite3_like_count;
  extern int sqlite3_tsd_count;
#if OS_WIN
  extern int sqlite3_os_type;
#endif
#ifdef SQLITE_DEBUG
  extern int sqlite3_vdbe_addop_trace;
#endif
#ifdef SQLITE_TEST
3457
3458
3459
3460
3461
3462
3463


3464
3465
3466
3467
3468
3469
3470
      (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_open_file_count", 
      (char*)&sqlite3_open_file_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_current_time", 
      (char*)&sqlite3_current_time, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_os_trace",
      (char*)&sqlite3_os_trace, TCL_LINK_INT);


#ifndef SQLITE_OMIT_UTF16
  Tcl_LinkVar(interp, "sqlite_last_needed_collation",
      (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
#endif
#ifdef SQLITE_MEMDEBUG
  Tcl_LinkVar(interp, "sqlite_malloc_id",
      (char*)&sqlite3_malloc_id, TCL_LINK_STRING);







>
>







3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
      (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_open_file_count", 
      (char*)&sqlite3_open_file_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_current_time", 
      (char*)&sqlite3_current_time, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_os_trace",
      (char*)&sqlite3_os_trace, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite3_tsd_count",
      (char*)&sqlite3_tsd_count, TCL_LINK_INT);
#ifndef SQLITE_OMIT_UTF16
  Tcl_LinkVar(interp, "sqlite_last_needed_collation",
      (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
#endif
#ifdef SQLITE_MEMDEBUG
  Tcl_LinkVar(interp, "sqlite_malloc_id",
      (char*)&sqlite3_malloc_id, TCL_LINK_STRING);
3503
3504
3505
3506
3507
3508
3509

3510

3511
3512

3513
3514
  Tcl_LinkVar(interp, "sqlite_sync_count",
      (char*)&sqlite3_sync_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_fullsync_count",
      (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
#endif /* OS_UNIX */
  set_options(interp);


  int sqlite3_shared_cache_report(void *, Tcl_Interp *, int, Tcl_Obj *CONST[]);

  Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report", 
      sqlite3_shared_cache_report, 0, 0);

  return TCL_OK;
}







>
|
>
|
|
>


3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
  Tcl_LinkVar(interp, "sqlite_sync_count",
      (char*)&sqlite3_sync_count, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_fullsync_count",
      (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
#endif /* OS_UNIX */
  set_options(interp);

  {
    extern int sqlite3_shared_cache_report(void *, Tcl_Interp *,
                                    int, Tcl_Obj *CONST[]);
    Tcl_CreateObjCommand(interp, "sqlite_shared_cache_report", 
        sqlite3_shared_cache_report, 0, 0);
  }
  return TCL_OK;
}
Changes to src/test4.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2003 December 18
**
** 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.
**
*************************************************************************
** Code for testing the the SQLite library in a multithreaded environment.
**
** $Id: test4.c,v 1.13 2005/08/11 02:10:19 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#if defined(OS_UNIX) && OS_UNIX==1 && defined(THREADSAFE) && THREADSAFE==1
#include <stdlib.h>
#include <string.h>













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2003 December 18
**
** 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.
**
*************************************************************************
** Code for testing the the SQLite library in a multithreaded environment.
**
** $Id: test4.c,v 1.14 2006/01/11 23:40:34 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#if defined(OS_UNIX) && OS_UNIX==1 && defined(THREADSAFE) && THREADSAFE==1
#include <stdlib.h>
#include <string.h>
93
94
95
96
97
98
99

100
101
102
103
104
105
106
    p->db = 0;
  }
  if( p->zErr && p->zErr!=p->zStaticErr ){
    sqlite3_free(p->zErr);
    p->zErr = 0;
  }
  p->completed++;

  return 0;
}

/*
** Get a thread ID which is an upper case letter.  Return the index.
** If the argument is not a valid thread ID put an error message in
** the interpreter and return -1.







>







93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    p->db = 0;
  }
  if( p->zErr && p->zErr!=p->zStaticErr ){
    sqlite3_free(p->zErr);
    p->zErr = 0;
  }
  p->completed++;
  sqlite3_thread_cleanup();
  return 0;
}

/*
** Get a thread ID which is an upper case letter.  Return the index.
** If the argument is not a valid thread ID put an error message in
** the interpreter and return -1.
Changes to src/test7.c.
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.
**
*************************************************************************
** Code for testing the client/server version of the SQLite library.
** Derived from test4.c.
**
** $Id: test7.c,v 1.1 2006/01/09 23:40:25 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"

/*
** This test only works on UNIX with a THREADSAFE build that includes







|







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.
**
*************************************************************************
** Code for testing the client/server version of the SQLite library.
** Derived from test4.c.
**
** $Id: test7.c,v 1.2 2006/01/11 23:40:34 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"

/*
** This test only works on UNIX with a THREADSAFE build that includes
114
115
116
117
118
119
120

121
122
123
124
125
126
127
    p->db = 0;
  }
  if( p->zErr && p->zErr!=p->zStaticErr ){
    sqlite3_free(p->zErr);
    p->zErr = 0;
  }
  p->completed++;

  return 0;
}

/*
** Get a thread ID which is an upper case letter.  Return the index.
** If the argument is not a valid thread ID put an error message in
** the interpreter and return -1.







>







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
    p->db = 0;
  }
  if( p->zErr && p->zErr!=p->zStaticErr ){
    sqlite3_free(p->zErr);
    p->zErr = 0;
  }
  p->completed++;
  sqlite3_thread_cleanup();
  return 0;
}

/*
** Get a thread ID which is an upper case letter.  Return the index.
** If the argument is not a valid thread ID put an error message in
** the interpreter and return -1.
Changes to test/tester.tcl.
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.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.58 2006/01/06 22:11:21 drh Exp $

# Make sure tclsqlite3 was compiled correctly.  Abort now with an
# error message if not.
#
if {[sqlite3 -tcl-uses-utf]} {
  if {"\u1234"=="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"













|







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.
#
#***********************************************************************
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.59 2006/01/11 23:40:34 drh Exp $

# Make sure tclsqlite3 was compiled correctly.  Abort now with an
# error message if not.
#
if {[sqlite3 -tcl-uses-utf]} {
  if {"\u1234"=="u1234"} {
    puts stderr "***** BUILD PROBLEM *****"
145
146
147
148
149
150
151








152

153
154
155
156
157
158
159
  catch {db close}
  catch {db2 close}
  catch {db3 close}

  catch {
    pp_check_for_leaks
  }










  puts "$nErr errors out of $nTest tests"
  puts "Failures on these tests: $::failList"
  if {$nProb>0} {
    puts "$nProb probabilistic tests also failed, but this does"
    puts "not necessarily indicate a malfunction."
  }
  if 0 {







>
>
>
>
>
>
>
>
|
>







145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
  catch {db close}
  catch {db2 close}
  catch {db3 close}

  catch {
    pp_check_for_leaks
  }
  sqlite3 db {}
  sqlite3_clear_tsd_memdebug
  db close
  if {$::sqlite3_tsd_count} {
     puts "Thread-specific data leak: $::sqlite3_tsd_count instances"
     incr nErr
  } else {
     puts "Thread-specific data deallocated properly"
  }
  incr nTest
  puts "$nErr errors out of $nTest tests"
  puts "Failures on these tests: $::failList"
  if {$nProb>0} {
    puts "$nProb probabilistic tests also failed, but this does"
    puts "not necessarily indicate a malfunction."
  }
  if 0 {
Changes to www/capi3ref.tcl.
1
2
3
4
5
6
7
8
set rcsid {$Id: capi3ref.tcl,v 1.27 2006/01/10 18:08:10 danielk1977 Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
|







1
2
3
4
5
6
7
8
set rcsid {$Id: capi3ref.tcl,v 1.28 2006/01/11 23:40:34 drh Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
1233
1234
1235
1236
1237
1238
1239




1240
1241
1242
1243
1244
1245
1246

  Cache sharing is enabled and disabled on a thread-by-thread basis.
  Each call to this routine enables or disables cache sharing only for
  connections created in the same thread in which this routine is called.
  There is no mechanism for sharing cache between database connections
  running in different threads.





  This routine must not be called when any database connections
  are active in the current thread.  Enabling or disabling shared
  cache while there are active database connections will result
  in memory corruption.

  For any given database connection, SQLite requires that the
  following routines always be called from the same thread:







>
>
>
>







1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250

  Cache sharing is enabled and disabled on a thread-by-thread basis.
  Each call to this routine enables or disables cache sharing only for
  connections created in the same thread in which this routine is called.
  There is no mechanism for sharing cache between database connections
  running in different threads.

  Sharing must be disabled prior to shutting down a thread or else
  the thread will leak memory.  Call this routine with an argument of
  0 to turn of sharing.  Or use the sqlite3_thread_cleanup() API.

  This routine must not be called when any database connections
  are active in the current thread.  Enabling or disabling shared
  cache while there are active database connections will result
  in memory corruption.

  For any given database connection, SQLite requires that the
  following routines always be called from the same thread:
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315

1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
  enabled or disabled successfully.  An error code is returned
  otherwise.

  Shared cache is disabled by default for backward compatibility.
}

api {} {
  int sqlite3_enable_memory_management(int);
} {
  This routine enables or disables heap memory management for the
  thread in which it is called.  Memory management is enabled if
  the argument is true and disabled if the argument is false.

  This routine must not be called when any database connections
  are active in the current thread.  Enabling or disabling memory
  management while there are active database connections will result
  in memory corruption.

  When memory management is enabled, SQLite tries to automatically
  recover from out-of-memory errors by freeing unused cache memory
  and retrying the allocation.
  This allows operations to continue when available memory is limit
  though with some loss of performance due to the reduction in cache
  size.

  The sqlite3_soft_heap_limit() API can be used to restrict SQLite's
  heap memory usage to a preset amount so that the reclamation of
  cache begins to occur before memory is exhausted.

  Memory management is enabled and disabled on a thread-by-thread basis.
  Each call to this routine enables or disabled memory management only for
  database connections created and used in the same thread in which this
  routine is called.

  For any given database connection, SQLite requires that the
  following routines always be called from the same thread:
  sqlite3_open(), sqlite3_prepare(), sqlite3_step(), sqlite3_reset(),
  sqlite3_finalize(), and sqlite3_close().  On some operating systems
  (ex: windows and linux 2.6) you can get away with calling these routines
  from different threads as long as their executions never overlap in time
  and memory management is disabled.
  But when the memory management is enabled, some information about the
  database connections is stored in thread-specific storage so that it
  will be available to remediate memory shortages.  Consequently,
  the previously enumerated routines must always be called from the
  same thread when memory management is enabled, regardless of what
  operating system is used.

  This routine returns SQLITE_OK if the memory management module was
  enabled or disabled successfully.  An error code is returned
  otherwise.

  Memory management is disabled by default for backwards compatibility
  and because it is normally only useful for embedded devices.  The
  code that implements the memory management feature can be omitted by
  recompiling SQLite with the SQLITE_OMIT_MEMORY_MANAGEMENT macro defined.

}

api {} {
  int sqlite3_release_memory(int N);
} {
  This routine attempts to free at least N bytes of memory from the caches
  of database connecions that were created in the same thread from which this
  routine is called.  The value returned is the number of bytes actually
  freed.  

  If memory management has not been enabled by calling
  sqlite3_enable_memory_management() then this routine is a no-op
  and always returns 0.
}

api {} {
  void sqlite3_soft_heap_limit(int N);
} {
  This routine sets the soft heap limit for the current thread to N.
  If memory management is enabled on the thread  by the
  sqlite3_enable_memory_management() function and the total heap usage
  by SQLite in that thread exceeds N, then sqlite3_release_memory() is
  called to try to reduce the memory usage below the soft limit.

  A negative value for N means that there is no soft heap limit and
  sqlite3_release_memory() will only be called when memory is exhaused.
  The default value for the soft heap limit is negative.

  SQLite makes a best effort to honor the soft heap limit.  But if it
  is unable to reduce memory usage below the soft limit, execution will
  continue without error or notification.  This is why the limit is 
  called a "soft" limit.  It is advisory only.

  If memory management is not enabled, the soft heap limit is ignored.

}

set n 0
set i 0
foreach item $apilist {
  set namelist [lindex $item 0]
  foreach name $namelist {







|

<
<
<
|
<
|
<
<
|
<
<
<
<
<
<
|
<
<
<

<
<
<
|
|
<
<
<
<
<
<
<
<
|
<
<
<
<
|
|
<
<
|
<
<
<
<
>










|
|
<






<
|
|


|

|






|
>







1264
1265
1266
1267
1268
1269
1270
1271
1272



1273

1274


1275






1276



1277



1278
1279








1280




1281
1282


1283




1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296

1297
1298
1299
1300
1301
1302

1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
  enabled or disabled successfully.  An error code is returned
  otherwise.

  Shared cache is disabled by default for backward compatibility.
}

api {} {
  void sqlite3_thread_cleanup(void);
} {



  This routine makes sure that all thread local storage used by SQLite

  in the current thread has been deallocated.  A thread can call this


  routine prior to terminating in order to make sure there are no memory






  leaks.







  This routine is not strictly necessary.  If cache sharing has been
  disabled using sqlite3_enable_shared_cache() and if all database








  connections have been closed and if SQLITE_ENABLE_MEMORY_MANAGMENT is




  on and all memory has been freed, then the thread local storage will
  already have been automatically deallocated.  This routine is provided


  as a convenience to the program who just wants to make sure that there




  are no leaks.
}

api {} {
  int sqlite3_release_memory(int N);
} {
  This routine attempts to free at least N bytes of memory from the caches
  of database connecions that were created in the same thread from which this
  routine is called.  The value returned is the number of bytes actually
  freed.  

  This routine is only available if memory management has been enabled
  by compiling with the SQLITE_ENABLE_MEMORY_MANAGMENT macro.

}

api {} {
  void sqlite3_soft_heap_limit(int N);
} {
  This routine sets the soft heap limit for the current thread to N.

  If the total heap usage by SQLite in the current thread exceeds N,
  then sqlite3_release_memory() is
  called to try to reduce the memory usage below the soft limit.

  A negative or zero value for N means that there is no soft heap limit and
  sqlite3_release_memory() will only be called when memory is exhaused.
  The default value for the soft heap limit is zero.

  SQLite makes a best effort to honor the soft heap limit.  But if it
  is unable to reduce memory usage below the soft limit, execution will
  continue without error or notification.  This is why the limit is 
  called a "soft" limit.  It is advisory only.

  This routine is only available if memory management has been enabled
  by compiling with the SQLITE_ENABLE_MEMORY_MANAGMENT macro.
}

set n 0
set i 0
foreach item $apilist {
  set namelist [lindex $item 0]
  foreach name $namelist {