Skip to content

Commit

Permalink
Merge pull request #377 from chewing/rust/sqlite-no-autocheckpoint
Browse files Browse the repository at this point in the history
refactor(dictionary): disable wal autocheckpoint
  • Loading branch information
kanru committed Jan 2, 2024
2 parents 42c252c + bb05466 commit d445946
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 17 deletions.
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 @@ pub trait Dictionary: Debug {
/// 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(())
}
/// An method for updating dictionaries.
///
/// For more about the concept of dictionaries generally, please see the
Expand Down Expand Up @@ -504,6 +518,22 @@ impl Dictionary for AnyDictionary {
}
}

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

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

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 @@ impl SqliteDictionary {
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 From<RusqliteError> for DictionaryUpdateError {

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 @@ impl Dictionary for SqliteDictionary {
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 @@ impl Dictionary for SqliteDictionary {
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 @@ impl Dictionary for SqliteDictionary {
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 @@ impl Dictionary for SqliteDictionary {
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 @@ impl DictionaryBuilder for SqliteDictionaryBuilder {
} else {
0
};
let syllables_bytes = syllables.into_syllables_bytes();
let syllables_bytes = syllables.into_bytes();
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

0 comments on commit d445946

Please sign in to comment.