mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Refactoring. Split btreeInt.h off from btree.c. Split malloc.c off from
util.c. Expect much more to follow. (CVS 3925) FossilOrigin-Name: 16041116aaaa2d52a289aa02a24bef579ba60896
This commit is contained in:
@@ -123,7 +123,7 @@ TCC += -DSQLITE_OMIT_LOAD_EXTENSION=1
|
||||
LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btree.lo build.lo \
|
||||
callback.lo complete.lo date.lo \
|
||||
delete.lo expr.lo func.lo hash.lo insert.lo loadext.lo \
|
||||
main.lo opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
|
||||
main.lo malloc.lo opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
|
||||
pager.lo parse.lo pragma.lo prepare.lo printf.lo random.lo \
|
||||
select.lo table.lo tokenize.lo trigger.lo update.lo \
|
||||
util.lo vacuum.lo \
|
||||
@@ -152,6 +152,7 @@ SRC = \
|
||||
$(TOP)/src/legacy.c \
|
||||
$(TOP)/src/loadext.c \
|
||||
$(TOP)/src/main.c \
|
||||
$(TOP)/src/mallo.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
$(TOP)/src/os_win.c \
|
||||
@@ -204,6 +205,7 @@ TESTSRC = \
|
||||
$(TOP)/src/date.c \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/malloc.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
@@ -238,6 +240,7 @@ TESTSRC = \
|
||||
HDR = \
|
||||
sqlite3.h \
|
||||
$(TOP)/src/btree.h \
|
||||
$(TOP)/src/btreeInt.h \
|
||||
$(TOP)/src/hash.h \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
@@ -366,6 +369,9 @@ loadext.lo: $(TOP)/src/loadext.c $(HDR)
|
||||
main.lo: $(TOP)/src/main.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c
|
||||
|
||||
malloc.lo: $(TOP)/src/malloc.c $(HDR)
|
||||
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/malloc.c
|
||||
|
||||
pager.lo: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
|
||||
$(LTCOMPILE) -c $(TOP)/src/pager.c
|
||||
|
||||
|
8
main.mk
8
main.mk
@@ -58,7 +58,7 @@ TCCX = $(TCC) $(OPTS) $(THREADSAFE) $(USLEEP) -I. -I$(TOP)/src
|
||||
LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.o \
|
||||
callback.o complete.o date.o delete.o \
|
||||
expr.o func.o hash.o insert.o loadext.o \
|
||||
main.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
|
||||
main.o malloc.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
|
||||
pager.o parse.o pragma.o prepare.o printf.o random.o \
|
||||
select.o table.o tclsqlite.o tokenize.o trigger.o \
|
||||
update.o util.o vacuum.o \
|
||||
@@ -87,6 +87,7 @@ SRC = \
|
||||
$(TOP)/src/legacy.c \
|
||||
$(TOP)/src/loadext.c \
|
||||
$(TOP)/src/main.c \
|
||||
$(TOP)/src/malloc.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
@@ -160,6 +161,7 @@ TESTSRC = \
|
||||
$(TOP)/src/func.c \
|
||||
$(TOP)/src/insert.c \
|
||||
$(TOP)/src/main.c \
|
||||
$(TOP)/src/malloc.c \
|
||||
$(TOP)/src/os.c \
|
||||
$(TOP)/src/os_os2.c \
|
||||
$(TOP)/src/os_unix.c \
|
||||
@@ -194,6 +196,7 @@ TESTSRC = \
|
||||
HDR = \
|
||||
sqlite3.h \
|
||||
$(TOP)/src/btree.h \
|
||||
$(TOP)/src/btreeInt.h \
|
||||
$(TOP)/src/hash.h \
|
||||
opcodes.h \
|
||||
$(TOP)/src/os.h \
|
||||
@@ -319,6 +322,9 @@ loadext.o: $(TOP)/src/loadext.c $(HDR)
|
||||
main.o: $(TOP)/src/main.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/main.c
|
||||
|
||||
malloc.o: $(TOP)/src/malloc.c $(HDR)
|
||||
$(TCCX) -c $(TOP)/src/malloc.c
|
||||
|
||||
pager.o: $(TOP)/src/pager.c $(HDR) $(TOP)/src/pager.h
|
||||
$(TCCX) -c $(TOP)/src/pager.c
|
||||
|
||||
|
28
manifest
28
manifest
@@ -1,6 +1,6 @@
|
||||
C Add\sdocumentation\son\sthe\sincremental\svacuum\sfeature.\s(CVS\s3924)
|
||||
D 2007-05-04T19:16:30
|
||||
F Makefile.in 8cab54f7c9f5af8f22fd97ddf1ecfd1e1860de62
|
||||
C Refactoring.\s\sSplit\sbtreeInt.h\soff\sfrom\sbtree.c.\s\sSplit\smalloc.c\soff\sfrom\nutil.c.\s\sExpect\smuch\smore\sto\sfollow.\s(CVS\s3925)
|
||||
D 2007-05-05T11:48:53
|
||||
F Makefile.in 80d63bf2c61619ae0e29795948ec19e79f91acc3
|
||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
F VERSION 6de5e9812c227f00155cb59af3535017aef3e258
|
||||
@@ -44,7 +44,7 @@ F ext/fts2/fts2_tokenizer1.c 5c979fe8815f95396beb22b627571da895a025af
|
||||
F ext/fts2/mkfts2amal.tcl 2a9ec76b0760fe7f3669dca5bc0d60728bc1c977
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
||||
F ltmain.sh 56abb507100ed2d4261f6dd1653dec3cf4066387
|
||||
F main.mk 2bc462dba2a8332a8a831f5ddd718b4ad7aac6c8
|
||||
F main.mk b9fd506a8ff3abd83b01dff9abdb98948a207f26
|
||||
F mkdll.sh ed62756baf44babf562a7843588790c02fee2106
|
||||
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
|
||||
F mkopcodeh.awk cde995d269aa06c94adbf6455bea0acedb913fa5
|
||||
@@ -59,8 +59,9 @@ F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3
|
||||
F src/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651
|
||||
F src/attach.c f088f8155541ff75542239ec40cf05f3d81390ba
|
||||
F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
|
||||
F src/btree.c 1bd7820b84e93ecd7b4364faeb58565c76cf3cad
|
||||
F src/btree.c 7311696faf137cb37421c8e1d0e22e2d3a15de51
|
||||
F src/btree.h a9cd72b05a14f6be22e057daf954ae548d2bcbe4
|
||||
F src/btreeInt.h 2de5f19abb59fcc5e87474fe59ef8110cfa0d343
|
||||
F src/build.c 0dd6f0d0a5d304be91374f4c7228a3e9b00ff7f1
|
||||
F src/callback.c 6414ed32d55859d0f65067aa5b88d2da27b3af9e
|
||||
F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
|
||||
@@ -75,6 +76,7 @@ F src/insert.c e595ca26805dfb3a9ebaabc28e7947c479f3b14d
|
||||
F src/legacy.c 388c71ad7fbcd898ba1bcbfc98a3ac954bfa5d01
|
||||
F src/loadext.c afe4f4755dc49c36ef505748bbdddecb9f1d02a2
|
||||
F src/main.c e6eb036c3580ba9116fedfe4a8b58ed63d5abb37
|
||||
F src/malloc.c b89e31258a85158d15795bf87ae3ba007e56329b
|
||||
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
||||
F src/os.c 4650e98aadd27abfe1698ff58edf6893c58d4881
|
||||
F src/os.h 9240adf088fd55732f8926f9017601ba3430ead8
|
||||
@@ -87,7 +89,7 @@ F src/os_unix.c cb1fb044b84870c7b1b8b2902e9d7be779f8b7ce
|
||||
F src/os_unix.h 5768d56d28240d3fe4537fac08cc85e4fb52279e
|
||||
F src/os_win.c 5e9e3d2aeed4d6f1b6ae81e866919f4f43b4a23d
|
||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c f01e0e577b7b54c3cdba24a30ecc585a805f23fa
|
||||
F src/pager.c 9c9a9df78636f4b9c8e18f90e93337a1231aaef7
|
||||
F src/pager.h d652ddf092d2318d00e41f8539760fe8e57c157c
|
||||
F src/parse.y a5bdc301e970ceb3826b56a84898b8966d5353f8
|
||||
F src/pragma.c 3f16c1274bc25afb630b61a3630ea19a2fd0b5dc
|
||||
@@ -99,10 +101,10 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c d07ae326b3815d80f71c69b3c7584382e47f6447
|
||||
F src/sqlite.h.in a666300976897eced975b448f722a722b362c6b1
|
||||
F src/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890
|
||||
F src/sqliteInt.h 93ac1a9f1c8facfd861cf548845d2abc36039670
|
||||
F src/sqliteInt.h 3ffe2f9c801575e315451e7d2831c4a90a165aa8
|
||||
F src/table.c a8de75bcedf84d4060d804264b067ab3b1a3561d
|
||||
F src/tclsqlite.c f3414b2d6bc37e6760b49c9abd3504ff69f4441b
|
||||
F src/test1.c ed62a5f1e319bb85232b98b97a438011b96da5a8
|
||||
F src/test1.c 9fb5a4300897c01add79ff8691114e54e5a83ff0
|
||||
F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88
|
||||
F src/test3.c 946ea9d1a8c928656e3c70f0a2fcb8e733a15e86
|
||||
F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
|
||||
@@ -123,7 +125,7 @@ F src/tokenize.c 7d611fc942ca0b12514eea2e1fbb148a65af23f2
|
||||
F src/trigger.c 420192efe3e6f03addf7897c60c3c8bf913d3493
|
||||
F src/update.c 3359041db390a8f856d67272f299600e2104f350
|
||||
F src/utf.c e64a48bc21aa973eb622dd47da87d56a4cdcf528
|
||||
F src/util.c 9f9fec5dc7ffab8ff982508d03af37269a59ff91
|
||||
F src/util.c 5eff5cec4ae43490ca3fb97f10a25aac1a5f9b55
|
||||
F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef
|
||||
F src/vdbe.c 725a808e9bdc317aba963f33054db2dbebdfeecd
|
||||
F src/vdbe.h 0025259af1939fb264a545816c69e4b5b8d52691
|
||||
@@ -409,7 +411,7 @@ F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
|
||||
F tool/memleak3.tcl 7707006ee908cffff210c98158788d85bb3fcdbf
|
||||
F tool/mkkeywordhash.c fe15d1cbc61c2b0375634b6d8c1ef24520799ea0
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
|
||||
F tool/mksqlite3c.tcl fa0429d32cb0756b23def531ec863bc0e216f375
|
||||
F tool/mksqlite3c.tcl 3664556f06f7e4acd81552195ea2a9f16b887dcc
|
||||
F tool/mksqlite3internalh.tcl a85bb0c812db1a060e6e6dfab4e4c817f53d194b
|
||||
F tool/omittest.tcl e6b3d6a1285f9813bc1dea53bb522b4b72774710
|
||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
|
||||
@@ -475,7 +477,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P a0f8adc692839d0645daf0630533a87b0543f6e8
|
||||
R 2ab54f3f4a04566149d9fc08dd42a530
|
||||
P b3e2cdaed3638f033437b5561705cb253449c392
|
||||
R f966d62a9229ee8e5f7295776797e7fa
|
||||
U drh
|
||||
Z d993c75ec553297a4f21ca68fdcc08cc
|
||||
Z 93ccb6a5bb856df574c55be8b837f833
|
||||
|
@@ -1 +1 @@
|
||||
b3e2cdaed3638f033437b5561705cb253449c392
|
||||
16041116aaaa2d52a289aa02a24bef579ba60896
|
574
src/btree.c
574
src/btree.c
@@ -9,431 +9,27 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.375 2007/05/04 19:03:03 danielk1977 Exp $
|
||||
** $Id: btree.c,v 1.376 2007/05/05 11:48:54 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
**
|
||||
** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
|
||||
** "Sorting And Searching", pages 473-480. Addison-Wesley
|
||||
** Publishing Company, Reading, Massachusetts.
|
||||
**
|
||||
** The basic idea is that each page of the file contains N database
|
||||
** entries and N+1 pointers to subpages.
|
||||
**
|
||||
** ----------------------------------------------------------------
|
||||
** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) |
|
||||
** ----------------------------------------------------------------
|
||||
**
|
||||
** All of the keys on the page that Ptr(0) points to have values less
|
||||
** than Key(0). All of the keys on page Ptr(1) and its subpages have
|
||||
** values greater than Key(0) and less than Key(1). All of the keys
|
||||
** on Ptr(N) and its subpages have values greater than Key(N-1). And
|
||||
** so forth.
|
||||
**
|
||||
** Finding a particular key requires reading O(log(M)) pages from the
|
||||
** disk where M is the number of entries in the tree.
|
||||
**
|
||||
** In this implementation, a single file can hold one or more separate
|
||||
** BTrees. Each BTree is identified by the index of its root page. The
|
||||
** key and data for any entry are combined to form the "payload". A
|
||||
** fixed amount of payload can be carried directly on the database
|
||||
** page. If the payload is larger than the preset amount then surplus
|
||||
** bytes are stored on overflow pages. The payload for an entry
|
||||
** and the preceding pointer are combined to form a "Cell". Each
|
||||
** page has a small header which contains the Ptr(N) pointer and other
|
||||
** information such as the size of key and data.
|
||||
**
|
||||
** FORMAT DETAILS
|
||||
**
|
||||
** The file is divided into pages. The first page is called page 1,
|
||||
** the second is page 2, and so forth. A page number of zero indicates
|
||||
** "no such page". The page size can be anything between 512 and 65536.
|
||||
** Each page can be either a btree page, a freelist page or an overflow
|
||||
** page.
|
||||
**
|
||||
** The first page is always a btree page. The first 100 bytes of the first
|
||||
** page contain a special header (the "file header") that describes the file.
|
||||
** The format of the file header is as follows:
|
||||
**
|
||||
** OFFSET SIZE DESCRIPTION
|
||||
** 0 16 Header string: "SQLite format 3\000"
|
||||
** 16 2 Page size in bytes.
|
||||
** 18 1 File format write version
|
||||
** 19 1 File format read version
|
||||
** 20 1 Bytes of unused space at the end of each page
|
||||
** 21 1 Max embedded payload fraction
|
||||
** 22 1 Min embedded payload fraction
|
||||
** 23 1 Min leaf payload fraction
|
||||
** 24 4 File change counter
|
||||
** 28 4 Reserved for future use
|
||||
** 32 4 First freelist page
|
||||
** 36 4 Number of freelist pages in the file
|
||||
** 40 60 15 4-byte meta values passed to higher layers
|
||||
**
|
||||
** All of the integer values are big-endian (most significant byte first).
|
||||
**
|
||||
** The file change counter is incremented when the database is changed more
|
||||
** than once within the same second. This counter, together with the
|
||||
** modification time of the file, allows other processes to know
|
||||
** when the file has changed and thus when they need to flush their
|
||||
** cache.
|
||||
**
|
||||
** The max embedded payload fraction is the amount of the total usable
|
||||
** space in a page that can be consumed by a single cell for standard
|
||||
** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default
|
||||
** is to limit the maximum cell size so that at least 4 cells will fit
|
||||
** on one page. Thus the default max embedded payload fraction is 64.
|
||||
**
|
||||
** If the payload for a cell is larger than the max payload, then extra
|
||||
** payload is spilled to overflow pages. Once an overflow page is allocated,
|
||||
** as many bytes as possible are moved into the overflow pages without letting
|
||||
** the cell size drop below the min embedded payload fraction.
|
||||
**
|
||||
** The min leaf payload fraction is like the min embedded payload fraction
|
||||
** except that it applies to leaf nodes in a LEAFDATA tree. The maximum
|
||||
** payload fraction for a LEAFDATA tree is always 100% (or 255) and it
|
||||
** not specified in the header.
|
||||
**
|
||||
** Each btree pages is divided into three sections: The header, the
|
||||
** cell pointer array, and the cell area area. Page 1 also has a 100-byte
|
||||
** file header that occurs before the page header.
|
||||
**
|
||||
** |----------------|
|
||||
** | file header | 100 bytes. Page 1 only.
|
||||
** |----------------|
|
||||
** | page header | 8 bytes for leaves. 12 bytes for interior nodes
|
||||
** |----------------|
|
||||
** | cell pointer | | 2 bytes per cell. Sorted order.
|
||||
** | array | | Grows downward
|
||||
** | | v
|
||||
** |----------------|
|
||||
** | unallocated |
|
||||
** | space |
|
||||
** |----------------| ^ Grows upwards
|
||||
** | cell content | | Arbitrary order interspersed with freeblocks.
|
||||
** | area | | and free space fragments.
|
||||
** |----------------|
|
||||
**
|
||||
** The page headers looks like this:
|
||||
**
|
||||
** OFFSET SIZE DESCRIPTION
|
||||
** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf
|
||||
** 1 2 byte offset to the first freeblock
|
||||
** 3 2 number of cells on this page
|
||||
** 5 2 first byte of the cell content area
|
||||
** 7 1 number of fragmented free bytes
|
||||
** 8 4 Right child (the Ptr(N) value). Omitted on leaves.
|
||||
**
|
||||
** The flags define the format of this btree page. The leaf flag means that
|
||||
** this page has no children. The zerodata flag means that this page carries
|
||||
** only keys and no data. The intkey flag means that the key is a integer
|
||||
** which is stored in the key size entry of the cell header rather than in
|
||||
** the payload area.
|
||||
**
|
||||
** The cell pointer array begins on the first byte after the page header.
|
||||
** The cell pointer array contains zero or more 2-byte numbers which are
|
||||
** offsets from the beginning of the page to the cell content in the cell
|
||||
** content area. The cell pointers occur in sorted order. The system strives
|
||||
** to keep free space after the last cell pointer so that new cells can
|
||||
** be easily added without having to defragment the page.
|
||||
**
|
||||
** Cell content is stored at the very end of the page and grows toward the
|
||||
** beginning of the page.
|
||||
**
|
||||
** Unused space within the cell content area is collected into a linked list of
|
||||
** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset
|
||||
** to the first freeblock is given in the header. Freeblocks occur in
|
||||
** increasing order. Because a freeblock must be at least 4 bytes in size,
|
||||
** any group of 3 or fewer unused bytes in the cell content area cannot
|
||||
** exist on the freeblock chain. A group of 3 or fewer free bytes is called
|
||||
** a fragment. The total number of bytes in all fragments is recorded.
|
||||
** in the page header at offset 7.
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 2 Byte offset of the next freeblock
|
||||
** 2 Bytes in this freeblock
|
||||
**
|
||||
** Cells are of variable length. Cells are stored in the cell content area at
|
||||
** the end of the page. Pointers to the cells are in the cell pointer array
|
||||
** that immediately follows the page header. Cells is not necessarily
|
||||
** contiguous or in order, but cell pointers are contiguous and in order.
|
||||
**
|
||||
** Cell content makes use of variable length integers. A variable
|
||||
** length integer is 1 to 9 bytes where the lower 7 bits of each
|
||||
** byte are used. The integer consists of all bytes that have bit 8 set and
|
||||
** the first byte with bit 8 clear. The most significant byte of the integer
|
||||
** appears first. A variable-length integer may not be more than 9 bytes long.
|
||||
** As a special case, all 8 bytes of the 9th byte are used as data. This
|
||||
** allows a 64-bit integer to be encoded in 9 bytes.
|
||||
**
|
||||
** 0x00 becomes 0x00000000
|
||||
** 0x7f becomes 0x0000007f
|
||||
** 0x81 0x00 becomes 0x00000080
|
||||
** 0x82 0x00 becomes 0x00000100
|
||||
** 0x80 0x7f becomes 0x0000007f
|
||||
** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678
|
||||
** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081
|
||||
**
|
||||
** Variable length integers are used for rowids and to hold the number of
|
||||
** bytes of key and data in a btree cell.
|
||||
**
|
||||
** The content of a cell looks like this:
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 4 Page number of the left child. Omitted if leaf flag is set.
|
||||
** var Number of bytes of data. Omitted if the zerodata flag is set.
|
||||
** var Number of bytes of key. Or the key itself if intkey flag is set.
|
||||
** * Payload
|
||||
** 4 First page of the overflow chain. Omitted if no overflow
|
||||
**
|
||||
** Overflow pages form a linked list. Each page except the last is completely
|
||||
** filled with data (pagesize - 4 bytes). The last page can have as little
|
||||
** as 1 byte of data.
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 4 Page number of next overflow page
|
||||
** * Data
|
||||
**
|
||||
** Freelist pages come in two subtypes: trunk pages and leaf pages. The
|
||||
** file header points to first in a linked list of trunk page. Each trunk
|
||||
** page points to multiple leaf pages. The content of a leaf page is
|
||||
** unspecified. A trunk page looks like this:
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 4 Page number of next trunk page
|
||||
** 4 Number of leaf pointers on this page
|
||||
** * zero or more pages numbers of leaves
|
||||
** See the header comment on "btreeInt.h" for additional information.
|
||||
** Including a description of file format and an overview of operation.
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
#include "btree.h"
|
||||
#include "os.h"
|
||||
#include <assert.h>
|
||||
|
||||
/* Round up a number to the next larger multiple of 8. This is used
|
||||
** to force 8-byte alignment on 64-bit architectures.
|
||||
*/
|
||||
#define ROUND8(x) ((x+7)&~7)
|
||||
|
||||
|
||||
/* The following value is the maximum cell size assuming a maximum page
|
||||
** size give above.
|
||||
*/
|
||||
#define MX_CELL_SIZE(pBt) (pBt->pageSize-8)
|
||||
|
||||
/* The maximum number of cells on a single page of the database. This
|
||||
** assumes a minimum cell size of 3 bytes. Such small cells will be
|
||||
** exceedingly rare, but they are possible.
|
||||
*/
|
||||
#define MX_CELL(pBt) ((pBt->pageSize-8)/3)
|
||||
|
||||
/* Forward declarations */
|
||||
typedef struct MemPage MemPage;
|
||||
typedef struct BtLock BtLock;
|
||||
#include "btreeInt.h"
|
||||
|
||||
/*
|
||||
** This is a magic string that appears at the beginning of every
|
||||
** SQLite database in order to identify the file as a real database.
|
||||
**
|
||||
** You can change this value at compile-time by specifying a
|
||||
** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
|
||||
** header must be exactly 16 bytes including the zero-terminator so
|
||||
** the string itself should be 15 characters long. If you change
|
||||
** the header, then your custom library will not be able to read
|
||||
** databases generated by the standard tools and the standard tools
|
||||
** will not be able to read databases created by your custom library.
|
||||
** The header string that appears at the beginning of every
|
||||
** SQLite database.
|
||||
*/
|
||||
#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
|
||||
# define SQLITE_FILE_HEADER "SQLite format 3"
|
||||
#endif
|
||||
static const char zMagicHeader[] = SQLITE_FILE_HEADER;
|
||||
|
||||
/*
|
||||
** Page type flags. An ORed combination of these flags appear as the
|
||||
** first byte of every BTree page.
|
||||
*/
|
||||
#define PTF_INTKEY 0x01
|
||||
#define PTF_ZERODATA 0x02
|
||||
#define PTF_LEAFDATA 0x04
|
||||
#define PTF_LEAF 0x08
|
||||
|
||||
/*
|
||||
** As each page of the file is loaded into memory, an instance of the following
|
||||
** structure is appended and initialized to zero. This structure stores
|
||||
** information about the page that is decoded from the raw file page.
|
||||
**
|
||||
** The pParent field points back to the parent page. This allows us to
|
||||
** walk up the BTree from any leaf to the root. Care must be taken to
|
||||
** unref() the parent page pointer when this page is no longer referenced.
|
||||
** The pageDestructor() routine handles that chore.
|
||||
*/
|
||||
struct MemPage {
|
||||
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
|
||||
u8 idxShift; /* True if Cell indices have changed */
|
||||
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
|
||||
u8 intKey; /* True if intkey flag is set */
|
||||
u8 leaf; /* True if leaf flag is set */
|
||||
u8 zeroData; /* True if table stores keys only */
|
||||
u8 leafData; /* True if tables stores data on leaves only */
|
||||
u8 hasData; /* True if this page stores data */
|
||||
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
||||
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
|
||||
u16 maxLocal; /* Copy of Btree.maxLocal or Btree.maxLeaf */
|
||||
u16 minLocal; /* Copy of Btree.minLocal or Btree.minLeaf */
|
||||
u16 cellOffset; /* Index in aData of first cell pointer */
|
||||
u16 idxParent; /* Index in parent of this node */
|
||||
u16 nFree; /* Number of free bytes on the page */
|
||||
u16 nCell; /* Number of cells on this page, local and ovfl */
|
||||
struct _OvflCell { /* Cells that will not fit on aData[] */
|
||||
u8 *pCell; /* Pointers to the body of the overflow cell */
|
||||
u16 idx; /* Insert this cell before idx-th non-overflow cell */
|
||||
} aOvfl[5];
|
||||
BtShared *pBt; /* Pointer back to BTree structure */
|
||||
u8 *aData; /* Pointer back to the start of the page */
|
||||
DbPage *pDbPage; /* Pager page handle */
|
||||
Pgno pgno; /* Page number for this page */
|
||||
MemPage *pParent; /* The parent of this page. NULL for root */
|
||||
};
|
||||
|
||||
/*
|
||||
** The in-memory image of a disk page has the auxiliary information appended
|
||||
** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
|
||||
** that extra information.
|
||||
*/
|
||||
#define EXTRA_SIZE sizeof(MemPage)
|
||||
|
||||
/* Btree handle */
|
||||
struct Btree {
|
||||
sqlite3 *pSqlite;
|
||||
BtShared *pBt;
|
||||
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
|
||||
};
|
||||
|
||||
/*
|
||||
** Btree.inTrans may take one of the following values.
|
||||
**
|
||||
** If the shared-data extension is enabled, there may be multiple users
|
||||
** of the Btree structure. At most one of these may open a write transaction,
|
||||
** but any number may have active read transactions. Variable Btree.pDb
|
||||
** points to the handle that owns any current write-transaction.
|
||||
*/
|
||||
#define TRANS_NONE 0
|
||||
#define TRANS_READ 1
|
||||
#define TRANS_WRITE 2
|
||||
|
||||
/*
|
||||
** Everything we need to know about an open database
|
||||
*/
|
||||
struct BtShared {
|
||||
Pager *pPager; /* The page cache */
|
||||
BtCursor *pCursor; /* A list of all open cursors */
|
||||
MemPage *pPage1; /* First page of the database */
|
||||
u8 inStmt; /* True if we are in a statement subtransaction */
|
||||
u8 readOnly; /* True if the underlying file is readonly */
|
||||
u8 maxEmbedFrac; /* Maximum payload as % of total page size */
|
||||
u8 minEmbedFrac; /* Minimum payload as % of total page size */
|
||||
u8 minLeafFrac; /* Minimum leaf payload as % of total page size */
|
||||
u8 pageSizeFixed; /* True if the page size can no longer be changed */
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
u8 autoVacuum; /* True if auto-vacuum is enabled */
|
||||
u8 incrVacuum; /* True if incr-vacuum is enabled */
|
||||
Pgno nTrunc; /* Non-zero if the db will be truncated (incr vacuum) */
|
||||
#endif
|
||||
u16 pageSize; /* Total number of bytes on a page */
|
||||
u16 usableSize; /* Number of usable bytes on each page */
|
||||
int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
|
||||
int minLocal; /* Minimum local payload in non-LEAFDATA tables */
|
||||
int maxLeaf; /* Maximum local payload in a LEAFDATA table */
|
||||
int minLeaf; /* Minimum local payload in a LEAFDATA table */
|
||||
BusyHandler *pBusyHandler; /* Callback for when there is lock contention */
|
||||
u8 inTransaction; /* Transaction state */
|
||||
int nRef; /* Number of references to this structure */
|
||||
int nTransaction; /* Number of open transactions (read + write) */
|
||||
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
|
||||
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
BtLock *pLock; /* List of locks held on this shared-btree struct */
|
||||
BtShared *pNext; /* Next in ThreadData.pBtree linked list */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of the following structure is used to hold information
|
||||
** about a cell. The parseCellPtr() function fills in this structure
|
||||
** based on information extract from the raw disk page.
|
||||
*/
|
||||
typedef struct CellInfo CellInfo;
|
||||
struct CellInfo {
|
||||
u8 *pCell; /* Pointer to the start of cell content */
|
||||
i64 nKey; /* The key for INTKEY tables, or number of bytes in key */
|
||||
u32 nData; /* Number of bytes of data */
|
||||
u32 nPayload; /* Total amount of payload */
|
||||
u16 nHeader; /* Size of the cell content header in bytes */
|
||||
u16 nLocal; /* Amount of payload held locally */
|
||||
u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
|
||||
u16 nSize; /* Size of the cell content on the main b-tree page */
|
||||
};
|
||||
|
||||
/*
|
||||
** A cursor is a pointer to a particular entry in the BTree.
|
||||
** The entry is identified by its MemPage and the index in
|
||||
** MemPage.aCell[] of the entry.
|
||||
*/
|
||||
struct BtCursor {
|
||||
Btree *pBtree; /* The Btree to which this cursor belongs */
|
||||
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
|
||||
int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */
|
||||
void *pArg; /* First arg to xCompare() */
|
||||
Pgno pgnoRoot; /* The root page of this tree */
|
||||
MemPage *pPage; /* Page that contains the entry */
|
||||
int idx; /* Index of the entry in pPage->aCell[] */
|
||||
CellInfo info; /* A parse of the cell we are pointing at */
|
||||
u8 wrFlag; /* True if writable */
|
||||
u8 eState; /* One of the CURSOR_XXX constants (see below) */
|
||||
void *pKey; /* Saved key that was cursor's last known position */
|
||||
i64 nKey; /* Size of pKey, or last integer key */
|
||||
int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
|
||||
Pgno *aOverflow; /* Cache of overflow page locations */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Potential values for BtCursor.eState.
|
||||
**
|
||||
** CURSOR_VALID:
|
||||
** Cursor points to a valid entry. getPayload() etc. may be called.
|
||||
**
|
||||
** CURSOR_INVALID:
|
||||
** Cursor does not point to a valid entry. This can happen (for example)
|
||||
** because the table is empty or because BtreeCursorFirst() has not been
|
||||
** called.
|
||||
**
|
||||
** CURSOR_REQUIRESEEK:
|
||||
** The table that this cursor was opened on still exists, but has been
|
||||
** modified since the cursor was last used. The cursor position is saved
|
||||
** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
|
||||
** this state, restoreOrClearCursorPosition() can be called to attempt to
|
||||
** seek the cursor to the saved position.
|
||||
*/
|
||||
#define CURSOR_INVALID 0
|
||||
#define CURSOR_VALID 1
|
||||
#define CURSOR_REQUIRESEEK 2
|
||||
|
||||
/*
|
||||
** The TRACE macro will print high-level status information about the
|
||||
** btree operation when the global variable sqlite3_btree_trace is
|
||||
** enabled.
|
||||
** Set this global variable to 1 to enable tracing using the TRACE
|
||||
** macro.
|
||||
*/
|
||||
#if SQLITE_TEST
|
||||
# define TRACE(X) if( sqlite3_btree_trace )\
|
||||
/* { sqlite3DebugPrintf X; fflush(stdout); } */ \
|
||||
{ printf X; fflush(stdout); }
|
||||
int sqlite3_btree_trace=0; /* True to enable tracing */
|
||||
#else
|
||||
# define TRACE(X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -441,66 +37,6 @@ int sqlite3_btree_trace=0; /* True to enable tracing */
|
||||
*/
|
||||
static int checkReadLocks(Btree*,Pgno,BtCursor*);
|
||||
|
||||
/*
|
||||
** Read or write a two- and four-byte big-endian integer values.
|
||||
*/
|
||||
static u32 get2byte(unsigned char *p){
|
||||
return (p[0]<<8) | p[1];
|
||||
}
|
||||
static u32 get4byte(unsigned char *p){
|
||||
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
|
||||
}
|
||||
static void put2byte(unsigned char *p, u32 v){
|
||||
p[0] = v>>8;
|
||||
p[1] = v;
|
||||
}
|
||||
static void put4byte(unsigned char *p, u32 v){
|
||||
p[0] = v>>24;
|
||||
p[1] = v>>16;
|
||||
p[2] = v>>8;
|
||||
p[3] = v;
|
||||
}
|
||||
|
||||
/*
|
||||
** Routines to read and write variable-length integers. These used to
|
||||
** be defined locally, but now we use the varint routines in the util.c
|
||||
** file.
|
||||
*/
|
||||
#define getVarint sqlite3GetVarint
|
||||
/* #define getVarint32 sqlite3GetVarint32 */
|
||||
#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B))
|
||||
#define putVarint sqlite3PutVarint
|
||||
|
||||
/* The database page the PENDING_BYTE occupies. This page is never used.
|
||||
** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They
|
||||
** should possibly be consolidated (presumably in pager.h).
|
||||
**
|
||||
** If disk I/O is omitted (meaning that the database is stored purely
|
||||
** in memory) then there is no pending byte.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_DISKIO
|
||||
# define PENDING_BYTE_PAGE(pBt) 0x7fffffff
|
||||
#else
|
||||
# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** A linked list of the following structures is stored at BtShared.pLock.
|
||||
** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
|
||||
** is opened on the table with root page BtShared.iTable. Locks are removed
|
||||
** from this list when a transaction is committed or rolled back, or when
|
||||
** a btree handle is closed.
|
||||
*/
|
||||
struct BtLock {
|
||||
Btree *pBtree; /* Btree handle holding this lock */
|
||||
Pgno iTable; /* Root page of table */
|
||||
u8 eLock; /* READ_LOCK or WRITE_LOCK */
|
||||
BtLock *pNext; /* Next in BtShared.pLock list */
|
||||
};
|
||||
|
||||
/* Candidate values for BtLock.eLock */
|
||||
#define READ_LOCK 1
|
||||
#define WRITE_LOCK 2
|
||||
|
||||
#ifdef SQLITE_OMIT_SHARED_CACHE
|
||||
/*
|
||||
@@ -785,24 +321,10 @@ static int restoreOrClearCursorPositionX(BtCursor *pCur){
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
/*
|
||||
** These macros define the location of the pointer-map entry for a
|
||||
** database page. The first argument to each is the number of usable
|
||||
** bytes on each page of the database (often 1024). The second is the
|
||||
** page number to look up in the pointer map.
|
||||
**
|
||||
** PTRMAP_PAGENO returns the database page number of the pointer-map
|
||||
** page that stores the required pointer. PTRMAP_PTROFFSET returns
|
||||
** the offset of the requested map entry.
|
||||
**
|
||||
** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
|
||||
** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
|
||||
** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
|
||||
** this test.
|
||||
** Given a page number of a regular database page, return the page
|
||||
** number for the pointer-map page that contains the entry for the
|
||||
** input page number.
|
||||
*/
|
||||
#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
|
||||
#define PTRMAP_PTROFFSET(pBt, pgno) (5*(pgno-ptrmapPageno(pBt, pgno)-1))
|
||||
#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
|
||||
|
||||
static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
|
||||
int nPagesPerMapPage = (pBt->usableSize/5)+1;
|
||||
int iPtrMap = (pgno-2)/nPagesPerMapPage;
|
||||
@@ -813,43 +335,6 @@ static Pgno ptrmapPageno(BtShared *pBt, Pgno pgno){
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
** The pointer map is a lookup table that identifies the parent page for
|
||||
** each child page in the database file. The parent page is the page that
|
||||
** contains a pointer to the child. Every page in the database contains
|
||||
** 0 or 1 parent pages. (In this context 'database page' refers
|
||||
** to any page that is not part of the pointer map itself.) Each pointer map
|
||||
** entry consists of a single byte 'type' and a 4 byte parent page number.
|
||||
** The PTRMAP_XXX identifiers below are the valid types.
|
||||
**
|
||||
** The purpose of the pointer map is to facility moving pages from one
|
||||
** position in the file to another as part of autovacuum. When a page
|
||||
** is moved, the pointer in its parent must be updated to point to the
|
||||
** new location. The pointer map is used to locate the parent page quickly.
|
||||
**
|
||||
** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
|
||||
** used in this case.
|
||||
**
|
||||
** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
|
||||
** is not used in this case.
|
||||
**
|
||||
** PTRMAP_OVERFLOW1: The database page is the first page in a list of
|
||||
** overflow pages. The page number identifies the page that
|
||||
** contains the cell with a pointer to this overflow page.
|
||||
**
|
||||
** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
|
||||
** overflow pages. The page-number identifies the previous
|
||||
** page in the overflow page list.
|
||||
**
|
||||
** PTRMAP_BTREE: The database page is a non-root btree page. The page number
|
||||
** identifies the parent page in the btree.
|
||||
*/
|
||||
#define PTRMAP_ROOTPAGE 1
|
||||
#define PTRMAP_FREEPAGE 2
|
||||
#define PTRMAP_OVERFLOW1 3
|
||||
#define PTRMAP_OVERFLOW2 4
|
||||
#define PTRMAP_BTREE 5
|
||||
|
||||
/*
|
||||
** Write an entry into the pointer map.
|
||||
**
|
||||
@@ -1090,15 +575,6 @@ static int ptrmapPutOvfl(MemPage *pPage, int iCell){
|
||||
#endif
|
||||
|
||||
|
||||
/* A bunch of assert() statements to check the transaction state variables
|
||||
** of handle p (type Btree*) are internally consistent.
|
||||
*/
|
||||
#define btreeIntegrity(p) \
|
||||
assert( p->inTrans!=TRANS_NONE || p->pBt->nTransaction<p->pBt->nRef ); \
|
||||
assert( p->pBt->nTransaction<=p->pBt->nRef ); \
|
||||
assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
|
||||
assert( p->pBt->inTransaction>=p->inTrans );
|
||||
|
||||
/*
|
||||
** Defragment the page given. All Cells are moved to the
|
||||
** end of the page and all free space is collected into one
|
||||
@@ -4767,19 +4243,6 @@ static int balance_quick(MemPage *pPage, MemPage *pParent){
|
||||
}
|
||||
#endif /* SQLITE_OMIT_QUICKBALANCE */
|
||||
|
||||
/*
|
||||
** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
|
||||
** if the database supports auto-vacuum or not. Because it is used
|
||||
** within an expression that is an argument to another macro
|
||||
** (sqliteMallocRaw), it is not possible to use conditional compilation.
|
||||
** So, this macro is defined instead.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
#define ISAUTOVACUUM (pBt->autoVacuum)
|
||||
#else
|
||||
#define ISAUTOVACUUM 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine redistributes Cells on pPage and up to NN*2 siblings
|
||||
** of pPage so that all pages have about the same amount of free space.
|
||||
@@ -6379,21 +5842,6 @@ Pager *sqlite3BtreePager(Btree *p){
|
||||
return p->pBt->pPager;
|
||||
}
|
||||
|
||||
/*
|
||||
** This structure is passed around through all the sanity checking routines
|
||||
** in order to keep track of some global state information.
|
||||
*/
|
||||
typedef struct IntegrityCk IntegrityCk;
|
||||
struct IntegrityCk {
|
||||
BtShared *pBt; /* The tree being checked out */
|
||||
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
|
||||
int nPage; /* Number of pages in the database */
|
||||
int *anRef; /* Number of times each page is referenced */
|
||||
int mxErr; /* Stop accumulating errors when this reaches zero */
|
||||
char *zErrMsg; /* An error message. NULL if no errors seen. */
|
||||
int nErr; /* Number of messages written to zErrMsg so far */
|
||||
};
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
/*
|
||||
** Append a message to the error message string.
|
||||
|
576
src/btreeInt.h
Normal file
576
src/btreeInt.h
Normal file
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
** 2004 April 6
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btreeInt.h,v 1.1 2007/05/05 11:48:54 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
**
|
||||
** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
|
||||
** "Sorting And Searching", pages 473-480. Addison-Wesley
|
||||
** Publishing Company, Reading, Massachusetts.
|
||||
**
|
||||
** The basic idea is that each page of the file contains N database
|
||||
** entries and N+1 pointers to subpages.
|
||||
**
|
||||
** ----------------------------------------------------------------
|
||||
** | Ptr(0) | Key(0) | Ptr(1) | Key(1) | ... | Key(N-1) | Ptr(N) |
|
||||
** ----------------------------------------------------------------
|
||||
**
|
||||
** All of the keys on the page that Ptr(0) points to have values less
|
||||
** than Key(0). All of the keys on page Ptr(1) and its subpages have
|
||||
** values greater than Key(0) and less than Key(1). All of the keys
|
||||
** on Ptr(N) and its subpages have values greater than Key(N-1). And
|
||||
** so forth.
|
||||
**
|
||||
** Finding a particular key requires reading O(log(M)) pages from the
|
||||
** disk where M is the number of entries in the tree.
|
||||
**
|
||||
** In this implementation, a single file can hold one or more separate
|
||||
** BTrees. Each BTree is identified by the index of its root page. The
|
||||
** key and data for any entry are combined to form the "payload". A
|
||||
** fixed amount of payload can be carried directly on the database
|
||||
** page. If the payload is larger than the preset amount then surplus
|
||||
** bytes are stored on overflow pages. The payload for an entry
|
||||
** and the preceding pointer are combined to form a "Cell". Each
|
||||
** page has a small header which contains the Ptr(N) pointer and other
|
||||
** information such as the size of key and data.
|
||||
**
|
||||
** FORMAT DETAILS
|
||||
**
|
||||
** The file is divided into pages. The first page is called page 1,
|
||||
** the second is page 2, and so forth. A page number of zero indicates
|
||||
** "no such page". The page size can be anything between 512 and 65536.
|
||||
** Each page can be either a btree page, a freelist page or an overflow
|
||||
** page.
|
||||
**
|
||||
** The first page is always a btree page. The first 100 bytes of the first
|
||||
** page contain a special header (the "file header") that describes the file.
|
||||
** The format of the file header is as follows:
|
||||
**
|
||||
** OFFSET SIZE DESCRIPTION
|
||||
** 0 16 Header string: "SQLite format 3\000"
|
||||
** 16 2 Page size in bytes.
|
||||
** 18 1 File format write version
|
||||
** 19 1 File format read version
|
||||
** 20 1 Bytes of unused space at the end of each page
|
||||
** 21 1 Max embedded payload fraction
|
||||
** 22 1 Min embedded payload fraction
|
||||
** 23 1 Min leaf payload fraction
|
||||
** 24 4 File change counter
|
||||
** 28 4 Reserved for future use
|
||||
** 32 4 First freelist page
|
||||
** 36 4 Number of freelist pages in the file
|
||||
** 40 60 15 4-byte meta values passed to higher layers
|
||||
**
|
||||
** All of the integer values are big-endian (most significant byte first).
|
||||
**
|
||||
** The file change counter is incremented when the database is changed more
|
||||
** than once within the same second. This counter, together with the
|
||||
** modification time of the file, allows other processes to know
|
||||
** when the file has changed and thus when they need to flush their
|
||||
** cache.
|
||||
**
|
||||
** The max embedded payload fraction is the amount of the total usable
|
||||
** space in a page that can be consumed by a single cell for standard
|
||||
** B-tree (non-LEAFDATA) tables. A value of 255 means 100%. The default
|
||||
** is to limit the maximum cell size so that at least 4 cells will fit
|
||||
** on one page. Thus the default max embedded payload fraction is 64.
|
||||
**
|
||||
** If the payload for a cell is larger than the max payload, then extra
|
||||
** payload is spilled to overflow pages. Once an overflow page is allocated,
|
||||
** as many bytes as possible are moved into the overflow pages without letting
|
||||
** the cell size drop below the min embedded payload fraction.
|
||||
**
|
||||
** The min leaf payload fraction is like the min embedded payload fraction
|
||||
** except that it applies to leaf nodes in a LEAFDATA tree. The maximum
|
||||
** payload fraction for a LEAFDATA tree is always 100% (or 255) and it
|
||||
** not specified in the header.
|
||||
**
|
||||
** Each btree pages is divided into three sections: The header, the
|
||||
** cell pointer array, and the cell area area. Page 1 also has a 100-byte
|
||||
** file header that occurs before the page header.
|
||||
**
|
||||
** |----------------|
|
||||
** | file header | 100 bytes. Page 1 only.
|
||||
** |----------------|
|
||||
** | page header | 8 bytes for leaves. 12 bytes for interior nodes
|
||||
** |----------------|
|
||||
** | cell pointer | | 2 bytes per cell. Sorted order.
|
||||
** | array | | Grows downward
|
||||
** | | v
|
||||
** |----------------|
|
||||
** | unallocated |
|
||||
** | space |
|
||||
** |----------------| ^ Grows upwards
|
||||
** | cell content | | Arbitrary order interspersed with freeblocks.
|
||||
** | area | | and free space fragments.
|
||||
** |----------------|
|
||||
**
|
||||
** The page headers looks like this:
|
||||
**
|
||||
** OFFSET SIZE DESCRIPTION
|
||||
** 0 1 Flags. 1: intkey, 2: zerodata, 4: leafdata, 8: leaf
|
||||
** 1 2 byte offset to the first freeblock
|
||||
** 3 2 number of cells on this page
|
||||
** 5 2 first byte of the cell content area
|
||||
** 7 1 number of fragmented free bytes
|
||||
** 8 4 Right child (the Ptr(N) value). Omitted on leaves.
|
||||
**
|
||||
** The flags define the format of this btree page. The leaf flag means that
|
||||
** this page has no children. The zerodata flag means that this page carries
|
||||
** only keys and no data. The intkey flag means that the key is a integer
|
||||
** which is stored in the key size entry of the cell header rather than in
|
||||
** the payload area.
|
||||
**
|
||||
** The cell pointer array begins on the first byte after the page header.
|
||||
** The cell pointer array contains zero or more 2-byte numbers which are
|
||||
** offsets from the beginning of the page to the cell content in the cell
|
||||
** content area. The cell pointers occur in sorted order. The system strives
|
||||
** to keep free space after the last cell pointer so that new cells can
|
||||
** be easily added without having to defragment the page.
|
||||
**
|
||||
** Cell content is stored at the very end of the page and grows toward the
|
||||
** beginning of the page.
|
||||
**
|
||||
** Unused space within the cell content area is collected into a linked list of
|
||||
** freeblocks. Each freeblock is at least 4 bytes in size. The byte offset
|
||||
** to the first freeblock is given in the header. Freeblocks occur in
|
||||
** increasing order. Because a freeblock must be at least 4 bytes in size,
|
||||
** any group of 3 or fewer unused bytes in the cell content area cannot
|
||||
** exist on the freeblock chain. A group of 3 or fewer free bytes is called
|
||||
** a fragment. The total number of bytes in all fragments is recorded.
|
||||
** in the page header at offset 7.
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 2 Byte offset of the next freeblock
|
||||
** 2 Bytes in this freeblock
|
||||
**
|
||||
** Cells are of variable length. Cells are stored in the cell content area at
|
||||
** the end of the page. Pointers to the cells are in the cell pointer array
|
||||
** that immediately follows the page header. Cells is not necessarily
|
||||
** contiguous or in order, but cell pointers are contiguous and in order.
|
||||
**
|
||||
** Cell content makes use of variable length integers. A variable
|
||||
** length integer is 1 to 9 bytes where the lower 7 bits of each
|
||||
** byte are used. The integer consists of all bytes that have bit 8 set and
|
||||
** the first byte with bit 8 clear. The most significant byte of the integer
|
||||
** appears first. A variable-length integer may not be more than 9 bytes long.
|
||||
** As a special case, all 8 bytes of the 9th byte are used as data. This
|
||||
** allows a 64-bit integer to be encoded in 9 bytes.
|
||||
**
|
||||
** 0x00 becomes 0x00000000
|
||||
** 0x7f becomes 0x0000007f
|
||||
** 0x81 0x00 becomes 0x00000080
|
||||
** 0x82 0x00 becomes 0x00000100
|
||||
** 0x80 0x7f becomes 0x0000007f
|
||||
** 0x8a 0x91 0xd1 0xac 0x78 becomes 0x12345678
|
||||
** 0x81 0x81 0x81 0x81 0x01 becomes 0x10204081
|
||||
**
|
||||
** Variable length integers are used for rowids and to hold the number of
|
||||
** bytes of key and data in a btree cell.
|
||||
**
|
||||
** The content of a cell looks like this:
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 4 Page number of the left child. Omitted if leaf flag is set.
|
||||
** var Number of bytes of data. Omitted if the zerodata flag is set.
|
||||
** var Number of bytes of key. Or the key itself if intkey flag is set.
|
||||
** * Payload
|
||||
** 4 First page of the overflow chain. Omitted if no overflow
|
||||
**
|
||||
** Overflow pages form a linked list. Each page except the last is completely
|
||||
** filled with data (pagesize - 4 bytes). The last page can have as little
|
||||
** as 1 byte of data.
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 4 Page number of next overflow page
|
||||
** * Data
|
||||
**
|
||||
** Freelist pages come in two subtypes: trunk pages and leaf pages. The
|
||||
** file header points to first in a linked list of trunk page. Each trunk
|
||||
** page points to multiple leaf pages. The content of a leaf page is
|
||||
** unspecified. A trunk page looks like this:
|
||||
**
|
||||
** SIZE DESCRIPTION
|
||||
** 4 Page number of next trunk page
|
||||
** 4 Number of leaf pointers on this page
|
||||
** * zero or more pages numbers of leaves
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
#include "btree.h"
|
||||
#include "os.h"
|
||||
#include <assert.h>
|
||||
|
||||
/* Round up a number to the next larger multiple of 8. This is used
|
||||
** to force 8-byte alignment on 64-bit architectures.
|
||||
*/
|
||||
#define ROUND8(x) ((x+7)&~7)
|
||||
|
||||
|
||||
/* The following value is the maximum cell size assuming a maximum page
|
||||
** size give above.
|
||||
*/
|
||||
#define MX_CELL_SIZE(pBt) (pBt->pageSize-8)
|
||||
|
||||
/* The maximum number of cells on a single page of the database. This
|
||||
** assumes a minimum cell size of 3 bytes. Such small cells will be
|
||||
** exceedingly rare, but they are possible.
|
||||
*/
|
||||
#define MX_CELL(pBt) ((pBt->pageSize-8)/3)
|
||||
|
||||
/* Forward declarations */
|
||||
typedef struct MemPage MemPage;
|
||||
typedef struct BtLock BtLock;
|
||||
|
||||
/*
|
||||
** This is a magic string that appears at the beginning of every
|
||||
** SQLite database in order to identify the file as a real database.
|
||||
**
|
||||
** You can change this value at compile-time by specifying a
|
||||
** -DSQLITE_FILE_HEADER="..." on the compiler command-line. The
|
||||
** header must be exactly 16 bytes including the zero-terminator so
|
||||
** the string itself should be 15 characters long. If you change
|
||||
** the header, then your custom library will not be able to read
|
||||
** databases generated by the standard tools and the standard tools
|
||||
** will not be able to read databases created by your custom library.
|
||||
*/
|
||||
#ifndef SQLITE_FILE_HEADER /* 123456789 123456 */
|
||||
# define SQLITE_FILE_HEADER "SQLite format 3"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Page type flags. An ORed combination of these flags appear as the
|
||||
** first byte of every BTree page.
|
||||
*/
|
||||
#define PTF_INTKEY 0x01
|
||||
#define PTF_ZERODATA 0x02
|
||||
#define PTF_LEAFDATA 0x04
|
||||
#define PTF_LEAF 0x08
|
||||
|
||||
/*
|
||||
** As each page of the file is loaded into memory, an instance of the following
|
||||
** structure is appended and initialized to zero. This structure stores
|
||||
** information about the page that is decoded from the raw file page.
|
||||
**
|
||||
** The pParent field points back to the parent page. This allows us to
|
||||
** walk up the BTree from any leaf to the root. Care must be taken to
|
||||
** unref() the parent page pointer when this page is no longer referenced.
|
||||
** The pageDestructor() routine handles that chore.
|
||||
*/
|
||||
struct MemPage {
|
||||
u8 isInit; /* True if previously initialized. MUST BE FIRST! */
|
||||
u8 idxShift; /* True if Cell indices have changed */
|
||||
u8 nOverflow; /* Number of overflow cell bodies in aCell[] */
|
||||
u8 intKey; /* True if intkey flag is set */
|
||||
u8 leaf; /* True if leaf flag is set */
|
||||
u8 zeroData; /* True if table stores keys only */
|
||||
u8 leafData; /* True if tables stores data on leaves only */
|
||||
u8 hasData; /* True if this page stores data */
|
||||
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
|
||||
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
|
||||
u16 maxLocal; /* Copy of Btree.maxLocal or Btree.maxLeaf */
|
||||
u16 minLocal; /* Copy of Btree.minLocal or Btree.minLeaf */
|
||||
u16 cellOffset; /* Index in aData of first cell pointer */
|
||||
u16 idxParent; /* Index in parent of this node */
|
||||
u16 nFree; /* Number of free bytes on the page */
|
||||
u16 nCell; /* Number of cells on this page, local and ovfl */
|
||||
struct _OvflCell { /* Cells that will not fit on aData[] */
|
||||
u8 *pCell; /* Pointers to the body of the overflow cell */
|
||||
u16 idx; /* Insert this cell before idx-th non-overflow cell */
|
||||
} aOvfl[5];
|
||||
BtShared *pBt; /* Pointer back to BTree structure */
|
||||
u8 *aData; /* Pointer back to the start of the page */
|
||||
DbPage *pDbPage; /* Pager page handle */
|
||||
Pgno pgno; /* Page number for this page */
|
||||
MemPage *pParent; /* The parent of this page. NULL for root */
|
||||
};
|
||||
|
||||
/*
|
||||
** The in-memory image of a disk page has the auxiliary information appended
|
||||
** to the end. EXTRA_SIZE is the number of bytes of space needed to hold
|
||||
** that extra information.
|
||||
*/
|
||||
#define EXTRA_SIZE sizeof(MemPage)
|
||||
|
||||
/* Btree handle */
|
||||
struct Btree {
|
||||
sqlite3 *pSqlite;
|
||||
BtShared *pBt;
|
||||
u8 inTrans; /* TRANS_NONE, TRANS_READ or TRANS_WRITE */
|
||||
};
|
||||
|
||||
/*
|
||||
** Btree.inTrans may take one of the following values.
|
||||
**
|
||||
** If the shared-data extension is enabled, there may be multiple users
|
||||
** of the Btree structure. At most one of these may open a write transaction,
|
||||
** but any number may have active read transactions. Variable Btree.pDb
|
||||
** points to the handle that owns any current write-transaction.
|
||||
*/
|
||||
#define TRANS_NONE 0
|
||||
#define TRANS_READ 1
|
||||
#define TRANS_WRITE 2
|
||||
|
||||
/*
|
||||
** Everything we need to know about an open database
|
||||
*/
|
||||
struct BtShared {
|
||||
Pager *pPager; /* The page cache */
|
||||
BtCursor *pCursor; /* A list of all open cursors */
|
||||
MemPage *pPage1; /* First page of the database */
|
||||
u8 inStmt; /* True if we are in a statement subtransaction */
|
||||
u8 readOnly; /* True if the underlying file is readonly */
|
||||
u8 maxEmbedFrac; /* Maximum payload as % of total page size */
|
||||
u8 minEmbedFrac; /* Minimum payload as % of total page size */
|
||||
u8 minLeafFrac; /* Minimum leaf payload as % of total page size */
|
||||
u8 pageSizeFixed; /* True if the page size can no longer be changed */
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
u8 autoVacuum; /* True if auto-vacuum is enabled */
|
||||
u8 incrVacuum; /* True if incr-vacuum is enabled */
|
||||
Pgno nTrunc; /* Non-zero if the db will be truncated (incr vacuum) */
|
||||
#endif
|
||||
u16 pageSize; /* Total number of bytes on a page */
|
||||
u16 usableSize; /* Number of usable bytes on each page */
|
||||
int maxLocal; /* Maximum local payload in non-LEAFDATA tables */
|
||||
int minLocal; /* Minimum local payload in non-LEAFDATA tables */
|
||||
int maxLeaf; /* Maximum local payload in a LEAFDATA table */
|
||||
int minLeaf; /* Minimum local payload in a LEAFDATA table */
|
||||
BusyHandler *pBusyHandler; /* Callback for when there is lock contention */
|
||||
u8 inTransaction; /* Transaction state */
|
||||
int nRef; /* Number of references to this structure */
|
||||
int nTransaction; /* Number of open transactions (read + write) */
|
||||
void *pSchema; /* Pointer to space allocated by sqlite3BtreeSchema() */
|
||||
void (*xFreeSchema)(void*); /* Destructor for BtShared.pSchema */
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
BtLock *pLock; /* List of locks held on this shared-btree struct */
|
||||
BtShared *pNext; /* Next in ThreadData.pBtree linked list */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of the following structure is used to hold information
|
||||
** about a cell. The parseCellPtr() function fills in this structure
|
||||
** based on information extract from the raw disk page.
|
||||
*/
|
||||
typedef struct CellInfo CellInfo;
|
||||
struct CellInfo {
|
||||
u8 *pCell; /* Pointer to the start of cell content */
|
||||
i64 nKey; /* The key for INTKEY tables, or number of bytes in key */
|
||||
u32 nData; /* Number of bytes of data */
|
||||
u32 nPayload; /* Total amount of payload */
|
||||
u16 nHeader; /* Size of the cell content header in bytes */
|
||||
u16 nLocal; /* Amount of payload held locally */
|
||||
u16 iOverflow; /* Offset to overflow page number. Zero if no overflow */
|
||||
u16 nSize; /* Size of the cell content on the main b-tree page */
|
||||
};
|
||||
|
||||
/*
|
||||
** A cursor is a pointer to a particular entry in the BTree.
|
||||
** The entry is identified by its MemPage and the index in
|
||||
** MemPage.aCell[] of the entry.
|
||||
*/
|
||||
struct BtCursor {
|
||||
Btree *pBtree; /* The Btree to which this cursor belongs */
|
||||
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
|
||||
int (*xCompare)(void*,int,const void*,int,const void*); /* Key comp func */
|
||||
void *pArg; /* First arg to xCompare() */
|
||||
Pgno pgnoRoot; /* The root page of this tree */
|
||||
MemPage *pPage; /* Page that contains the entry */
|
||||
int idx; /* Index of the entry in pPage->aCell[] */
|
||||
CellInfo info; /* A parse of the cell we are pointing at */
|
||||
u8 wrFlag; /* True if writable */
|
||||
u8 eState; /* One of the CURSOR_XXX constants (see below) */
|
||||
void *pKey; /* Saved key that was cursor's last known position */
|
||||
i64 nKey; /* Size of pKey, or last integer key */
|
||||
int skip; /* (skip<0) -> Prev() is a no-op. (skip>0) -> Next() is */
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
|
||||
Pgno *aOverflow; /* Cache of overflow page locations */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
** Potential values for BtCursor.eState.
|
||||
**
|
||||
** CURSOR_VALID:
|
||||
** Cursor points to a valid entry. getPayload() etc. may be called.
|
||||
**
|
||||
** CURSOR_INVALID:
|
||||
** Cursor does not point to a valid entry. This can happen (for example)
|
||||
** because the table is empty or because BtreeCursorFirst() has not been
|
||||
** called.
|
||||
**
|
||||
** CURSOR_REQUIRESEEK:
|
||||
** The table that this cursor was opened on still exists, but has been
|
||||
** modified since the cursor was last used. The cursor position is saved
|
||||
** in variables BtCursor.pKey and BtCursor.nKey. When a cursor is in
|
||||
** this state, restoreOrClearCursorPosition() can be called to attempt to
|
||||
** seek the cursor to the saved position.
|
||||
*/
|
||||
#define CURSOR_INVALID 0
|
||||
#define CURSOR_VALID 1
|
||||
#define CURSOR_REQUIRESEEK 2
|
||||
|
||||
/*
|
||||
** The TRACE macro will print high-level status information about the
|
||||
** btree operation when the global variable sqlite3_btree_trace is
|
||||
** enabled.
|
||||
*/
|
||||
#if SQLITE_TEST
|
||||
# define TRACE(X) if( sqlite3_btree_trace ){ printf X; fflush(stdout); }
|
||||
#else
|
||||
# define TRACE(X)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Routines to read and write variable-length integers. These used to
|
||||
** be defined locally, but now we use the varint routines in the util.c
|
||||
** file.
|
||||
*/
|
||||
#define getVarint sqlite3GetVarint
|
||||
#define getVarint32(A,B) ((*B=*(A))<=0x7f?1:sqlite3GetVarint32(A,B))
|
||||
#define putVarint sqlite3PutVarint
|
||||
|
||||
/* The database page the PENDING_BYTE occupies. This page is never used.
|
||||
** TODO: This macro is very similary to PAGER_MJ_PGNO() in pager.c. They
|
||||
** should possibly be consolidated (presumably in pager.h).
|
||||
**
|
||||
** If disk I/O is omitted (meaning that the database is stored purely
|
||||
** in memory) then there is no pending byte.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_DISKIO
|
||||
# define PENDING_BYTE_PAGE(pBt) 0x7fffffff
|
||||
#else
|
||||
# define PENDING_BYTE_PAGE(pBt) ((PENDING_BYTE/(pBt)->pageSize)+1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** A linked list of the following structures is stored at BtShared.pLock.
|
||||
** Locks are added (or upgraded from READ_LOCK to WRITE_LOCK) when a cursor
|
||||
** is opened on the table with root page BtShared.iTable. Locks are removed
|
||||
** from this list when a transaction is committed or rolled back, or when
|
||||
** a btree handle is closed.
|
||||
*/
|
||||
struct BtLock {
|
||||
Btree *pBtree; /* Btree handle holding this lock */
|
||||
Pgno iTable; /* Root page of table */
|
||||
u8 eLock; /* READ_LOCK or WRITE_LOCK */
|
||||
BtLock *pNext; /* Next in BtShared.pLock list */
|
||||
};
|
||||
|
||||
/* Candidate values for BtLock.eLock */
|
||||
#define READ_LOCK 1
|
||||
#define WRITE_LOCK 2
|
||||
|
||||
/*
|
||||
** These macros define the location of the pointer-map entry for a
|
||||
** database page. The first argument to each is the number of usable
|
||||
** bytes on each page of the database (often 1024). The second is the
|
||||
** page number to look up in the pointer map.
|
||||
**
|
||||
** PTRMAP_PAGENO returns the database page number of the pointer-map
|
||||
** page that stores the required pointer. PTRMAP_PTROFFSET returns
|
||||
** the offset of the requested map entry.
|
||||
**
|
||||
** If the pgno argument passed to PTRMAP_PAGENO is a pointer-map page,
|
||||
** then pgno is returned. So (pgno==PTRMAP_PAGENO(pgsz, pgno)) can be
|
||||
** used to test if pgno is a pointer-map page. PTRMAP_ISPAGE implements
|
||||
** this test.
|
||||
*/
|
||||
#define PTRMAP_PAGENO(pBt, pgno) ptrmapPageno(pBt, pgno)
|
||||
#define PTRMAP_PTROFFSET(pBt, pgno) (5*(pgno-ptrmapPageno(pBt, pgno)-1))
|
||||
#define PTRMAP_ISPAGE(pBt, pgno) (PTRMAP_PAGENO((pBt),(pgno))==(pgno))
|
||||
|
||||
/*
|
||||
** The pointer map is a lookup table that identifies the parent page for
|
||||
** each child page in the database file. The parent page is the page that
|
||||
** contains a pointer to the child. Every page in the database contains
|
||||
** 0 or 1 parent pages. (In this context 'database page' refers
|
||||
** to any page that is not part of the pointer map itself.) Each pointer map
|
||||
** entry consists of a single byte 'type' and a 4 byte parent page number.
|
||||
** The PTRMAP_XXX identifiers below are the valid types.
|
||||
**
|
||||
** The purpose of the pointer map is to facility moving pages from one
|
||||
** position in the file to another as part of autovacuum. When a page
|
||||
** is moved, the pointer in its parent must be updated to point to the
|
||||
** new location. The pointer map is used to locate the parent page quickly.
|
||||
**
|
||||
** PTRMAP_ROOTPAGE: The database page is a root-page. The page-number is not
|
||||
** used in this case.
|
||||
**
|
||||
** PTRMAP_FREEPAGE: The database page is an unused (free) page. The page-number
|
||||
** is not used in this case.
|
||||
**
|
||||
** PTRMAP_OVERFLOW1: The database page is the first page in a list of
|
||||
** overflow pages. The page number identifies the page that
|
||||
** contains the cell with a pointer to this overflow page.
|
||||
**
|
||||
** PTRMAP_OVERFLOW2: The database page is the second or later page in a list of
|
||||
** overflow pages. The page-number identifies the previous
|
||||
** page in the overflow page list.
|
||||
**
|
||||
** PTRMAP_BTREE: The database page is a non-root btree page. The page number
|
||||
** identifies the parent page in the btree.
|
||||
*/
|
||||
#define PTRMAP_ROOTPAGE 1
|
||||
#define PTRMAP_FREEPAGE 2
|
||||
#define PTRMAP_OVERFLOW1 3
|
||||
#define PTRMAP_OVERFLOW2 4
|
||||
#define PTRMAP_BTREE 5
|
||||
|
||||
/* A bunch of assert() statements to check the transaction state variables
|
||||
** of handle p (type Btree*) are internally consistent.
|
||||
*/
|
||||
#define btreeIntegrity(p) \
|
||||
assert( p->inTrans!=TRANS_NONE || p->pBt->nTransaction<p->pBt->nRef ); \
|
||||
assert( p->pBt->nTransaction<=p->pBt->nRef ); \
|
||||
assert( p->pBt->inTransaction!=TRANS_NONE || p->pBt->nTransaction==0 ); \
|
||||
assert( p->pBt->inTransaction>=p->inTrans );
|
||||
|
||||
|
||||
/*
|
||||
** The ISAUTOVACUUM macro is used within balance_nonroot() to determine
|
||||
** if the database supports auto-vacuum or not. Because it is used
|
||||
** within an expression that is an argument to another macro
|
||||
** (sqliteMallocRaw), it is not possible to use conditional compilation.
|
||||
** So, this macro is defined instead.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
#define ISAUTOVACUUM (pBt->autoVacuum)
|
||||
#else
|
||||
#define ISAUTOVACUUM 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** This structure is passed around through all the sanity checking routines
|
||||
** in order to keep track of some global state information.
|
||||
*/
|
||||
typedef struct IntegrityCk IntegrityCk;
|
||||
struct IntegrityCk {
|
||||
BtShared *pBt; /* The tree being checked out */
|
||||
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
|
||||
int nPage; /* Number of pages in the database */
|
||||
int *anRef; /* Number of times each page is referenced */
|
||||
int mxErr; /* Stop accumulating errors when this reaches zero */
|
||||
char *zErrMsg; /* An error message. NULL if no errors seen. */
|
||||
int nErr; /* Number of messages written to zErrMsg so far */
|
||||
};
|
||||
|
||||
/*
|
||||
** Read or write a two- and four-byte big-endian integer values.
|
||||
*/
|
||||
#define get2byte sqlite3Get2byte
|
||||
#define get4byte sqlite3Get4byte
|
||||
#define put2byte sqlite3Put2byte
|
||||
#define put4byte sqlite3Put4byte
|
839
src/malloc.c
Normal file
839
src/malloc.c
Normal file
@@ -0,0 +1,839 @@
|
||||
/*
|
||||
** 2001 September 15
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** Memory allocation functions used throughout sqlite.
|
||||
**
|
||||
**
|
||||
** $Id: malloc.c,v 1.1 2007/05/05 11:48:54 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/*
|
||||
** MALLOC WRAPPER ARCHITECTURE
|
||||
**
|
||||
** The sqlite code accesses dynamic memory allocation/deallocation by invoking
|
||||
** the following six APIs (which may be implemented as macros).
|
||||
**
|
||||
** sqlite3Malloc()
|
||||
** sqlite3MallocRaw()
|
||||
** sqlite3Realloc()
|
||||
** sqlite3ReallocOrFree()
|
||||
** sqlite3Free()
|
||||
** sqlite3AllocSize()
|
||||
**
|
||||
** The function sqlite3FreeX performs the same task as sqlite3Free and is
|
||||
** guaranteed to be a real function. The same holds for sqlite3MallocX
|
||||
**
|
||||
** The above APIs are implemented in terms of the functions provided in the
|
||||
** operating-system interface. The OS interface is never accessed directly
|
||||
** by code outside of this file.
|
||||
**
|
||||
** sqlite3OsMalloc()
|
||||
** sqlite3OsRealloc()
|
||||
** sqlite3OsFree()
|
||||
** sqlite3OsAllocationSize()
|
||||
**
|
||||
** Functions sqlite3MallocRaw() and sqlite3Realloc() may invoke
|
||||
** sqlite3_release_memory() if a call to sqlite3OsMalloc() or
|
||||
** sqlite3OsRealloc() fails (or if the soft-heap-limit for the thread is
|
||||
** exceeded). Function sqlite3Malloc() usually invokes
|
||||
** sqlite3MallocRaw().
|
||||
**
|
||||
** MALLOC TEST WRAPPER ARCHITECTURE
|
||||
**
|
||||
** The test wrapper provides extra test facilities to ensure the library
|
||||
** does not leak memory and handles the failure of the underlying OS level
|
||||
** allocation system correctly. It is only present if the library is
|
||||
** compiled with the SQLITE_MEMDEBUG macro set.
|
||||
**
|
||||
** * Guardposts to detect overwrites.
|
||||
** * Ability to cause a specific Malloc() or Realloc() to fail.
|
||||
** * Audit outstanding memory allocations (i.e check for leaks).
|
||||
*/
|
||||
|
||||
#define MAX(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
#if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
|
||||
/*
|
||||
** Set the soft heap-size limit for the current thread. Passing a negative
|
||||
** value indicates no limit.
|
||||
*/
|
||||
void sqlite3_soft_heap_limit(int n){
|
||||
ThreadData *pTd = sqlite3ThreadData();
|
||||
if( pTd ){
|
||||
pTd->nSoftHeapLimit = n;
|
||||
}
|
||||
sqlite3ReleaseThreadData();
|
||||
}
|
||||
|
||||
/*
|
||||
** Release memory held by SQLite instances created by the current thread.
|
||||
*/
|
||||
int sqlite3_release_memory(int n){
|
||||
return sqlite3PagerReleaseMemory(n);
|
||||
}
|
||||
#else
|
||||
/* If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, then define a version
|
||||
** of sqlite3_release_memory() to be used by other code in this file.
|
||||
** This is done for no better reason than to reduce the number of
|
||||
** pre-processor #ifndef statements.
|
||||
*/
|
||||
#define sqlite3_release_memory(x) 0 /* 0 == no memory freed */
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
/*--------------------------------------------------------------------------
|
||||
** Begin code for memory allocation system test layer.
|
||||
**
|
||||
** Memory debugging is turned on by defining the SQLITE_MEMDEBUG macro.
|
||||
**
|
||||
** SQLITE_MEMDEBUG==1 -> Fence-posting only (thread safe)
|
||||
** SQLITE_MEMDEBUG==2 -> Fence-posting + linked list of allocations (not ts)
|
||||
** SQLITE_MEMDEBUG==3 -> Above + backtraces (not thread safe, req. glibc)
|
||||
*/
|
||||
|
||||
/* Figure out whether or not to store backtrace() information for each malloc.
|
||||
** The backtrace() function is only used if SQLITE_MEMDEBUG is set to 2 or
|
||||
** greater and glibc is in use. If we don't want to use backtrace(), then just
|
||||
** define it as an empty macro and set the amount of space reserved to 0.
|
||||
*/
|
||||
#if defined(__GLIBC__) && SQLITE_MEMDEBUG>2
|
||||
extern int backtrace(void **, int);
|
||||
#define TESTALLOC_STACKSIZE 128
|
||||
#define TESTALLOC_STACKFRAMES ((TESTALLOC_STACKSIZE-8)/sizeof(void*))
|
||||
#else
|
||||
#define backtrace(x, y)
|
||||
#define TESTALLOC_STACKSIZE 0
|
||||
#define TESTALLOC_STACKFRAMES 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Number of 32-bit guard words. This should probably be a multiple of
|
||||
** 2 since on 64-bit machines we want the value returned by sqliteMalloc()
|
||||
** to be 8-byte aligned.
|
||||
*/
|
||||
#ifndef TESTALLOC_NGUARD
|
||||
# define TESTALLOC_NGUARD 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Size reserved for storing file-name along with each malloc()ed blob.
|
||||
*/
|
||||
#define TESTALLOC_FILESIZE 64
|
||||
|
||||
/*
|
||||
** Size reserved for storing the user string. Each time a Malloc() or Realloc()
|
||||
** call succeeds, up to TESTALLOC_USERSIZE bytes of the string pointed to by
|
||||
** sqlite3_malloc_id are stored along with the other test system metadata.
|
||||
*/
|
||||
#define TESTALLOC_USERSIZE 64
|
||||
const char *sqlite3_malloc_id = 0;
|
||||
|
||||
/*
|
||||
** Blocks used by the test layer have the following format:
|
||||
**
|
||||
** <sizeof(void *) pNext pointer>
|
||||
** <sizeof(void *) pPrev pointer>
|
||||
** <TESTALLOC_NGUARD 32-bit guard words>
|
||||
** <The application level allocation>
|
||||
** <TESTALLOC_NGUARD 32-bit guard words>
|
||||
** <32-bit line number>
|
||||
** <TESTALLOC_FILESIZE bytes containing null-terminated file name>
|
||||
** <TESTALLOC_STACKSIZE bytes of backtrace() output>
|
||||
*/
|
||||
|
||||
#define TESTALLOC_OFFSET_GUARD1(p) (sizeof(void *) * 2)
|
||||
#define TESTALLOC_OFFSET_DATA(p) ( \
|
||||
TESTALLOC_OFFSET_GUARD1(p) + sizeof(u32) * TESTALLOC_NGUARD \
|
||||
)
|
||||
#define TESTALLOC_OFFSET_GUARD2(p) ( \
|
||||
TESTALLOC_OFFSET_DATA(p) + sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD \
|
||||
)
|
||||
#define TESTALLOC_OFFSET_LINENUMBER(p) ( \
|
||||
TESTALLOC_OFFSET_GUARD2(p) + sizeof(u32) * TESTALLOC_NGUARD \
|
||||
)
|
||||
#define TESTALLOC_OFFSET_FILENAME(p) ( \
|
||||
TESTALLOC_OFFSET_LINENUMBER(p) + sizeof(u32) \
|
||||
)
|
||||
#define TESTALLOC_OFFSET_USER(p) ( \
|
||||
TESTALLOC_OFFSET_FILENAME(p) + TESTALLOC_FILESIZE \
|
||||
)
|
||||
#define TESTALLOC_OFFSET_STACK(p) ( \
|
||||
TESTALLOC_OFFSET_USER(p) + TESTALLOC_USERSIZE + 8 - \
|
||||
(TESTALLOC_OFFSET_USER(p) % 8) \
|
||||
)
|
||||
|
||||
#define TESTALLOC_OVERHEAD ( \
|
||||
sizeof(void *)*2 + /* pPrev and pNext pointers */ \
|
||||
TESTALLOC_NGUARD*sizeof(u32)*2 + /* Guard words */ \
|
||||
sizeof(u32) + TESTALLOC_FILESIZE + /* File and line number */ \
|
||||
TESTALLOC_USERSIZE + /* User string */ \
|
||||
TESTALLOC_STACKSIZE /* backtrace() stack */ \
|
||||
)
|
||||
|
||||
|
||||
/*
|
||||
** For keeping track of the number of mallocs and frees. This
|
||||
** is used to check for memory leaks. The iMallocFail and iMallocReset
|
||||
** values are used to simulate malloc() failures during testing in
|
||||
** order to verify that the library correctly handles an out-of-memory
|
||||
** condition.
|
||||
*/
|
||||
int sqlite3_nMalloc; /* Number of sqliteMalloc() calls */
|
||||
int sqlite3_nFree; /* Number of sqliteFree() calls */
|
||||
int sqlite3_memUsed; /* TODO Total memory obtained from malloc */
|
||||
int sqlite3_memMax; /* TODO Mem usage high-water mark */
|
||||
int sqlite3_iMallocFail; /* Fail sqliteMalloc() after this many calls */
|
||||
int sqlite3_iMallocReset = -1; /* When iMallocFail reaches 0, set to this */
|
||||
|
||||
void *sqlite3_pFirst = 0; /* Pointer to linked list of allocations */
|
||||
int sqlite3_nMaxAlloc = 0; /* High water mark of ThreadData.nAlloc */
|
||||
int sqlite3_mallocDisallowed = 0; /* assert() in sqlite3Malloc() if set */
|
||||
int sqlite3_isFail = 0; /* True if all malloc calls should fail */
|
||||
const char *sqlite3_zFile = 0; /* Filename to associate debug info with */
|
||||
int sqlite3_iLine = 0; /* Line number for debug info */
|
||||
|
||||
/*
|
||||
** Check for a simulated memory allocation failure. Return true if
|
||||
** the failure should be simulated. Return false to proceed as normal.
|
||||
*/
|
||||
int sqlite3TestMallocFail(){
|
||||
if( sqlite3_isFail ){
|
||||
return 1;
|
||||
}
|
||||
if( sqlite3_iMallocFail>=0 ){
|
||||
sqlite3_iMallocFail--;
|
||||
if( sqlite3_iMallocFail==0 ){
|
||||
sqlite3_iMallocFail = sqlite3_iMallocReset;
|
||||
sqlite3_isFail = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument is a pointer returned by sqlite3OsMalloc() or xRealloc().
|
||||
** assert() that the first and last (TESTALLOC_NGUARD*4) bytes are set to the
|
||||
** values set by the applyGuards() function.
|
||||
*/
|
||||
static void checkGuards(u32 *p)
|
||||
{
|
||||
int i;
|
||||
char *zAlloc = (char *)p;
|
||||
char *z;
|
||||
|
||||
/* First set of guard words */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_GUARD1(p)];
|
||||
for(i=0; i<TESTALLOC_NGUARD; i++){
|
||||
assert(((u32 *)z)[i]==0xdead1122);
|
||||
}
|
||||
|
||||
/* Second set of guard words */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_GUARD2(p)];
|
||||
for(i=0; i<TESTALLOC_NGUARD; i++){
|
||||
u32 guard = 0;
|
||||
memcpy(&guard, &z[i*sizeof(u32)], sizeof(u32));
|
||||
assert(guard==0xdead3344);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument is a pointer returned by sqlite3OsMalloc() or Realloc(). The
|
||||
** first and last (TESTALLOC_NGUARD*4) bytes are set to known values for use as
|
||||
** guard-posts.
|
||||
*/
|
||||
static void applyGuards(u32 *p)
|
||||
{
|
||||
int i;
|
||||
char *z;
|
||||
char *zAlloc = (char *)p;
|
||||
|
||||
/* First set of guard words */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_GUARD1(p)];
|
||||
for(i=0; i<TESTALLOC_NGUARD; i++){
|
||||
((u32 *)z)[i] = 0xdead1122;
|
||||
}
|
||||
|
||||
/* Second set of guard words */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_GUARD2(p)];
|
||||
for(i=0; i<TESTALLOC_NGUARD; i++){
|
||||
static const int guard = 0xdead3344;
|
||||
memcpy(&z[i*sizeof(u32)], &guard, sizeof(u32));
|
||||
}
|
||||
|
||||
/* Line number */
|
||||
z = &((char *)z)[TESTALLOC_NGUARD*sizeof(u32)]; /* Guard words */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)];
|
||||
memcpy(z, &sqlite3_iLine, sizeof(u32));
|
||||
|
||||
/* File name */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)];
|
||||
strncpy(z, sqlite3_zFile, TESTALLOC_FILESIZE);
|
||||
z[TESTALLOC_FILESIZE - 1] = '\0';
|
||||
|
||||
/* User string */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_USER(p)];
|
||||
z[0] = 0;
|
||||
if( sqlite3_malloc_id ){
|
||||
strncpy(z, sqlite3_malloc_id, TESTALLOC_USERSIZE);
|
||||
z[TESTALLOC_USERSIZE-1] = 0;
|
||||
}
|
||||
|
||||
/* backtrace() stack */
|
||||
z = &zAlloc[TESTALLOC_OFFSET_STACK(p)];
|
||||
backtrace((void **)z, TESTALLOC_STACKFRAMES);
|
||||
|
||||
/* Sanity check to make sure checkGuards() is working */
|
||||
checkGuards(p);
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument is a malloc()ed pointer as returned by the test-wrapper.
|
||||
** Return a pointer to the Os level allocation.
|
||||
*/
|
||||
static void *getOsPointer(void *p)
|
||||
{
|
||||
char *z = (char *)p;
|
||||
return (void *)(&z[-1 * TESTALLOC_OFFSET_DATA(p)]);
|
||||
}
|
||||
|
||||
|
||||
#if SQLITE_MEMDEBUG>1
|
||||
/*
|
||||
** The argument points to an Os level allocation. Link it into the threads list
|
||||
** of allocations.
|
||||
*/
|
||||
static void linkAlloc(void *p){
|
||||
void **pp = (void **)p;
|
||||
pp[0] = 0;
|
||||
pp[1] = sqlite3_pFirst;
|
||||
if( sqlite3_pFirst ){
|
||||
((void **)sqlite3_pFirst)[0] = p;
|
||||
}
|
||||
sqlite3_pFirst = p;
|
||||
}
|
||||
|
||||
/*
|
||||
** The argument points to an Os level allocation. Unlinke it from the threads
|
||||
** list of allocations.
|
||||
*/
|
||||
static void unlinkAlloc(void *p)
|
||||
{
|
||||
void **pp = (void **)p;
|
||||
if( p==sqlite3_pFirst ){
|
||||
assert(!pp[0]);
|
||||
assert(!pp[1] || ((void **)(pp[1]))[0]==p);
|
||||
sqlite3_pFirst = pp[1];
|
||||
if( sqlite3_pFirst ){
|
||||
((void **)sqlite3_pFirst)[0] = 0;
|
||||
}
|
||||
}else{
|
||||
void **pprev = pp[0];
|
||||
void **pnext = pp[1];
|
||||
assert(pprev);
|
||||
assert(pprev[1]==p);
|
||||
pprev[1] = (void *)pnext;
|
||||
if( pnext ){
|
||||
assert(pnext[0]==p);
|
||||
pnext[0] = (void *)pprev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Pointer p is a pointer to an OS level allocation that has just been
|
||||
** realloc()ed. Set the list pointers that point to this entry to it's new
|
||||
** location.
|
||||
*/
|
||||
static void relinkAlloc(void *p)
|
||||
{
|
||||
void **pp = (void **)p;
|
||||
if( pp[0] ){
|
||||
((void **)(pp[0]))[1] = p;
|
||||
}else{
|
||||
sqlite3_pFirst = p;
|
||||
}
|
||||
if( pp[1] ){
|
||||
((void **)(pp[1]))[0] = p;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define linkAlloc(x)
|
||||
#define relinkAlloc(x)
|
||||
#define unlinkAlloc(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function sets the result of the Tcl interpreter passed as an argument
|
||||
** to a list containing an entry for each currently outstanding call made to
|
||||
** sqliteMalloc and friends by the current thread. Each list entry is itself a
|
||||
** list, consisting of the following (in order):
|
||||
**
|
||||
** * The number of bytes allocated
|
||||
** * The __FILE__ macro at the time of the sqliteMalloc() call.
|
||||
** * The __LINE__ macro ...
|
||||
** * The value of the sqlite3_malloc_id variable ...
|
||||
** * The output of backtrace() (if available) ...
|
||||
**
|
||||
** Todo: We could have a version of this function that outputs to stdout,
|
||||
** to debug memory leaks when Tcl is not available.
|
||||
*/
|
||||
#if defined(TCLSH) && defined(SQLITE_DEBUG) && SQLITE_MEMDEBUG>1
|
||||
#include <tcl.h>
|
||||
int sqlite3OutstandingMallocs(Tcl_Interp *interp){
|
||||
void *p;
|
||||
Tcl_Obj *pRes = Tcl_NewObj();
|
||||
Tcl_IncrRefCount(pRes);
|
||||
|
||||
|
||||
for(p=sqlite3_pFirst; p; p=((void **)p)[1]){
|
||||
Tcl_Obj *pEntry = Tcl_NewObj();
|
||||
Tcl_Obj *pStack = Tcl_NewObj();
|
||||
char *z;
|
||||
u32 iLine;
|
||||
int nBytes = sqlite3OsAllocationSize(p) - TESTALLOC_OVERHEAD;
|
||||
char *zAlloc = (char *)p;
|
||||
int i;
|
||||
|
||||
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(nBytes));
|
||||
|
||||
z = &zAlloc[TESTALLOC_OFFSET_FILENAME(p)];
|
||||
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1));
|
||||
|
||||
z = &zAlloc[TESTALLOC_OFFSET_LINENUMBER(p)];
|
||||
memcpy(&iLine, z, sizeof(u32));
|
||||
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewIntObj(iLine));
|
||||
|
||||
z = &zAlloc[TESTALLOC_OFFSET_USER(p)];
|
||||
Tcl_ListObjAppendElement(0, pEntry, Tcl_NewStringObj(z, -1));
|
||||
|
||||
z = &zAlloc[TESTALLOC_OFFSET_STACK(p)];
|
||||
for(i=0; i<TESTALLOC_STACKFRAMES; i++){
|
||||
char zHex[128];
|
||||
sqlite3_snprintf(sizeof(zHex), zHex, "%p", ((void **)z)[i]);
|
||||
Tcl_ListObjAppendElement(0, pStack, Tcl_NewStringObj(zHex, -1));
|
||||
}
|
||||
|
||||
Tcl_ListObjAppendElement(0, pEntry, pStack);
|
||||
Tcl_ListObjAppendElement(0, pRes, pEntry);
|
||||
}
|
||||
|
||||
Tcl_ResetResult(interp);
|
||||
Tcl_SetObjResult(interp, pRes);
|
||||
Tcl_DecrRefCount(pRes);
|
||||
return TCL_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This is the test layer's wrapper around sqlite3OsMalloc().
|
||||
*/
|
||||
static void * OSMALLOC(int n){
|
||||
sqlite3OsEnterMutex();
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
sqlite3_nMaxAlloc =
|
||||
MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);
|
||||
#endif
|
||||
assert( !sqlite3_mallocDisallowed );
|
||||
if( !sqlite3TestMallocFail() ){
|
||||
u32 *p;
|
||||
p = (u32 *)sqlite3OsMalloc(n + TESTALLOC_OVERHEAD);
|
||||
assert(p);
|
||||
sqlite3_nMalloc++;
|
||||
applyGuards(p);
|
||||
linkAlloc(p);
|
||||
sqlite3OsLeaveMutex();
|
||||
return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
|
||||
}
|
||||
sqlite3OsLeaveMutex();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OSSIZEOF(void *p){
|
||||
if( p ){
|
||||
u32 *pOs = (u32 *)getOsPointer(p);
|
||||
return sqlite3OsAllocationSize(pOs) - TESTALLOC_OVERHEAD;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the test layer's wrapper around sqlite3OsFree(). The argument is a
|
||||
** pointer to the space allocated for the application to use.
|
||||
*/
|
||||
static void OSFREE(void *pFree){
|
||||
u32 *p; /* Pointer to the OS-layer allocation */
|
||||
sqlite3OsEnterMutex();
|
||||
p = (u32 *)getOsPointer(pFree);
|
||||
checkGuards(p);
|
||||
unlinkAlloc(p);
|
||||
memset(pFree, 0x55, OSSIZEOF(pFree));
|
||||
sqlite3OsFree(p);
|
||||
sqlite3_nFree++;
|
||||
sqlite3OsLeaveMutex();
|
||||
}
|
||||
|
||||
/*
|
||||
** This is the test layer's wrapper around sqlite3OsRealloc().
|
||||
*/
|
||||
static void * OSREALLOC(void *pRealloc, int n){
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
sqlite3_nMaxAlloc =
|
||||
MAX(sqlite3_nMaxAlloc, sqlite3ThreadDataReadOnly()->nAlloc);
|
||||
#endif
|
||||
assert( !sqlite3_mallocDisallowed );
|
||||
if( !sqlite3TestMallocFail() ){
|
||||
u32 *p = (u32 *)getOsPointer(pRealloc);
|
||||
checkGuards(p);
|
||||
p = sqlite3OsRealloc(p, n + TESTALLOC_OVERHEAD);
|
||||
applyGuards(p);
|
||||
relinkAlloc(p);
|
||||
return (void *)(&p[TESTALLOC_NGUARD + 2*sizeof(void *)/sizeof(u32)]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void OSMALLOC_FAILED(){
|
||||
sqlite3_isFail = 0;
|
||||
}
|
||||
|
||||
#else
|
||||
/* Define macros to call the sqlite3OsXXX interface directly if
|
||||
** the SQLITE_MEMDEBUG macro is not defined.
|
||||
*/
|
||||
#define OSMALLOC(x) sqlite3OsMalloc(x)
|
||||
#define OSREALLOC(x,y) sqlite3OsRealloc(x,y)
|
||||
#define OSFREE(x) sqlite3OsFree(x)
|
||||
#define OSSIZEOF(x) sqlite3OsAllocationSize(x)
|
||||
#define OSMALLOC_FAILED()
|
||||
|
||||
#endif /* SQLITE_MEMDEBUG */
|
||||
/*
|
||||
** End code for memory allocation system test layer.
|
||||
**--------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
** This routine is called when we are about to allocate n additional bytes
|
||||
** of memory. If the new allocation will put is over the soft allocation
|
||||
** limit, then invoke sqlite3_release_memory() to try to release some
|
||||
** memory before continuing with the allocation.
|
||||
**
|
||||
** This routine also makes sure that the thread-specific-data (TSD) has
|
||||
** be allocated. If it has not and can not be allocated, then return
|
||||
** false. The updateMemoryUsedCount() routine below will deallocate
|
||||
** the TSD if it ought to be.
|
||||
**
|
||||
** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is
|
||||
** a no-op
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
static int enforceSoftLimit(int n){
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
if( pTsd==0 ){
|
||||
return 0;
|
||||
}
|
||||
assert( pTsd->nAlloc>=0 );
|
||||
if( n>0 && pTsd->nSoftHeapLimit>0 ){
|
||||
while( pTsd->nAlloc+n>pTsd->nSoftHeapLimit && sqlite3_release_memory(n) ){}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
# define enforceSoftLimit(X) 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Update the count of total outstanding memory that is held in
|
||||
** thread-specific-data (TSD). If after this update the TSD is
|
||||
** no longer being used, then deallocate it.
|
||||
**
|
||||
** If SQLITE_ENABLE_MEMORY_MANAGEMENT is not defined, this routine is
|
||||
** a no-op
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
static void updateMemoryUsedCount(int n){
|
||||
ThreadData *pTsd = sqlite3ThreadData();
|
||||
if( pTsd ){
|
||||
pTsd->nAlloc += n;
|
||||
assert( pTsd->nAlloc>=0 );
|
||||
if( pTsd->nAlloc==0 && pTsd->nSoftHeapLimit==0 ){
|
||||
sqlite3ReleaseThreadData();
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define updateMemoryUsedCount(x) /* no-op */
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Allocate and return N bytes of uninitialised memory by calling
|
||||
** sqlite3OsMalloc(). If the Malloc() call fails, attempt to free memory
|
||||
** by calling sqlite3_release_memory().
|
||||
*/
|
||||
void *sqlite3MallocRaw(int n, int doMemManage){
|
||||
void *p = 0;
|
||||
if( n>0 && !sqlite3MallocFailed() && (!doMemManage || enforceSoftLimit(n)) ){
|
||||
while( (p = OSMALLOC(n))==0 && sqlite3_release_memory(n) ){}
|
||||
if( !p ){
|
||||
sqlite3FailedMalloc();
|
||||
OSMALLOC_FAILED();
|
||||
}else if( doMemManage ){
|
||||
updateMemoryUsedCount(OSSIZEOF(p));
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Resize the allocation at p to n bytes by calling sqlite3OsRealloc(). The
|
||||
** pointer to the new allocation is returned. If the Realloc() call fails,
|
||||
** attempt to free memory by calling sqlite3_release_memory().
|
||||
*/
|
||||
void *sqlite3Realloc(void *p, int n){
|
||||
if( sqlite3MallocFailed() ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !p ){
|
||||
return sqlite3Malloc(n, 1);
|
||||
}else{
|
||||
void *np = 0;
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
int origSize = OSSIZEOF(p);
|
||||
#endif
|
||||
if( enforceSoftLimit(n - origSize) ){
|
||||
while( (np = OSREALLOC(p, n))==0 && sqlite3_release_memory(n) ){}
|
||||
if( !np ){
|
||||
sqlite3FailedMalloc();
|
||||
OSMALLOC_FAILED();
|
||||
}else{
|
||||
updateMemoryUsedCount(OSSIZEOF(np) - origSize);
|
||||
}
|
||||
}
|
||||
return np;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Free the memory pointed to by p. p must be either a NULL pointer or a
|
||||
** value returned by a previous call to sqlite3Malloc() or sqlite3Realloc().
|
||||
*/
|
||||
void sqlite3FreeX(void *p){
|
||||
if( p ){
|
||||
updateMemoryUsedCount(0 - OSSIZEOF(p));
|
||||
OSFREE(p);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** A version of sqliteMalloc() that is always a function, not a macro.
|
||||
** Currently, this is used only to alloc to allocate the parser engine.
|
||||
*/
|
||||
void *sqlite3MallocX(int n){
|
||||
return sqliteMalloc(n);
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3Malloc
|
||||
** sqlite3ReallocOrFree
|
||||
**
|
||||
** These two are implemented as wrappers around sqlite3MallocRaw(),
|
||||
** sqlite3Realloc() and sqlite3Free().
|
||||
*/
|
||||
void *sqlite3Malloc(int n, int doMemManage){
|
||||
void *p = sqlite3MallocRaw(n, doMemManage);
|
||||
if( p ){
|
||||
memset(p, 0, n);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
void *sqlite3ReallocOrFree(void *p, int n){
|
||||
void *pNew;
|
||||
pNew = sqlite3Realloc(p, n);
|
||||
if( !pNew ){
|
||||
sqlite3FreeX(p);
|
||||
}
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/*
|
||||
** sqlite3ThreadSafeMalloc() and sqlite3ThreadSafeFree() are used in those
|
||||
** rare scenarios where sqlite may allocate memory in one thread and free
|
||||
** it in another. They are exactly the same as sqlite3Malloc() and
|
||||
** sqlite3Free() except that:
|
||||
**
|
||||
** * The allocated memory is not included in any calculations with
|
||||
** respect to the soft-heap-limit, and
|
||||
**
|
||||
** * sqlite3ThreadSafeMalloc() must be matched with ThreadSafeFree(),
|
||||
** not sqlite3Free(). Calling sqlite3Free() on memory obtained from
|
||||
** ThreadSafeMalloc() will cause an error somewhere down the line.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
void *sqlite3ThreadSafeMalloc(int n){
|
||||
(void)ENTER_MALLOC;
|
||||
return sqlite3Malloc(n, 0);
|
||||
}
|
||||
void sqlite3ThreadSafeFree(void *p){
|
||||
(void)ENTER_MALLOC;
|
||||
if( p ){
|
||||
OSFREE(p);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Return the number of bytes allocated at location p. p must be either
|
||||
** a NULL pointer (in which case 0 is returned) or a pointer returned by
|
||||
** sqlite3Malloc(), sqlite3Realloc() or sqlite3ReallocOrFree().
|
||||
**
|
||||
** The number of bytes allocated does not include any overhead inserted by
|
||||
** any malloc() wrapper functions that may be called. So the value returned
|
||||
** is the number of bytes that were available to SQLite using pointer p,
|
||||
** regardless of how much memory was actually allocated.
|
||||
*/
|
||||
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
int sqlite3AllocSize(void *p){
|
||||
return OSSIZEOF(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Make a copy of a string in memory obtained from sqliteMalloc(). These
|
||||
** functions call sqlite3MallocRaw() directly instead of sqliteMalloc(). This
|
||||
** is because when memory debugging is turned on, these two functions are
|
||||
** called via macros that record the current file and line number in the
|
||||
** ThreadData structure.
|
||||
*/
|
||||
char *sqlite3StrDup(const char *z){
|
||||
char *zNew;
|
||||
int n;
|
||||
if( z==0 ) return 0;
|
||||
n = strlen(z)+1;
|
||||
zNew = sqlite3MallocRaw(n, 1);
|
||||
if( zNew ) memcpy(zNew, z, n);
|
||||
return zNew;
|
||||
}
|
||||
char *sqlite3StrNDup(const char *z, int n){
|
||||
char *zNew;
|
||||
if( z==0 ) return 0;
|
||||
zNew = sqlite3MallocRaw(n+1, 1);
|
||||
if( zNew ){
|
||||
memcpy(zNew, z, n);
|
||||
zNew[n] = 0;
|
||||
}
|
||||
return zNew;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a string from the 2nd and subsequent arguments (up to the
|
||||
** first NULL argument), store the string in memory obtained from
|
||||
** sqliteMalloc() and make the pointer indicated by the 1st argument
|
||||
** point to that string. The 1st argument must either be NULL or
|
||||
** point to memory obtained from sqliteMalloc().
|
||||
*/
|
||||
void sqlite3SetString(char **pz, ...){
|
||||
va_list ap;
|
||||
int nByte;
|
||||
const char *z;
|
||||
char *zResult;
|
||||
|
||||
assert( pz!=0 );
|
||||
nByte = 1;
|
||||
va_start(ap, pz);
|
||||
while( (z = va_arg(ap, const char*))!=0 ){
|
||||
nByte += strlen(z);
|
||||
}
|
||||
va_end(ap);
|
||||
sqliteFree(*pz);
|
||||
*pz = zResult = sqliteMallocRaw( nByte );
|
||||
if( zResult==0 ){
|
||||
return;
|
||||
}
|
||||
*zResult = 0;
|
||||
va_start(ap, pz);
|
||||
while( (z = va_arg(ap, const char*))!=0 ){
|
||||
int n = strlen(z);
|
||||
memcpy(zResult, z, n);
|
||||
zResult += n;
|
||||
}
|
||||
zResult[0] = 0;
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** This function must be called before exiting any API function (i.e.
|
||||
** returning control to the user) that has called sqlite3Malloc or
|
||||
** sqlite3Realloc.
|
||||
**
|
||||
** The returned value is normally a copy of the second argument to this
|
||||
** function. However, if a malloc() failure has occured since the previous
|
||||
** invocation SQLITE_NOMEM is returned instead.
|
||||
**
|
||||
** If the first argument, db, is not NULL and a malloc() error has occured,
|
||||
** then the connection error-code (the value returned by sqlite3_errcode())
|
||||
** is set to SQLITE_NOMEM.
|
||||
*/
|
||||
static int mallocHasFailed = 0;
|
||||
int sqlite3ApiExit(sqlite3* db, int rc){
|
||||
if( sqlite3MallocFailed() ){
|
||||
mallocHasFailed = 0;
|
||||
sqlite3OsLeaveMutex();
|
||||
sqlite3Error(db, SQLITE_NOMEM, 0);
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc & (db ? db->errMask : 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return true is a malloc has failed in this thread since the last call
|
||||
** to sqlite3ApiExit(), or false otherwise.
|
||||
*/
|
||||
int sqlite3MallocFailed(){
|
||||
return (mallocHasFailed && sqlite3OsInMutex(1));
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the "malloc has failed" condition to true for this thread.
|
||||
*/
|
||||
void sqlite3FailedMalloc(){
|
||||
if( !sqlite3MallocFailed() ){
|
||||
sqlite3OsEnterMutex();
|
||||
assert( mallocHasFailed==0 );
|
||||
mallocHasFailed = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SQLITE_MEMDEBUG
|
||||
/*
|
||||
** This function sets a flag in the thread-specific-data structure that will
|
||||
** cause an assert to fail if sqliteMalloc() or sqliteRealloc() is called.
|
||||
*/
|
||||
void sqlite3MallocDisallow(){
|
||||
assert( sqlite3_mallocDisallowed>=0 );
|
||||
sqlite3_mallocDisallowed++;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function clears the flag set in the thread-specific-data structure set
|
||||
** by sqlite3MallocDisallow().
|
||||
*/
|
||||
void sqlite3MallocAllow(){
|
||||
assert( sqlite3_mallocDisallowed>0 );
|
||||
sqlite3_mallocDisallowed--;
|
||||
}
|
||||
#endif
|
13
src/pager.c
13
src/pager.c
@@ -18,7 +18,7 @@
|
||||
** file simultaneously, or one process from reading the database while
|
||||
** another is writing.
|
||||
**
|
||||
** @(#) $Id: pager.c,v 1.335 2007/05/04 13:15:56 drh Exp $
|
||||
** @(#) $Id: pager.c,v 1.336 2007/05/05 11:48:54 drh Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_DISKIO
|
||||
#include "sqliteInt.h"
|
||||
@@ -458,7 +458,7 @@ static int read32bits(OsFile *fd, u32 *pRes){
|
||||
unsigned char ac[4];
|
||||
int rc = sqlite3OsRead(fd, ac, sizeof(ac));
|
||||
if( rc==SQLITE_OK ){
|
||||
*pRes = (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];
|
||||
*pRes = sqlite3Get4byte(ac);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -466,12 +466,7 @@ static int read32bits(OsFile *fd, u32 *pRes){
|
||||
/*
|
||||
** Write a 32-bit integer into a string buffer in big-endian byte order.
|
||||
*/
|
||||
static void put32bits(char *ac, u32 val){
|
||||
ac[0] = (val>>24) & 0xff;
|
||||
ac[1] = (val>>16) & 0xff;
|
||||
ac[2] = (val>>8) & 0xff;
|
||||
ac[3] = val & 0xff;
|
||||
}
|
||||
#define put32bits(A,B) sqlite3Put4byte((u8*)A,B)
|
||||
|
||||
/*
|
||||
** Write a 32-bit integer into the given file descriptor. Return SQLITE_OK
|
||||
@@ -490,7 +485,7 @@ static int write32bits(OsFile *fd, u32 val){
|
||||
static u32 retrieve32bits(PgHdr *p, int offset){
|
||||
unsigned char *ac;
|
||||
ac = &((unsigned char*)PGHDR_TO_DATA(p))[offset];
|
||||
return (ac[0]<<24) | (ac[1]<<16) | (ac[2]<<8) | ac[3];
|
||||
return sqlite3Get4byte(ac);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.556 2007/05/04 18:30:41 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.557 2007/05/05 11:48:54 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@@ -1915,6 +1915,11 @@ FuncDef *sqlite3VtabOverloadFunction(FuncDef*, int nArg, Expr*);
|
||||
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
|
||||
int sqlite3Reprepare(Vdbe*);
|
||||
|
||||
u32 sqlite3Get2byte(const u8*);
|
||||
u32 sqlite3Get4byte(const u8*);
|
||||
void sqlite3Put2byte(u8*, u32);
|
||||
void sqlite3Put4byte(u8*, u32);
|
||||
|
||||
#ifdef SQLITE_SSE
|
||||
#include "sseInt.h"
|
||||
#endif
|
||||
|
39
src/test1.c
39
src/test1.c
@@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test1.c,v 1.244 2007/05/04 19:03:03 danielk1977 Exp $
|
||||
** $Id: test1.c,v 1.245 2007/05/05 11:48:54 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "tcl.h"
|
||||
@@ -31,6 +31,43 @@ struct SqliteDb {
|
||||
sqlite3 *db;
|
||||
};
|
||||
|
||||
/*
|
||||
** Convert text generated by the "%p" conversion format back into
|
||||
** a pointer.
|
||||
*/
|
||||
static int testHexToInt(int h){
|
||||
if( h>='0' && h<='9' ){
|
||||
return h - '0';
|
||||
}else if( h>='a' && h<='f' ){
|
||||
return h - 'a' + 10;
|
||||
}else{
|
||||
assert( h>='A' && h<='F' );
|
||||
return h - 'A' + 10;
|
||||
}
|
||||
}
|
||||
void *sqlite3TextToPtr(const char *z){
|
||||
void *p;
|
||||
u64 v;
|
||||
u32 v2;
|
||||
if( z[0]=='0' && z[1]=='x' ){
|
||||
z += 2;
|
||||
}
|
||||
v = 0;
|
||||
while( *z ){
|
||||
v = (v<<4) + testHexToInt(*z);
|
||||
z++;
|
||||
}
|
||||
if( sizeof(p)==sizeof(v) ){
|
||||
memcpy(&p, &v, sizeof(p));
|
||||
}else{
|
||||
assert( sizeof(p)==sizeof(v2) );
|
||||
v2 = (u32)v;
|
||||
memcpy(&p, &v2, sizeof(p));
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** A TCL command that returns the address of the sqlite* pointer
|
||||
** for an sqlite connection instance. Bad things happen if the
|
||||
|
965
src/util.c
965
src/util.c
File diff suppressed because it is too large
Load Diff
@@ -72,6 +72,7 @@ puts $out [subst \
|
||||
#
|
||||
foreach hdr {
|
||||
btree.h
|
||||
btreeInt.h
|
||||
hash.h
|
||||
keywordhash.h
|
||||
opcodes.h
|
||||
@@ -152,6 +153,7 @@ foreach file {
|
||||
date.c
|
||||
os.c
|
||||
|
||||
malloc.c
|
||||
printf.c
|
||||
random.c
|
||||
utf.c
|
||||
|
Reference in New Issue
Block a user