sl@0
|
1 |
/*
|
sl@0
|
2 |
** 2005 June 16
|
sl@0
|
3 |
**
|
sl@0
|
4 |
** The author disclaims copyright to this source code. In place of
|
sl@0
|
5 |
** a legal notice, here is a blessing:
|
sl@0
|
6 |
**
|
sl@0
|
7 |
** May you do good and not evil.
|
sl@0
|
8 |
** May you find forgiveness for yourself and forgive others.
|
sl@0
|
9 |
** May you share freely, never taking more than you give.
|
sl@0
|
10 |
**
|
sl@0
|
11 |
*************************************************************************
|
sl@0
|
12 |
** This file implements a FIFO queue of rowids used for processing
|
sl@0
|
13 |
** UPDATE and DELETE statements.
|
sl@0
|
14 |
**
|
sl@0
|
15 |
** $Id: vdbefifo.c,v 1.8 2008/07/28 19:34:54 drh Exp $
|
sl@0
|
16 |
*/
|
sl@0
|
17 |
#include "sqliteInt.h"
|
sl@0
|
18 |
#include "vdbeInt.h"
|
sl@0
|
19 |
|
sl@0
|
20 |
/*
|
sl@0
|
21 |
** Constants FIFOSIZE_FIRST and FIFOSIZE_MAX are the initial
|
sl@0
|
22 |
** number of entries in a fifo page and the maximum number of
|
sl@0
|
23 |
** entries in a fifo page.
|
sl@0
|
24 |
*/
|
sl@0
|
25 |
#define FIFOSIZE_FIRST (((128-sizeof(FifoPage))/8)+1)
|
sl@0
|
26 |
#ifdef SQLITE_MALLOC_SOFT_LIMIT
|
sl@0
|
27 |
# define FIFOSIZE_MAX (((SQLITE_MALLOC_SOFT_LIMIT-sizeof(FifoPage))/8)+1)
|
sl@0
|
28 |
#else
|
sl@0
|
29 |
# define FIFOSIZE_MAX (((262144-sizeof(FifoPage))/8)+1)
|
sl@0
|
30 |
#endif
|
sl@0
|
31 |
|
sl@0
|
32 |
/*
|
sl@0
|
33 |
** Allocate a new FifoPage and return a pointer to it. Return NULL if
|
sl@0
|
34 |
** we run out of memory. Leave space on the page for nEntry entries.
|
sl@0
|
35 |
*/
|
sl@0
|
36 |
static FifoPage *allocateFifoPage(sqlite3 *db, int nEntry){
|
sl@0
|
37 |
FifoPage *pPage;
|
sl@0
|
38 |
if( nEntry>FIFOSIZE_MAX ){
|
sl@0
|
39 |
nEntry = FIFOSIZE_MAX;
|
sl@0
|
40 |
}
|
sl@0
|
41 |
pPage = sqlite3DbMallocRaw(db, sizeof(FifoPage) + sizeof(i64)*(nEntry-1) );
|
sl@0
|
42 |
if( pPage ){
|
sl@0
|
43 |
pPage->nSlot = nEntry;
|
sl@0
|
44 |
pPage->iWrite = 0;
|
sl@0
|
45 |
pPage->iRead = 0;
|
sl@0
|
46 |
pPage->pNext = 0;
|
sl@0
|
47 |
}
|
sl@0
|
48 |
return pPage;
|
sl@0
|
49 |
}
|
sl@0
|
50 |
|
sl@0
|
51 |
/*
|
sl@0
|
52 |
** Initialize a Fifo structure.
|
sl@0
|
53 |
*/
|
sl@0
|
54 |
void sqlite3VdbeFifoInit(Fifo *pFifo, sqlite3 *db){
|
sl@0
|
55 |
memset(pFifo, 0, sizeof(*pFifo));
|
sl@0
|
56 |
pFifo->db = db;
|
sl@0
|
57 |
}
|
sl@0
|
58 |
|
sl@0
|
59 |
/*
|
sl@0
|
60 |
** Push a single 64-bit integer value into the Fifo. Return SQLITE_OK
|
sl@0
|
61 |
** normally. SQLITE_NOMEM is returned if we are unable to allocate
|
sl@0
|
62 |
** memory.
|
sl@0
|
63 |
*/
|
sl@0
|
64 |
int sqlite3VdbeFifoPush(Fifo *pFifo, i64 val){
|
sl@0
|
65 |
FifoPage *pPage;
|
sl@0
|
66 |
pPage = pFifo->pLast;
|
sl@0
|
67 |
if( pPage==0 ){
|
sl@0
|
68 |
pPage = pFifo->pLast = pFifo->pFirst =
|
sl@0
|
69 |
allocateFifoPage(pFifo->db, FIFOSIZE_FIRST);
|
sl@0
|
70 |
if( pPage==0 ){
|
sl@0
|
71 |
return SQLITE_NOMEM;
|
sl@0
|
72 |
}
|
sl@0
|
73 |
}else if( pPage->iWrite>=pPage->nSlot ){
|
sl@0
|
74 |
pPage->pNext = allocateFifoPage(pFifo->db, pFifo->nEntry);
|
sl@0
|
75 |
if( pPage->pNext==0 ){
|
sl@0
|
76 |
return SQLITE_NOMEM;
|
sl@0
|
77 |
}
|
sl@0
|
78 |
pPage = pFifo->pLast = pPage->pNext;
|
sl@0
|
79 |
}
|
sl@0
|
80 |
pPage->aSlot[pPage->iWrite++] = val;
|
sl@0
|
81 |
pFifo->nEntry++;
|
sl@0
|
82 |
return SQLITE_OK;
|
sl@0
|
83 |
}
|
sl@0
|
84 |
|
sl@0
|
85 |
/*
|
sl@0
|
86 |
** Extract a single 64-bit integer value from the Fifo. The integer
|
sl@0
|
87 |
** extracted is the one least recently inserted. If the Fifo is empty
|
sl@0
|
88 |
** return SQLITE_DONE.
|
sl@0
|
89 |
*/
|
sl@0
|
90 |
int sqlite3VdbeFifoPop(Fifo *pFifo, i64 *pVal){
|
sl@0
|
91 |
FifoPage *pPage;
|
sl@0
|
92 |
if( pFifo->nEntry==0 ){
|
sl@0
|
93 |
return SQLITE_DONE;
|
sl@0
|
94 |
}
|
sl@0
|
95 |
assert( pFifo->nEntry>0 );
|
sl@0
|
96 |
pPage = pFifo->pFirst;
|
sl@0
|
97 |
assert( pPage!=0 );
|
sl@0
|
98 |
assert( pPage->iWrite>pPage->iRead );
|
sl@0
|
99 |
assert( pPage->iWrite<=pPage->nSlot );
|
sl@0
|
100 |
assert( pPage->iRead<pPage->nSlot );
|
sl@0
|
101 |
assert( pPage->iRead>=0 );
|
sl@0
|
102 |
*pVal = pPage->aSlot[pPage->iRead++];
|
sl@0
|
103 |
pFifo->nEntry--;
|
sl@0
|
104 |
if( pPage->iRead>=pPage->iWrite ){
|
sl@0
|
105 |
pFifo->pFirst = pPage->pNext;
|
sl@0
|
106 |
sqlite3DbFree(pFifo->db, pPage);
|
sl@0
|
107 |
if( pFifo->nEntry==0 ){
|
sl@0
|
108 |
assert( pFifo->pLast==pPage );
|
sl@0
|
109 |
pFifo->pLast = 0;
|
sl@0
|
110 |
}else{
|
sl@0
|
111 |
assert( pFifo->pFirst!=0 );
|
sl@0
|
112 |
}
|
sl@0
|
113 |
}else{
|
sl@0
|
114 |
assert( pFifo->nEntry>0 );
|
sl@0
|
115 |
}
|
sl@0
|
116 |
return SQLITE_OK;
|
sl@0
|
117 |
}
|
sl@0
|
118 |
|
sl@0
|
119 |
/*
|
sl@0
|
120 |
** Delete all information from a Fifo object. Free all memory held
|
sl@0
|
121 |
** by the Fifo.
|
sl@0
|
122 |
*/
|
sl@0
|
123 |
void sqlite3VdbeFifoClear(Fifo *pFifo){
|
sl@0
|
124 |
FifoPage *pPage, *pNextPage;
|
sl@0
|
125 |
for(pPage=pFifo->pFirst; pPage; pPage=pNextPage){
|
sl@0
|
126 |
pNextPage = pPage->pNext;
|
sl@0
|
127 |
sqlite3DbFree(pFifo->db, pPage);
|
sl@0
|
128 |
}
|
sl@0
|
129 |
sqlite3VdbeFifoInit(pFifo, pFifo->db);
|
sl@0
|
130 |
}
|