@@ -12,36 +12,31 @@ Why it is needed:
1212- without it, Codex can fail at startup on Solaris NFS homes with
1313 `SQLITE_IOERR_SHMMAP` / SQLite extended error code 5386
1414
15- diff --git a/codex-rs/state/src/runtime.rs b/codex-rs/state/src/runtime.rs
16- index 4b1d264..6a40994 100644
17- --- a/codex-rs/state/src/runtime.rs
18- +++ b/codex-rs/state/src/runtime.rs
19- @@ -38,6 +38,8 @@ use codex_protocol::protocol::RolloutItem;
15+ diff --git a/codex-rs/state/src/sqlite.rs b/codex-rs/state/src/sqlite.rs
16+ index ca6f224..e141672 100644
17+ --- a/codex-rs/state/src/sqlite.rs
18+ +++ b/codex-rs/state/src/sqlite.rs
19+ @@ -3,16 +3,100 @@
20+ use codex_utils_absolute_path::AbsolutePathBuf;
2021 use log::LevelFilter;
21- use serde_json::Value;
2222 use sqlx::ConnectOptions;
2323+ #[cfg(target_os = "solaris")]
2424+ use sqlx::Connection;
25- use sqlx::QueryBuilder;
26- use sqlx::Row;
27- use sqlx::Sqlite;
28- @@ -47,9 +49,13 @@ use sqlx::migrate::Migrator;
25+ use sqlx::Error;
26+ use sqlx::SqlitePool;
2927 use sqlx::sqlite::SqliteAutoVacuum;
3028 use sqlx::sqlite::SqliteConnectOptions;
3129 use sqlx::sqlite::SqliteJournalMode;
3230+ #[cfg(target_os = "solaris")]
3331+ use sqlx::sqlite::SqliteLockingMode;
3432 use sqlx::sqlite::SqlitePoolOptions;
3533 use sqlx::sqlite::SqliteSynchronous;
36- use std::collections::BTreeSet;
3734+ #[cfg(target_os = "solaris")]
3835+ use std::ffi::OsString;
3936 use std::path::Path;
40- use std::path::PathBuf;
41- use std::sync::Arc;
42- @@ -359,11 +365,90 @@ async fn close_sqlite_pools(pools: &[&SqlitePool]) {
43- }
44- }
37+ + #[cfg(target_os = "solaris")]
38+ + use std::path::PathBuf;
39+ use std::time::Duration;
4540
4641+ fn default_sqlite_journal_mode() -> SqliteJournalMode {
4742+ if cfg!(target_os = "solaris") {
@@ -63,7 +58,7 @@ index 4b1d264..6a40994 100644
6358+ Ok(metadata) => metadata.len() == 0,
6459+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => true,
6560+ Err(err) => {
66- + warn!(
61+ + tracing:: warn!(
6762+ "failed to inspect SQLite WAL sidecar {} before Solaris cleanup: {err}",
6863+ wal_path.display()
6964+ );
@@ -79,7 +74,7 @@ index 4b1d264..6a40994 100644
7974+ match std::fs::remove_file(&sidecar) {
8075+ Ok(()) => {}
8176+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => {}
82- + Err(err) => warn!(
77+ + Err(err) => tracing:: warn!(
8378+ "failed to remove stale SQLite sidecar {} before Solaris startup: {err}",
8479+ sidecar.display()
8580+ ),
@@ -95,11 +90,11 @@ index 4b1d264..6a40994 100644
9590+ }
9691+
9792+ #[cfg(target_os = "solaris")]
98- + async fn prepare_solaris_sqlite_for_rollback_journal(path: &Path) -> anyhow:: Result<()> {
93+ + async fn prepare_solaris_sqlite_for_rollback_journal(path: &Path) -> Result<(), Error > {
9994+ match std::fs::metadata(path) {
10095+ Ok(_) => {}
10196+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(()),
102- + Err(err) => return Err(err.into( )),
97+ + Err(err) => return Err(Error::Io(err )),
10398+ }
10499+
105100+ cleanup_solaris_wal_sidecars(path);
@@ -119,25 +114,20 @@ index 4b1d264..6a40994 100644
119114+ Ok(())
120115+ }
121116+
122- fn base_sqlite_options(path: &Path) -> SqliteConnectOptions {
123- + #[cfg(target_os = "solaris")]
124- + cleanup_solaris_wal_sidecars(path);
125- +
126- SqliteConnectOptions::new()
127- .filename(path)
128- .create_if_missing(true)
129- - .journal_mode(SqliteJournalMode::Wal)
130- + .journal_mode(default_sqlite_journal_mode())
131- .synchronous(SqliteSynchronous::Normal)
132- .busy_timeout(Duration::from_secs(5))
133- .log_statements(LevelFilter::Off)
134- @@ -410,6 +495,9 @@ async fn open_sqlite(
135- spec: RuntimeDbSpec,
136- telemetry_override: Option<&dyn DbTelemetry>,
137- ) -> anyhow::Result<SqlitePool> {
138- + #[cfg(target_os = "solaris")]
139- + prepare_solaris_sqlite_for_rollback_journal(path).await?;
117+ /// Resolved configuration shared by all Codex SQLite connections.
118+ #[derive(Clone, Debug, Eq, PartialEq)]
119+ pub struct SqliteConfig {
120+ @@ -35,9 +119,12 @@ impl SqliteConfig {
121+ /// Open a writable Codex SQLite database, creating it if necessary.
122+ pub async fn open_read_write_pool(&self, path: &Path) -> Result<SqlitePool, Error> {
123+ + #[cfg(target_os = "solaris")]
124+ + prepare_solaris_sqlite_for_rollback_journal(path).await?;
140125+
141- let options = base_sqlite_options(path).auto_vacuum(SqliteAutoVacuum::Incremental);
142- let started = Instant::now();
143- let pool_result = SqlitePoolOptions::new()
126+ let options = SqliteConnectOptions::new()
127+ .filename(path)
128+ .create_if_missing(true)
129+ - .journal_mode(SqliteJournalMode::Wal)
130+ + .journal_mode(default_sqlite_journal_mode())
131+ .synchronous(SqliteSynchronous::Normal)
132+ .auto_vacuum(SqliteAutoVacuum::Incremental)
133+ .busy_timeout(Duration::from_secs(5))
0 commit comments