Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From 7bf5b6c8d0fe0ce9 To 3b2515079a119e6b
2013-03-08
| ||
09:59 | Merge prefix-mmap branch with trunk. This allows lsm to memory map a prefix of the database file and use regular read and write system calls to access the remainder. check-in: 02954a5b8d user: dan tags: trunk | |
2013-03-06
| ||
20:15 | Allow accessing a prefix of the database file using mmap and the remainder using read and write. check-in: abe0420724 user: dan tags: prefix-mmap | |
2013-03-04
| ||
22:37 |
New autoconf/make apparatus. Usage:
./autogen.sh ./configure make check-in: 7bf5b6c8d0 user: owensmk tags: trunk | |
17:09 | Merge xPutMeta and xGetMeta related changes from experimental branch. check-in: 03550f6b28 user: dan tags: trunk | |
2013-02-25
| ||
17:18 | Various fixes for test cases. check-in: 6b27bf4069 user: dan tags: trunk | |
16:36 | File Format Change Modify the key encoding so that final BLOBs are entered byte-for-byte with no terminator. check-in: 3b2515079a user: drh tags: trunk | |
2013-02-24
| ||
00:43 | Enhancements to the sqlite4_mm implementation. Fix the amalgamation generator so that it works after the addition of sqlite4_mm. check-in: 4424d6f7b3 user: drh tags: trunk | |
Deleted Make.defines.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Make.freebsd.
|
| < < < < |
Deleted Make.linux.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Make.mingw.
|
| < < < |
Deleted Make.opts.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Make.solaris.
|
| < < < < |
Deleted Make.unix.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted Make.win.
|
| < < < < < < < < |
Added Makefile.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | #!/usr/make # # Makefile for SQLITE # # This is a template makefile for SQLite. Most people prefer to # use the autoconf generated "configure" script to generate the # makefile automatically. But that does not work for everybody # and in every situation. If you are having problems with the # "configure" script, you might want to try this makefile as an # alternative. Create a copy of this file, edit the parameters # below and type "make". # #### The toplevel directory of the source tree. This is the directory # that contains this "Makefile.in" and the "configure.in" script. # TOP = . #### C Compiler and options for use in building executables that # will run on the platform that is doing the build. # BCC = clang -g #BCC = /opt/ancic/bin/c89 -0 #### If the target operating system supports the "usleep()" system # call, then define the HAVE_USLEEP macro for all C modules. # #USLEEP = USLEEP = -DHAVE_USLEEP=1 #### Leave SQLITE4_DEBUG undefined for maximum speed. Use SQLITE4_DEBUG=1 # to check for memory leaks. Use SQLITE4_DEBUG=2 to print a log of all # malloc()s and free()s in order to track down memory leaks. # # SQLite uses some expensive assert() statements in the inner loop. # You can make the library go almost twice as fast if you compile # with -DNDEBUG=1 # #OPTS += -DHAVE_DLOPEN OPTS += -DSQLITE4_DEBUG=1 OPTS += -DHAVE_GMTIME_R OPTS += -DHAVE_LOCALTIME_R OPTS += -DHAVE_MALLOC_USABLE_SIZE OPTS += -DHAVE_USLEEP #OPTS += -DLONGDOUBLE_TYPE=double #OPTS += -DSQLITE4_64BIT_STATS #OPTS += -DSQLITE4_CASE_SENSITIVE_LIKE #OPTS += -DSQLITE4_CHECK_PAGES #OPTS += -DSQLITE4_COVERAGE_TEST #OPTS += -DSQLITE4_DEBUG #OPTS += -DSQLITE4_DEFAULT_AUTOVACUUM=1 #OPTS += -DSQLITE4_DEFAULT_CACHE_SIZE=64 #OPTS += -DSQLITE4_DEFAULT_FILE_FORMAT=4 #OPTS += -DSQLITE4_DEFAULT_MEMSTATUS=0 #OPTS += -DSQLITE4_DEFAULT_PAGE_SIZE=1024 #OPTS += -DSQLITE4_DEFAULT_TEMP_CACHE_SIZE=32 #OPTS += -DSQLITE4_DISABLE_LFS=1 #OPTS += -DSQLITE4_ENABLE_8_3_NAMES #OPTS += -DSQLITE4_ENABLE_ASYNCIO #OPTS += -DSQLITE4_ENABLE_ATOMIC_WRITE #OPTS += -DSQLITE4_ENABLE_COLUMN_METADATA #OPTS += -DSQLITE4_ENABLE_EXPENSIVE_ASSERT #OPTS += -DSQLITE4_ENABLE_FTS3 OPTS += -DSQLITE4_ENABLE_FTS4 #OPTS += -DSQLITE4_ENABLE_FTS3_PARENTHESIS #OPTS += -DSQLITE4_ENABLE_INSTVFS=1 #OPTS += -DSQLITE4_ENABLE_ICU #OPTS += -DSQLITE4_ENABLE_IOTRACE=1 #OPTS += -DSQLITE4_ENABLE_LOAD_EXTENSION=1 #OPTS += -DSQLITE4_ENABLE_LOCKING_STYLE=1 #OPTS += -DSQLITE4_ENABLE_MEMORY_MANAGEMENT=1 #OPTS += -DSQLITE4_ENABLE_MEMSYS3=1 #OPTS += -DSQLITE4_ENABLE_MEMSYS5=1 #OPTS += -DSQLITE4_ENABLE_OVERSIZE_CELL_CHECK #OPTS += -DSQLITE4_ENABLE_PREUPDATE_HOOK OPTS += -DSQLITE4_ENABLE_RTREE #OPTS += -DSQLITE4_ENABLE_RTREE -DVARIANT_RSTARTREE_CHOOSESUBTREE #OPTS += -DSQLITE4_ENABLE_SESSION #OPTS += -DSQLITE4_ENABLE_STAT2 #OPTS += -DSQLITE4_ENABLE_STAT3 #OPTS += -DSQLITE4_ENABLE_TREE_EXPLAIN #OPTS += -DSQLITE4_ENABLE_UNLOCK_NOTIFY #OPTS += -DSQLITE4_ENABLE_UPDATE_DELETE_LIMIT #OPTS += '-DSQLITE4_FILE_HEADER="MotorolaDB v001"' #OPTS += -DSQLITE4_HAVE_ISNAN #OPTS += -DSQLITE4_HOMEGROWN_RECURSIVE_MUTEX=1 #OPTS += -DSQLITE4_INT64_TYPE=int #OPTS += -DSQLITE4_LOCK_TRACE #OPTS += -DSQLITE4_MALLOC_SOFT_LIMIT=1024 #OPTS += -DSQLITE4_MAX_EXPR_DEPTH=0 #OPTS += -DSQLITE4_MAX_PAGE_SIZE=4096 #OPTS += -DSQLITE4_MAX_VARIABLE_NUMBER=500000 #OPTS += -DSQLITE4_MEMDEBUG=1 #OPTS += -DSQLITE4_MIXED_ENDIAN_64BIT_FLOAT=1 #OPTS += -DSQLITE4_MUTEX_NOOP=1 #OPTS += -DNO_GETTOD=1 OPTS += -DSQLITE4_NO_SYNC=1 #OPTS += -DSQLITE4_OMIT_ALTER_TABLE=1 #OPTS += -DSQLITE4_OMIT_AUTOMATIC_INDEX #OPTS += -DSQLITE4_OMIT_AUTOVACUUM=1 #OPTS += -DSQLITE4_OMIT_BLOB_LITERAL=1 #OPTS += -DSQLITE4_OMIT_CHECK=1 #OPTS += -DSQLITE4_OMIT_DATETIME_FUNCS=1 #OPTS += -DSQLITE4_OMIT_DEPRECATED=1 #OPTS += -DSQLITE4_OMIT_DISKIO #OPTS += -DSQLITE4_OMIT_FLOATING_POINT=1 #OPTS += -DSQLITE4_OMIT_ICU_LIKE #OPTS += -DSQLITE4_OMIT_LOAD_EXTENSION=1 #OPTS += -DSQLITE4_OMIT_LOOKASIDE=1 #OPTS += -DSQLITE4_OMIT_MEMORYDB=1 #OPTS += -DSQLITE4_OMIT_MERGE_SORT=1 #OPTS += -DSQLITE4_OMIT_PROGESS_CALLBACK=1 #OPTS += -DSQLITE4_OMIT_REINDEX=1 #OPTS += -DSQLITE4_OMIT_SHARED_CACHE=1 #OPTS += -DSQLITE4_OMIT_TRACE=1 #OPTS += -DSQLITE4_OMIT_UTF16=1 #OPTS += -DSQLITE4_OMIT_VIEW=1 #OPTS += -DSQLITE4_OMIT_VIRTUALTABLE=1 #OPTS += -DSQLITE4_OMIT_WAL #OPTS += -DSQLITE4_OMIT_WSD=1 #OPTS += -DSQLITE4_OS_OTHER=1 #OPTS += -DSQLITE4_OS_UNIX=1 #OPTS += -DSQLITE4_PCACHE_SEPARATE_HEADER #OPTS += -DSQLITE4_PAGECACHE_BLOCKALLOC #OPTS += -DSQLITE4_SECURE_DELETE=1 #OPTS += '-DSQLITE4_SHM_DIRECTORY="/dev/shm"' #OPTS += -DSQLITE4_SMALL_STACK #OPTS += -DSQLITE4_SOUNDEX=1 #OPTS += -DSQLITE4_TCL_DEFAULT_FULLMUTEX=1 #OPTS += -DSQLITE4_TEMP_STORE=3 #OPTS += -DSQLITE4_THREADSAFE=0 #OPTS += -DSQLITE4_THREADSAFE=1 #OPTS += -DSQLITE4_USE_ALLOCA #OPTS += -DSQLITE4_ZERO_MALLOC=1 #OPTS += -DUSE_PREAD64=1 #OPTS += -DYYSTACKDEPTH=0 #OPTS += -DSQLITE4_DEFAULT_AUTOVACUUM=1 #OPTS += -DSQLITE4_DEFAULT_CACHE_SIZE=64 #OPTS += -DSQLITE4_DEFAULT_PAGE_SIZE=1024 #OPTS += -DSQLITE4_DEFAULT_TEMP_CACHE_SIZE=32 #OPTS += -DSQLITE4_DISABLE_LFS=1 #OPTS += -DSQLITE4_ENABLE_ATOMIC_WRITE=1 #OPTS += -DSQLITE4_ENABLE_IOTRACE=1 #OPTS += -DSQLITE4_ENABLE_MEMORY_MANAGEMENT=1 #OPTS += -DSQLITE4_MAX_PAGE_SIZE=4096 #OPTS += -DSQLITE4_OMIT_LOAD_EXTENSION=1 #OPTS += -DSQLITE4_OMIT_PROGRESS_CALLBACK=1 #OPTS += -DSQLITE4_OMIT_VIRTUALTABLE=1 #OPTS += -DSQLITE4_TEMP_STORE=3 #### The suffix to add to executable files. ".exe" for windows. # Nothing for unix. # #EXE = .exe EXE = #### C Compile and options for use in building executables that # will run on the target platform. This is usually the same # as BCC, unless you are cross-compiling. # #TCC = gcc -O6 #TCC = gcc -g -rdynamic -O0 -Wall -fstrict-aliasing TCC = clang -g -O0 -Wall -fstrict-aliasing #TCC = gcc420 -g -O2 -Wall #TCC = gcc -g -O0 -Wall -fprofile-arcs -ftest-coverage #TCC = /opt/mingw/bin/i386-mingw32-gcc -O6 #TCC = /opt/ansic/bin/c89 -O +z -Wl,-a,archive #### Tools used to build a static library. # AR = ar cr #AR = /opt/mingw/bin/i386-mingw32-ar cr RANLIB = ranlib #RANLIB = /opt/mingw/bin/i386-mingw32-ranlib #### Extra compiler options needed for programs that use the TCL library. # #TCL_FLAGS = #TCL_FLAGS = -DSTATIC_BUILD=1 #TCL_FLAGS = -I/home/drh/tcltk/85linux #TCL_FLAGS = -I/home/drh/tcltk/86linux #TCL_FLAGS = -I/home/drh/tcltk/84win -DSTATIC_BUILD=1 #TCL_FLAGS = -I/home/drh/tcltk/8.3hpux #### Linker options needed to link against the TCL library. # #LIBTCL = -ltcl8.4 -lm -ldl #LIBTCL = /home/drh/tcltk/85linux/libtcl8.5.a -lm -ldl -lpthread LIBTCL = -ltcl8.6 -lm -lpthread -ldl -lz #LIBTCL = /home/drh/tcltk/84linux/libtcl84thread.a -lm -ldl #LIBTCL = /home/drh/tcltk/8.4win/libtcl84s.a -lmsvcrt #LIBTCL = /home/drh/tcltk/8.3hpux/libtcl8.3.a -ldld -lm -lc #### Compiler options needed for programs that use the readline() library. # READLINE_FLAGS = #READLINE_FLAGS = -DHAVE_READLINE=1 -I/usr/include/readline #### Linker options needed by programs using readline() must link against. # LIBREADLINE = -ldl -lpthread #LIBREADLINE = -static -lreadline -ltermcap #### Should the database engine assume text is coded as UTF-8 or iso8859? # ENCODING = UTF8 #ENCODING = ISO8859 #### Math library # MATHLIB = -lm # MATHLIB = #### AWK (Needed by brain-dead Solaris systems) # NAWK = awk #### THREADLIB Libraries needed for threadtest # THREADLIB = -ldl -lpthread #OPTS += -DSQLITE4_FILE_HEADER='"bogus header..."' # You should not have to change anything below this line ############################################################################### include $(TOP)/main.mk |
Deleted Makefile.in.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to README.
1 2 3 4 5 6 7 8 9 10 11 12 13 | This directory contains source code to SQLite: An Embeddable SQL Database Engine To compile the project, first create a directory in which to place the build products. It is recommended, but not required, that the build directory be separate from the source directory. Cd into the build directory and then from the build directory run the configure script found at the root of the source tree. Then run "make". For example: tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" | | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | This directory contains source code to SQLite: An Embeddable SQL Database Engine To compile the project, first create a directory in which to place the build products. It is recommended, but not required, that the build directory be separate from the source directory. Cd into the build directory and then from the build directory run the configure script found at the root of the source tree. Then run "make". For example: tar xzf sqlite.tar.gz ;# Unpack the source tree into "sqlite" mkdir bld ;# Build will occur in a sibling directory cd bld ;# Change to the build directory ../sqlite/configure ;# Run the configure script make ;# Run the makefile. make install ;# (Optional) Install the build products The configure script uses autoconf 2.61 and libtool. If the configure script does not work out for you, there is a generic makefile named "Makefile.linux-gcc" in the top directory of the source tree that you can copy and edit to suit your needs. Comments on the generic makefile |
︙ | ︙ |
Deleted autogen.sh.
|
| < < < < |
Deleted config.h.in.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted config/config.guess.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted config/config.sub.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted config/install-sh.
Deleted config/missing.
Deleted config/mkinstalldirs.
Deleted configure.in.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to lsm-test/lsmtest_main.c.
︙ | ︙ | |||
563 564 565 566 567 568 569 | "Options are:\n" " -repeat $repeat (default value 10)\n" " -write $write (default value 10000)\n" " -pause $pause (default value 0)\n" " -fetch $fetch (default value 0)\n" " -keysize $keysize (default value 12)\n" " -valsize $valsize (default value 100)\n" | | | 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 | "Options are:\n" " -repeat $repeat (default value 10)\n" " -write $write (default value 10000)\n" " -pause $pause (default value 0)\n" " -fetch $fetch (default value 0)\n" " -keysize $keysize (default value 12)\n" " -valsize $valsize (default value 100)\n" " -system $system (default value \"lsm\"\n" "\n" ); } int do_speed_test2(int nArg, char **azArg){ struct Option { const char *zOpt; |
︙ | ︙ | |||
642 643 644 645 646 647 648 | } printf("#"); for(i=0; i<ArraySize(aOpt); i++){ if( aOpt[i].zOpt ){ if( aOpt[i].eVal>=0 ){ printf(" %s=%d", &aOpt[i].zOpt[1], aParam[aOpt[i].eVal]); | | | 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 | } printf("#"); for(i=0; i<ArraySize(aOpt); i++){ if( aOpt[i].zOpt ){ if( aOpt[i].eVal>=0 ){ printf(" %s=%d", &aOpt[i].zOpt[1], aParam[aOpt[i].eVal]); }else{ printf(" %s=\"%s\"", &aOpt[i].zOpt[1], zSystem); } } } printf("\n"); defn.nMinKey = defn.nMaxKey = aParam[ST_KEYSIZE]; |
︙ | ︙ | |||
1426 1427 1428 1429 1430 1431 1432 | #ifdef __linux__ #include <sys/time.h> #include <sys/resource.h> static void lsmtest_rusage_report(void){ int res; struct rusage r; | | | 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 | #ifdef __linux__ #include <sys/time.h> #include <sys/resource.h> static void lsmtest_rusage_report(void){ int res; struct rusage r; memset(&r, sizeof(r), 0); res = getrusage(RUSAGE_SELF, &r); assert( res==0 ); printf("# getrusage: { ru_maxrss %d ru_oublock %d ru_inblock %d }\n", (int)r.ru_maxrss, (int)r.ru_oublock, (int)r.ru_inblock ); |
︙ | ︙ | |||
1454 1455 1456 1457 1458 1459 1460 | {"writespeed", do_writer_test}, {"io", st_do_io}, {"insert", do_insert}, {"replay", do_replay}, {"speed", do_speed_tests}, | | | 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 | {"writespeed", do_writer_test}, {"io", st_do_io}, {"insert", do_insert}, {"replay", do_replay}, {"speed", do_speed_tests}, {"speed2", do_speed_test2}, {"show", st_do_show}, {"work", st_do_work}, {"test", do_test}, {0, 0} }; int rc; /* Return Code */ int iFunc; /* Index into aTest[] */ |
︙ | ︙ |
Changes to lsm-test/lsmtest_tdb3.c.
︙ | ︙ | |||
812 813 814 815 816 817 818 | if( rc!=0 ) return rc; eParam = aParam[i].eParam; z++; zStart = z; while( *z>='0' && *z<='9' ) z++; if( *z=='k' || *z=='K' ){ | | | | 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | if( rc!=0 ) return rc; eParam = aParam[i].eParam; z++; zStart = z; while( *z>='0' && *z<='9' ) z++; if( *z=='k' || *z=='K' ){ iMul = 1024; z++; }else if( *z=='M' || *z=='M' ){ iMul = 1024 * 1024; z++; } nParam = z-zStart; if( nParam==0 || nParam>sizeof(zParam)-1 ) goto syntax_error; memcpy(zParam, zStart, nParam); zParam[nParam] = '\0'; iVal = atoi(zParam) * iMul; |
︙ | ︙ | |||
837 838 839 840 841 842 843 | case TEST_NO_RECOVERY: if( pLsm ) pLsm->bNoRecovery = iVal; break; case TEST_MT_MODE: if( pLsm ) nThread = iVal; break; case TEST_MT_MIN_CKPT: | | | | 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | case TEST_NO_RECOVERY: if( pLsm ) pLsm->bNoRecovery = iVal; break; case TEST_MT_MODE: if( pLsm ) nThread = iVal; break; case TEST_MT_MIN_CKPT: if( pLsm && iVal>0 ) pLsm->nMtMinCkpt = iVal; break; case TEST_MT_MAX_CKPT: if( pLsm && iVal>0 ) pLsm->nMtMaxCkpt = iVal; break; #ifdef HAVE_ZLIB case TEST_COMPRESSION: testConfigureCompression(db); break; #endif } |
︙ | ︙ |
Changes to lsm-test/lsmtest_util.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #include <stdarg.h> #include <stdio.h> #include <string.h> #include <sys/time.h> /* ** Global variables used within this module. */ static struct TestutilGlobal { char **argv; int argc; } g = {0, 0}; static struct TestutilRnd { | > > > | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include "lsmtest.h" #include <stdarg.h> #include <stdio.h> #include <string.h> #include <sys/time.h> /* ** Global variables used within this module. */ static struct TestutilGlobal { char **argv; int argc; } g = {0, 0}; static struct TestutilRnd { u32 aRand1[2048]; /* Bits 0..10 */ u32 aRand2[2048]; /* Bits 11..21 */ u32 aRand3[1024]; /* Bits 22..31 */ } r; /************************************************************************* ** The following block is a copy of the implementation of SQLite function ** sqlite3_randomness. This version has two important differences: ** ** 1. It always uses the same seed. So the sequence of random data output |
︙ | ︙ | |||
65 66 67 68 69 70 71 | 0xC4, 0xEC, 0x80, 0xD0, 0x98, 0xA7, 0x76, 0xCC, 0x9C, 0x2F, 0x7B, 0xFF, 0x8E, 0x0E, 0xBB, 0x90, 0xAE, 0x13, 0x06, 0xF5, 0x1C, 0x4E, 0x52, 0xF7 } }; /* Generate and return single random byte */ | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | 0xC4, 0xEC, 0x80, 0xD0, 0x98, 0xA7, 0x76, 0xCC, 0x9C, 0x2F, 0x7B, 0xFF, 0x8E, 0x0E, 0xBB, 0x90, 0xAE, 0x13, 0x06, 0xF5, 0x1C, 0x4E, 0x52, 0xF7 } }; /* Generate and return single random byte */ static u8 randomByte(void){ unsigned char t; sqlite3Prng.i++; t = sqlite3Prng.s[sqlite3Prng.i]; sqlite3Prng.j += t; sqlite3Prng.s[sqlite3Prng.i] = sqlite3Prng.s[sqlite3Prng.j]; sqlite3Prng.s[sqlite3Prng.j] = t; t += sqlite3Prng.s[sqlite3Prng.i]; |
︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 | } /* ** End of code copied from SQLite. *************************************************************************/ int testPrngInit(void){ randomBlob(sizeof(r.aRand1), (unsigned char *)r.aRand1); randomBlob(sizeof(r.aRand2), (unsigned char *)r.aRand2); randomBlob(sizeof(r.aRand3), (unsigned char *)r.aRand3); | > | | | | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | } /* ** End of code copied from SQLite. *************************************************************************/ int testPrngInit(void){ sqlite3_initialize(); randomBlob(sizeof(r.aRand1), (unsigned char *)r.aRand1); randomBlob(sizeof(r.aRand2), (unsigned char *)r.aRand2); randomBlob(sizeof(r.aRand3), (unsigned char *)r.aRand3); return LSM_OK; } u32 testPrngValue(u32 iVal){ return r.aRand1[iVal & 0x000007FF] ^ r.aRand2[(iVal>>11) & 0x000007FF] ^ r.aRand3[(iVal>>22) & 0x000003FF] ; } void testPrngArray(u32 iVal, u32 *aOut, int nOut){ int i; for(i=0; i<nOut; i++){ aOut[i] = testPrngValue(iVal+i); } } void testPrngString(u32 iVal, char *aOut, int nOut){ int i; for(i=0; i<(nOut-1); i++){ aOut[i] = 'a' + (testPrngValue(iVal+i) % 26); } aOut[i] = '\0'; } |
︙ | ︙ | |||
144 145 146 147 148 149 150 | struct Entry { const char *zName; }; struct Entry *pEntry; const char *zPrev = 0; testPrintError("unrecognized %s \"%s\": must be ", zType, zArg); for(pEntry=(struct Entry *)aData; pEntry->zName; | | | 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | struct Entry { const char *zName; }; struct Entry *pEntry; const char *zPrev = 0; testPrintError("unrecognized %s \"%s\": must be ", zType, zArg); for(pEntry=(struct Entry *)aData; pEntry->zName; pEntry=(struct Entry *)&((u8 *)pEntry)[sz] ){ if( zPrev ){ testPrintError("%s, ", zPrev); } zPrev = pEntry->zName; } testPrintError("or %s\n", zPrev); } |
︙ | ︙ | |||
169 170 171 172 173 174 175 | int i = 0; int iOut = -1; int nOut = 0; for(pEntry=(struct Entry *)aData; pEntry->zName; | | | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | int i = 0; int iOut = -1; int nOut = 0; for(pEntry=(struct Entry *)aData; pEntry->zName; pEntry=(struct Entry *)&((u8 *)pEntry)[sz] ){ int nName = strlen(pEntry->zName); if( nArg<=nName && memcmp(pEntry->zName, zArg, nArg)==0 ){ iOut = i; if( nName==nArg ){ nOut = 1; break; |
︙ | ︙ |
Deleted lsm-test/sqltest.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to main.mk.
︙ | ︙ | |||
40 41 42 43 44 45 46 | # Once the macros above are defined, the rest of this make script will # build the SQLite library and testing tools. ################################################################################ # FIXME: Required options for now. # OPTS += -DLSM_MUTEX_NONE | | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | # Once the macros above are defined, the rest of this make script will # build the SQLite library and testing tools. ################################################################################ # FIXME: Required options for now. # OPTS += -DLSM_MUTEX_NONE OPTS += -DSQLITE4_DEBUG=1 -DLSM_DEBUG=1 OPTS += -DHAVE_GMTIME_R OPTS += -DHAVE_LOCALTIME_R OPTS += -DHAVE_MALLOC_USABLE_SIZE OPTS += -DHAVE_USLEEP OPTS += -DSQLITE4_MEMDEBUG=1 #OPTS += -DSQLITE4_NO_SYNC=1 -DLSM_NO_SYNC=1 OPTS += -DSQLITE4_OMIT_ANALYZE OPTS += -DSQLITE4_OMIT_AUTOMATIC_INDEX OPTS += -DSQLITE4_OMIT_BTREECOUNT OPTS += -DSQLITE4_OMIT_VIRTUALTABLE=1 OPTS += -DSQLITE4_OMIT_XFER_OPT OPTS += -DSQLITE4_THREADSAFE=0 |
︙ | ︙ | |||
487 488 489 490 491 492 493 | TESTFIXTURE_PREREQ = $(TESTSRC) $(TESTSRC2) TESTFIXTURE_PREREQ += $(TOP)/src/tclsqlite.c TESTFIXTURE_PREREQ += libsqlite4.a testfixture$(EXE): $(TESTFIXTURE_PREREQ) $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \ | | | 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 | TESTFIXTURE_PREREQ = $(TESTSRC) $(TESTSRC2) TESTFIXTURE_PREREQ += $(TOP)/src/tclsqlite.c TESTFIXTURE_PREREQ += libsqlite4.a testfixture$(EXE): $(TESTFIXTURE_PREREQ) $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \ -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) libsqlite4.a amalgamation-testfixture$(EXE): sqlite4.c $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite4.c \ -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) fts3-testfixture$(EXE): sqlite4.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c |
︙ | ︙ | |||
530 531 532 533 534 535 536 | threadtest3$(EXE): sqlite4.o $(TOP)/test/threadtest3.c $(TOP)/test/tt3_checkpoint.c $(TCCX) -O2 sqlite4.o $(TOP)/test/threadtest3.c \ -o threadtest3$(EXE) $(THREADLIB) threadtest: threadtest3$(EXE) ./threadtest3$(EXE) | < < < < < | 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | threadtest3$(EXE): sqlite4.o $(TOP)/test/threadtest3.c $(TOP)/test/tt3_checkpoint.c $(TCCX) -O2 sqlite4.o $(TOP)/test/threadtest3.c \ -o threadtest3$(EXE) $(THREADLIB) threadtest: threadtest3$(EXE) ./threadtest3$(EXE) TEST_EXTENSION = $(SHPREFIX)testloadext.$(SO) $(TEST_EXTENSION): $(TOP)/test/test_loadext.c $(MKSHLIB) $(TOP)/test/test_loadext.c -o $(TEST_EXTENSION) extensiontest: testfixture$(EXE) $(TEST_EXTENSION) ./testfixture$(EXE) $(TOP)/test/loadext.test |
︙ | ︙ |
Changes to src/fts5func.c.
︙ | ︙ | |||
542 543 544 545 546 547 548 | iOff += nShift; mask = mask >> nShift; pSnip->iOff = iOff; pSnip->hlmask = mask; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 542 543 544 545 546 547 548 549 550 551 552 553 554 555 | iOff += nShift; mask = mask >> nShift; pSnip->iOff = iOff; pSnip->hlmask = mask; } static void fts5Snippet(sqlite4_context *pCtx, int nArg, sqlite4_value **apArg){ Snippet aSnip[4]; int nSnip; int iCol = -1; int nToken = -15; int rc; |
︙ | ︙ | |||
612 613 614 615 616 617 618 | memset(aSnip, 0, sizeof(aSnip)); for(i=0; rc==SQLITE4_OK && i<nSnip; i++){ rc = fts5BestSnippet(pCtx, iCol, &mask, nTok, &aSnip[i]); } if( mask==0 || nSnip==4 ){ SnippetText text = {0, 0, 0}; | < | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | memset(aSnip, 0, sizeof(aSnip)); for(i=0; rc==SQLITE4_OK && i<nSnip; i++){ rc = fts5BestSnippet(pCtx, iCol, &mask, nTok, &aSnip[i]); } if( mask==0 || nSnip==4 ){ SnippetText text = {0, 0, 0}; for(i=0; rc==SQLITE4_OK && i<nSnip; i++){ int nSz; rc = sqlite4_mi_size(pCtx, aSnip[i].iCol, -1, &nSz); if( rc==SQLITE4_OK ){ fts5SnippetImprove(pCtx, nTok, nSz, &aSnip[i]); rc = fts5SnippetText( pCtx, &aSnip[i], &text, nTok, zStart, zEnd, zEllipses |
︙ | ︙ |
Changes to src/kv.c.
︙ | ︙ | |||
370 371 372 373 374 375 376 | while( i<nMeta ) a[i++] = 0; } sqlite4KVCursorClose(pCur); } return rc; } | < < < < < < < < < < < < < < < < < | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 | while( i<nMeta ) a[i++] = 0; } sqlite4KVCursorClose(pCur); } return rc; } /* ** Write nMeta unsigned 32-bit integers beginning with iStart. */ int sqlite4KVStorePutMeta( sqlite4 *db, /* Database connection. Needed to malloc */ KVStore *p, /* Write to this database */ int iStart, /* Start writing here */ |
︙ | ︙ |
Changes to src/kv.h.
︙ | ︙ | |||
170 171 172 173 174 175 176 | int sqlite4KVStoreCommit(KVStore *p, int iLevel); int sqlite4KVStoreRollback(KVStore *p, int iLevel); int sqlite4KVStoreRevert(KVStore *p, int iLevel); int sqlite4KVStoreClose(KVStore *p); int sqlite4KVStoreGetMeta(KVStore *p, int, int, unsigned int*); int sqlite4KVStorePutMeta(sqlite4*, KVStore *p, int, int, unsigned int*); | < < < < | 170 171 172 173 174 175 176 177 178 179 | int sqlite4KVStoreCommit(KVStore *p, int iLevel); int sqlite4KVStoreRollback(KVStore *p, int iLevel); int sqlite4KVStoreRevert(KVStore *p, int iLevel); int sqlite4KVStoreClose(KVStore *p); int sqlite4KVStoreGetMeta(KVStore *p, int, int, unsigned int*); int sqlite4KVStorePutMeta(sqlite4*, KVStore *p, int, int, unsigned int*); #ifdef SQLITE4_DEBUG void sqlite4KVStoreDump(KVStore *p); #endif |
Changes to src/kvlsm.c.
︙ | ︙ | |||
405 406 407 408 409 410 411 | rc = SQLITE4_NOTFOUND; break; } return rc; } | < < < < < < < < < < | | | | | | | | | | | | | | | | | | | < < < < < | 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 | rc = SQLITE4_NOTFOUND; break; } return rc; } /* ** Create a new in-memory storage engine and return a pointer to it. */ int sqlite4KVStoreOpenLsm( sqlite4_env *pEnv, /* Run-time environment */ KVStore **ppKVStore, /* OUT: write the new KVStore here */ const char *zName, /* Name of the file to open */ unsigned openFlags /* Flags */ ){ /* Virtual methods for an LSM data store */ static const KVStoreMethods kvlsmMethods = { 1, /* iVersion */ sizeof(KVStoreMethods), /* szSelf */ kvlsmReplace, /* xReplace */ kvlsmOpenCursor, /* xOpenCursor */ kvlsmSeek, /* xSeek */ kvlsmNextEntry, /* xNext */ kvlsmPrevEntry, /* xPrev */ kvlsmDelete, /* xDelete */ kvlsmKey, /* xKey */ kvlsmData, /* xData */ kvlsmReset, /* xReset */ kvlsmCloseCursor, /* xCloseCursor */ kvlsmBegin, /* xBegin */ kvlsmCommitPhaseOne, /* xCommitPhaseOne */ kvlsmCommitPhaseTwo, /* xCommitPhaseTwo */ kvlsmRollback, /* xRollback */ kvlsmRevert, /* xRevert */ kvlsmClose, /* xClose */ kvlsmControl /* xControl */ }; KVLsm *pNew; int rc = SQLITE4_OK; pNew = (KVLsm *)sqlite4_malloc(pEnv, sizeof(KVLsm)); if( pNew==0 ){ rc = SQLITE4_NOMEM; }else{ struct Config { const char *zParam; int eParam; } aConfig[] = { { "lsm_block_size", LSM_CONFIG_BLOCK_SIZE }, { "lsm_multiple_processes", LSM_CONFIG_MULTIPLE_PROCESSES } }; memset(pNew, 0, sizeof(KVLsm)); pNew->base.pStoreVfunc = &kvlsmMethods; pNew->base.pEnv = pEnv; rc = lsm_new(0, &pNew->pDb); if( rc==SQLITE4_OK ){ int i; int bMmap = 0; lsm_config(pNew->pDb, LSM_CONFIG_MMAP, &bMmap); for(i=0; i<ArraySize(aConfig); i++){ const char *zVal = sqlite4_uri_parameter(zName, aConfig[i].zParam); if( zVal ){ int nVal = sqlite4Atoi(zVal); lsm_config(pNew->pDb, aConfig[i].eParam, &nVal); } } |
︙ | ︙ |
Changes to src/kvmem.c.
︙ | ︙ | |||
66 67 68 69 70 71 72 | struct KVMem { KVStore base; /* Base class, must be first */ KVMemNode *pRoot; /* Root of the tree of content */ unsigned openFlags; /* Flags used at open */ KVMemChng **apLog; /* Array of transaction logs */ int nCursor; /* Number of outstanding cursors */ int iMagicKVMemBase; /* Magic number of sanity */ | < | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | struct KVMem { KVStore base; /* Base class, must be first */ KVMemNode *pRoot; /* Root of the tree of content */ unsigned openFlags; /* Flags used at open */ KVMemChng **apLog; /* Array of transaction logs */ int nCursor; /* Number of outstanding cursors */ int iMagicKVMemBase; /* Magic number of sanity */ }; #define SQLITE4_KVMEMBASE_MAGIC 0xbfcd47d0 /* ** A cursor used for scanning through the tree */ struct KVMemCursor { |
︙ | ︙ | |||
913 914 915 916 917 918 919 | return SQLITE4_OK; } static int kvmemControl(KVStore *pKVStore, int op, void *pArg){ return SQLITE4_NOTFOUND; } | < < < < < < < < < < < < | < < | 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 | return SQLITE4_OK; } static int kvmemControl(KVStore *pKVStore, int op, void *pArg){ return SQLITE4_NOTFOUND; } /* Virtual methods for the in-memory storage engine */ static const KVStoreMethods kvmemMethods = { 1, /* iVersion */ sizeof(KVStoreMethods), /* szSelf */ kvmemReplace, /* xReplace */ kvmemOpenCursor, /* xOpenCursor */ kvmemSeek, /* xSeek */ kvmemNextEntry, /* xNext */ kvmemPrevEntry, /* xPrev */ kvmemDelete, /* xDelete */ kvmemKey, /* xKey */ kvmemData, /* xData */ kvmemReset, /* xReset */ kvmemCloseCursor, /* xCloseCursor */ kvmemBegin, /* xBegin */ kvmemCommitPhaseOne, /* xCommitPhaseOne */ kvmemCommitPhaseTwo, /* xCommitPhaseTwo */ kvmemRollback, /* xRollback */ kvmemRevert, /* xRevert */ kvmemClose, /* xClose */ kvmemControl /* xControl */ }; /* ** Create a new in-memory storage engine and return a pointer to it. */ int sqlite4KVStoreOpenMem( sqlite4_env *pEnv, /* Runtime environment */ |
︙ | ︙ |
Changes to src/lsm.h.
︙ | ︙ | |||
330 331 332 333 334 335 336 | /* ** CAPI: Querying a Connection For Operational Data ** ** Query a database connection for operational statistics or data. */ int lsm_info(lsm_db *, int, ...); | < < < | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | /* ** CAPI: Querying a Connection For Operational Data ** ** Query a database connection for operational statistics or data. */ int lsm_info(lsm_db *, int, ...); /* ** The following values may be passed as the second argument to lsm_info(). ** ** LSM_INFO_NWRITE: ** The third parameter should be of type (int *). The location pointed ** to by the third parameter is set to the number of 4KB pages written to ** the database file during the lifetime of this connection. |
︙ | ︙ |
Changes to src/lsmInt.h.
︙ | ︙ | |||
167 168 169 170 171 172 173 | #define LSM_START_DELETE 0x01 /* Start of open-ended delete range */ #define LSM_END_DELETE 0x02 /* End of open-ended delete range */ #define LSM_POINT_DELETE 0x04 /* Delete this key */ #define LSM_INSERT 0x08 /* Insert this key and value */ #define LSM_SEPARATOR 0x10 /* True if entry is separator key only */ #define LSM_SYSTEMKEY 0x20 /* True if entry is a system key (FREELIST) */ | < < | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | #define LSM_START_DELETE 0x01 /* Start of open-ended delete range */ #define LSM_END_DELETE 0x02 /* End of open-ended delete range */ #define LSM_POINT_DELETE 0x04 /* Delete this key */ #define LSM_INSERT 0x08 /* Insert this key and value */ #define LSM_SEPARATOR 0x10 /* True if entry is separator key only */ #define LSM_SYSTEMKEY 0x20 /* True if entry is a system key (FREELIST) */ /* ** A string that can grow by appending. */ struct LsmString { lsm_env *pEnv; /* Run-time environment */ int n; /* Size of string. -1 indicates error */ int nAlloc; /* Space allocated for z[] */ |
︙ | ︙ | |||
277 278 279 280 281 282 283 | u32 iNextShmid; /* Shm-id of next chunk allocated */ u32 iFirst; /* Chunk number of smallest shm-id */ u32 nChunk; /* Number of chunks in shared-memory file */ TreeRoot root; /* Root and height of current tree */ u32 iWrite; /* Write offset in shm file */ TreeRoot oldroot; /* Root and height of the previous tree */ u32 iOldShmid; /* Last shm-id used by previous tree */ | < | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | u32 iNextShmid; /* Shm-id of next chunk allocated */ u32 iFirst; /* Chunk number of smallest shm-id */ u32 nChunk; /* Number of chunks in shared-memory file */ TreeRoot root; /* Root and height of current tree */ u32 iWrite; /* Write offset in shm file */ TreeRoot oldroot; /* Root and height of the previous tree */ u32 iOldShmid; /* Last shm-id used by previous tree */ i64 iOldLog; /* Log offset associated with old tree */ u32 oldcksum0; u32 oldcksum1; DbLog log; /* Current layout of log file */ u32 aCksum[2]; /* Checksums 1 and 2. */ }; |
︙ | ︙ | |||
303 304 305 306 307 308 309 | ** lock on lock region iLock, then the following is true: ** ** (mLock & ((iLock+32-1) << 1)) ** ** Or for an EXCLUSIVE lock: ** ** (mLock & ((iLock-1) << 1)) | < < < < < < < < < < < < | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | ** lock on lock region iLock, then the following is true: ** ** (mLock & ((iLock+32-1) << 1)) ** ** Or for an EXCLUSIVE lock: ** ** (mLock & ((iLock-1) << 1)) */ struct lsm_db { /* Database handle configuration */ lsm_env *pEnv; /* runtime environment */ int (*xCmp)(void *, int, void *, int); /* Compare function */ |
︙ | ︙ | |||
356 357 358 359 360 361 362 | LogWriter *pLogWriter; /* Context for writing to the log file */ int nTransOpen; /* Number of opened write transactions */ int nTransAlloc; /* Allocated size of aTrans[] array */ TransMark *aTrans; /* Array of marks for transaction rollback */ IntArray rollback; /* List of tree-nodes to roll back */ int bDiscardOld; /* True if lsmTreeDiscardOld() was called */ | < < | 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | LogWriter *pLogWriter; /* Context for writing to the log file */ int nTransOpen; /* Number of opened write transactions */ int nTransAlloc; /* Allocated size of aTrans[] array */ TransMark *aTrans; /* Array of marks for transaction rollback */ IntArray rollback; /* List of tree-nodes to roll back */ int bDiscardOld; /* True if lsmTreeDiscardOld() was called */ /* Worker context */ Snapshot *pWorker; /* Worker snapshot (or NULL) */ Freelist *pFreelist; /* See sortedNewToplevel() */ int bUseFreelist; /* True to use pFreelist */ int bIncrMerge; /* True if currently doing a merge */ int bInFactory; /* True if within factory.xFactory() */ |
︙ | ︙ | |||
766 767 768 769 770 771 772 | void lsmEnvSleep(lsm_env *, int); int lsmFsReadSyncedId(lsm_db *db, int, i64 *piVal); int lsmFsSegmentContainsPg(FileSystem *pFS, Segment *, Pgno, int *); Pgno lsmFsRedirectPage(FileSystem *, Redirect *, Pgno); | < < | 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | void lsmEnvSleep(lsm_env *, int); int lsmFsReadSyncedId(lsm_db *db, int, i64 *piVal); int lsmFsSegmentContainsPg(FileSystem *pFS, Segment *, Pgno, int *); Pgno lsmFsRedirectPage(FileSystem *, Redirect *, Pgno); /* ** End of functions from "lsm_file.c". **************************************************************************/ /* ** Functions from file "lsm_sorted.c". */ |
︙ | ︙ | |||
799 800 801 802 803 804 805 | int lsmSortedLoadFreelist(lsm_db *pDb, void **, int *); void *lsmSortedSplitKey(Level *pLevel, int *pnByte); void lsmSortedSaveTreeCursors(lsm_db *); int lsmMCursorNew(lsm_db *, MultiCursor **); | | < | 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | int lsmSortedLoadFreelist(lsm_db *pDb, void **, int *); void *lsmSortedSplitKey(Level *pLevel, int *pnByte); void lsmSortedSaveTreeCursors(lsm_db *); int lsmMCursorNew(lsm_db *, MultiCursor **); void lsmMCursorClose(MultiCursor *); int lsmMCursorSeek(MultiCursor *, int, void *, int , int); int lsmMCursorFirst(MultiCursor *); int lsmMCursorPrev(MultiCursor *); int lsmMCursorLast(MultiCursor *); int lsmMCursorValid(MultiCursor *); int lsmMCursorNext(MultiCursor *); int lsmMCursorKey(MultiCursor *, void **, int *); int lsmMCursorValue(MultiCursor *, void **, int *); int lsmMCursorType(MultiCursor *, int *); lsm_db *lsmMCursorDb(MultiCursor *); int lsmSaveCursors(lsm_db *pDb); int lsmRestoreCursors(lsm_db *pDb); void lsmSortedDumpStructure(lsm_db *pDb, Snapshot *, int, int, const char *); void lsmFsDumpBlocklists(lsm_db *); |
︙ | ︙ |
Changes to src/lsm_file.c.
︙ | ︙ | |||
558 559 560 561 562 563 564 | /* Make a copy of the database and log file names. */ memcpy(pFS->zDb, zDb, nDb+1); memcpy(pFS->zLog, zDb, nDb); memcpy(&pFS->zLog[nDb], "-log", 5); /* Allocate the hash-table here. At some point, it should be changed ** so that it can grow dynamicly. */ | | | 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 | /* Make a copy of the database and log file names. */ memcpy(pFS->zDb, zDb, nDb+1); memcpy(pFS->zLog, zDb, nDb); memcpy(&pFS->zLog[nDb], "-log", 5); /* Allocate the hash-table here. At some point, it should be changed ** so that it can grow dynamicly. */ pFS->nCacheMax = 2048; pFS->nHash = 4096; pFS->apHash = lsmMallocZeroRc(pDb->pEnv, sizeof(Page *) * pFS->nHash, &rc); /* Open the database file */ pLsmFile = lsmDbRecycleFd(pDb); if( pLsmFile ){ pFS->pLsmFile = pLsmFile; |
︙ | ︙ | |||
725 726 727 728 729 730 731 | /* ** Configure the nominal page-size used by this file-system. Actual ** pages may be smaller or larger than this value. */ void lsmFsSetPageSize(FileSystem *pFS, int nPgsz){ pFS->nPagesize = nPgsz; | < | 725 726 727 728 729 730 731 732 733 734 735 736 737 738 | /* ** Configure the nominal page-size used by this file-system. Actual ** pages may be smaller or larger than this value. */ void lsmFsSetPageSize(FileSystem *pFS, int nPgsz){ pFS->nPagesize = nPgsz; } /* ** Configure the block-size used by this file-system. Actual pages may be ** smaller or larger than this value. */ void lsmFsSetBlockSize(FileSystem *pFS, int nBlocksize){ |
︙ | ︙ | |||
884 885 886 887 888 889 890 | Page **pp; iHash = fsHashKey(pFS->nHash, pPg->iPg); for(pp=&pFS->apHash[iHash]; *pp!=pPg; pp=&(*pp)->pHashNext); *pp = pPg->pHashNext; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | > > < < | < < < | | | 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 | Page **pp; iHash = fsHashKey(pFS->nHash, pPg->iPg); for(pp=&pFS->apHash[iHash]; *pp!=pPg; pp=&(*pp)->pHashNext); *pp = pPg->pHashNext; } static int fsPageBuffer( FileSystem *pFS, int bRequireData, /* True to allocate buffer as well */ Page **ppOut ){ int rc = LSM_OK; Page *pPage = 0; if( pFS->bUseMmap || pFS->pLruFirst==0 || pFS->nCacheAlloc<pFS->nCacheMax ){ pPage = lsmMallocZero(pFS->pEnv, sizeof(Page)); if( !pPage ){ rc = LSM_NOMEM_BKPT; }else if( bRequireData ){ pPage->aData = (u8 *)lsmMalloc(pFS->pEnv, pFS->nPagesize); pPage->flags = PAGE_FREE; if( !pPage->aData ){ lsmFree(pFS->pEnv, pPage); rc = LSM_NOMEM_BKPT; pPage = 0; } pFS->nCacheAlloc++; }else{ fsPageAddToLru(pFS, pPage); } }else{ pPage = pFS->pLruFirst; fsPageRemoveFromLru(pFS, pPage); fsPageRemoveFromHash(pFS, pPage); } assert( pPage==0 || (pPage->flags & PAGE_DIRTY)==0 ); *ppOut = pPage; return rc; } static void fsPageBufferFree(Page *pPg){ if( pPg->flags & PAGE_FREE ){ lsmFree(pPg->pFS->pEnv, pPg->aData); |
︙ | ︙ | |||
1375 1376 1377 1378 1379 1380 1381 | p = lsmMallocZeroRc(pFS->pEnv, sizeof(Page), &rc); if( rc ) return rc; fsPageAddToLru(pFS, p); p->pFS = pFS; } p->aData = &((u8 *)pFS->pMap)[pFS->nPagesize * (iReal-1)]; p->iPg = iReal; | < | | 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 | p = lsmMallocZeroRc(pFS->pEnv, sizeof(Page), &rc); if( rc ) return rc; fsPageAddToLru(pFS, p); p->pFS = pFS; } p->aData = &((u8 *)pFS->pMap)[pFS->nPagesize * (iReal-1)]; p->iPg = iReal; }else{ /* Search the hash-table for the page */ iHash = fsHashKey(pFS->nHash, iReal); for(p=pFS->apHash[iHash]; p; p=p->pHashNext){ if( p->iPg==iReal) break; } if( p==0 ){ rc = fsPageBuffer(pFS, 1, &p); if( rc==LSM_OK ){ int nSpace = 0; p->iPg = iReal; p->nRef = 0; p->pFS = pFS; assert( p->flags==0 || p->flags==PAGE_FREE ); |
︙ | ︙ | |||
1866 1867 1868 1869 1870 1871 1872 | assert( p->pRedirect==0 ); if( pFS->pCompress || bDefer ){ /* In compressed database mode the page is not assigned a page number ** or location in the database file at this point. This will be done ** by the lsmFsPagePersist() call. */ | | | 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 | assert( p->pRedirect==0 ); if( pFS->pCompress || bDefer ){ /* In compressed database mode the page is not assigned a page number ** or location in the database file at this point. This will be done ** by the lsmFsPagePersist() call. */ rc = fsPageBuffer(pFS, 1, &pPg); if( rc==LSM_OK ){ pPg->pFS = pFS; pPg->pSeg = p; pPg->iPg = 0; pPg->flags |= PAGE_DIRTY; pPg->nData = pFS->nPagesize; assert( pPg->aData ); |
︙ | ︙ | |||
2154 2155 2156 2157 2158 2159 2160 | i64 iOff = iFromOff + i*nSz; rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aData, nSz); if( rc==LSM_OK ){ iOff = iToOff + i*nSz; rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, aData, nSz); } } | < | 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 | i64 iOff = iFromOff + i*nSz; rc = lsmEnvRead(pFS->pEnv, pFS->fdDb, iOff, aData, nSz); if( rc==LSM_OK ){ iOff = iToOff + i*nSz; rc = lsmEnvWrite(pFS->pEnv, pFS->fdDb, iOff, aData, nSz); } } } } /* Update append-point list if necessary */ if( rc==LSM_OK ){ int i; for(i=0; i<LSM_APPLIST_SZ; i++){ |
︙ | ︙ | |||
2352 2353 2354 2355 2356 2357 2358 | assert( pPg->nRef==1 ); lsmFsPageRelease(pPg); pPg = pNext; } *pRc = rc; } | < < < < < < < < < < < < < < < < | 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 | assert( pPg->nRef==1 ); lsmFsPageRelease(pPg); pPg = pNext; } *pRc = rc; } /* ** If the page passed as an argument is dirty, update the database file ** (or mapping of the database file) with its current contents and mark ** the page as clean. ** ** Return LSM_OK if the operation is a success, or an LSM error code ** otherwise. |
︙ | ︙ | |||
2430 2431 2432 2433 2434 2435 2436 | assert( pPg->nData==pFS->nPagesize-4 ); rc = fsAppendPage(pFS, pPg->pSeg, &pPg->iPg, &iPrev, &iNext); if( rc!=LSM_OK ) return rc; if( pFS->bUseMmap==0 ){ int iHash = fsHashKey(pFS->nHash, pPg->iPg); | < | 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 | assert( pPg->nData==pFS->nPagesize-4 ); rc = fsAppendPage(pFS, pPg->pSeg, &pPg->iPg, &iPrev, &iNext); if( rc!=LSM_OK ) return rc; if( pFS->bUseMmap==0 ){ int iHash = fsHashKey(pFS->nHash, pPg->iPg); pPg->pHashNext = pFS->apHash[iHash]; pFS->apHash[iHash] = pPg; assert( pPg->pHashNext==0 || pPg->pHashNext->iPg!=pPg->iPg ); } if( iPrev ){ assert( iNext==0 ); |
︙ | ︙ | |||
2576 2577 2578 2579 2580 2581 2582 | pPg->aData -= (pPg->flags & PAGE_HASPREV); pPg->flags &= ~PAGE_HASPREV; if( pFS->bUseMmap ){ pPg->pHashNext = pFS->pFree; pFS->pFree = pPg; }else{ | < < < < | 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 | pPg->aData -= (pPg->flags & PAGE_HASPREV); pPg->flags &= ~PAGE_HASPREV; if( pFS->bUseMmap ){ pPg->pHashNext = pFS->pFree; pFS->pFree = pPg; }else{ assert( pPg->pLruNext==0 ); assert( pPg->pLruPrev==0 ); fsPageRemoveFromHash(pFS, pPg); fsPageBufferFree(pPg); } } } return rc; } |
︙ | ︙ |
Changes to src/lsm_main.c.
︙ | ︙ | |||
139 140 141 142 143 144 145 | lsmFree(pEnv, zAlloc); zAlloc = 0; } *pzAbs = zAlloc; return rc; } | < < < < < < < < < < < < < < < < < < < | 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | lsmFree(pEnv, zAlloc); zAlloc = 0; } *pzAbs = zAlloc; return rc; } /* ** Open a new connection to database zFilename. */ int lsm_open(lsm_db *pDb, const char *zFilename){ int rc; if( pDb->pDatabase ){ |
︙ | ︙ | |||
197 198 199 200 201 202 203 | if( rc==LSM_OK && LSM_OK==(rc = lsmCheckpointLoad(pDb, 0)) ){ lsmFsSetPageSize(pDb->pFS, lsmCheckpointPgsz(pDb->aSnapshot)); lsmFsSetBlockSize(pDb->pFS, lsmCheckpointBlksz(pDb->aSnapshot)); } } lsmFree(pDb->pEnv, zFull); | < > < < < | 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | if( rc==LSM_OK && LSM_OK==(rc = lsmCheckpointLoad(pDb, 0)) ){ lsmFsSetPageSize(pDb->pFS, lsmCheckpointPgsz(pDb->aSnapshot)); lsmFsSetBlockSize(pDb->pFS, lsmCheckpointBlksz(pDb->aSnapshot)); } } lsmFree(pDb->pEnv, zFull); } assert( pDb->bReadonly==0 || pDb->bReadonly==1 ); assert( rc!=LSM_OK || (pDb->pShmhdr==0)==(pDb->bReadonly==1) ); return rc; } int lsm_close(lsm_db *pDb){ int rc = LSM_OK; if( pDb ){ assert_db_state(pDb); if( pDb->pCsr || pDb->nTransOpen ){ rc = LSM_MISUSE_BKPT; }else{ lsmFreeSnapshot(pDb->pEnv, pDb->pClient); pDb->pClient = 0; lsmDbDatabaseRelease(pDb); lsmLogClose(pDb); lsmFsClose(pDb->pFS); assert( pDb->mLock==0 ); /* Invoke any destructors registered for the compression or ** compression factory callbacks. */ |
︙ | ︙ | |||
752 753 754 755 756 757 758 | /* ** Open a new cursor handle. ** ** If there are currently no other open cursor handles, and no open write ** transaction, open a read transaction here. */ int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr){ | | | < | < | | | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 | /* ** Open a new cursor handle. ** ** If there are currently no other open cursor handles, and no open write ** transaction, open a read transaction here. */ int lsm_csr_open(lsm_db *pDb, lsm_cursor **ppCsr){ int rc; /* Return code */ MultiCursor *pCsr = 0; /* New cursor object */ /* Open a read transaction if one is not already open. */ assert_db_state(pDb); if( pDb->pShmhdr==0 ){ assert( pDb->bReadonly ); rc = lsmBeginRoTrans(pDb); }else{ rc = lsmBeginReadTrans(pDb); } /* Allocate the multi-cursor. */ if( rc==LSM_OK ) rc = lsmMCursorNew(pDb, &pCsr); /* If an error has occured, set the output to NULL and delete any partially ** allocated cursor. If this means there are no open cursors, release the ** client snapshot. */ if( rc!=LSM_OK ){ lsmMCursorClose(pCsr); dbReleaseClientSnapshot(pDb); } assert_db_state(pDb); *ppCsr = (lsm_cursor *)pCsr; return rc; } /* ** Close a cursor opened using lsm_csr_open(). */ int lsm_csr_close(lsm_cursor *p){ if( p ){ lsm_db *pDb = lsmMCursorDb((MultiCursor *)p); assert_db_state(pDb); lsmMCursorClose((MultiCursor *)p); dbReleaseClientSnapshot(pDb); assert_db_state(pDb); } return LSM_OK; } /* |
︙ | ︙ | |||
953 954 955 956 957 958 959 960 961 962 | if( pDb->nTransOpen==0 ){ lsmFinishWriteTrans(pDb, 0); } dbReleaseClientSnapshot(pDb); } return rc; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 929 930 931 932 933 934 935 936 937 938 939 | if( pDb->nTransOpen==0 ){ lsmFinishWriteTrans(pDb, 0); } dbReleaseClientSnapshot(pDb); } return rc; } |
Changes to src/lsm_shared.c.
︙ | ︙ | |||
314 315 316 317 318 319 320 | } } } } if( pDb->iRwclient>=0 ){ lsmShmLock(pDb, LSM_LOCK_RWCLIENT(pDb->iRwclient), LSM_LOCK_UNLOCK, 0); | < | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | } } } } if( pDb->iRwclient>=0 ){ lsmShmLock(pDb, LSM_LOCK_RWCLIENT(pDb->iRwclient), LSM_LOCK_UNLOCK, 0); } lsmShmLock(pDb, LSM_LOCK_DMS2, LSM_LOCK_UNLOCK, 0); lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0); } pDb->pShmhdr = 0; } |
︙ | ︙ | |||
398 399 400 401 402 403 404 | if( rc2!=LSM_BUSY ){ rc = rc2; break; } } } lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0); | < | 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | if( rc2!=LSM_BUSY ){ rc = rc2; break; } } } lsmShmLock(pDb, LSM_LOCK_DMS1, LSM_LOCK_UNLOCK, 0); return rc; } static int dbOpenSharedFd(lsm_env *pEnv, Database *p, int bRoOk){ int rc; rc = lsmEnvOpen(pEnv, p->zName, 0, &p->pFile); |
︙ | ︙ | |||
1147 1148 1149 1150 1151 1152 1153 | rc = lsmTreeLoadHeader(pDb, &iTreehdr); /* Load the database snapshot */ if( rc==LSM_OK ){ if( lsmCheckpointClientCacheOk(pDb)==0 ){ lsmFreeSnapshot(pDb->pEnv, pDb->pClient); pDb->pClient = 0; | < < | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 | rc = lsmTreeLoadHeader(pDb, &iTreehdr); /* Load the database snapshot */ if( rc==LSM_OK ){ if( lsmCheckpointClientCacheOk(pDb)==0 ){ lsmFreeSnapshot(pDb->pEnv, pDb->pClient); pDb->pClient = 0; rc = lsmCheckpointLoad(pDb, &iSnap); }else{ iSnap = 1; } } /* Take a read-lock on the tree and snapshot just loaded. Then check |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | dbReleaseReadlock(pDb); } /* ** Open a write transaction. */ int lsmBeginWriteTrans(lsm_db *pDb){ | | < | < | 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 | dbReleaseReadlock(pDb); } /* ** Open a write transaction. */ int lsmBeginWriteTrans(lsm_db *pDb){ int rc; /* Return code */ ShmHeader *pShm = pDb->pShmhdr; /* Shared memory header */ assert( pDb->nTransOpen==0 ); assert( pDb->bDiscardOld==0 ); assert( pDb->bReadonly==0 ); /* If there is no read-transaction open, open one now. */ rc = lsmBeginReadTrans(pDb); /* Attempt to take the WRITER lock */ if( rc==LSM_OK ){ rc = lsmShmLock(pDb, LSM_LOCK_WRITER, LSM_LOCK_EXCL, 0); } /* If the previous writer failed mid-transaction, run emergency rollback. */ |
︙ | ︙ | |||
1819 1820 1821 1822 1823 1824 1825 | case LSM_LOCK_SHARED: if( nExcl ){ rc = LSM_BUSY; }else{ if( nShared==0 ){ rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_SHARED); } | < | | < < | < | 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 | case LSM_LOCK_SHARED: if( nExcl ){ rc = LSM_BUSY; }else{ if( nShared==0 ){ rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_SHARED); } db->mLock |= ms; db->mLock &= ~me; } break; default: assert( eOp==LSM_LOCK_EXCL ); if( nExcl || nShared ){ rc = LSM_BUSY; }else{ rc = lockSharedFile(db->pEnv, p, iLock, LSM_LOCK_EXCL); db->mLock |= (me|ms); } break; } lsmMutexLeave(db->pEnv, p->pClientMutex); } |
︙ | ︙ |
Changes to src/lsm_sorted.c.
︙ | ︙ | |||
2241 2242 2243 2244 2245 2246 2247 | pCsr->aTree = 0; pCsr->pSystemVal = 0; pCsr->apTreeCsr[0] = 0; pCsr->apTreeCsr[1] = 0; pCsr->pBtCsr = 0; } | < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < | | | | | | | < | 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 | pCsr->aTree = 0; pCsr->pSystemVal = 0; pCsr->apTreeCsr[0] = 0; pCsr->apTreeCsr[1] = 0; pCsr->pBtCsr = 0; } void lsmMCursorClose(MultiCursor *pCsr){ if( pCsr ){ lsm_db *pDb = pCsr->pDb; MultiCursor **pp; /* Iterator variable */ /* The cursor may or may not be currently part of the linked list ** starting at lsm_db.pCsr. If it is, extract it. */ for(pp=&pDb->pCsr; *pp; pp=&((*pp)->pNext)){ if( *pp==pCsr ){ *pp = pCsr->pNext; break; } } /* Free the allocation used to cache the current key, if any. */ sortedBlobFree(&pCsr->key); sortedBlobFree(&pCsr->val); /* Free the component cursors */ mcursorFreeComponents(pCsr); /* Free the cursor structure itself */ lsmFree(pDb->pEnv, pCsr); } } #define TREE_NONE 0 #define TREE_OLD 1 #define TREE_BOTH 2 |
︙ | ︙ | |||
2458 2459 2460 2461 2462 2463 2464 | pCsr->flags |= CURSOR_FLUSH_FREELIST; pCsr->pSystemVal = lsmMallocRc(pCsr->pDb->pEnv, 4 + 8, &rc); return rc; } /* ** Allocate and return a new database cursor. | < < < < < < < < < < < < < < < < < < < < < < < < | | | < | | 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 | pCsr->flags |= CURSOR_FLUSH_FREELIST; pCsr->pSystemVal = lsmMallocRc(pCsr->pDb->pEnv, 4 + 8, &rc); return rc; } /* ** Allocate and return a new database cursor. */ int lsmMCursorNew( lsm_db *pDb, /* Database handle */ MultiCursor **ppCsr /* OUT: Allocated cursor */ ){ MultiCursor *pCsr = 0; int rc = LSM_OK; pCsr = multiCursorNew(pDb, &rc); if( rc==LSM_OK ) rc = multiCursorInit(pCsr, pDb->pClient); if( rc!=LSM_OK ){ lsmMCursorClose(pCsr); pCsr = 0; } assert( (rc==LSM_OK)==(pCsr!=0) ); *ppCsr = pCsr; return rc; } |
︙ | ︙ | |||
2614 2615 2616 2617 2618 2619 2620 | iSnap = (i64)lsmGetU64((u8 *)pVal); if( x(pCtx, iBlk, iSnap) ) break; rc = multiCursorAdvance(pCsr, !bReverse); } } } | | | 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 | iSnap = (i64)lsmGetU64((u8 *)pVal); if( x(pCtx, iBlk, iSnap) ) break; rc = multiCursorAdvance(pCsr, !bReverse); } } } lsmMCursorClose(pCsr); if( pSnap!=pDb->pWorker ){ lsmFreeSnapshot(pDb->pEnv, pSnap); } return rc; } |
︙ | ︙ | |||
2657 2658 2659 2660 2661 2662 2663 | if( *ppVal ){ memcpy(*ppVal, pVal, nVal); *pnVal = nVal; } } } | | | 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 | if( *ppVal ){ memcpy(*ppVal, pVal, nVal); *pnVal = nVal; } } } lsmMCursorClose(pCsr); } return rc; } static int multiCursorAllocTree(MultiCursor *pCsr){ int rc = LSM_OK; |
︙ | ︙ | |||
4092 4093 4094 4095 4096 4097 4098 | }else{ btreeCursorSplitkey(pCsr->pBtCsr, &pMerge->splitkey); } pMerge->iOutputOff = -1; } | | | 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 | }else{ btreeCursorSplitkey(pCsr->pBtCsr, &pMerge->splitkey); } pMerge->iOutputOff = -1; } lsmMCursorClose(pCsr); /* Persist and release the output page. */ if( rc==LSM_OK ) rc = mergeWorkerPersistAndRelease(pMW); if( rc==LSM_OK ) rc = mergeWorkerBtreeIndirect(pMW); if( rc==LSM_OK ) rc = mergeWorkerFinishHierarchy(pMW); if( rc==LSM_OK ) rc = mergeWorkerAddPadding(pMW); lsmFsFlushWaiting(pMW->pDb->pFS, &rc); |
︙ | ︙ | |||
4346 4347 4348 4349 4350 4351 4352 | ** markers present in the in-memory tree. */ if( pNext==0 ){ multiCursorIgnoreDelete(pCsr); } } if( rc!=LSM_OK ){ | | | 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 | ** markers present in the in-memory tree. */ if( pNext==0 ){ multiCursorIgnoreDelete(pCsr); } } if( rc!=LSM_OK ){ lsmMCursorClose(pCsr); }else{ Pgno iLeftPtr = 0; Merge merge; /* Merge object used to create new level */ MergeWorker mergeworker; /* MergeWorker object for the same purpose */ memset(&merge, 0, sizeof(Merge)); memset(&mergeworker, 0, sizeof(MergeWorker)); |
︙ | ︙ | |||
5309 5310 5311 5312 5313 5314 5315 | int nWrite = 0; /* Number of pages written */ /* This function may not be called if pDb has an open read or write ** transaction. Return LSM_MISUSE if an application attempts this. */ if( pDb->nTransOpen || pDb->pCsr ) return LSM_MISUSE_BKPT; if( nMerge<=0 ) nMerge = pDb->nMerge; | < < | 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 | int nWrite = 0; /* Number of pages written */ /* This function may not be called if pDb has an open read or write ** transaction. Return LSM_MISUSE if an application attempts this. */ if( pDb->nTransOpen || pDb->pCsr ) return LSM_MISUSE_BKPT; if( nMerge<=0 ) nMerge = pDb->nMerge; /* Convert from KB to pages */ nPgsz = lsmFsPageSize(pDb->pFS); if( nKB>=0 ){ nPage = ((i64)nKB * 1024 + nPgsz - 1) / nPgsz; }else{ nPage = -1; } |
︙ | ︙ | |||
5398 5399 5400 5401 5402 5403 5404 | nUnit, nDepth, nRemaining); #endif assert( nRemaining>=0 ); rc = doLsmWork(pDb, pDb->nMerge, nRemaining, 0); if( rc==LSM_BUSY ) rc = LSM_OK; if( bRestore && pDb->pCsr ){ | < | 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 | nUnit, nDepth, nRemaining); #endif assert( nRemaining>=0 ); rc = doLsmWork(pDb, pDb->nMerge, nRemaining, 0); if( rc==LSM_BUSY ) rc = LSM_OK; if( bRestore && pDb->pCsr ){ lsmFreeSnapshot(pDb->pEnv, pDb->pClient); pDb->pClient = 0; rc = lsmCheckpointLoad(pDb, 0); if( rc==LSM_OK ){ rc = lsmCheckpointDeserialize(pDb, 0, pDb->aSnapshot, &pDb->pClient); } if( rc==LSM_OK ){ |
︙ | ︙ | |||
5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 | int bKeys, /* Output the keys from each segment */ int bVals, /* Output the values from each segment */ const char *zWhy /* Caption to print near top of dump */ ){ Snapshot *pDump = pSnap; Level *pTopLevel; char *zFree = 0; assert( pSnap ); pTopLevel = lsmDbSnapshotLevel(pDump); if( pDb->xLog && pTopLevel ){ static int nCall = 0; Level *pLevel; int iLevel = 0; | > | 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 | int bKeys, /* Output the keys from each segment */ int bVals, /* Output the values from each segment */ const char *zWhy /* Caption to print near top of dump */ ){ Snapshot *pDump = pSnap; Level *pTopLevel; char *zFree = 0; assert( pSnap ); pTopLevel = lsmDbSnapshotLevel(pDump); if( pDb->xLog && pTopLevel ){ static int nCall = 0; Level *pLevel; int iLevel = 0; |
︙ | ︙ |
Changes to src/lsm_tree.c.
︙ | ︙ | |||
264 265 266 267 268 269 270 | */ static void intArrayTruncate(IntArray *p, int nVal){ p->nArray = nVal; } /* End of IntArray methods. ***********************************************************************/ | < < < < < < < < < < | | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 | */ static void intArrayTruncate(IntArray *p, int nVal){ p->nArray = nVal; } /* End of IntArray methods. ***********************************************************************/ /* ** The pointer passed as the first argument points to an interior node, ** not a leaf. This function returns the offset of the iCell'th child ** sub-tree of the node. */ static u32 getChildPtr(TreeNode *p, int iVersion, int iCell){ assert( iCell>=0 && iCell<=array_size(p->aiChildPtr) ); if( p->iV2 && p->iV2<=iVersion && iCell==p->iV2Child ) return p->iV2Ptr; return p->aiChildPtr[iCell]; } /* ** Given an offset within the *-shm file, return the associated chunk number. */ static int treeOffsetToChunk(u32 iOff){ assert( LSM_SHM_CHUNK_SIZE==(1<<15) ); return (int)(iOff>>15); } /* ** Return a pointer to the mapped memory location associated with *-shm ** file offset iPtr. */ static void *treeShmptr(lsm_db *pDb, u32 iPtr){ assert( (iPtr>>15)<pDb->nShm ); assert( pDb->apShm[iPtr>>15] ); return iPtr?(&((u8*)(pDb->apShm[iPtr>>15]))[iPtr & (LSM_SHM_CHUNK_SIZE-1)]):0; } static ShmChunk * treeShmChunk(lsm_db *pDb, int iChunk){ return (ShmChunk *)(pDb->apShm[iChunk]); } static ShmChunk * treeShmChunkRc(lsm_db *pDb, int iChunk, int *pRc){ |
︙ | ︙ | |||
571 572 573 574 575 576 577 | } /* ** Return a pointer to the mapping of the TreeKey object that the cursor ** is pointing to. */ static TreeKey *csrGetKey(TreeCursor *pCsr, TreeBlob *pBlob, int *pRc){ | | < | < < < < | < | > | 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 | } /* ** Return a pointer to the mapping of the TreeKey object that the cursor ** is pointing to. */ static TreeKey *csrGetKey(TreeCursor *pCsr, TreeBlob *pBlob, int *pRc){ TreeKey *pRet = (TreeKey *)treeShmkey(pCsr->pDb, pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]], TKV_LOADVAL, pBlob, pRc ); assert( pRet==0 || assertFlagsOk(pRet->flags) ); return pRet; } /* ** Save the current position of tree cursor pCsr. */ int lsmTreeCursorSave(TreeCursor *pCsr){ |
︙ | ︙ | |||
732 733 734 735 736 737 738 | u32 *piPtr, void *pKey, int nKey, /* Key data */ void *pVal, int nVal, /* Value data (or nVal<0 for delete) */ int *pRc ){ TreeKey *p; u32 iPtr; | < | 717 718 719 720 721 722 723 724 725 726 727 728 729 730 | u32 *piPtr, void *pKey, int nKey, /* Key data */ void *pVal, int nVal, /* Value data (or nVal<0 for delete) */ int *pRc ){ TreeKey *p; u32 iPtr; int nRem; u8 *a; int n; /* Allocate space for the TreeKey structure itself */ *piPtr = iPtr = treeShmalloc(pDb, 1, sizeof(TreeKey), pRc); p = treeShmptr(pDb, iPtr); |
︙ | ︙ | |||
767 768 769 770 771 772 773 | nRem -= nAlloc; } a = pVal; n = nRem = nVal; pVal = 0; } | < < < < < < < | 751 752 753 754 755 756 757 758 759 760 761 762 763 764 | nRem -= nAlloc; } a = pVal; n = nRem = nVal; pVal = 0; } if( *pRc ) return 0; #if 0 printf("store: %d %s\n", (int)iPtr, (char *)pKey); #endif return p; } |
︙ | ︙ | |||
1459 1460 1461 1462 1463 1464 1465 | int res; /* Result of seek operation on csr */ assert( nVal>=0 || pVal==0 ); assert_tree_looks_ok(LSM_OK, pTree); assert( flags==LSM_INSERT || flags==LSM_POINT_DELETE || flags==LSM_START_DELETE || flags==LSM_END_DELETE ); | < | 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 | int res; /* Result of seek operation on csr */ assert( nVal>=0 || pVal==0 ); assert_tree_looks_ok(LSM_OK, pTree); assert( flags==LSM_INSERT || flags==LSM_POINT_DELETE || flags==LSM_START_DELETE || flags==LSM_END_DELETE ); #if 0 dump_tree_contents(pDb, "before"); #endif if( p->iRoot ){ TreeKey *pRes; /* Key at end of seek operation */ treeCursorInit(pDb, 0, &csr); |
︙ | ︙ | |||
1517 1518 1519 1520 1521 1522 1523 | }else{ memset(&csr, 0, sizeof(TreeCursor)); } /* Allocate and populate a new key-value pair structure */ pTreeKey = newTreeKey(pDb, &iTreeKey, pKey, nKey, pVal, nVal, &rc); if( rc!=LSM_OK ) return rc; | < | | 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 | }else{ memset(&csr, 0, sizeof(TreeCursor)); } /* Allocate and populate a new key-value pair structure */ pTreeKey = newTreeKey(pDb, &iTreeKey, pKey, nKey, pVal, nVal, &rc); if( rc!=LSM_OK ) return rc; pTreeKey->flags = flags; if( p->iRoot==0 ){ /* The tree is completely empty. Add a new root node and install ** (pKey/nKey) as the middle entry. Even though it is a leaf at the ** moment, use newTreeNode() to allocate the node (i.e. allocate enough ** space for the fields used by interior nodes). This is because the ** treeInsert() routine may convert this node to an interior node. */ |
︙ | ︙ | |||
1804 1805 1806 1807 1808 1809 1810 | ){ int rc = LSM_OK; int bDone = 0; TreeRoot *p = &db->treehdr.root; TreeBlob blob = {0, 0}; /* The range must be sensible - that (key1 < key2). */ | | | 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 | ){ int rc = LSM_OK; int bDone = 0; TreeRoot *p = &db->treehdr.root; TreeBlob blob = {0, 0}; /* The range must be sensible - that (key1 < key2). */ assert( db->xCmp(pKey1, nKey1, pKey2, nKey2)<0 ); assert( assert_delete_ranges_match(db) ); #if 0 static int nCall = 0; printf("\n"); nCall++; printf("%d delete %s .. %s\n", nCall, (char *)pKey1, (char *)pKey2); |
︙ | ︙ | |||
1836 1837 1838 1839 1840 1841 1842 | /* If there is no such entry, or if it is greater than pKey2, then the ** tree now contains no keys in the range being deleted. In this case ** break out of the loop. */ bDone = 1; if( lsmTreeCursorValid(&csr) ){ lsmTreeCursorKey(&csr, 0, &pDel, &nDel); | | | 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 | /* If there is no such entry, or if it is greater than pKey2, then the ** tree now contains no keys in the range being deleted. In this case ** break out of the loop. */ bDone = 1; if( lsmTreeCursorValid(&csr) ){ lsmTreeCursorKey(&csr, 0, &pDel, &nDel); if( db->xCmp(pDel, nDel, pKey2, nKey2)<0 ) bDone = 0; } if( bDone==0 ){ if( csr.iNode==(p->nHeight-1) ){ /* The element to delete already lies on a leaf node */ rc = treeDeleteEntry(db, &csr, 0); }else{ |
︙ | ︙ | |||
1953 1954 1955 1956 1957 1958 1959 | static int treeCsrCompare(TreeCursor *pCsr, void *pKey, int nKey){ TreeKey *p; int cmp = 0; int rc = LSM_OK; assert( pCsr->iNode>=0 ); p = csrGetKey(pCsr, &pCsr->blob, &rc); if( p ){ | | | 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 | static int treeCsrCompare(TreeCursor *pCsr, void *pKey, int nKey){ TreeKey *p; int cmp = 0; int rc = LSM_OK; assert( pCsr->iNode>=0 ); p = csrGetKey(pCsr, &pCsr->blob, &rc); if( p ){ cmp = pCsr->pDb->xCmp(TKV_KEY(p), p->nKey, pKey, nKey); } return cmp; } #endif /* |
︙ | ︙ | |||
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 | ** ** * If the tree is empty, leave the cursor at EOF and set *pRes to -1. */ int lsmTreeCursorSeek(TreeCursor *pCsr, void *pKey, int nKey, int *pRes){ int rc = LSM_OK; /* Return code */ lsm_db *pDb = pCsr->pDb; TreeRoot *pRoot = pCsr->pRoot; u32 iNodePtr; /* Location of current node in search */ /* Discard any saved position data */ treeCursorRestore(pCsr, 0); iNodePtr = pRoot->iRoot; if( iNodePtr==0 ){ /* Either an error occurred or the tree is completely empty. */ assert( rc!=LSM_OK || pRoot->iRoot==0 ); *pRes = -1; pCsr->iNode = -1; }else{ TreeBlob b = {0, 0}; int res = 0; /* Result of comparison function */ int iNode = -1; while( iNodePtr ){ TreeNode *pNode; /* Node at location iNodePtr */ int iTest; /* Index of second key to test (0 or 2) */ | > > < | < < | | < | < < < < | | > > | | < < | 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 | ** ** * If the tree is empty, leave the cursor at EOF and set *pRes to -1. */ int lsmTreeCursorSeek(TreeCursor *pCsr, void *pKey, int nKey, int *pRes){ int rc = LSM_OK; /* Return code */ lsm_db *pDb = pCsr->pDb; TreeRoot *pRoot = pCsr->pRoot; int (*xCmp)(void *, int, void *, int) = pDb->xCmp; u32 iNodePtr; /* Location of current node in search */ /* Discard any saved position data */ treeCursorRestore(pCsr, 0); iNodePtr = pRoot->iRoot; if( iNodePtr==0 ){ /* Either an error occurred or the tree is completely empty. */ assert( rc!=LSM_OK || pRoot->iRoot==0 ); *pRes = -1; pCsr->iNode = -1; }else{ TreeBlob b = {0, 0}; int res = 0; /* Result of comparison function */ int iNode = -1; while( iNodePtr ){ TreeNode *pNode; /* Node at location iNodePtr */ int iTest; /* Index of second key to test (0 or 2) */ TreeKey *pTreeKey; /* Key to compare against */ pNode = (TreeNode *)treeShmptr(pDb, iNodePtr); iNode++; pCsr->apTreeNode[iNode] = pNode; /* Compare (pKey/nKey) with the key in the middle slot of B-tree node ** pNode. The middle slot is never empty. If the comparison is a match, ** then the search is finished. Break out of the loop. */ pTreeKey = treeShmkey(pDb, pNode->aiKeyPtr[1], TKV_LOADKEY, &b, &rc); if( rc!=LSM_OK ) break; res = xCmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey); if( res==0 ){ pCsr->aiCell[iNode] = 1; break; } /* Based on the results of the previous comparison, compare (pKey/nKey) ** to either the left or right key of the B-tree node, if such a key ** exists. */ iTest = (res>0 ? 0 : 2); pTreeKey = treeShmkey(pDb, pNode->aiKeyPtr[iTest], TKV_LOADKEY, &b, &rc); if( rc ) break; if( pTreeKey==0 ){ iTest = 1; }else{ res = xCmp((void *)&pTreeKey[1], pTreeKey->nKey, pKey, nKey); if( res==0 ){ pCsr->aiCell[iNode] = iTest; break; } } if( iNode<(pRoot->nHeight-1) ){ iNodePtr = getChildPtr(pNode, pRoot->iTransId, iTest + (res<0)); }else{ iNodePtr = 0; } |
︙ | ︙ | |||
2119 2120 2121 2122 2123 2124 2125 | if( iCell<3 && pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[iCell] ) break; } } #ifndef NDEBUG if( pCsr->iNode>=0 ){ TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc); | | | 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 | if( iCell<3 && pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[iCell] ) break; } } #ifndef NDEBUG if( pCsr->iNode>=0 ){ TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc); assert( rc || pDb->xCmp(TKV_KEY(pK2),pK2->nKey,TKV_KEY(pK1),pK1->nKey)>=0 ); } tblobFree(pDb, &key1); #endif return rc; } |
︙ | ︙ | |||
2187 2188 2189 2190 2191 2192 2193 | }while( (--pCsr->iNode)>=0 ); pCsr->aiCell[pCsr->iNode] = iCell; } #ifndef NDEBUG if( pCsr->iNode>=0 ){ TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc); | | | 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 | }while( (--pCsr->iNode)>=0 ); pCsr->aiCell[pCsr->iNode] = iCell; } #ifndef NDEBUG if( pCsr->iNode>=0 ){ TreeKey *pK2 = csrGetKey(pCsr, &pCsr->blob, &rc); assert( rc || pDb->xCmp(TKV_KEY(pK2), pK2->nKey, TKV_KEY(pK1), pK1->nKey)<0 ); } tblobFree(pDb, &key1); #endif return rc; } |
︙ | ︙ | |||
2241 2242 2243 2244 2245 2246 2247 | return rc; } int lsmTreeCursorFlags(TreeCursor *pCsr){ int flags = 0; if( pCsr && pCsr->iNode>=0 ){ int rc = LSM_OK; | | | | 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 | return rc; } int lsmTreeCursorFlags(TreeCursor *pCsr){ int flags = 0; if( pCsr && pCsr->iNode>=0 ){ int rc = LSM_OK; TreeKey *pKey = (TreeKey *)treeShmptr(pCsr->pDb, pCsr->apTreeNode[pCsr->iNode]->aiKeyPtr[pCsr->aiCell[pCsr->iNode]] ); assert( rc==LSM_OK ); flags = pKey->flags; } return flags; } int lsmTreeCursorKey(TreeCursor *pCsr, int *pFlags, void **ppKey, int *pnKey){ TreeKey *pTreeKey; int rc = LSM_OK; |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
132 133 134 135 136 137 138 139 140 141 142 143 144 145 | ** indicate success or failure. */ static int sqlite4InitOne(sqlite4 *db, int iDb, char **pzErrMsg){ int rc; Table *pTab; Db *pDb; char const *azArg[4]; InitData initData; char const *zMasterSchema; char const *zMasterName; int openedTransaction = 0; /* ** The master database table has a structure like this | > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | ** indicate success or failure. */ static int sqlite4InitOne(sqlite4 *db, int iDb, char **pzErrMsg){ int rc; Table *pTab; Db *pDb; char const *azArg[4]; unsigned int meta[5]; InitData initData; char const *zMasterSchema; char const *zMasterName; int openedTransaction = 0; /* ** The master database table has a structure like this |
︙ | ︙ | |||
219 220 221 222 223 224 225 | if( rc!=SQLITE4_OK ){ sqlite4SetString(pzErrMsg, db, "%s", sqlite4ErrStr(rc)); goto initone_error_out; } openedTransaction = 1; } | | > > > > > > > > > > > > > > > > | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | if( rc!=SQLITE4_OK ){ sqlite4SetString(pzErrMsg, db, "%s", sqlite4ErrStr(rc)); goto initone_error_out; } openedTransaction = 1; } /* Get the database meta information. ** ** Meta values are as follows: ** meta[0] Schema cookie. Changes with each schema change. ** meta[1] unused ** meta[2] unused ** meta[3] unused ** meta[4] unused ** meta[5] unused ** meta[6] unused ** meta[7] unused ** meta[8] unused ** meta[9] unused ** ** Note: The #defined SQLITE4_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ sqlite4KVStoreGetMeta(pDb->pKV, 0, ArraySize(meta), meta); pDb->pSchema->schema_cookie = meta[0]; /* Read the schema information out of the schema tables */ assert( db->init.busy ); { char *zSql; zSql = sqlite4MPrintf(db, |
︙ | ︙ | |||
381 382 383 384 385 386 387 | if( rc!=SQLITE4_OK ) return; openedTransaction = 1; } /* Read the schema cookie from the database. If it does not match the ** value stored as part of the in-memory schema representation, ** set Parse.rc to SQLITE4_SCHEMA. */ | | | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 | if( rc!=SQLITE4_OK ) return; openedTransaction = 1; } /* Read the schema cookie from the database. If it does not match the ** value stored as part of the in-memory schema representation, ** set Parse.rc to SQLITE4_SCHEMA. */ sqlite4KVStoreGetMeta(pKV, 0, 1, (u32 *)&cookie); if( cookie!=db->aDb[iDb].pSchema->schema_cookie ){ sqlite4ResetInternalSchema(db, iDb); pParse->rc = SQLITE4_SCHEMA; } /* Close the transaction, if one was opened. */ if( openedTransaction ){ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 | ** need to be reinitialized each time the statement is run.</dd> ** </dl> */ #define SQLITE4_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE4_STMTSTATUS_SORT 2 #define SQLITE4_STMTSTATUS_AUTOINDEX 3 /* ** CAPIREF: String Comparison ** ** ^The [sqlite4_strnicmp()] API allows applications and extensions to ** compare the contents of two buffers containing UTF-8 strings in a ** case-independent fashion, using the same definition of case independence | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 | ** need to be reinitialized each time the statement is run.</dd> ** </dl> */ #define SQLITE4_STMTSTATUS_FULLSCAN_STEP 1 #define SQLITE4_STMTSTATUS_SORT 2 #define SQLITE4_STMTSTATUS_AUTOINDEX 3 /* ** CAPIREF: Unlock Notification ** ** ^When running in shared-cache mode, a database operation may fail with ** an [SQLITE4_LOCKED] error if the required locks on the shared-cache or ** individual tables within the shared-cache cannot be obtained. See ** [SQLite Shared-Cache Mode] for a description of shared-cache locking. ** ^This API may be used to register a callback that SQLite will invoke ** when the connection currently holding the required lock relinquishes it. ** ^This API is only available if the library was compiled with the ** [SQLITE4_ENABLE_UNLOCK_NOTIFY] C-preprocessor symbol defined. ** ** See Also: [Using the SQLite Unlock Notification Feature]. ** ** ^Shared-cache locks are released when a database connection concludes ** its current transaction, either by committing it or rolling it back. ** ** ^When a connection (known as the blocked connection) fails to obtain a ** shared-cache lock and SQLITE4_LOCKED is returned to the caller, the ** identity of the database connection (the blocking connection) that ** has locked the required resource is stored internally. ^After an ** application receives an SQLITE4_LOCKED error, it may call the ** sqlite4_unlock_notify() method with the blocked connection handle as ** the first argument to register for a callback that will be invoked ** when the blocking connections current transaction is concluded. ^The ** callback is invoked from within the [sqlite4_step] or [sqlite4_close] ** call that concludes the blocking connections transaction. ** ** ^(If sqlite4_unlock_notify() is called in a multi-threaded application, ** there is a chance that the blocking connection will have already ** concluded its transaction by the time sqlite4_unlock_notify() is invoked. ** If this happens, then the specified callback is invoked immediately, ** from within the call to sqlite4_unlock_notify().)^ ** ** ^If the blocked connection is attempting to obtain a write-lock on a ** shared-cache table, and more than one other connection currently holds ** a read-lock on the same table, then SQLite arbitrarily selects one of ** the other connections to use as the blocking connection. ** ** ^(There may be at most one unlock-notify callback registered by a ** blocked connection. If sqlite4_unlock_notify() is called when the ** blocked connection already has a registered unlock-notify callback, ** then the new callback replaces the old.)^ ^If sqlite4_unlock_notify() is ** called with a NULL pointer as its second argument, then any existing ** unlock-notify callback is canceled. ^The blocked connections ** unlock-notify callback may also be canceled by closing the blocked ** connection using [sqlite4_close()]. ** ** The unlock-notify callback is not reentrant. If an application invokes ** any sqlite4_xxx API functions from within an unlock-notify callback, a ** crash or deadlock may be the result. ** ** ^Unless deadlock is detected (see below), sqlite4_unlock_notify() always ** returns SQLITE4_OK. ** ** <b>Callback Invocation Details</b> ** ** When an unlock-notify callback is registered, the application provides a ** single void* pointer that is passed to the callback when it is invoked. ** However, the signature of the callback function allows SQLite to pass ** it an array of void* context pointers. The first argument passed to ** an unlock-notify callback is a pointer to an array of void* pointers, ** and the second is the number of entries in the array. ** ** When a blocking connections transaction is concluded, there may be ** more than one blocked connection that has registered for an unlock-notify ** callback. ^If two or more such blocked connections have specified the ** same callback function, then instead of invoking the callback function ** multiple times, it is invoked once with the set of void* context pointers ** specified by the blocked connections bundled together into an array. ** This gives the application an opportunity to prioritize any actions ** related to the set of unblocked database connections. ** ** <b>Deadlock Detection</b> ** ** Assuming that after registering for an unlock-notify callback a ** database waits for the callback to be issued before taking any further ** action (a reasonable assumption), then using this API may cause the ** application to deadlock. For example, if connection X is waiting for ** connection Y's transaction to be concluded, and similarly connection ** Y is waiting on connection X's transaction, then neither connection ** will proceed and the system may remain deadlocked indefinitely. ** ** To avoid this scenario, the sqlite4_unlock_notify() performs deadlock ** detection. ^If a given call to sqlite4_unlock_notify() would put the ** system in a deadlocked state, then SQLITE4_LOCKED is returned and no ** unlock-notify callback is registered. The system is said to be in ** a deadlocked state if connection A has registered for an unlock-notify ** callback on the conclusion of connection B's transaction, and connection ** B has itself registered for an unlock-notify callback when connection ** A's transaction is concluded. ^Indirect deadlock is also detected, so ** the system is also considered to be deadlocked if connection B has ** registered for an unlock-notify callback on the conclusion of connection ** C's transaction, where connection C is waiting on connection A. ^Any ** number of levels of indirection are allowed. ** ** <b>The "DROP TABLE" Exception</b> ** ** When a call to [sqlite4_step()] returns SQLITE4_LOCKED, it is almost ** always appropriate to call sqlite4_unlock_notify(). There is however, ** one exception. When executing a "DROP TABLE" or "DROP INDEX" statement, ** SQLite checks if there are any currently executing SELECT statements ** that belong to the same connection. If there are, SQLITE4_LOCKED is ** returned. In this case there is no "blocking connection", so invoking ** sqlite4_unlock_notify() results in the unlock-notify callback being ** invoked immediately. If the application then re-attempts the "DROP TABLE" ** or "DROP INDEX" query, an infinite loop might be the result. ** ** One way around this problem is to check the extended error code returned ** by an sqlite4_step() call. ^(If there is a blocking connection, then the ** extended error code is set to SQLITE4_LOCKED_SHAREDCACHE. Otherwise, in ** the special "DROP TABLE/INDEX" case, the extended error code is just ** SQLITE4_LOCKED.)^ */ int sqlite4_unlock_notify( sqlite4 *pBlocked, /* Waiting connection */ void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */ void *pNotifyArg /* Argument to pass to xNotify */ ); /* ** CAPIREF: String Comparison ** ** ^The [sqlite4_strnicmp()] API allows applications and extensions to ** compare the contents of two buffers containing UTF-8 strings in a ** case-independent fashion, using the same definition of case independence |
︙ | ︙ | |||
4227 4228 4229 4230 4231 4232 4233 | int (*xBegin)(sqlite4_kvstore*, int); int (*xCommitPhaseOne)(sqlite4_kvstore*, int); int (*xCommitPhaseTwo)(sqlite4_kvstore*, int); int (*xRollback)(sqlite4_kvstore*, int); int (*xRevert)(sqlite4_kvstore*, int); int (*xClose)(sqlite4_kvstore*); int (*xControl)(sqlite4_kvstore*, int, void*); | < < | 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 | int (*xBegin)(sqlite4_kvstore*, int); int (*xCommitPhaseOne)(sqlite4_kvstore*, int); int (*xCommitPhaseTwo)(sqlite4_kvstore*, int); int (*xRollback)(sqlite4_kvstore*, int); int (*xRevert)(sqlite4_kvstore*, int); int (*xClose)(sqlite4_kvstore*); int (*xControl)(sqlite4_kvstore*, int, void*); }; typedef struct sqlite4_kv_methods sqlite4_kv_methods; /* ** CAPI4REF: Key-value storage engine open flags ** ** Allowed values to the flags parameter of an [sqlite4_kvfactory] object. |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
114 115 116 117 118 119 120 121 122 123 124 125 126 127 | char *zTrace; /* The trace callback routine */ char *zProfile; /* The profile callback routine */ char *zProgress; /* The progress callback routine */ char *zAuth; /* The authorization callback routine */ int disableAuth; /* Disable the authorizer if it exists */ char *zNull; /* Text to substitute for an SQL NULL value */ SqlFunc *pFunc; /* List of SQL functions */ SqlCollate *pCollate; /* List of SQL collation functions */ int rc; /* Return code of most recent sqlite4_exec() */ Tcl_Obj *pCollateNeeded; /* Collation needed script */ SqlPreparedStmt *stmtList; /* List of prepared statements*/ SqlPreparedStmt *stmtLast; /* Last statement in the list */ int maxStmt; /* The next maximum number of stmtList */ int nStmt; /* Number of statements in stmtList */ | > | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | char *zTrace; /* The trace callback routine */ char *zProfile; /* The profile callback routine */ char *zProgress; /* The progress callback routine */ char *zAuth; /* The authorization callback routine */ int disableAuth; /* Disable the authorizer if it exists */ char *zNull; /* Text to substitute for an SQL NULL value */ SqlFunc *pFunc; /* List of SQL functions */ Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */ SqlCollate *pCollate; /* List of SQL collation functions */ int rc; /* Return code of most recent sqlite4_exec() */ Tcl_Obj *pCollateNeeded; /* Collation needed script */ SqlPreparedStmt *stmtList; /* List of prepared statements*/ SqlPreparedStmt *stmtLast; /* Last statement in the list */ int maxStmt; /* The next maximum number of stmtList */ int nStmt; /* Number of statements in stmtList */ |
︙ | ︙ | |||
308 309 310 311 312 313 314 315 316 317 318 319 320 321 | Tcl_DStringInit(&str); Tcl_DStringAppend(&str, pDb->zProfile, -1); Tcl_DStringAppendElement(&str, zSql); Tcl_DStringAppendElement(&str, zTm); Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); Tcl_DStringFree(&str); Tcl_ResetResult(pDb->interp); } #endif static void tclCollateNeeded( void *pCtx, sqlite4 *db, int enc, | > > > > > > > > > > > > > > > > > > > > > > > > > > > | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | Tcl_DStringInit(&str); Tcl_DStringAppend(&str, pDb->zProfile, -1); Tcl_DStringAppendElement(&str, zSql); Tcl_DStringAppendElement(&str, zTm); Tcl_Eval(pDb->interp, Tcl_DStringValue(&str)); Tcl_DStringFree(&str); Tcl_ResetResult(pDb->interp); } #endif #if defined(SQLITE4_TEST) && defined(SQLITE4_ENABLE_UNLOCK_NOTIFY) static void setTestUnlockNotifyVars(Tcl_Interp *interp, int iArg, int nArg){ char zBuf[64]; sprintf(zBuf, "%d", iArg); Tcl_SetVar(interp, "sqlite_unlock_notify_arg", zBuf, TCL_GLOBAL_ONLY); sprintf(zBuf, "%d", nArg); Tcl_SetVar(interp, "sqlite_unlock_notify_argcount", zBuf, TCL_GLOBAL_ONLY); } #else # define setTestUnlockNotifyVars(x,y,z) #endif #ifdef SQLITE4_ENABLE_UNLOCK_NOTIFY static void DbUnlockNotify(void **apArg, int nArg){ int i; for(i=0; i<nArg; i++){ const int flags = (TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); SqliteDb *pDb = (SqliteDb *)apArg[i]; setTestUnlockNotifyVars(pDb->interp, i, nArg); assert( pDb->pUnlockNotify); Tcl_EvalObjEx(pDb->interp, pDb->pUnlockNotify, flags); Tcl_DecrRefCount(pDb->pUnlockNotify); pDb->pUnlockNotify = 0; } } #endif static void tclCollateNeeded( void *pCtx, sqlite4 *db, int enc, |
︙ | ︙ | |||
1244 1245 1246 1247 1248 1249 1250 | "authorizer", "cache", "changes", "close", "collate", "collation_needed", "complete", "copy", "enable_load_extension", "errorcode", "eval", "exists", "function", "interrupt", "nullvalue", "onecolumn", "profile", "rekey", "status", "total_changes", | | | | 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 | "authorizer", "cache", "changes", "close", "collate", "collation_needed", "complete", "copy", "enable_load_extension", "errorcode", "eval", "exists", "function", "interrupt", "nullvalue", "onecolumn", "profile", "rekey", "status", "total_changes", "trace", "transaction", "unlock_notify", "version", 0 }; enum DB_enum { DB_AUTHORIZER, DB_CACHE, DB_CHANGES, DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED, DB_COMPLETE, DB_COPY, DB_ENABLE_LOAD_EXTENSION, DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_INTERRUPT, DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE, DB_REKEY, DB_STATUS, DB_TOTAL_CHANGES, DB_TRACE, DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_VERSION }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; |
︙ | ︙ | |||
2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 | Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0); Tcl_NREvalObj(interp, pScript, 0); }else{ rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0)); } break; } /* $db version ** ** Return the version string for this database. */ case DB_VERSION: { Tcl_SetResult(interp, (char *)sqlite4_libversion(), TCL_STATIC); | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 | Tcl_NRAddCallback(interp, DbTransPostCmd, cd, 0, 0, 0); Tcl_NREvalObj(interp, pScript, 0); }else{ rc = DbTransPostCmd(&cd, interp, Tcl_EvalObjEx(interp, pScript, 0)); } break; } /* ** $db unlock_notify ?script? */ case DB_UNLOCK_NOTIFY: { #ifndef SQLITE4_ENABLE_UNLOCK_NOTIFY Tcl_AppendResult(interp, "unlock_notify not available in this build", 0); rc = TCL_ERROR; #else if( objc!=2 && objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); rc = TCL_ERROR; }else{ void (*xNotify)(void **, int) = 0; void *pNotifyArg = 0; if( pDb->pUnlockNotify ){ Tcl_DecrRefCount(pDb->pUnlockNotify); pDb->pUnlockNotify = 0; } if( objc==3 ){ xNotify = DbUnlockNotify; pNotifyArg = (void *)pDb; pDb->pUnlockNotify = objv[2]; Tcl_IncrRefCount(pDb->pUnlockNotify); } if( sqlite4_unlock_notify(pDb->db, xNotify, pNotifyArg) ){ Tcl_AppendResult(interp, sqlite4_errmsg(pDb->db), 0); rc = TCL_ERROR; } } #endif break; } /* $db version ** ** Return the version string for this database. */ case DB_VERSION: { Tcl_SetResult(interp, (char *)sqlite4_libversion(), TCL_STATIC); |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2555 2556 2557 2558 2559 2560 2561 | u32 v; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pDb = &db->aDb[pOp->p1]; pIn3 = &aMem[pOp->p3]; sqlite4VdbeMemIntegerify(pIn3); v = (u32)pIn3->u.i; | | | | 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 | u32 v; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pDb = &db->aDb[pOp->p1]; pIn3 = &aMem[pOp->p3]; sqlite4VdbeMemIntegerify(pIn3); v = (u32)pIn3->u.i; rc = sqlite4KVStorePutMeta(db, pDb->pKV, 0, 1, &v); pDb->pSchema->schema_cookie = (int)pIn3->u.i; db->flags |= SQLITE4_InternChanges; if( pOp->p1==1 ){ /* Invalidate all prepared statements whenever the TEMP database ** schema is changed. Ticket #1644 */ sqlite4ExpirePreparedStatements(db); p->expired = 0; } break; } /* Opcode: VerifyCookie P1 P2 P3 * * ** ** cHECK THe value of global database parameter number 0 (the ** schema version) and make sure it is equal to P2 and that the ** generation counter on the local schema parse equals P3. ** ** P1 is the database number which is 0 for the main database file ** and 1 for the file holding temporary tables and some higher number ** for auxiliary databases. ** |
︙ | ︙ | |||
2593 2594 2595 2596 2597 2598 2599 | unsigned int iMeta; int iGen; KVStore *pKV; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pKV = db->aDb[pOp->p1].pKV; if( pKV ){ | | | 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 | unsigned int iMeta; int iGen; KVStore *pKV; assert( pOp->p1>=0 && pOp->p1<db->nDb ); pKV = db->aDb[pOp->p1].pKV; if( pKV ){ rc = sqlite4KVStoreGetMeta(pKV, 0, 1, &iMeta); if( rc ) break; iGen = db->aDb[pOp->p1].pSchema->iGeneration; }else{ iGen = iMeta = 0; } if( iMeta!=pOp->p2 || iGen!=pOp->p3 ){ sqlite4DbFree(db, p->zErrMsg); |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
4161 4162 4163 4164 4165 4166 4167 | testcase( op==OP_Rewind ); testcase( op==OP_Last ); testcase( op==OP_SeekGt ); testcase( op==OP_SeekGe ); testcase( op==OP_SeekLe ); testcase( op==OP_SeekLt ); sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); | | | 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 | testcase( op==OP_Rewind ); testcase( op==OP_Last ); testcase( op==OP_SeekGt ); testcase( op==OP_SeekGe ); testcase( op==OP_SeekLe ); testcase( op==OP_SeekLt ); sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); if( pIdx->nColumn>nEq ){ sqlite4VdbeChangeP5(v, OPFLAG_PARTIALKEY); } /* Set variable op to the instruction required to determine if the ** cursor is passed the end of the range. If the range is unbounded, ** then set op to OP_Noop. Nothing to do in this case. */ assert( (endEq==0 || endEq==1) ); |
︙ | ︙ |
Changes to test/ckpt1.test.
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 4K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 8K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 16K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 32K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 64K } do_test 3.2 { sqlite4_lsm_work db main -nmerge 1 -npage 1000000 execsql { SELECT count(*) FROM t1 } } {65536} do_test 3.3 { db close sqlite4 db test.db execsql { SELECT count(*) FROM t1 } } {65536} do_test 3.4 { execsql { INSERT INTO t1 VALUES(randstr(100,100), randstr(100,100)) } | > < | | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 4K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 8K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 16K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 32K INSERT INTO t1 SELECT randstr(100,100), randstr(100,100) FROM t1; -- 64K } do_test 3.2 { sqlite4_lsm_flush db main sqlite4_lsm_work db main -nmerge 1 -npage 1000000 execsql { SELECT count(*) FROM t1 } } {65536} do_test 3.3 { db close sqlite4 db test.db execsql { SELECT count(*) FROM t1 } } {65536} do_test 3.4 { execsql { INSERT INTO t1 VALUES(randstr(100,100), randstr(100,100)) } sqlite4_lsm_flush db main sqlite4_lsm_work db main -nmerge 1 -npage 1000000 execsql { SELECT count(*) FROM t1 } } {65537} finish_test |
Changes to test/csr1.test.
︙ | ︙ | |||
73 74 75 76 77 78 79 | # tree to be flushed to disk, # populate_db_2 do_execsql_test 3.1 { BEGIN; INSERT INTO t1 VALUES(10, randstr(910, 910)); } | | | | 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | # tree to be flushed to disk, # populate_db_2 do_execsql_test 3.1 { BEGIN; INSERT INTO t1 VALUES(10, randstr(910, 910)); } do_test 3.2 { sqlite4_lsm_config db main autoflush } [expr 1*1024*1024] do_test 3.3 { sqlite4_lsm_config db main autoflush 4096 } 4096 do_test 3.4 { set res [list] db eval { SELECT a, length(b) AS l FROM t1 } { lappend res $a $l # The following commit will flush the in-memory tree to disk. if {$a == 5} { db eval COMMIT } |
︙ | ︙ |
Changes to test/log3.test.
︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | do_test 1.7 { sqlite4_lsm_config db main safety } {2} do_test 1.8 { sqlite4_lsm_config db main safety 3 } {2} do_test 1.9 { sqlite4_lsm_config db main safety } {2} #------------------------------------------------------------------------- reset_db do_test 2.0 { sqlite4_lsm_config db main safety 2 } {2} do_execsql_test 2.2 { CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); } {} do_filesize_test 2.3 0 1024 do_execsql_test 2.4 { BEGIN; INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); COMMIT; } {} do_filesize_test 2.5 0 2048 | > | | | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | do_test 1.7 { sqlite4_lsm_config db main safety } {2} do_test 1.8 { sqlite4_lsm_config db main safety 3 } {2} do_test 1.9 { sqlite4_lsm_config db main safety } {2} #------------------------------------------------------------------------- reset_db do_test 2.0 { sqlite4_lsm_config db main safety 2 } {2} do_test 2.1 { sqlite4_lsm_config db main log-size 1024 } {1024} do_execsql_test 2.2 { CREATE TABLE t1(a PRIMARY KEY, b); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); } {} do_filesize_test 2.3 0 1024 do_execsql_test 2.4 { BEGIN; INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); COMMIT; } {} do_filesize_test 2.5 0 2048 do_test 2.6 { sqlite4_lsm_flush db main } {} do_execsql_test 2.7 { INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)) } do_test 2.8 { sqlite4_lsm_checkpoint db main } {} do_test 2.9 { sqlite4_lsm_info db main log-structure } {0 0 0 0 2560 3072} for {set i 1} {$i <= 6} {incr i} { do_execsql_test 2.10.$i.1 { INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50)); } do_execsql_test 2.10.$i.2 { SELECT count(*) FROM t1 } [expr 8 + $i] do_recover_test 2.10.$i.3 { SELECT count(*) FROM t1 } [expr 8 + $i] } do_test 2.11 { sqlite4_lsm_info db main log-structure } {2560 3080 0 2216 3584 4608} finish_test |
Changes to test/lsm1.test.
︙ | ︙ | |||
86 87 88 89 90 91 92 93 94 95 96 97 98 99 | db write ccc three db write ddd four db write eee five db write fff six reopen db delete_range a bbb reopen db work 10 } {1} do_contents_test 2.2 { {bbb two} {ccc three} {ddd four} {eee five} {fff six} } #------------------------------------------------------------------------- | > | 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | db write ccc three db write ddd four db write eee five db write fff six reopen db delete_range a bbb reopen breakpoint db work 10 } {1} do_contents_test 2.2 { {bbb two} {ccc three} {ddd four} {eee five} {fff six} } #------------------------------------------------------------------------- |
︙ | ︙ | |||
114 115 116 117 118 119 120 | } {1} do_test 3.2 { db write bx seven reopen db delete_range aaa bx reopen | | | | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | } {1} do_test 3.2 { db write bx seven reopen db delete_range aaa bx reopen db work 10 } {2} do_contents_test 3.3 { {aaa one} {bx seven} {ccc three} {ddd four} {eee five} {fff six} } do_test 3.4 { fetch ddd } four |
︙ | ︙ |
Changes to test/permutations.test.
︙ | ︙ | |||
131 132 133 134 135 136 137 | # lappend ::testsuitelist xxx test_suite "src4" -prefix "" -description { } -files { simple.test simple2.test log3.test | | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | # lappend ::testsuitelist xxx test_suite "src4" -prefix "" -description { } -files { simple.test simple2.test log3.test lsm1.test lsm2.test csr1.test ckpt1.test mc1.test fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test fts5snippet.test aggerror.test |
︙ | ︙ |
Changes to test/simple.test.
︙ | ︙ | |||
83 84 85 86 87 88 89 | do_execsql_test 3.1 { CREATE TABLE t1(k PRIMARY KEY, v UNIQUE) } do_execsql_test 3.2 { SELECT * FROM sqlite_master } { table t1 t1 2 {CREATE TABLE t1(k PRIMARY KEY, v UNIQUE)} | | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | do_execsql_test 3.1 { CREATE TABLE t1(k PRIMARY KEY, v UNIQUE) } do_execsql_test 3.2 { SELECT * FROM sqlite_master } { table t1 t1 2 {CREATE TABLE t1(k PRIMARY KEY, v UNIQUE)} index sqlite_autoindex_t1_2 t1 3 {} } #explain { INSERT INTO t1 VALUES('one', '111') } #execsql { PRAGMA vdbe_trace = 1 } #execsql { PRAGMA kv_trace = 1 } # do_execsql_test 3.3 { INSERT INTO t1 VALUES('one', '111') } {} |
︙ | ︙ | |||
123 124 125 126 127 128 129 | do_execsql_test 5.1 { CREATE TABLE t1(k, v UNIQUE) } do_execsql_test 5.2 { CREATE INDEX i1 ON t1(v) } do_execsql_test 5.3 { SELECT * FROM sqlite_master } { table t1 t1 3 {CREATE TABLE t1(k, v UNIQUE)} | | | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | do_execsql_test 5.1 { CREATE TABLE t1(k, v UNIQUE) } do_execsql_test 5.2 { CREATE INDEX i1 ON t1(v) } do_execsql_test 5.3 { SELECT * FROM sqlite_master } { table t1 t1 3 {CREATE TABLE t1(k, v UNIQUE)} index sqlite_autoindex_t1_1 t1 2 {} index i1 t1 4 {CREATE INDEX i1 ON t1(v)} } do_execsql_test 5.3 { INSERT INTO t1 VALUES('one', '111') } {} do_execsql_test 5.4 { SELECT * FROM t1 } {one 111} do_execsql_test 5.5 { PRAGMA integrity_check } {ok} |
︙ | ︙ | |||
1457 1458 1459 1460 1461 1462 1463 1464 1465 | do_test 74.2 { for {set i 0} {$i<30} {incr i} { db close sqlite4 db test.db execsql "INSERT INTO t1 VALUES('k$i', randstr(500,500))" } } {} db close | > < < < < < < < < < < < < < < < < < < | 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 | do_test 74.2 { for {set i 0} {$i<30} {incr i} { db close sqlite4 db test.db execsql "INSERT INTO t1 VALUES('k$i', randstr(500,500))" } } {} breakpoint db close finish_test |
Changes to test/test_kv2.c.
︙ | ︙ | |||
230 231 232 233 234 235 236 | ** Invoke the xControl() method of the underlying KVStore object. */ static int kvwrapControl(KVStore *pKVStore, int op, void *pArg){ KVWrap *p = (KVWrap *)pKVStore; return p->pReal->pStoreVfunc->xControl(p->pReal, op, pArg); } | < < < < < < < < < < | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | ** Invoke the xControl() method of the underlying KVStore object. */ static int kvwrapControl(KVStore *pKVStore, int op, void *pArg){ KVWrap *p = (KVWrap *)pKVStore; return p->pReal->pStoreVfunc->xControl(p->pReal, op, pArg); } static int newFileStorage( sqlite4_env *pEnv, KVStore **ppKVStore, const char *zName, unsigned openFlags ){ |
︙ | ︙ | |||
267 268 269 270 271 272 273 | kvwrapCloseCursor, kvwrapBegin, kvwrapCommitPhaseOne, kvwrapCommitPhaseTwo, kvwrapRollback, kvwrapRevert, kvwrapClose, | | < < | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | kvwrapCloseCursor, kvwrapBegin, kvwrapCommitPhaseOne, kvwrapCommitPhaseTwo, kvwrapRollback, kvwrapRevert, kvwrapClose, kvwrapControl }; KVWrap *pNew; int rc = SQLITE4_OK; pNew = (KVWrap *)sqlite4_malloc(0, sizeof(KVWrap)); if( pNew==0 ){ |
︙ | ︙ |
Changes to test/test_lsm.c.
︙ | ︙ | |||
143 144 145 146 147 148 149 | } static void testCompressNoopFree(void *pCtx){ } /* ** End of compression routines "noop". *************************************************************************/ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > | > | > > > > > | > | > > > > | | > | < | | < | | > | | 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | } static void testCompressNoopFree(void *pCtx){ } /* ** End of compression routines "noop". *************************************************************************/ /* ** TCLCMD: sqlite4_lsm_config DB DBNAME PARAM ... */ static int test_sqlite4_lsm_config( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ struct Switch { const char *zSwitch; int iVal; } aParam[] = { { "safety", LSM_CONFIG_SAFETY }, { "autoflush", LSM_CONFIG_AUTOFLUSH }, { "mmap", LSM_CONFIG_MMAP }, { "page-size", LSM_CONFIG_PAGE_SIZE }, { "autowork", LSM_CONFIG_AUTOWORK }, { 0, 0 } }; const char *zDb; /* objv[1] as a string */ const char *zName; /* objv[2] as a string */ int iParam; /* Second argument for lsm_config() */ int iConfig = -1; /* Third argument for lsm_config() */ int rc; sqlite4 *db; lsm_db *pLsm; /* Process arguments. Return early if there is a problem. */ if( objc!=4 && objc!=5 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME PARAM ?VALUE?"); return TCL_ERROR; } zDb = Tcl_GetString(objv[1]); zName = Tcl_GetString(objv[2]); rc = Tcl_GetIndexFromObjStruct( interp, objv[3], aParam, sizeof(aParam[0]), "param", 0, &iParam ); if( rc!=TCL_OK ) return rc; if( rc==TCL_OK ){ iParam = aParam[iParam].iVal; rc = getDbPointer(interp, zDb, &db); } if( rc==TCL_OK && objc==5 ){ rc = Tcl_GetIntFromObj(interp, objv[4], &iConfig); } if( rc!=TCL_OK ) return rc; rc = sqlite4_kvstore_control(db, zName, SQLITE4_KVCTRL_LSM_HANDLE, &pLsm); if( rc==SQLITE4_OK ){ rc = lsm_config(pLsm, iParam, &iConfig); Tcl_SetObjResult(interp, Tcl_NewIntObj(iConfig)); } if( rc!=SQLITE4_OK ){ Tcl_SetResult(interp, (char *)sqlite4TestErrorName(rc), TCL_STATIC); return TCL_ERROR; } return TCL_OK; } /* ** TCLCMD: sqlite4_lsm_info DB DBNAME PARAM */ static int test_sqlite4_lsm_info( void * clientData, |
︙ | ︙ | |||
495 496 497 498 499 500 501 502 503 504 505 506 507 508 | Tcl_SetResult(interp, (char *)sqlite4TestErrorName(rc), TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult(interp); return TCL_OK; } typedef struct TclLsmCursor TclLsmCursor; typedef struct TclLsm TclLsm; struct TclLsm { lsm_db *db; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 | Tcl_SetResult(interp, (char *)sqlite4TestErrorName(rc), TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult(interp); return TCL_OK; } /* ** TCLCMD: sqlite4_lsm_flush DB DBNAME */ static int test_sqlite4_lsm_flush( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ const char *zDb; const char *zName; int rc; sqlite4 *db; lsm_db *pLsm; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME"); return TCL_ERROR; } zDb = Tcl_GetString(objv[1]); zName = Tcl_GetString(objv[2]); rc = getDbPointer(interp, zDb, &db); if( rc!=TCL_OK ) return rc; rc = sqlite4_kvstore_control(db, zName, SQLITE4_KVCTRL_LSM_HANDLE, &pLsm); if( rc==SQLITE4_OK ){ int nZero = 0; int nOrig = -1; lsm_config(pLsm, LSM_CONFIG_AUTOFLUSH, &nOrig); lsm_config(pLsm, LSM_CONFIG_AUTOFLUSH, &nZero); rc = lsm_begin(pLsm, 1); if( rc==LSM_OK ) rc = lsm_commit(pLsm, 0); lsm_config(pLsm, LSM_CONFIG_AUTOFLUSH, &nOrig); } if( rc!=SQLITE4_OK ){ Tcl_SetResult(interp, (char *)sqlite4TestErrorName(rc), TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult(interp); return TCL_OK; } static int testConfigureSetCompression( Tcl_Interp *interp, lsm_db *db, Tcl_Obj *pCmp, unsigned int iId ){ struct CompressionScheme { const char *zName; lsm_compress cmp; } aCmp[] = { { "encrypt", { 0, 43, testCompressEncBound, testCompressEncCompress, testCompressEncUncompress, testCompressEncFree } }, { "rle", { 0, 44, testCompressRleBound, testCompressRleCompress, testCompressRleUncompress, testCompressRleFree } }, { "noop", { 0, 45, testCompressNoopBound, testCompressNoopCompress, testCompressNoopUncompress, testCompressNoopFree } }, { 0, {0, 0, 0, 0, 0, 0} } }; int iOpt; int rc; if( interp ){ rc = Tcl_GetIndexFromObjStruct( interp, pCmp, aCmp, sizeof(aCmp[0]), "scheme", 0, &iOpt ); if( rc!=TCL_OK ) return rc; }else{ int nOpt = sizeof(aCmp)/sizeof(aCmp[0]); for(iOpt=0; iOpt<nOpt; iOpt++){ if( iId==aCmp[iOpt].cmp.iId ) break; } if( iOpt==nOpt ) return 0; } rc = lsm_config(db, LSM_CONFIG_SET_COMPRESSION, &aCmp[iOpt].cmp); return rc; } static int testCompressFactory(void *pCtx, lsm_db *db, unsigned int iId){ return testConfigureSetCompression(0, db, 0, iId); } static int testConfigureSetFactory( Tcl_Interp *interp, lsm_db *db, Tcl_Obj *pArg ){ lsm_compress_factory aFactory[2] = { { 0, 0, 0 }, { 0, testCompressFactory, 0 }, }; int bArg = 0; int rc; rc = Tcl_GetBooleanFromObj(interp, pArg, &bArg); if( rc!=TCL_OK ) return rc; assert( bArg==1 || bArg==0 ); rc = lsm_config(db, LSM_CONFIG_SET_COMPRESSION_FACTORY, &aFactory[bArg]); return rc; } static int testConfigureLsm(Tcl_Interp *interp, lsm_db *db, Tcl_Obj *pObj){ struct Lsmconfig { const char *zOpt; int eOpt; } aConfig[] = { { "autoflush", LSM_CONFIG_AUTOFLUSH }, { "page_size", LSM_CONFIG_PAGE_SIZE }, { "block_size", LSM_CONFIG_BLOCK_SIZE }, { "safety", LSM_CONFIG_SAFETY }, { "autowork", LSM_CONFIG_AUTOWORK }, { "autocheckpoint", LSM_CONFIG_AUTOCHECKPOINT }, { "mmap", LSM_CONFIG_MMAP }, { "use_log", LSM_CONFIG_USE_LOG }, { "automerge", LSM_CONFIG_AUTOMERGE }, { "max_freelist", LSM_CONFIG_MAX_FREELIST }, { "multi_proc", LSM_CONFIG_MULTIPLE_PROCESSES }, { "set_compression", LSM_CONFIG_SET_COMPRESSION }, { "set_compression_factory", LSM_CONFIG_SET_COMPRESSION_FACTORY }, { "readonly", LSM_CONFIG_READONLY }, { 0, 0 } }; int nElem; int i; Tcl_Obj **apElem; int rc; rc = Tcl_ListObjGetElements(interp, pObj, &nElem, &apElem); for(i=0; rc==TCL_OK && i<nElem; i+=2){ int iOpt; rc = Tcl_GetIndexFromObjStruct( interp, apElem[i], aConfig, sizeof(aConfig[0]), "option", 0, &iOpt ); if( rc==TCL_OK ){ if( i==(nElem-1) ){ Tcl_ResetResult(interp); Tcl_AppendResult(interp, "option \"", Tcl_GetString(apElem[i]), "\" requires an argument", 0 ); rc = TCL_ERROR; }else{ if( aConfig[iOpt].eOpt==LSM_CONFIG_SET_COMPRESSION ){ rc = testConfigureSetCompression(interp, db, apElem[i+1], 0); } else if( aConfig[iOpt].eOpt==LSM_CONFIG_SET_COMPRESSION_FACTORY ){ rc = testConfigureSetFactory(interp, db, apElem[i+1]); } else { int iVal; rc = Tcl_GetIntFromObj(interp, apElem[i+1], &iVal); if( rc==TCL_OK ){ lsm_config(db, aConfig[iOpt].eOpt, &iVal); } Tcl_SetObjResult(interp, Tcl_NewIntObj(iVal)); } } } } return rc; } typedef struct TclLsmCursor TclLsmCursor; typedef struct TclLsm TclLsm; struct TclLsm { lsm_db *db; |
︙ | ︙ | |||
841 842 843 844 845 846 847 | case 9: assert( 0==strcmp(aCmd[9].zCmd, "flush") ); { rc = lsm_flush(p->db); return test_lsm_error(interp, "lsm_flush", rc); } case 10: assert( 0==strcmp(aCmd[10].zCmd, "config") ); { | < < < | < < | 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 | case 9: assert( 0==strcmp(aCmd[9].zCmd, "flush") ); { rc = lsm_flush(p->db); return test_lsm_error(interp, "lsm_flush", rc); } case 10: assert( 0==strcmp(aCmd[10].zCmd, "config") ); { return testConfigureLsm(interp, p->db, objv[2]); } case 11: assert( 0==strcmp(aCmd[11].zCmd, "checkpoint") ); { rc = lsm_checkpoint(p->db, 0); return test_lsm_error(interp, "lsm_checkpoint", rc); } |
︙ | ︙ | |||
904 905 906 907 908 909 910 | if( rc!=LSM_OK ){ test_lsm_del((void *)p); test_lsm_error(interp, "lsm_new", rc); return TCL_ERROR; } if( objc==4 ){ | < < < < | < | 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | if( rc!=LSM_OK ){ test_lsm_del((void *)p); test_lsm_error(interp, "lsm_new", rc); return TCL_ERROR; } if( objc==4 ){ rc = testConfigureLsm(interp, p->db, objv[3]); if( rc!=TCL_OK ){ test_lsm_del((void *)p); return rc; } } lsm_config_log(p->db, xLog, 0); |
︙ | ︙ | |||
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 | int SqlitetestLsm_Init(Tcl_Interp *interp){ struct SyscallCmd { const char *zName; Tcl_ObjCmdProc *xCmd; } aCmd[] = { { "sqlite4_lsm_work", test_sqlite4_lsm_work }, { "sqlite4_lsm_checkpoint", test_sqlite4_lsm_checkpoint }, { "sqlite4_lsm_info", test_sqlite4_lsm_info }, { "sqlite4_lsm_config", test_sqlite4_lsm_config }, { "lsm_open", test_lsm_open }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xCmd, 0, 0); } return TCL_OK; } | > | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 | int SqlitetestLsm_Init(Tcl_Interp *interp){ struct SyscallCmd { const char *zName; Tcl_ObjCmdProc *xCmd; } aCmd[] = { { "sqlite4_lsm_work", test_sqlite4_lsm_work }, { "sqlite4_lsm_checkpoint", test_sqlite4_lsm_checkpoint }, { "sqlite4_lsm_flush", test_sqlite4_lsm_flush }, { "sqlite4_lsm_info", test_sqlite4_lsm_info }, { "sqlite4_lsm_config", test_sqlite4_lsm_config }, { "lsm_open", test_lsm_open }, }; int i; for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateObjCommand(interp, aCmd[i].zName, aCmd[i].xCmd, 0, 0); } return TCL_OK; } |
Changes to test/tester.tcl.
︙ | ︙ | |||
1562 1563 1564 1565 1566 1567 1568 | # Flush the in-memory tree to disk and merge all runs together into # a single b-tree structure. Because this annihilates all delete keys, # the next rowid allocated for each table with an IPK will be as expected # by SQLite 3 tests. # proc optimize_db {} { #catch { | < | < < < | 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 | # Flush the in-memory tree to disk and merge all runs together into # a single b-tree structure. Because this annihilates all delete keys, # the next rowid allocated for each table with an IPK will be as expected # by SQLite 3 tests. # proc optimize_db {} { #catch { sqlite4_lsm_flush db main sqlite4_lsm_work db main -nmerge 1 -npage 100000 sqlite4_lsm_checkpoint db main #} return "" } |
︙ | ︙ |
Changes to test/tkt-bd484a090c.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | do_test 1.1 { lindex [catchsql { SELECT datetime('now', 'localtime') }] 0 } {0} do_test 1.2 { lindex [catchsql { SELECT datetime('now', 'utc') }] 0 } {0} | < < | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | do_test 1.1 { lindex [catchsql { SELECT datetime('now', 'localtime') }] 0 } {0} do_test 1.2 { lindex [catchsql { SELECT datetime('now', 'utc') }] 0 } {0} sqlite4_test_control SQLITE4_TESTCTRL_LOCALTIME_FAULT 1 do_test 2.1 { catchsql { SELECT datetime('now', 'localtime') } } {1 {local time unavailable}} do_test 2.2 { catchsql { SELECT datetime('now', 'utc') } } {1 {local time unavailable}} sqlite4_test_control SQLITE4_TESTCTRL_LOCALTIME_FAULT 0 finish_test |
Changes to test/tkt3761.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 | # database can be rolled back. # # $Id: tkt3761.test,v 1.1 2009/03/31 02:54:40 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl | < < < < < | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # database can be rolled back. # # $Id: tkt3761.test,v 1.1 2009/03/31 02:54:40 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test tkt3761-1.1 { db close sqlite4 db :memory: db eval { PRAGMA auto_vacuum=INCREMENTAL; CREATE TABLE t1(x); INSERT INTO t1 VALUES(zeroblob(900)); INSERT INTO t1 VALUES(zeroblob(900)); INSERT INTO t1 SELECT x FROM t1; INSERT INTO t1 SELECT x FROM t1; |
︙ | ︙ |
Changes to test/where8.test.
︙ | ︙ | |||
326 327 328 329 330 331 332 | INSERT INTO t3 VALUES('Alpine', 378678316.5, 'unalike'); INSERT INTO t3 VALUES('Alpine', NULL, 'same'); INSERT INTO t3 VALUES(1339.360726, 2847564.823, 'over'); INSERT INTO t3 VALUES('villages', 'their', 'have'); INSERT INTO t3 VALUES('unalike', 'remarkably', 'in'); INSERT INTO t3 VALUES('and', 8979323846, 'and'); INSERT INTO t3 VALUES(NULL, 1415926535, 'an'); | | | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | INSERT INTO t3 VALUES('Alpine', 378678316.5, 'unalike'); INSERT INTO t3 VALUES('Alpine', NULL, 'same'); INSERT INTO t3 VALUES(1339.360726, 2847564.823, 'over'); INSERT INTO t3 VALUES('villages', 'their', 'have'); INSERT INTO t3 VALUES('unalike', 'remarkably', 'in'); INSERT INTO t3 VALUES('and', 8979323846, 'and'); INSERT INTO t3 VALUES(NULL, 1415926535, 'an'); INSERT INTO t3 VALUES(271.2019091, 8628034825, 0.4811174502); INSERT INTO t3 VALUES('all', 3421170679, 'the'); INSERT INTO t3 VALUES('Not', 'and', 1415926535); INSERT INTO t3 VALUES('of', 'other', 'light'); INSERT INTO t3 VALUES(NULL, 'towering', 'Not'); INSERT INTO t3 VALUES(346.0348610, NULL, 'other'); INSERT INTO t3 VALUES('Not', 378678316.5, NULL); INSERT INTO t3 VALUES('snapshots', 8628034825, 'of'); |
︙ | ︙ |
Changes to www/lsm.wiki.
1 2 3 4 5 6 7 | <title>LSM Design Overview</title> <nowiki> | < > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <title>LSM Design Overview</title> <nowiki> <div id=start_of_toc></div> <a href=#summary style=text-decoration:none>1. Summary </a><br> <a href=#locks style=text-decoration:none>2. Locks </a><br> <a href=#database_connect_and_disconnect_operations style=text-decoration:none>3. Database Connect and Disconnect Operations</a><br> <a href=#read-write_clients style=text-decoration:none>3.1. Read-write clients</a><br> <a href=#read-only_clients style=text-decoration:none>3.2. Read-only clients</a><br> <a href=#data_structures style=text-decoration:none>4. Data Structures </a><br> <a href=#database_file style=text-decoration:none>4.1. Database file</a><br> <a href=#sorted_runs style=text-decoration:none>4.1.1. Sorted Runs</a><br> <a href=#levels style=text-decoration:none>4.1.2. Levels</a><br> <a href=#snapshots style=text-decoration:none>4.1.3. Snapshots</a><br> <a href=#in-memory_tree style=text-decoration:none>4.2. In-Memory Tree</a><br> <a href=#memory_allocation style=text-decoration:none>4.2.1. Memory Allocation</a><br> <a href=#header_fields style=text-decoration:none>4.2.2. Header Fields</a><br> <a href=#other_shared-memory_fields style=text-decoration:none>4.3. Other Shared-Memory Fields</a><br> <a href=#log_file style=text-decoration:none>4.4. Log file</a><br> <a href=#database_operations style=text-decoration:none>5. Database Operations </a><br> <a href=#reading style=text-decoration:none>5.1. Reading</a><br> <a href=#writing style=text-decoration:none>5.2. Writing</a><br> <a href=#flushing_the_in-memory_tree_to_disk style=text-decoration:none>5.2.1. Flushing the in-memory tree to disk</a><br> <a href=#shared-memory_management style=text-decoration:none>5.2.2. Shared-memory management</a><br> <a href=#log_file_management style=text-decoration:none>5.2.3. Log file management</a><br> <a href=#working style=text-decoration:none>5.3. Working</a><br> <a href=#free-block_list_management style=text-decoration:none>5.3.1. Free-block list management</a><br> <a href=#checkpoint_operations style=text-decoration:none>5.4. Checkpoint Operations</a><br> <div id=end_of_toc></div> <h1 id=summary>1. Summary </h1> |
︙ | ︙ | |||
699 700 701 702 703 704 705 706 707 708 709 710 711 712 | <li> Sweep the shared-memory area to rebuild the linked list of chunks so that it is consistent with the current tree-header. <li> Clear the writer flag. </ol> <h2 id=working>5.3. Working</h2> <p> Working is similar to writing. The difference is that a "writer" modifies the in-memory tree. A "worker" modifies the contents of the database file. <ol> | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 | <li> Sweep the shared-memory area to rebuild the linked list of chunks so that it is consistent with the current tree-header. <li> Clear the writer flag. </ol> <h3 id=flushing_the_in-memory_tree_to_disk>5.2.1. Flushing the in-memory tree to disk</h3> <p> For the purposes of writing, the database file and the in-memory tree are largely independent. Processes holding the WRITER lock write to the in-memory tree, and processes holding the WORKER lock write to the database file. <ol> <li> If a write transaction is open, write the new tree-header to shared-memory (as described above). Otherwise, if no write-transaction is open, open one - repairing the tree headers if required. <li> Execute a WORKER transaction (see "Working" below) to add a new level to the LSM. The new level contains the current contents of the in-memory tree. <li> Update the private copy of the tree-header to reflect a new, empty tree. <li> Commit the write transaction, writing the new, empty tree to shared-memory. </ol> <h3 id=shared-memory_management>5.2.2. Shared-memory management</h3> <p> A writer client may have to allocate new shared-memory chunks. This can be done either by extending the shared-memory region or by recycling the first chunk in the linked-list. To check if the first chunk in the linked-list may be reused, the writer must check that: <ul> <li> The chunk is not part of the current in-memory tree (the one being appended to by the writer). A writer can check this by examining its private copy of the tree-header. <li> The chunk is not part of an in-memory tree being used by an existing reader. A writer checks this by scanning (and possibly updating) the values associated with the READER locks - similar to the way SQLite does in WAL mode. </ul> <h3 id=log_file_management>5.2.3. Log file management</h3> <p> A writer client also writes to the log file. All information required to write to the log file (the offset to write to and the initial checksum values) is embedded in the tree-header. Except, in order to reuse log file space (wrap around to the start of the log file), a writer needs to know that the space being recycled will not be required by any recovery process in the future. In other words, that the information contained in the transactions being overwritten has been written into the database file and is part of the snapshot written into the database file by a checkpointer (see "Checkpoint Operations" below). <p> To determine whether or not the log file can be wrapped, the writer requires access to information stored in the newest snapshot written into the database header. Their exists a shared-memory variable indicating which of the two meta-pages contain this snapshot, but the writer process still has to read the snapshot data and verify its checksum from disk. <h2 id=working>5.3. Working</h2> <p> Working is similar to writing. The difference is that a "writer" modifies the in-memory tree. A "worker" modifies the contents of the database file. <ol> |
︙ | ︙ | |||
778 779 780 781 782 783 784 | <li> Sync the database file again. <li> Update the shared-memory variable to indicate the meta-page written in step 5. <li> Drop the CHECKPOINTER lock. </ol> | < < | 841 842 843 844 845 846 847 848 849 850 851 | <li> Sync the database file again. <li> Update the shared-memory variable to indicate the meta-page written in step 5. <li> Drop the CHECKPOINTER lock. </ol> |