about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--lib/PublicInbox/Msgmap.pm3
-rw-r--r--lib/PublicInbox/Over.pm23
-rw-r--r--lib/PublicInbox/OverIdx.pm5
-rw-r--r--t/over.t10
4 files changed, 32 insertions, 9 deletions
diff --git a/lib/PublicInbox/Msgmap.pm b/lib/PublicInbox/Msgmap.pm
index 5b4cebc1..d28e96c8 100644
--- a/lib/PublicInbox/Msgmap.pm
+++ b/lib/PublicInbox/Msgmap.pm
@@ -31,9 +31,6 @@ sub new_file {
         my $self = bless { filename => $f }, $class;
         my $dbh = $self->{dbh} = PublicInbox::Over::dbh_new($self, $rw);
         if ($rw) {
-                # TRUNCATE reduces I/O compared to the default (DELETE)
-                $dbh->do('PRAGMA journal_mode = TRUNCATE');
-
                 $dbh->begin_work;
                 create_tables($dbh);
                 $self->created_at(time) unless $self->created_at;
diff --git a/lib/PublicInbox/Over.pm b/lib/PublicInbox/Over.pm
index a2f04117..3e74b7a6 100644
--- a/lib/PublicInbox/Over.pm
+++ b/lib/PublicInbox/Over.pm
@@ -42,7 +42,28 @@ sub dbh_new {
                 $st = pack('dd', $st[0], $st[1]);
         } while ($st ne $self->{st} && $tries++ < 3);
         warn "W: $f: .st_dev, .st_ino unstable\n" if $st ne $self->{st};
-        $dbh->do('PRAGMA synchronous = OFF') if ($rw // 0) > 1;
+
+        if ($rw) {
+                # TRUNCATE reduces I/O compared to the default (DELETE).
+                #
+                # Do not use WAL by default since we expect the case
+                # where any users may read via read-only daemons
+                # (-httpd/-imapd/-nntpd); but only a single user has
+                # write permissions for -watch/-mda.
+                #
+                # Read-only WAL support in SQLite 3.22.0 (2018-01-22)
+                # doesn't do what we need: it is only intended for
+                # immutable read-only media (e.g. CD-ROM) and not
+                # usable for our use case described above.
+                #
+                # If an admin is willing to give read-only daemons R/W
+                # permissions; they can enable WAL manually and we will
+                # respect that by not clobbering it.
+                my $jm = $dbh->selectrow_array('PRAGMA journal_mode');
+                $dbh->do('PRAGMA journal_mode = TRUNCATE') if $jm ne 'wal';
+
+                $dbh->do('PRAGMA synchronous = OFF') if $rw > 1;
+        }
         $dbh;
 }
 
diff --git a/lib/PublicInbox/OverIdx.pm b/lib/PublicInbox/OverIdx.pm
index d42d6fe7..9f4a56fb 100644
--- a/lib/PublicInbox/OverIdx.pm
+++ b/lib/PublicInbox/OverIdx.pm
@@ -23,11 +23,6 @@ sub dbh_new {
         my ($self) = @_;
         my $dbh = $self->SUPER::dbh_new($self->{-no_fsync} ? 2 : 1);
 
-        # TRUNCATE reduces I/O compared to the default (DELETE)
-        # We do not use WAL since we're optimized for read-only ops,
-        # (and read-only requires SQLite 3.22.0 (2018-01-22)).
-        $dbh->do('PRAGMA journal_mode = TRUNCATE');
-
         # 80000 pages (80MiB on SQLite <3.12.0, 320MiB on 3.12.0+)
         # was found to be good in 2018 during the large LKML import
         # at the time.  This ought to be configurable based on HW
diff --git a/t/over.t b/t/over.t
index 07672aa7..8bf64ecb 100644
--- a/t/over.t
+++ b/t/over.t
@@ -65,4 +65,14 @@ isnt($over->max, 0, 'max is non-zero');
 
 $over->rollback_lazy;
 
+# L<perldata/"Version Strings">
+my $v = eval 'v'.$over->{dbh}->{sqlite_version};
+SKIP: {
+        skip("no WAL in SQLite version $v < 3.7.0", 1) if $v lt v3.7.0;
+        $over->{dbh}->do('PRAGMA journal_mode = WAL');
+        $over = PublicInbox::OverIdx->new("$tmpdir/over.sqlite3");
+        is($over->connect->selectrow_array('PRAGMA journal_mode'), 'wal',
+                'WAL journal_mode not clobbered if manually set');
+}
+
 done_testing();