mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-21 09:00:59 +03:00
Add the sqlite3_hard_heap_limit64() interface and the corresponding
"PRAGMA hard_heap_limit=N" command. FossilOrigin-Name: b0ccef61a7f92d20228becbf4f997bf0f4e46dad2deaf0896dc63b976ad1dd11
This commit is contained in:
@@ -461,7 +461,9 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
#endif
|
||||
/* Version 3.28.0 and later */
|
||||
sqlite3_stmt_isexplain,
|
||||
sqlite3_value_frombind
|
||||
sqlite3_value_frombind,
|
||||
/* Version 3.29.0 and later */
|
||||
sqlite3_hard_heap_limit64
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
53
src/malloc.c
53
src/malloc.c
@@ -38,6 +38,7 @@ int sqlite3_release_memory(int n){
|
||||
static SQLITE_WSD struct Mem0Global {
|
||||
sqlite3_mutex *mutex; /* Mutex to serialize access */
|
||||
sqlite3_int64 alarmThreshold; /* The soft heap limit */
|
||||
sqlite3_int64 hardLimit; /* The hard upper bound on memory */
|
||||
|
||||
/*
|
||||
** True if heap is nearly "full" where "full" is defined by the
|
||||
@@ -74,8 +75,15 @@ int sqlite3_memory_alarm(
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Set the soft heap-size limit for the library. Passing a zero or
|
||||
** negative value indicates no limit.
|
||||
** Set the soft heap-size limit for the library. An argument of
|
||||
** zero disables the limit. A negative argument is a no-op used to
|
||||
** obtain the return value.
|
||||
**
|
||||
** The return value is the value of the heap limit just before this
|
||||
** interface was called.
|
||||
**
|
||||
** If the hard heap limit is enabled, then the soft heap limit cannot
|
||||
** be disabled nor raised above the hard heap limit.
|
||||
*/
|
||||
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
|
||||
sqlite3_int64 priorLimit;
|
||||
@@ -91,6 +99,9 @@ sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
return priorLimit;
|
||||
}
|
||||
if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
|
||||
n = mem0.hardLimit;
|
||||
}
|
||||
mem0.alarmThreshold = n;
|
||||
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
mem0.nearlyFull = (n>0 && n<=nUsed);
|
||||
@@ -104,6 +115,37 @@ void sqlite3_soft_heap_limit(int n){
|
||||
sqlite3_soft_heap_limit64(n);
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the hard heap-size limit for the library. An argument of zero
|
||||
** disables the hard heap limit. A negative argument is a no-op used
|
||||
** to obtain the return value without affecting the hard heap limit.
|
||||
**
|
||||
** The return value is the value of the hard heap limit just prior to
|
||||
** calling this interface.
|
||||
**
|
||||
** Setting the hard heap limit will also activate the soft heap limit
|
||||
** and constrain the soft heap limit to be no more than the hard heap
|
||||
** limit.
|
||||
*/
|
||||
sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){
|
||||
sqlite3_int64 priorLimit;
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
int rc = sqlite3_initialize();
|
||||
if( rc ) return -1;
|
||||
#endif
|
||||
sqlite3_mutex_enter(mem0.mutex);
|
||||
priorLimit = mem0.hardLimit;
|
||||
if( n>=0 ){
|
||||
mem0.hardLimit = n;
|
||||
if( n<mem0.alarmThreshold || mem0.alarmThreshold==0 ){
|
||||
mem0.alarmThreshold = n;
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(mem0.mutex);
|
||||
return priorLimit;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Initialize the memory allocation subsystem.
|
||||
*/
|
||||
@@ -203,6 +245,13 @@ static void mallocWithAlarm(int n, void **pp){
|
||||
if( nUsed >= mem0.alarmThreshold - nFull ){
|
||||
mem0.nearlyFull = 1;
|
||||
sqlite3MallocAlarm(nFull);
|
||||
if( mem0.hardLimit ){
|
||||
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
||||
if( nUsed >= mem0.hardLimit - nFull ){
|
||||
*pp = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
mem0.nearlyFull = 0;
|
||||
}
|
||||
|
||||
21
src/pragma.c
21
src/pragma.c
@@ -2064,6 +2064,27 @@ void sqlite3Pragma(
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA hard_heap_limit
|
||||
** PRAGMA hard_heap_limit = N
|
||||
**
|
||||
** Invoke sqlite3_hard_heap_limit64() to query or set the hard heap
|
||||
** limit. The hard heap limit can be activated or lowered by this
|
||||
** pragma, but not raised or deactivated. Only the
|
||||
** sqlite3_hard_heap_limit64() C-language API can raise or deactivate
|
||||
** the hard heap limit. This allows an application to set a heap limit
|
||||
** constraint that cannot be relaxed by an untrusted SQL script.
|
||||
*/
|
||||
case PragTyp_HARD_HEAP_LIMIT: {
|
||||
sqlite3_int64 N;
|
||||
if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
|
||||
sqlite3_int64 iPrior = sqlite3_hard_heap_limit64(-1);
|
||||
if( N>0 && (iPrior==0 || iPrior>N) ) sqlite3_hard_heap_limit64(N);
|
||||
}
|
||||
returnSingleInt(v, sqlite3_soft_heap_limit64(-1));
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
** PRAGMA threads
|
||||
** PRAGMA threads = N
|
||||
|
||||
66
src/pragma.h
66
src/pragma.h
@@ -21,35 +21,36 @@
|
||||
#define PragTyp_FOREIGN_KEY_CHECK 13
|
||||
#define PragTyp_FOREIGN_KEY_LIST 14
|
||||
#define PragTyp_FUNCTION_LIST 15
|
||||
#define PragTyp_INCREMENTAL_VACUUM 16
|
||||
#define PragTyp_INDEX_INFO 17
|
||||
#define PragTyp_INDEX_LIST 18
|
||||
#define PragTyp_INTEGRITY_CHECK 19
|
||||
#define PragTyp_JOURNAL_MODE 20
|
||||
#define PragTyp_JOURNAL_SIZE_LIMIT 21
|
||||
#define PragTyp_LOCK_PROXY_FILE 22
|
||||
#define PragTyp_LOCKING_MODE 23
|
||||
#define PragTyp_PAGE_COUNT 24
|
||||
#define PragTyp_MMAP_SIZE 25
|
||||
#define PragTyp_MODULE_LIST 26
|
||||
#define PragTyp_OPTIMIZE 27
|
||||
#define PragTyp_PAGE_SIZE 28
|
||||
#define PragTyp_PRAGMA_LIST 29
|
||||
#define PragTyp_SECURE_DELETE 30
|
||||
#define PragTyp_SHRINK_MEMORY 31
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 32
|
||||
#define PragTyp_SYNCHRONOUS 33
|
||||
#define PragTyp_TABLE_INFO 34
|
||||
#define PragTyp_TEMP_STORE 35
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 36
|
||||
#define PragTyp_THREADS 37
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 38
|
||||
#define PragTyp_WAL_CHECKPOINT 39
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 40
|
||||
#define PragTyp_HEXKEY 41
|
||||
#define PragTyp_KEY 42
|
||||
#define PragTyp_LOCK_STATUS 43
|
||||
#define PragTyp_STATS 44
|
||||
#define PragTyp_HARD_HEAP_LIMIT 16
|
||||
#define PragTyp_INCREMENTAL_VACUUM 17
|
||||
#define PragTyp_INDEX_INFO 18
|
||||
#define PragTyp_INDEX_LIST 19
|
||||
#define PragTyp_INTEGRITY_CHECK 20
|
||||
#define PragTyp_JOURNAL_MODE 21
|
||||
#define PragTyp_JOURNAL_SIZE_LIMIT 22
|
||||
#define PragTyp_LOCK_PROXY_FILE 23
|
||||
#define PragTyp_LOCKING_MODE 24
|
||||
#define PragTyp_PAGE_COUNT 25
|
||||
#define PragTyp_MMAP_SIZE 26
|
||||
#define PragTyp_MODULE_LIST 27
|
||||
#define PragTyp_OPTIMIZE 28
|
||||
#define PragTyp_PAGE_SIZE 29
|
||||
#define PragTyp_PRAGMA_LIST 30
|
||||
#define PragTyp_SECURE_DELETE 31
|
||||
#define PragTyp_SHRINK_MEMORY 32
|
||||
#define PragTyp_SOFT_HEAP_LIMIT 33
|
||||
#define PragTyp_SYNCHRONOUS 34
|
||||
#define PragTyp_TABLE_INFO 35
|
||||
#define PragTyp_TEMP_STORE 36
|
||||
#define PragTyp_TEMP_STORE_DIRECTORY 37
|
||||
#define PragTyp_THREADS 38
|
||||
#define PragTyp_WAL_AUTOCHECKPOINT 39
|
||||
#define PragTyp_WAL_CHECKPOINT 40
|
||||
#define PragTyp_ACTIVATE_EXTENSIONS 41
|
||||
#define PragTyp_HEXKEY 42
|
||||
#define PragTyp_KEY 43
|
||||
#define PragTyp_LOCK_STATUS 44
|
||||
#define PragTyp_STATS 45
|
||||
|
||||
/* Property flags associated with various pragma. */
|
||||
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
|
||||
@@ -318,6 +319,11 @@ static const PragmaName aPragmaName[] = {
|
||||
/* iArg: */ 0 },
|
||||
#endif
|
||||
#endif
|
||||
{/* zName: */ "hard_heap_limit",
|
||||
/* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT,
|
||||
/* ePragFlg: */ PragFlg_Result0,
|
||||
/* ColNames: */ 0, 0,
|
||||
/* iArg: */ 0 },
|
||||
#if defined(SQLITE_HAS_CODEC)
|
||||
{/* zName: */ "hexkey",
|
||||
/* ePragTyp: */ PragTyp_HEXKEY,
|
||||
@@ -667,4 +673,4 @@ static const PragmaName aPragmaName[] = {
|
||||
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
|
||||
#endif
|
||||
};
|
||||
/* Number of pragmas: 62 on by default, 81 total. */
|
||||
/* Number of pragmas: 63 on by default, 82 total. */
|
||||
|
||||
@@ -6038,6 +6038,9 @@ int sqlite3_db_release_memory(sqlite3*);
|
||||
/*
|
||||
** CAPI3REF: Impose A Limit On Heap Size
|
||||
**
|
||||
** These interfaces impose limits on the amount of heap memory that will be
|
||||
** by all database connections within a single process.
|
||||
**
|
||||
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
|
||||
** soft limit on the amount of heap memory that may be allocated by SQLite.
|
||||
** ^SQLite strives to keep heap memory utilization below the soft heap
|
||||
@@ -6048,20 +6051,41 @@ int sqlite3_db_release_memory(sqlite3*);
|
||||
** an [SQLITE_NOMEM] error. In other words, the soft heap limit
|
||||
** is advisory only.
|
||||
**
|
||||
** ^The return value from sqlite3_soft_heap_limit64() is the size of
|
||||
** the soft heap limit prior to the call, or negative in the case of an
|
||||
** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
|
||||
** N bytes on the amount of memory that will be allocated. ^The
|
||||
** sqlite3_hard_heap_limit64(N) interface is similar to
|
||||
** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
|
||||
** when the hard heap limit is reached.
|
||||
**
|
||||
** ^The return value from both sqlite3_soft_heap_limit64() and
|
||||
** sqlite3_hard_heap_limit64() is the size of
|
||||
** the heap limit prior to the call, or negative in the case of an
|
||||
** error. ^If the argument N is negative
|
||||
** then no change is made to the soft heap limit. Hence, the current
|
||||
** size of the soft heap limit can be determined by invoking
|
||||
** sqlite3_soft_heap_limit64() with a negative argument.
|
||||
** then no change is made to the heap limit. Hence, the current
|
||||
** size of heap limits can be determined by invoking
|
||||
** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
|
||||
**
|
||||
** ^If the argument N is zero then the soft heap limit is disabled.
|
||||
** ^Setting the heap limits to zero disables the heap limiter mechanism.
|
||||
**
|
||||
** ^(The soft heap limit is not enforced in the current implementation
|
||||
** ^The soft heap limit may not be greater than the hard heap limit.
|
||||
** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
|
||||
** is invoked with a value of N that is greater than the hard heap limit,
|
||||
** the the soft heap limit is set to the value of the hard heap limit.
|
||||
** ^The soft heap limit is automatically enabled whenever the hard heap
|
||||
** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
|
||||
** the soft heap limit is outside the range of 1..N, then the soft heap
|
||||
** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the
|
||||
** hard heap limit is enabled makes the soft heap limit equal to the
|
||||
** hard heap limit.
|
||||
**
|
||||
** The soft heap limits can also be adjusted using
|
||||
** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
|
||||
**
|
||||
** ^(The heap limits are not enforced in the current implementation
|
||||
** if one or more of following conditions are true:
|
||||
**
|
||||
** <ul>
|
||||
** <li> The soft heap limit is set to zero.
|
||||
** <li> The limit value is set to zero.
|
||||
** <li> Memory accounting is disabled using a combination of the
|
||||
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
|
||||
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
|
||||
@@ -6072,21 +6096,11 @@ int sqlite3_db_release_memory(sqlite3*);
|
||||
** from the heap.
|
||||
** </ul>)^
|
||||
**
|
||||
** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
|
||||
** the soft heap limit is enforced
|
||||
** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
|
||||
** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
|
||||
** the soft heap limit is enforced on every memory allocation. Without
|
||||
** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
|
||||
** when memory is allocated by the page cache. Testing suggests that because
|
||||
** the page cache is the predominate memory user in SQLite, most
|
||||
** applications will achieve adequate soft heap limit enforcement without
|
||||
** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
|
||||
**
|
||||
** The circumstances under which SQLite will enforce the soft heap limit may
|
||||
** The circumstances under which SQLite will enforce the heap limits may
|
||||
** changes in future releases of SQLite.
|
||||
*/
|
||||
sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
|
||||
sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Deprecated Soft Heap Limit Interface
|
||||
|
||||
@@ -322,6 +322,8 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.28.0 and later */
|
||||
int (*stmt_isexplain)(sqlite3_stmt*);
|
||||
int (*value_frombind)(sqlite3_value*);
|
||||
/* Version 3.29.0 and later */
|
||||
sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -614,6 +616,8 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
/* Version 3.28.0 and later */
|
||||
#define sqlite3_stmt_isexplain sqlite3_api->isexplain
|
||||
#define sqlite3_value_frombind sqlite3_api->frombind
|
||||
/* Version 3.29.0 and later */
|
||||
#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
29
src/test1.c
29
src/test1.c
@@ -5477,6 +5477,33 @@ static int SQLITE_TCLAPI test_soft_heap_limit(
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_hard_heap_limit ?N?
|
||||
**
|
||||
** Query or set the hard heap limit for the current thread. The
|
||||
** limit is only changed if the N is present. The previous limit
|
||||
** is returned.
|
||||
*/
|
||||
static int SQLITE_TCLAPI test_hard_heap_limit(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
sqlite3_int64 amt;
|
||||
Tcl_WideInt N = -1;
|
||||
if( objc!=1 && objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "?N?");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if( objc==2 ){
|
||||
if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
|
||||
}
|
||||
amt = sqlite3_hard_heap_limit64(N);
|
||||
Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_thread_cleanup
|
||||
**
|
||||
@@ -7880,6 +7907,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_db_filename", test_db_filename, 0},
|
||||
{ "sqlite3_db_readonly", test_db_readonly, 0},
|
||||
{ "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
|
||||
{ "sqlite3_soft_heap_limit64", test_soft_heap_limit, 0},
|
||||
{ "sqlite3_hard_heap_limit64", test_hard_heap_limit, 0},
|
||||
{ "sqlite3_thread_cleanup", test_thread_cleanup, 0},
|
||||
{ "sqlite3_pager_refcounts", test_pager_refcounts, 0},
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
|
||||
va_start(ap, zFormat);
|
||||
sqlite3_str_vappendf(&acc, zFormat, ap);
|
||||
va_end(ap);
|
||||
assert( acc.nChar>0 );
|
||||
assert( acc.nChar>0 || acc.accError );
|
||||
sqlite3_str_append(&acc, "\n", 1);
|
||||
}
|
||||
sqlite3StrAccumFinish(&acc);
|
||||
|
||||
Reference in New Issue
Block a user