From: dan Date: Thu, 21 Mar 2024 11:37:36 +0000 (+0000) Subject: Have os_unix.c reuse cached file-descriptors in the case when a read-write fd is... X-Git-Tag: version-3.46.0~113 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=af64a22762e068ae8926cdb3e338023cff16cbb3;p=thirdparty%2Fsqlite.git Have os_unix.c reuse cached file-descriptors in the case when a read-write fd is requested on a read-only file and a read-only fd returned. FossilOrigin-Name: a678e85402af08c1e387bf30ff2205f84dd7da749755da565d70f831c007a3d9 --- diff --git a/manifest b/manifest index 0e4698a26a..d352d9cc2b 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sall\stest\scases\sso\sthat\sthey\swork\swith\sSQLITE_ALLOW_ROWID_IN_VIEW. -D 2024-03-21T10:35:33.254 +C Have\sos_unix.c\sreuse\scached\sfile-descriptors\sin\sthe\scase\swhen\sa\sread-write\sfd\sis\srequested\son\sa\sread-only\sfile\sand\sa\sread-only\sfd\sreturned. +D 2024-03-21T11:37:36.346 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -734,7 +734,7 @@ F src/os.h 1ff5ae51d339d0e30d8a9d814f4b8f8e448169304d83a7ed9db66a65732f3e63 F src/os_common.h 6c0eb8dd40ef3e12fe585a13e709710267a258e2c8dd1c40b1948a1d14582e06 F src/os_kv.c 4d39e1f1c180b11162c6dc4aa8ad34053873a639bac6baae23272fc03349986a F src/os_setup.h 6011ad7af5db4e05155f385eb3a9b4470688de6f65d6166b8956e58a3d872107 -F src/os_unix.c 8d7533b3b4d0d2d6ddd34d1ebc92f50a91f04e722a3a9295a000bc3c25128e2f +F src/os_unix.c 6227cbc4ac93046f121436886cf3712da6f4e2082af6314f976eeae1d86b794a F src/os_win.c 6ff43bac175bd9ed79e7c0f96840b139f2f51d01689a638fd05128becf94908a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c ff60e98138d2499082ac6230f01ac508aba545315debccfca2fd6042f5f10fcd @@ -1522,6 +1522,7 @@ F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df F test/rbu.test 168573d353cd0fd10196b87b0caa322c144ef736 F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8 +F test/readonly.test bdf5a451f415bc3153764122d034f553797c27194ffbd1e9763ecd9500af41d2 F test/recover.test 6463509a7404e0c35431dd9b4a1c3b4a29d7a6af8a08462b31670c8a5a616d3a F test/regexp1.test 8f2a8bc1569666e29a4cee6c1a666cd224eb6d50e2470d1dc1df995170f3e0f1 F test/regexp2.test 55ed41da802b0e284ac7e2fe944be3948f93ff25abbca0361a609acfed1368b5 @@ -2181,8 +2182,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 7e13a2c7583dbcb660adde6b0465da037365971c56726b8f18a541d8803ffeed -R 2027b60f20ab6be3fc26d73a48e5361c -U drh -Z 4767141a590293471cedda2bdaf01e5d +P 66c69e2f20f7692e0f34743ae97b09c4d8d11b874cdc5381795f2d1e0410f724 +R 41345a246cf3c264839b8ebe82b82196 +U dan +Z d2317639297bfb820720d835feec7e58 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 423f236b45..ac95fcbf05 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -66c69e2f20f7692e0f34743ae97b09c4d8d11b874cdc5381795f2d1e0410f724 \ No newline at end of file +a678e85402af08c1e387bf30ff2205f84dd7da749755da565d70f831c007a3d9 \ No newline at end of file diff --git a/src/os_unix.c b/src/os_unix.c index 4663c22d94..9e7ba05d68 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -6398,12 +6398,19 @@ static int unixOpen( rc = SQLITE_READONLY_DIRECTORY; }else if( errno!=EISDIR && isReadWrite ){ /* Failed to open the file for read/write access. Try read-only. */ + UnixUnusedFd *pReadonly = 0; flags &= ~(SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE); openFlags &= ~(O_RDWR|O_CREAT); flags |= SQLITE_OPEN_READONLY; openFlags |= O_RDONLY; isReadonly = 1; - fd = robust_open(zName, openFlags, openMode); + pReadonly = findReusableFd(zName, flags); + if( pReadonly ){ + fd = pReadonly->fd; + sqlite3_free(pReadonly); + }else{ + fd = robust_open(zName, openFlags, openMode); + } } } if( fd<0 ){ diff --git a/test/readonly.test b/test/readonly.test new file mode 100644 index 0000000000..811d54f3b5 --- /dev/null +++ b/test/readonly.test @@ -0,0 +1,54 @@ +# 2024 March 21 +# +# 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 using databases in read-only mode on +# unix. +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +source $testdir/lock_common.tcl +source $testdir/wal_common.tcl +set ::testprefix readonly + +do_execsql_test 1.0 { + CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1, 2), (3, 4), (5, 6); +} + +db close +file attributes test.db -permissions r--r--r-- + +sqlite3 db test.db + +do_catchsql_test 1.1 { + INSERT INTO t1 VALUES(7, 8); +} {1 {attempt to write a readonly database}} + +do_execsql_test 1.2 { + BEGIN; + SELECT * FROM t1; +} {1 2 3 4 5 6} + +# The following attempts to open a read/write fd on the database 20,000 +# times. And each time instead opens a read-only fd. At one point this +# was failing to reuse cached fds, causing a "too many open file-descriptors" +# error. +do_test 1.3 { + for {set ii 0} {$ii < 20000} {incr ii} { + sqlite3 db2 test.db + db2 close + } + set {} {} +} {} + + +finish_test