aboutsummaryrefslogtreecommitdiff
path: root/ext/fts5/fts5_index.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fts5/fts5_index.c')
-rw-r--r--ext/fts5/fts5_index.c92
1 files changed, 68 insertions, 24 deletions
diff --git a/ext/fts5/fts5_index.c b/ext/fts5/fts5_index.c
index 262d5db97..b51e7bad1 100644
--- a/ext/fts5/fts5_index.c
+++ b/ext/fts5/fts5_index.c
@@ -42,7 +42,6 @@
*/
#define FTS5_WORK_UNIT 64 /* Number of leaf pages in unit of work */
-#define FTS5_MIN_MERGE 4 /* Minimum number of segments to merge */
#define FTS5_CRISIS_MERGE 16 /* Maximum number of segments to merge */
#define FTS5_MIN_DLIDX_SIZE 4 /* Add dlidx if this many empty pages */
@@ -61,10 +60,14 @@
** 1. Structure Records:
**
** The set of segments that make up an index - the index structure - are
-** recorded in a single record within the %_data table. The record is a list
-** of SQLite varints.
+** recorded in a single record within the %_data table. The record consists
+** of a single 32-bit configuration cookie value followed by a list of
+** SQLite varints. If the FTS table features more than one index (because
+** there are one or more prefix indexes), it is guaranteed that all share
+** the same cookie value.
**
-** The record begins with three varints:
+** Immediately following the configuration cookie, the record begins with
+** three varints:
**
** + number of levels,
** + total number of segments on all levels,
@@ -288,7 +291,6 @@ typedef struct Fts5StructureSegment Fts5StructureSegment;
struct Fts5Index {
Fts5Config *pConfig; /* Virtual table configuration */
char *zDataTbl; /* Name of %_data table */
- int nMinMerge; /* Minimum input segments in a merge */
int nCrisisMerge; /* Maximum allowed segments per level */
int nWorkUnit; /* Leaf pages in a "unit" of work */
@@ -960,6 +962,7 @@ static void fts5DataRemoveSegment(Fts5Index *p, int iIdx, int iSegid){
static int fts5StructureDecode(
const u8 *pData, /* Buffer containing serialized structure */
int nData, /* Size of buffer pData in bytes */
+ int *piCookie, /* Configuration cookie value */
Fts5Structure **ppOut /* OUT: Deserialized object */
){
int rc = SQLITE_OK;
@@ -970,9 +973,13 @@ static int fts5StructureDecode(
int nByte; /* Bytes of space to allocate at pRet */
Fts5Structure *pRet = 0; /* Structure object to return */
+ /* Grab the cookie value */
+ if( piCookie ) *piCookie = sqlite3Fts5Get32(pData);
+ i = 4;
+
/* Read the total number of levels and segments from the start of the
** structure record. */
- i = getVarint32(&pData[i], nLevel);
+ i += getVarint32(&pData[i], nLevel);
i += getVarint32(&pData[i], nSegment);
nByte = (
sizeof(Fts5Structure) + /* Main structure */
@@ -1083,11 +1090,16 @@ static Fts5Structure *fts5StructureRead(Fts5Index *p, int iIdx){
Fts5Config *pConfig = p->pConfig;
Fts5Structure *pRet = 0; /* Object to return */
Fts5Data *pData; /* %_data entry containing structure record */
+ int iCookie; /* Configuration cookie */
assert( iIdx<=pConfig->nPrefix );
pData = fts5DataRead(p, FTS5_STRUCTURE_ROWID(iIdx));
if( !pData ) return 0;
- p->rc = fts5StructureDecode(pData->p, pData->n, &pRet);
+ p->rc = fts5StructureDecode(pData->p, pData->n, &iCookie, &pRet);
+
+ if( p->rc==SQLITE_OK && p->pConfig->iCookie!=iCookie ){
+ p->rc = sqlite3Fts5ConfigLoad(p->pConfig, iCookie);
+ }
fts5DataRelease(pData);
return pRet;
@@ -1129,9 +1141,16 @@ static void fts5StructureWrite(Fts5Index *p, int iIdx, Fts5Structure *pStruct){
int nSegment; /* Total number of segments */
Fts5Buffer buf; /* Buffer to serialize record into */
int iLvl; /* Used to iterate through levels */
+ int iCookie; /* Cookie value to store */
nSegment = fts5StructureCountSegments(pStruct);
memset(&buf, 0, sizeof(Fts5Buffer));
+
+ /* Append the current configuration cookie */
+ iCookie = p->pConfig->iCookie;
+ if( iCookie<0 ) iCookie = 0;
+ fts5BufferAppend32(&p->rc, &buf, iCookie);
+
fts5BufferAppendVarint(&p->rc, &buf, pStruct->nLevel);
fts5BufferAppendVarint(&p->rc, &buf, nSegment);
fts5BufferAppendVarint(&p->rc, &buf, (i64)pStruct->nWriteCounter);
@@ -2825,6 +2844,7 @@ static void fts5WriteAppendPoslistData(
const u8 *a = aData;
int n = nData;
+ assert( p->pConfig->pgsz>0 );
while( p->rc==SQLITE_OK && (pPage->buf.n + n)>=p->pConfig->pgsz ){
int nReq = p->pConfig->pgsz - pPage->buf.n;
int nCopy = 0;
@@ -3179,7 +3199,11 @@ static void fts5IndexWork(
}
#endif
- if( nBest<p->nMinMerge && pStruct->aLevel[iBestLvl].nMerge==0 ) break;
+ if( nBest<p->pConfig->nAutomerge
+ && pStruct->aLevel[iBestLvl].nMerge==0
+ ){
+ break;
+ }
fts5IndexMergeLevel(p, iIdx, &pStruct, iBestLvl, &nRem);
fts5StructurePromote(p, iBestLvl+1, pStruct);
assert( nRem==0 || p->rc==SQLITE_OK );
@@ -3293,7 +3317,7 @@ static void fts5FlushOneHash(Fts5Index *p, int iHash, int *pnLeaf){
}
}
- if( p->nMinMerge>0 ) fts5IndexWork(p, iHash, &pStruct, pgnoLast);
+ if( p->pConfig->nAutomerge>0 ) fts5IndexWork(p, iHash, &pStruct, pgnoLast);
fts5IndexCrisisMerge(p, iHash, &pStruct);
fts5StructureWrite(p, iHash, pStruct);
fts5StructureRelease(pStruct);
@@ -3371,7 +3395,6 @@ int sqlite3Fts5IndexOpen(
memset(p, 0, sizeof(Fts5Index));
p->pConfig = pConfig;
- p->nMinMerge = FTS5_MIN_MERGE;
p->nCrisisMerge = FTS5_CRISIS_MERGE;
p->nWorkUnit = FTS5_WORK_UNIT;
p->nMaxPendingData = 1024*1024;
@@ -3781,6 +3804,11 @@ int sqlite3Fts5IndexIntegrityCheck(Fts5Index *p, u64 cksum){
}
/*
+** This is part of the fts5_decode() debugging aid.
+**
+** Arguments pBlob/nBlob contain a serialized Fts5Structure object. This
+** function appends a human-readable representation of the same object
+** to the buffer passed as the second argument.
*/
static void fts5DecodeStructure(
int *pRc, /* IN/OUT: error code */
@@ -3790,7 +3818,7 @@ static void fts5DecodeStructure(
int rc; /* Return code */
Fts5Structure *p = 0; /* Decoded structure object */
- rc = fts5StructureDecode(pBlob, nBlob, &p);
+ rc = fts5StructureDecode(pBlob, nBlob, 0, &p);
if( rc!=SQLITE_OK ){
*pRc = rc;
return;
@@ -3986,19 +4014,6 @@ int sqlite3Fts5IndexInit(sqlite3 *db){
}
/*
-** Set the minimum number of segments that an auto-merge operation should
-** attempt to merge together. A value of 1 sets the object to use the
-** compile time default. Zero or less disables auto-merge altogether.
-*/
-void sqlite3Fts5IndexAutomerge(Fts5Index *p, int nMinMerge){
- if( nMinMerge==1 ){
- p->nMinMerge = FTS5_MIN_MERGE;
- }else{
- p->nMinMerge = nMinMerge;
- }
-}
-
-/*
** Iterator pMulti currently points to a valid entry (not EOF). This
** function appends a copy of the position-list of the entry pMulti
** currently points to to buffer pBuf.
@@ -4408,3 +4423,32 @@ int sqlite3Fts5IndexReads(Fts5Index *p){
return p->nRead;
}
+/*
+** Set the 32-bit cookie value at the start of all structure records to
+** the value passed as the second argument.
+**
+** Return SQLITE_OK if successful, or an SQLite error code if an error
+** occurs.
+*/
+int sqlite3Fts5IndexSetCookie(Fts5Index *p, int iNew){
+ int rc = SQLITE_OK;
+ Fts5Config *pConfig = p->pConfig;
+ u8 aCookie[4];
+ int i;
+
+ sqlite3Fts5Put32(aCookie, iNew);
+ for(i=0; rc==SQLITE_OK && i<=pConfig->nPrefix; i++){
+ sqlite3_blob *pBlob = 0;
+ i64 iRowid = FTS5_STRUCTURE_ROWID(i);
+ rc = sqlite3_blob_open(
+ pConfig->db, pConfig->zDb, p->zDataTbl, "block", iRowid, 1, &pBlob
+ );
+ if( rc==SQLITE_OK ){
+ sqlite3_blob_write(pBlob, aCookie, 4, 0);
+ rc = sqlite3_blob_close(pBlob);
+ }
+ }
+
+ return rc;
+}
+