From b43137b508691be18516f7c6557f2f02f39f217e Mon Sep 17 00:00:00 2001 From: many Date: Mon, 7 Sep 2020 15:51:34 +0200 Subject: [PATCH] add version guard in copy_and_compact_to_path function --- meilisearch-core/src/database.rs | 35 ++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/meilisearch-core/src/database.rs b/meilisearch-core/src/database.rs index 5f4efef96..5dc6d8a76 100644 --- a/meilisearch-core/src/database.rs +++ b/meilisearch-core/src/database.rs @@ -40,6 +40,7 @@ pub struct Database { indexes_store: heed::Database, indexes: RwLock>)>>, update_fn: Arc, + database_version: (u32, u32, u32), } pub struct DatabaseOptions { @@ -165,7 +166,7 @@ fn update_awaiter( /// Ensures Meilisearch version is compatible with the database, returns an error versions mismatch. /// If create is set to true, a VERSION file is created with the current version. -fn version_guard(path: &Path, create: bool) -> MResult<()> { +fn version_guard(path: &Path, create: bool) -> MResult<(u32, u32, u32)> { let current_version_major = env!("CARGO_PKG_VERSION_MAJOR"); let current_version_minor = env!("CARGO_PKG_VERSION_MINOR"); let current_version_patch = env!("CARGO_PKG_VERSION_PATCH"); @@ -186,9 +187,16 @@ fn version_guard(path: &Path, create: bool) -> MResult<()> { // the first is always the complete match, safe to unwrap because we have a match let version_major = version.get(1).unwrap().as_str(); let version_minor = version.get(2).unwrap().as_str(); + let version_patch = version.get(3).unwrap().as_str(); if version_major != current_version_major || version_minor != current_version_minor { - return Err(Error::VersionMismatch(format!("{}.{}.XX", version_major, version_minor))); + Err(Error::VersionMismatch(format!("{}.{}.XX", version_major, version_minor))) + } else { + Ok(( + version_major.parse().or_else(|e| Err(Error::VersionMismatch(format!("error parsing database version: {}", e))))?, + version_minor.parse().or_else(|e| Err(Error::VersionMismatch(format!("error parsing database version: {}", e))))?, + version_patch.parse().or_else(|e| Err(Error::VersionMismatch(format!("error parsing database version: {}", e))))? + )) } } Err(error) => { @@ -202,17 +210,22 @@ fn version_guard(path: &Path, create: bool) -> MResult<()> { current_version_major, current_version_minor, current_version_patch).as_bytes())?; + + Ok(( + current_version_major.parse().or_else(|e| Err(Error::VersionMismatch(format!("error parsing database version: {}", e))))?, + current_version_minor.parse().or_else(|e| Err(Error::VersionMismatch(format!("error parsing database version: {}", e))))?, + current_version_patch.parse().or_else(|e| Err(Error::VersionMismatch(format!("error parsing database version: {}", e))))? + )) } else { // when no version file is found and we were not told to create one, this // means that the version is inferior to the one this feature was added in. - return Err(Error::VersionMismatch("<0.12.0".to_string())); + Err(Error::VersionMismatch("<0.12.0".to_string())) } } - _ => return Err(error.into()) + _ => Err(error.into()) } } } - Ok(()) } impl Database { @@ -224,7 +237,7 @@ impl Database { fs::create_dir_all(&path)?; // create file only if main db wasn't created before (first run) - version_guard(path.as_ref(), !main_path.exists() && !update_path.exists())?; + let database_version = version_guard(path.as_ref(), !main_path.exists() && !update_path.exists())?; fs::create_dir_all(&main_path)?; let env = heed::EnvOpenOptions::new() @@ -302,6 +315,7 @@ impl Database { indexes_store, indexes: RwLock::new(indexes), update_fn, + database_version, }) } @@ -469,9 +483,18 @@ impl Database { let env_path = path.join("main"); let env_update_path = path.join("update"); + let env_version_path = path.join("VERSION"); fs::create_dir(&env_path)?; fs::create_dir(&env_update_path)?; + + // write Database Version + let (current_version_major, current_version_minor, current_version_patch) = self.database_version; + let mut version_file = File::create(&env_version_path)?; + version_file.write_all(format!("{}.{}.{}", + current_version_major, + current_version_minor, + current_version_patch).as_bytes())?; let env_path = env_path.join("data.mdb"); let env_file = self.env.copy_to_path(&env_path, CompactionOption::Enabled)?;