SQLite

Check-in [4ae3300b]
Login

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

Overview
Comment:Fix a problem with rolling back hot journals using the unix-dotfile VFS.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | unix-dotfile-fix
Files: files | file ages | folders
SHA3-256: 4ae3300b79e03381fd7f1033bb7978bb6367369790f17c3bdacac51e205edaf9
User & Date: dan 2024-06-11 20:03:32
Context
2024-06-11
20:28
Handle the case where unix-dotfile is used with URI parameter nolock=1. (check-in: 3925a5b9 user: dan tags: unix-dotfile-fix)
20:03
Fix a problem with rolling back hot journals using the unix-dotfile VFS. (check-in: 4ae3300b user: dan tags: unix-dotfile-fix)
17:04
Remove some dead JS code and update some JS docs. (check-in: 6935ac71 user: stephan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/os_unix.c.

2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288

2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
** The file suffix added to the data base filename in order to create the
** lock directory.
*/
#define DOTLOCK_SUFFIX ".lock"

/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. If such a lock is held, set *pResOut
** to a non-zero value otherwise *pResOut is set to zero.  The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
**
** In dotfile locking, either a lock exists or it does not.  So in this
** variation of CheckReservedLock(), *pResOut is set to true if any lock
** is held on the file and false if the file is unlocked.

*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {
  int rc = SQLITE_OK;
  int reserved = 0;
  unixFile *pFile = (unixFile*)id;

  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );

  assert( pFile );
  reserved = osAccess((const char*)pFile->lockingContext, 0)==0;
  OSTRACE(("TEST WR-LOCK %d %d %d (dotlock)\n", pFile->h, rc, reserved));
  *pResOut = reserved;
  return rc;
}

/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
**
**     (1) SHARED_LOCK







|
|
|
<
|
<
<
>


<
<
<
<

|
<
<
<
|
|







2275
2276
2277
2278
2279
2280
2281
2282
2283
2284

2285


2286
2287
2288




2289
2290



2291
2292
2293
2294
2295
2296
2297
2298
2299
** The file suffix added to the data base filename in order to create the
** lock directory.
*/
#define DOTLOCK_SUFFIX ".lock"

/*
** This routine checks if there is a RESERVED lock held on the specified
** file by this or any other process. The caller always holds a SHARED
** lock when it is called. This means that no other connection could
** hold a RESERVED lock, as unix-dotfile uses just a single exclusive lock -

** the presence of the dotfile - for all 4 VFS locks. So this function sets


** (*pResOut) to 0 (no other connection holds RESERVED) and returns SQLITE_OK.
*/
static int dotlockCheckReservedLock(sqlite3_file *id, int *pResOut) {




  SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
  assert( ((unixFile*)id)->eFileLock>=SHARED_LOCK );



  *pResOut = 0;
  return SQLITE_OK;
}

/*
** Lock the file with the lock specified by parameter eFileLock - one
** of the following:
**
**     (1) SHARED_LOCK

Changes to test/lock5.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
# 2008 June 28
#
# 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 implements regression tests for SQLite library.  The
# focus of this script is database locks.
#
# $Id: lock5.test,v 1.6 2008/12/04 12:34:16 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl


# This file is only run if using the unix backend compiled with the
# SQLITE_ENABLE_LOCKING_STYLE macro.
db close
if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
  finish_test
  return













<



>







1
2
3
4
5
6
7
8
9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
# 2008 June 28
#
# 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 implements regression tests for SQLite library.  The
# focus of this script is database locks.
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix lock5

# This file is only run if using the unix backend compiled with the
# SQLITE_ENABLE_LOCKING_STYLE macro.
db close
if {[catch {sqlite3 db test.db -vfs unix-none} msg]} {
  finish_test
  return
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  db close
  file exists test.db.lock
} {0}

#####################################################################

forcedelete test.db
if {[catch {sqlite3 db test.db -vfs unix-flock} msg]} {
  finish_test
  return
}

do_test lock5-flock.1 {
  sqlite3 db test.db -vfs unix-flock
  execsql {
    CREATE TABLE t1(a, b);
    BEGIN;
    INSERT INTO t1 VALUES(1, 2);







|
<
<
<







97
98
99
100
101
102
103
104



105
106
107
108
109
110
111
  db close
  file exists test.db.lock
} {0}

#####################################################################

forcedelete test.db
if {0==[catch {sqlite3 db test.db -vfs unix-flock} msg]} {




do_test lock5-flock.1 {
  sqlite3 db test.db -vfs unix-flock
  execsql {
    CREATE TABLE t1(a, b);
    BEGIN;
    INSERT INTO t1 VALUES(1, 2);
144
145
146
147
148
149
150
151


152


153
154
155
156
157
158


159
160
161
162
163
164
165
  db close
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}

do_test lock5-flock.8 {
  db2 close
} {}



#####################################################################



do_test lock5-none.1 {
  sqlite3 db test.db -vfs unix-none
  sqlite3 db2 test.db -vfs unix-none
  execsql { PRAGMA mmap_size = 0 } db2
  execsql {


    BEGIN;
    INSERT INTO t1 VALUES(3, 4);
  }
} {}
do_test lock5-none.2 {
  execsql { SELECT * FROM t1 }
} {1 2 3 4}








>
>

>
>






>
>







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
  db close
  catchsql { SELECT * FROM t1 } db2
} {0 {1 2}}

do_test lock5-flock.8 {
  db2 close
} {}

}

#####################################################################

reset_db

do_test lock5-none.1 {
  sqlite3 db test.db -vfs unix-none
  sqlite3 db2 test.db -vfs unix-none
  execsql { PRAGMA mmap_size = 0 } db2
  execsql {
    CREATE TABLE t1(a, b);
    INSERT INTO t1 VALUES(1, 2);
    BEGIN;
    INSERT INTO t1 VALUES(3, 4);
  }
} {}
do_test lock5-none.2 {
  execsql { SELECT * FROM t1 }
} {1 2 3 4}
188
189
190
191
192
193
194
195
























































196


  db close
  db2 close
} {}

ifcapable lock_proxy_pragmas {
  set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
}

























































finish_test










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
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
255
256
257
  db close
  db2 close
} {}

ifcapable lock_proxy_pragmas {
  set env(SQLITE_FORCE_PROXY_LOCKING) $::using_proxy
}

#####################################################################
reset_db

# 1. Create a large database using the unix-dotfile VFS
# 2. Write a large transaction to the db, so that the cache spills, but do
#    not commit it.
# 3. Make a copy of the database files on disk.
# 4. Try to read from the copy using unix-dotfile VFS. This fails because
#    the dotfile still exists, so SQLite things the database is locked.
# 5. Remove the dotfile.
# 6. Try to read the db again. This time, the old transaction is rolled
#    back and the read permitted.
#
do_test 2.dotfile.1 {
  sqlite3 db test.db -vfs unix-dotfile
  execsql {
    PRAGMA cache_size = 10;
    CREATE TABLE t1(x, y, z);
    CREATE INDEX t1x ON t1(x);
    WITH s(i) AS (
      SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000
    )
    INSERT INTO t1 SELECT hex(randomblob(20)), hex(randomblob(500)), i FROM s;
  }
} {}

do_execsql_test 2.dotfile.2 {
  BEGIN;
    UPDATE t1 SET z=z+1, x=hex(randomblob(20));
}

do_test 2.dotfile.3 {
  list                            \
    [file exists test.db]         \
    [file exists test.db-journal] \
    [file exists test.db.lock]
} {1 1 1}

do_test 2.dotfile.4 {
  forcecopy test.db test.db2
  forcecopy test.db-journal test.db2-journal
  file mkdir test.db2.lock

  sqlite3 db2 test.db2 -vfs unix-dotfile
  catchsql {
    SELECT count(*) FROM t1;
  } db2
} {1 {database is locked}}

do_test 2.dotfile.5 {
  file delete test.db2.lock
  execsql {
    PRAGMA integrity_check
  } db2
} {ok}

finish_test