📄 main.c
字号:
/*** 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.***************************************************************************** Main file for the SQLite library. The routines in this file** implement the programmer interface to the library. Routines in** other files are for internal use by SQLite and should not be** accessed by users of the library.**** $Id: main.c,v 1.514 2008/11/19 09:05:27 danielk1977 Exp $*/#include "sqliteInt.h"#include <ctype.h>#ifdef SQLITE_ENABLE_FTS3# include "fts3.h"#endif#ifdef SQLITE_ENABLE_RTREE# include "rtree.h"#endif#ifdef SQLITE_ENABLE_ICU# include "sqliteicu.h"#endif/*** The version of the library*/const char sqlite3_version[] = SQLITE_VERSION;const char *sqlite3_libversion(void){ return sqlite3_version; }int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)/*** If the following function pointer is not NULL and if** SQLITE_ENABLE_IOTRACE is enabled, then messages describing** I/O active are written using this function. These messages** are intended for debugging activity only.*/void (*sqlite3IoTrace)(const char*, ...) = 0;#endif/*** If the following global variable points to a string which is the** name of a directory, then that directory will be used to store** temporary files.**** See also the "PRAGMA temp_store_directory" SQL command.*/char *sqlite3_temp_directory = 0;/*** Initialize SQLite. **** This routine must be called to initialize the memory allocation,** VFS, and mutex subsystems prior to doing any serious work with** SQLite. But as long as you do not compile with SQLITE_OMIT_AUTOINIT** this routine will be called automatically by key routines such as** sqlite3_open(). **** This routine is a no-op except on its very first call for the process,** or for the first call after a call to sqlite3_shutdown.**** The first thread to call this routine runs the initialization to** completion. If subsequent threads call this routine before the first** thread has finished the initialization process, then the subsequent** threads must block until the first thread finishes with the initialization.**** The first thread might call this routine recursively. Recursive** calls to this routine should not block, of course. Otherwise the** initialization process would never complete.**** Let X be the first thread to enter this routine. Let Y be some other** thread. Then while the initial invocation of this routine by X is** incomplete, it is required that:**** * Calls to this routine from Y must block until the outer-most** call by X completes.**** * Recursive calls to this routine from thread X return immediately** without blocking.*/int sqlite3_initialize(void){ sqlite3_mutex *pMaster; /* The main static mutex */ int rc; /* Result code */#ifdef SQLITE_OMIT_WSD rc = sqlite3_wsd_init(4096, 24); if( rc!=SQLITE_OK ){ return rc; }#endif /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end ** of this routine. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; /* Make sure the mutex subsystem is initialized. If unable to ** initialize the mutex subsystem, return early with the error. ** If the system is so sick that we are unable to allocate a mutex, ** there is not much SQLite is going to be able to do. ** ** The mutex subsystem must take care of serializing its own ** initialization. */ rc = sqlite3MutexInit(); if( rc ) return rc; /* Initialize the malloc() system and the recursive pInitMutex mutex. ** This operation is protected by the STATIC_MASTER mutex. Note that ** MutexAlloc() is called for a static mutex prior to initializing the ** malloc subsystem - this implies that the allocation of a static ** mutex must not require support from the malloc subsystem. */ pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); sqlite3_mutex_enter(pMaster); if( !sqlite3GlobalConfig.isMallocInit ){ rc = sqlite3MallocInit(); } if( rc==SQLITE_OK ){ sqlite3GlobalConfig.isMallocInit = 1; if( !sqlite3GlobalConfig.pInitMutex ){ sqlite3GlobalConfig.pInitMutex = sqlite3MutexAlloc(SQLITE_MUTEX_RECURSIVE); if( sqlite3GlobalConfig.bCoreMutex && !sqlite3GlobalConfig.pInitMutex ){ rc = SQLITE_NOMEM; } } } if( rc==SQLITE_OK ){ sqlite3GlobalConfig.nRefInitMutex++; } sqlite3_mutex_leave(pMaster); /* If unable to initialize the malloc subsystem, then return early. ** There is little hope of getting SQLite to run if the malloc ** subsystem cannot be initialized. */ if( rc!=SQLITE_OK ){ return rc; } /* Do the rest of the initialization under the recursive mutex so ** that we will be able to handle recursive calls into ** sqlite3_initialize(). The recursive calls normally come through ** sqlite3_os_init() when it invokes sqlite3_vfs_register(), but other ** recursive calls might also be possible. */ sqlite3_mutex_enter(sqlite3GlobalConfig.pInitMutex); if( sqlite3GlobalConfig.isInit==0 && sqlite3GlobalConfig.inProgress==0 ){ FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions); sqlite3GlobalConfig.inProgress = 1; memset(pHash, 0, sizeof(sqlite3GlobalFunctions)); sqlite3RegisterGlobalFunctions(); rc = sqlite3_os_init(); if( rc==SQLITE_OK ){ rc = sqlite3PcacheInitialize(); sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage, sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage); } sqlite3GlobalConfig.inProgress = 0; sqlite3GlobalConfig.isInit = (rc==SQLITE_OK ? 1 : 0); } sqlite3_mutex_leave(sqlite3GlobalConfig.pInitMutex); /* Go back under the static mutex and clean up the recursive ** mutex to prevent a resource leak. */ sqlite3_mutex_enter(pMaster); sqlite3GlobalConfig.nRefInitMutex--; if( sqlite3GlobalConfig.nRefInitMutex<=0 ){ assert( sqlite3GlobalConfig.nRefInitMutex==0 ); sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex); sqlite3GlobalConfig.pInitMutex = 0; } sqlite3_mutex_leave(pMaster); /* The following is just a sanity check to make sure SQLite has ** been compiled correctly. It is important to run this code, but ** we don't want to run it too often and soak up CPU cycles for no ** reason. So we run it once during initialization. */#ifndef NDEBUG /* This section of code's only "output" is via assert() statements. */ if ( rc==SQLITE_OK ){ u64 x = (((u64)1)<<63)-1; double y; assert(sizeof(x)==8); assert(sizeof(x)==sizeof(y)); memcpy(&y, &x, 8); assert( sqlite3IsNaN(y) ); }#endif return rc;}/*** Undo the effects of sqlite3_initialize(). Must not be called while** there are outstanding database connections or memory allocations or** while any part of SQLite is otherwise in use in any thread. This** routine is not threadsafe. Not by a long shot.*/int sqlite3_shutdown(void){ sqlite3GlobalConfig.isMallocInit = 0; sqlite3PcacheShutdown(); if( sqlite3GlobalConfig.isInit ){ sqlite3_os_end(); } sqlite3MallocEnd(); sqlite3MutexEnd(); sqlite3GlobalConfig.isInit = 0; return SQLITE_OK;}/*** This API allows applications to modify the global configuration of** the SQLite library at run-time.**** This routine should only be called when there are no outstanding** database connections or memory allocations. This routine is not** threadsafe. Failure to heed these warnings can lead to unpredictable** behavior.*/int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while ** the SQLite library is in use. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE; va_start(ap, op); switch( op ){ /* Mutex configuration options are only available in a threadsafe ** compile. */#if SQLITE_THREADSAFE case SQLITE_CONFIG_SINGLETHREAD: { /* Disable all mutexing */ sqlite3GlobalConfig.bCoreMutex = 0; sqlite3GlobalConfig.bFullMutex = 0; break; } case SQLITE_CONFIG_MULTITHREAD: { /* Disable mutexing of database connections */ /* Enable mutexing of core data structures */ sqlite3GlobalConfig.bCoreMutex = 1; sqlite3GlobalConfig.bFullMutex = 0; break; } case SQLITE_CONFIG_SERIALIZED: { /* Enable all mutexing */ sqlite3GlobalConfig.bCoreMutex = 1; sqlite3GlobalConfig.bFullMutex = 1; break; } case SQLITE_CONFIG_MUTEX: { /* Specify an alternative mutex implementation */ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*); break; } case SQLITE_CONFIG_GETMUTEX: { /* Retrieve the current mutex implementation */ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; break; }#endif case SQLITE_CONFIG_MALLOC: { /* Specify an alternative malloc implementation */ sqlite3GlobalConfig.m = *va_arg(ap, sqlite3_mem_methods*); break; } case SQLITE_CONFIG_GETMALLOC: { /* Retrieve the current malloc() implementation */ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; break; } case SQLITE_CONFIG_MEMSTATUS: { /* Enable or disable the malloc status collection */ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); break; } case SQLITE_CONFIG_SCRATCH: { /* Designate a buffer for scratch memory space */ sqlite3GlobalConfig.pScratch = va_arg(ap, void*); sqlite3GlobalConfig.szScratch = va_arg(ap, int); sqlite3GlobalConfig.nScratch = va_arg(ap, int); break; } case SQLITE_CONFIG_PAGECACHE: { /* Designate a buffer for scratch memory space */ sqlite3GlobalConfig.pPage = va_arg(ap, void*); sqlite3GlobalConfig.szPage = va_arg(ap, int); sqlite3GlobalConfig.nPage = va_arg(ap, int); break; } case SQLITE_CONFIG_PCACHE: { /* Specify an alternative malloc implementation */ sqlite3GlobalConfig.pcache = *va_arg(ap, sqlite3_pcache_methods*); break; } case SQLITE_CONFIG_GETPCACHE: { if( sqlite3GlobalConfig.pcache.xInit==0 ){ sqlite3PCacheSetDefault(); } *va_arg(ap, sqlite3_pcache_methods*) = sqlite3GlobalConfig.pcache; break; }#if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) case SQLITE_CONFIG_HEAP: { /* Designate a buffer for heap memory space */ sqlite3GlobalConfig.pHeap = va_arg(ap, void*); sqlite3GlobalConfig.nHeap = va_arg(ap, int); sqlite3GlobalConfig.mnReq = va_arg(ap, int); if( sqlite3GlobalConfig.pHeap==0 ){ /* If the heap pointer is NULL, then restore the malloc implementation ** back to NULL pointers too. This will cause the malloc to go ** back to its default implementation when sqlite3_initialize() is ** run. */ memset(&sqlite3GlobalConfig.m, 0, sizeof(sqlite3GlobalConfig.m)); }else{ /* The heap pointer is not NULL, then install one of the ** mem5.c/mem3.c methods. If neither ENABLE_MEMSYS3 nor ** ENABLE_MEMSYS5 is defined, return an error. ** the default case and return an error. */#ifdef SQLITE_ENABLE_MEMSYS3 sqlite3GlobalConfig.m = *sqlite3MemGetMemsys3();#endif#ifdef SQLITE_ENABLE_MEMSYS5 sqlite3GlobalConfig.m = *sqlite3MemGetMemsys5();#endif } break; }#endif case SQLITE_CONFIG_LOOKASIDE: { sqlite3GlobalConfig.szLookaside = va_arg(ap, int); sqlite3GlobalConfig.nLookaside = va_arg(ap, int); break; } default: { rc = SQLITE_ERROR; break; } } va_end(ap); return rc;}/*** Set up the lookaside buffers for a database connection.** Return SQLITE_OK on success. ** If lookaside is already active, return SQLITE_BUSY.**** The sz parameter is the number of bytes in each lookaside slot.** The cnt parameter is the number of slots. If pStart is NULL the** space for the lookaside memory is obtained from sqlite3_malloc().** If pStart is not NULL then it is sz*cnt bytes of memory to use for** the lookaside memory.*/static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){ void *pStart; if( db->lookaside.nOut ){ return SQLITE_BUSY; } if( sz<0 ) sz = 0; if( cnt<0 ) cnt = 0; if( pBuf==0 ){ sz = (sz + 7)&~7; sqlite3BeginBenignMalloc(); pStart = sqlite3Malloc( sz*cnt ); sqlite3EndBenignMalloc(); }else{ sz = sz&~7; pStart = pBuf; } if( db->lookaside.bMalloced ){ sqlite3_free(db->lookaside.pStart); } db->lookaside.pStart = pStart; db->lookaside.pFree = 0; db->lookaside.sz = sz; db->lookaside.bMalloced = pBuf==0; if( pStart ){ int i; LookasideSlot *p; p = (LookasideSlot*)pStart; for(i=cnt-1; i>=0; i--){ p->pNext = db->lookaside.pFree; db->lookaside.pFree = p; p = (LookasideSlot*)&((u8*)p)[sz]; } db->lookaside.pEnd = p; db->lookaside.bEnabled = 1; }else{ db->lookaside.pEnd = 0; db->lookaside.bEnabled = 0; } return SQLITE_OK;}/*** Return the mutex associated with a database connection.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -