recreate manifest entries if manifest is recreated due to error fixes #199

This commit is contained in:
Cooper Quintin
2025-06-03 18:18:27 -07:00
committed by Cooper Quintin
parent a72e4b2234
commit 5db24e4b21
2 changed files with 61 additions and 2 deletions
+23 -1
View File
@@ -34,6 +34,8 @@ use diag::{
use log::{error, info};
use qmdl_store::RecordingStoreError;
use rayhunter::diag_device::DiagDevice;
use std::path::Path;
use tokio::fs;
use tokio::net::TcpListener;
use tokio::select;
use tokio::sync::mpsc::{self, Sender};
@@ -109,7 +111,27 @@ async fn init_qmdl_store(config: &config::Config) -> Result<RecordingStore, Rayh
Err(RecordingStoreError::ParseManifestError(err)) => {
error!("failed to parse QMDL manifest: {err}");
info!("creating new empty manifest...");
Ok(RecordingStore::create(&config.qmdl_store_path).await?)
let mut recording_store = RecordingStore::create(&config.qmdl_store_path).await?;
info!("parsing existing qmdl files into recording store...");
let path = Path::new(&config.qmdl_store_path);
let mut entries = fs::read_dir(path).await?;
// We might want to sort these newest to oldest so we don't have entries in manifest.toml in random order
while let Some(entry) = entries.next_entry().await? {
let file_name = entry.file_name();
let file_name_str = match file_name.to_str() {
Some(s) => s,
None => continue, // skip non-UTF-8 names
};
if file_name_str.ends_with(".qmdl") {
let name = file_name_str.trim_end_matches(".qmdl");
info!("making entry for {}", name);
recording_store.new_entry_from_existing(name.to_string()).await?;
}
}
Ok(recording_store)
}
Err(err) => Err(err.into()),
}
+38 -1
View File
@@ -1,7 +1,9 @@
use std::io::{self, ErrorKind};
use std::path::{Path, PathBuf};
use std::time::UNIX_EPOCH;
use chrono::{DateTime, Local};
use chrono::{DateTime, Local, TimeZone};
use rayhunter::analysis;
use rayhunter::util::RuntimeMetadata;
use serde::{Deserialize, Serialize};
use thiserror::Error;
@@ -71,6 +73,7 @@ impl ManifestEntry {
}
}
pub fn get_qmdl_filepath<P: AsRef<Path>>(&self, path: P) -> PathBuf {
let mut filepath = path.as_ref().join(&self.name);
filepath.set_extension("qmdl");
@@ -171,6 +174,40 @@ impl RecordingStore {
self.write_manifest().await?;
Ok((qmdl_file, analysis_file))
}
pub async fn new_entry_from_existing(&mut self, name: String) -> Result<(File, File), RecordingStoreError> {
// if we've already got an entry open, close it
if self.current_entry.is_some() {
self.close_current_entry().await?;
}
let mut new_entry = ManifestEntry::new();
new_entry.name = name;
let qmdl_filepath = new_entry.get_qmdl_filepath(&self.path);
let qmdl_file = File::open(&qmdl_filepath)
.await
.map_err(RecordingStoreError::ReadFileError)?;
let qmdl_meta = qmdl_file.metadata().await.map_err(RecordingStoreError::ReadFileError)?;
let analysis_filepath = new_entry.get_analysis_filepath(&self.path);
let analysis_file = File::open(&analysis_filepath)
.await
.map_err(RecordingStoreError::ReadFileError)?;
let timestamp = Local.timestamp_opt(new_entry.name.parse::<i64>().expect("Invalid timestamp"), 0).unwrap();
new_entry.start_time = timestamp;
// I can't think of a better way to find this
let update = qmdl_meta.modified().expect("no mod date").duration_since(UNIX_EPOCH)
.expect("Time went backwards");
new_entry.last_message_time = Some(Local.timestamp_opt(update.as_secs().try_into().expect("error"), 0).unwrap());
new_entry.analysis_size_bytes = analysis_file.metadata().await.map_err(RecordingStoreError::ReadFileError)?.len().try_into().expect("file too large");
new_entry.qmdl_size_bytes = qmdl_meta.len().try_into().expect("file too large");
self.manifest.entries.push(new_entry);
self.current_entry = Some(self.manifest.entries.len() - 1);
self.write_manifest().await?;
Ok((qmdl_file, analysis_file))
}
// Returns the corresponding QMDL file for a given entry
pub async fn open_entry_qmdl(&self, entry_index: usize) -> Result<File, RecordingStoreError> {