/ Check-in [97914266]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a problem preventing resumption of RBU operations after recovering from a process or system failure that occurs during the incremental-checkpoint phase.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 97914266cb4ec63b0c9185ab139673139bd2f0ed
User & Date: dan 2017-01-13 18:24:37
Context
2017-01-16
18:10
Back out check-in [0b3174e0b1364c] and replace it with a better fix for \ticket [91e2e8ba6ff2e2] - a fix that does not cause the problem identified by ticket [7ffd1ca1d2ad4ec]. Add new test cases for both tickets. check-in: 9b64af7b user: drh tags: trunk
16:01
Add test cases for tickets [91e2e8ba6ff2e2] and [7ffd1ca1d2ad4ec]. check-in: 9d0dfe0b user: drh tags: automatic-index-affinity
11:54
An example showing how to improve performance of sqlite3VdbeSerialPut() using the GCC intrinsic function __builtin_bswap64(). Leaf check-in: e42ed9b4 user: drh tags: builtin-bswap64
2017-01-13
22:21
Merge updates from trunk. check-in: 8b42b8e3 user: mistachkin tags: winSectorSize
18:24
Fix a problem preventing resumption of RBU operations after recovering from a process or system failure that occurs during the incremental-checkpoint phase. check-in: 97914266 user: dan tags: trunk
12:53
Fix the build for SQLITE_ENABLE_MEMORY_MANAGEMENT. check-in: 8c85b8fd user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Added ext/rbu/rburesume.test.





























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
# 2017 January 13
#
# 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.
#
#***********************************************************************
#
# This file contains tests for resumption of RBU operations in the
# case where the previous RBU process crashed.
#

source [file join [file dirname [info script]] rbu_common.tcl]
set ::testprefix rburesume

forcedelete test.db-shm test.db-oal
do_execsql_test 1.0 {
  CREATE TABLE t1(a PRIMARY KEY, b, c);
  CREATE INDEX t1a ON t1(a);
  CREATE INDEX t1b ON t1(b);
  CREATE INDEX t1c ON t1(c);
  WITH s(i) AS (
    VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<50
  )
  INSERT INTO t1 SELECT randomblob(50), randomblob(75), randomblob(100) FROM s;
}
db_save_and_close

do_test 1.1 {
  list [file exists test.db] \
       [file exists test.db-wal] \
       [file exists test.db-shm] \
       [file exists test.db-oal]
} {1 0 0 0}

# Each iteration of the following loop:
#
#   1. Restores the db to the state it was in following test case 1.0
#   2. Opens an RBU vacuum and steps it $n times.
#   3. Closes the RBU vacuum handled opened in (2).
#   4. Opens a second RBU vacuum handle, resumes and completes the vacuum op. 
#
# The loop runs until $n is large enough that step (2) vacuums the entire
# database.
#
for {set n 1} {$n < 5000} {incr n} {
  db_restore
  forcedelete state.db
  sqlite3rbu_vacuum rbu test.db state.db
  for {set i 0} {$i<$n} {incr i} {
    set rc [rbu step]
    if {$rc == "SQLITE_DONE"} break
  }
  rbu close
  if {$rc == "SQLITE_DONE"} break

  do_test 1.2.$n.1 {
    sqlite3rbu_vacuum rbu test.db state.db
    while {[rbu step]=="SQLITE_OK"} {}
    rbu close
  } {SQLITE_DONE}

  do_test 1.2.$n.2 {
    sqlite3 db2 test.db
    db2 eval { 
      SELECT count(*) FROM t1;
      PRAGMA integrity_check;
    }
  } {50 ok}
  db2 close
}

# Each iteration of this loop:
#
#   1. Restores the db to the state it was in following test case 1.0
#   2. Opens an RBU vacuum and steps it $n times.
#   3. Takes a copy of all database files and the state db.
#   4. Opens a second RBU vacuum handle on the copy, resumes and completes the
#      vacuum op. 
#
# The loop runs until $n is large enough that step (2) vacuums the entire
# database.
#
for {set n 1} {$n < 5000} {incr n} {
  db_restore
  forcedelete state.db state.db-shm state.db-oal state.db-wal
  sqlite3rbu_vacuum rbu test.db state.db
  for {set i 0} {$i<$n} {incr i} {
    set rc [rbu step]
    if {$rc == "SQLITE_DONE"} break
  }
  if {$rc == "SQLITE_DONE"} {
    rbu close
    break
  }

  foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
    set f2 [string map [list test.db test.db2] $f]
    if {[file exists $f]} {
      forcecopy $f $f2
    } else {
      forcedelete $f2
    }
  }
  forcecopy state.db state.db2
  rbu close

  do_test 1.3.$n.1 {
    sqlite3rbu_vacuum rbu test.db2 state.db2
    while {[rbu step]=="SQLITE_OK"} {}
    rbu close
  } {SQLITE_DONE}

  do_test 1.3.$n.2 {
    sqlite3 db2 test.db2
    db2 eval { 
      SELECT count(*) FROM t1;
      PRAGMA integrity_check;
    }
  } {50 ok}
  db2 close
}

# Each iteration of this loop:
#
#   1. Restores the db to the state it was in following test case 1.0
#   2. Opens an RBU vacuum and steps it 10 times. Then closes it.
#   2. Opens an RBU vacuum and steps it $n times.
#   3. Takes a copy of all database files and the state db.
#   4. Opens a second RBU vacuum handle on the copy, resumes and completes the
#      vacuum op. 
#
# The loop runs until $n is large enough that step (3) vacuums the entire
# database.
#
for {set n 1} {$n < 5000} {incr n} {
  db_restore
  forcedelete state.db state.db-shm state.db-oal state.db-wal

  sqlite3rbu_vacuum rbu test.db state.db
  for {set i 0} {$i<10} {incr i} {
    rbu step
  }
  rbu close

  sqlite3rbu_vacuum rbu test.db state.db
  for {set i 0} {$i<$n} {incr i} {
    set rc [rbu step]
    if {$rc == "SQLITE_DONE"} break
  }
  if {$rc == "SQLITE_DONE"} {
    rbu close
    break
  }

  foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
    set f2 [string map [list test.db test.db2] $f]
    if {[file exists $f]} {
      forcecopy $f $f2
    } else {
      forcedelete $f2
    }
  }
  forcecopy state.db state.db2
  rbu close

  do_test 1.4.$n.1 {
    sqlite3rbu_vacuum rbu test.db2 state.db2
    while {[rbu step]=="SQLITE_OK"} {}
    rbu close
  } {SQLITE_DONE}

  do_test 1.4.$n.2 {
    sqlite3 db2 test.db2
    db2 eval { 
      SELECT count(*) FROM t1;
      PRAGMA integrity_check;
    }
  } {50 ok}
  db2 close
}

forcedelete rbu.db
do_test 2.0 {
  sqlite3 db2 rbu.db
  db2 eval {
    CREATE TABLE data_t1(a, b, c, rbu_control);
    WITH s(i) AS (
        VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<10
    )
    INSERT INTO data_t1 
      SELECT randomblob(50), randomblob(75), randomblob(100), 0 FROM s;
  }
  db2 close
} {}

# Each iteration of this loop:
#
#   1. Restores the db to the state it was in following test case 1.0
#   2. Opens an RBU handle to apply the RBU update created in test case 2.0.
#   3. Steps the RBU handle $n times.
#   4. Takes a copy of all database files and the state db.
#   5. Opens a second RBU handle on the copy, resumes and completes the
#      RBU op. Checks it worked as expected.
#
# The loop runs until $n is large enough that step (3) applies the entire
# update.
#
for {set n 1} {$n < 5000} {incr n} {
  db_restore
  forcedelete state.db state.db-shm state.db-oal state.db-wal
  sqlite3rbu rbu test.db rbu.db state.db

  for {set i 0} {$i<$n} {incr i} {
    set rc [rbu step]
    if {$rc == "SQLITE_DONE"} break
  }
  if {$rc == "SQLITE_DONE"} {
    rbu close
    break
  }

  foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} {
    set f2 [string map [list test.db test.db2] $f]
    if {[file exists $f]} {
      forcecopy $f $f2
    } else {
      forcedelete $f2
    }
  }
  forcecopy state.db state.db2
  rbu close

  do_test 2.$n.1 {
    sqlite3rbu rbu test.db2 rbu.db state.db2
    while {[rbu step]=="SQLITE_OK"} {}
    rbu close
  } {SQLITE_DONE}

  do_test 2.$n.2 {
    sqlite3 db2 test.db2
    db2 eval { 
      SELECT count(*) FROM t1;
      PRAGMA integrity_check;
    }
  } {60 ok}
  db2 close
}

finish_test

Changes to ext/rbu/sqlite3rbu.c.

2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
    rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
    if( rc!=SQLITE_NOTFOUND ) p->rc = rc;
    if( p->eStage>=RBU_STAGE_MOVE ){
      bOpen = 1;
    }else{
      RbuState *pState = rbuLoadState(p);
      if( pState ){
        bOpen = (pState->eStage>RBU_STAGE_MOVE);
        rbuFreeState(pState);
      }
    }
    if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1);
  }

  p->eStage = 0;







|







2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
    rc = sqlite3_file_control(p->dbRbu, "main", SQLITE_FCNTL_RBUCNT, (void*)p);
    if( rc!=SQLITE_NOTFOUND ) p->rc = rc;
    if( p->eStage>=RBU_STAGE_MOVE ){
      bOpen = 1;
    }else{
      RbuState *pState = rbuLoadState(p);
      if( pState ){
        bOpen = (pState->eStage>=RBU_STAGE_MOVE);
        rbuFreeState(pState);
      }
    }
    if( bOpen ) p->dbMain = rbuOpenDbhandle(p, p->zRbu, p->nRbu<=1);
  }

  p->eStage = 0;