Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(dictionary): disable wal autocheckpoint #377

Merged
merged 3 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/dictionary/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,20 @@
/// Returns information about the dictionary instance.
fn about(&self) -> DictionaryInfo;

/// Reopens the dictionary if it was changed by a different process
///
/// It should not fail if the dictionary is read-only or able to sync across
/// processes automatically.
fn reopen(&mut self) -> Result<(), DictionaryUpdateError> {
Ok(())
}
/// Flushes all the changes back to the filesystem
///
/// The change made to the dictionary might not be persisted without
/// calling this method.
fn flush(&mut self) -> Result<(), DictionaryUpdateError> {
Ok(())
}

Check warning on line 314 in src/dictionary/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dictionary/mod.rs#L312-L314

Added lines #L312 - L314 were not covered by tests
/// An method for updating dictionaries.
///
/// For more about the concept of dictionaries generally, please see the
Expand Down Expand Up @@ -504,6 +518,22 @@
}
}

fn reopen(&mut self) -> Result<(), DictionaryUpdateError> {
match self {
AnyDictionary::SqliteDictionary(dict) => dict.reopen(),
AnyDictionary::TrieDictionary(dict) => dict.reopen(),
AnyDictionary::HashMapDictionary(dict) => dict.reopen(),

Check warning on line 525 in src/dictionary/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dictionary/mod.rs#L524-L525

Added lines #L524 - L525 were not covered by tests
}
}

fn flush(&mut self) -> Result<(), DictionaryUpdateError> {
match self {
AnyDictionary::SqliteDictionary(dict) => dict.flush(),
AnyDictionary::TrieDictionary(dict) => dict.flush(),
AnyDictionary::HashMapDictionary(dict) => dict.flush(),

Check warning on line 533 in src/dictionary/mod.rs

View check run for this annotation

Codecov / codecov/patch

src/dictionary/mod.rs#L532-L533

Added lines #L532 - L533 were not covered by tests
}
}

fn insert<Syl: AsRef<Syllable>>(
&mut self,
syllables: &[Syl],
Expand Down
16 changes: 11 additions & 5 deletions src/dictionary/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
fn initialize_tables(conn: &Connection) -> Result<(), SqliteDictionaryError> {
conn.pragma_update(None, "journal_mode", "WAL")?;
conn.pragma_update(None, "synchronous", "NORMAL")?;
conn.pragma_update(None, "wal_autocheckpoint", 0)?;
conn.execute(
"CREATE TABLE IF NOT EXISTS dictionary_v1 (
syllables BLOB NOT NULL,
Expand Down Expand Up @@ -269,7 +270,7 @@

impl Dictionary for SqliteDictionary {
fn lookup_phrase<Syl: AsRef<Syllable>>(&self, syllables: &[Syl]) -> Phrases<'static> {
let syllables_bytes = syllables.into_syllables_bytes();
let syllables_bytes = syllables.into_bytes();
let mut stmt = self
.conn
.prepare_cached(
Expand Down Expand Up @@ -337,6 +338,11 @@
self.info.clone()
}

fn flush(&mut self) -> Result<(), DictionaryUpdateError> {
self.conn.pragma_update(None, "wal_checkpoint", "PASSIVE")?;
Ok(())
}

fn insert<Syl: AsRef<Syllable>>(
&mut self,
syllables: &[Syl],
Expand All @@ -347,7 +353,7 @@
source: Some(Box::new(SqliteDictionaryError::ReadOnly)),
});
}
let syllables_bytes = syllables.into_syllables_bytes();
let syllables_bytes = syllables.into_bytes();
let mut stmt = self.conn.prepare_cached(
"INSERT OR REPLACE INTO dictionary_v1 (
syllables,
Expand All @@ -371,7 +377,7 @@
source: Some(Box::new(SqliteDictionaryError::ReadOnly)),
});
}
let syllables_bytes = syllables.into_syllables_bytes();
let syllables_bytes = syllables.into_bytes();
let tx = self.conn.transaction()?;
{
let mut stmt = tx.prepare_cached(
Expand Down Expand Up @@ -418,7 +424,7 @@
syllables: &[Syl],
phrase_str: &str,
) -> Result<(), DictionaryUpdateError> {
let syllables_bytes = syllables.into_syllables_bytes();
let syllables_bytes = syllables.into_bytes();
let mut stmt = self
.conn
.prepare_cached("DELETE FROM dictionary_v1 WHERE syllables = ? AND phrase = ?")?;
Expand Down Expand Up @@ -501,7 +507,7 @@
} else {
0
};
let syllables_bytes = syllables.into_syllables_bytes();
let syllables_bytes = syllables.into_bytes();

Check warning on line 510 in src/dictionary/sqlite.rs

View check run for this annotation

Codecov / codecov/patch

src/dictionary/sqlite.rs#L510

Added line #L510 was not covered by tests
let mut stmt = self.dict.conn.prepare_cached(
"INSERT OR REPLACE INTO dictionary_v1 (
syllables,
Expand Down
14 changes: 6 additions & 8 deletions src/editor/estimate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl SqliteUserFreqEstimate {
fn initialize_tables(conn: &Connection) -> Result<(), EstimateError> {
conn.pragma_update(None, "journal_mode", "WAL")?;
conn.pragma_update(None, "synchronous", "NORMAL")?;
conn.pragma_update(None, "wal_autocheckpoint", 0)?;
conn.execute(
"CREATE TABLE IF NOT EXISTS config_v1 (
id INTEGER PRIMARY KEY,
Expand All @@ -84,14 +85,11 @@ const MAX_USER_FREQ: u32 = 99999999;

impl UserFreqEstimate for SqliteUserFreqEstimate {
fn tick(&mut self) -> Result<(), EstimateError> {
// TODO debounce write
self.conn
.execute("UPDATE config_v1 SET value = value + 1 WHERE id = 0", [])?;
self.lifetime =
self.conn
.query_row("SELECT value FROM config_v1 WHERE id = 0", [], |row| {
row.get(0)
})?;
self.lifetime = self.conn.query_row(
"UPDATE config_v1 SET value = value + 1 WHERE id = 0 RETURNING value",
[],
|row| row.get(0),
)?;
Ok(())
}

Expand Down
18 changes: 16 additions & 2 deletions src/editor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ where
options: EditorOptions,
state: Transition,

dirty_dict: bool,
nth_conversion: usize,
commit_buffer: String,
notice_buffer: String,
Expand All @@ -143,6 +144,7 @@ where
estimate,
options: EditorOptions::default(),
state: Transition::Entering(EditorKeyBehavior::Ignore, Entering),
dirty_dict: false,
nth_conversion: 0,
commit_buffer: String::new(),
notice_buffer: String::new(),
Expand Down Expand Up @@ -303,10 +305,15 @@ where
{
return Err(format!("已有:{phrase}"));
}
self.dict
let result = self
.dict
.insert(&syllables, (&phrase, 100).into())
.map(|_| phrase)
.map_err(|_| "加詞失敗:字數不符或夾雜符號".to_owned())
.map_err(|_| "加詞失敗:字數不符或夾雜符號".to_owned());
if result.is_ok() {
self.dirty_dict = true;
}
result
}
pub fn learn_phrase<Syl: AsRef<Syllable>>(&mut self, syllables: &[Syl], phrase: &str) {
let phrases = Vec::from_iter(self.dict.lookup_phrase(syllables));
Expand All @@ -326,9 +333,11 @@ where
let time = self.estimate.now().unwrap();

let _ = self.dict.update(&syllables, phrase, user_freq, time);
self.dirty_dict = true;
}
pub fn unlearn_phrase(&mut self, syllables: &[Syllable], phrase: &str) {
let _ = self.dict.remove(&syllables, phrase);
self.dirty_dict = true;
}
pub fn switch_character_form(&mut self) {
self.options = EditorOptions {
Expand Down Expand Up @@ -548,6 +557,11 @@ where
if self.last_key_behavior() == EditorKeyBehavior::Absorb {
self.try_auto_commit();
}
if self.dirty_dict {
let _ = self.user_dict().reopen();
let _ = self.user_dict().flush();
self.dirty_dict = false;
}
self.last_key_behavior()
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/zhuyin/syllable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,11 +281,11 @@ impl AsRef<Syllable> for Syllable {
/// TODO: docs
pub trait IntoSyllablesBytes {
/// TODO: docs
fn into_syllables_bytes(&self) -> Vec<u8>;
fn into_bytes(&self) -> Vec<u8>;
}

impl<Syl: AsRef<Syllable>> IntoSyllablesBytes for &[Syl] {
fn into_syllables_bytes(&self) -> Vec<u8> {
fn into_bytes(&self) -> Vec<u8> {
let mut syllables_bytes = vec![];
self.iter()
.for_each(|syl| syllables_bytes.extend_from_slice(&syl.as_ref().to_le_bytes()));
Expand Down