mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-12-05 07:12:34 -05:00
overhaul error messages
Inspired by the poor error message here: https://github.com/scottlamb/moonfire-nvr/issues/107#issuecomment-777587727 * print the friendlier Display version of the error rather than Debug. Eg, "EROFS: Read-only filesystem" rather than "Sys(EROFS)". Do this everywhere: on command exit, on syncer retries, and on stream retries. * print the most immediate problem and additional lines for each cause. * print the backtrace or an advertisement for RUST_BACKTRACE=1 if it's unavailable. * also mention RUST_BACKTRACE=1 in the troubleshooting guide. * add context in various places, including pathnames. There are surely many places more it'd be helpful, but this is a start. * allow subcommands to return failure without an Error. In particular, "moonfire-nvr check" does its own error printing because it wants to print all the errors it finds. Printing "see earlier errors" with a meaningless stack trace seems like it'd just confuse. But I also want to get rid of the misleading "Success" at the end and 0 return to the OS.
This commit is contained in:
@@ -151,7 +151,7 @@ pub(crate) fn read_meta(dir: &Fd) -> Result<schema::DirMeta, Error> {
|
||||
}
|
||||
let data = &data[pos..pos+len as usize];
|
||||
let mut s = protobuf::CodedInputStream::from_bytes(&data);
|
||||
meta.merge_from(&mut s).map_err(|e| e.context("Unable to parse metadata proto: {}"))?;
|
||||
meta.merge_from(&mut s).map_err(|e| e.context("Unable to parse metadata proto"))?;
|
||||
Ok(meta)
|
||||
}
|
||||
|
||||
@@ -164,17 +164,18 @@ pub(crate) fn write_meta(dirfd: RawFd, meta: &schema::DirMeta) -> Result<(), Err
|
||||
}
|
||||
data.resize(FIXED_DIR_META_LEN, 0); // pad to required length.
|
||||
let mut f = crate::fs::openat(dirfd, cstr!("meta"), OFlag::O_CREAT | OFlag::O_WRONLY,
|
||||
Mode::S_IRUSR | Mode::S_IWUSR)?;
|
||||
let stat = f.metadata()?;
|
||||
Mode::S_IRUSR | Mode::S_IWUSR)
|
||||
.map_err(|e| e.context("Unable to open meta file"))?;
|
||||
let stat = f.metadata().map_err(|e| e.context("Unable to stat meta file"))?;
|
||||
if stat.len() == 0 {
|
||||
// Need to sync not only the data but also the file metadata and dirent.
|
||||
f.write_all(&data)?;
|
||||
f.sync_all()?;
|
||||
nix::unistd::fsync(dirfd)?;
|
||||
f.write_all(&data).map_err(|e| e.context("Unable to write to meta file"))?;
|
||||
f.sync_all().map_err(|e| e.context("Unable to sync meta file"))?;
|
||||
nix::unistd::fsync(dirfd).map_err(|e| e.context("Unable to sync dir"))?;
|
||||
} else if stat.len() == FIXED_DIR_META_LEN as u64 {
|
||||
// Just syncing the data will suffice; existing metadata and dirent are fine.
|
||||
f.write_all(&data)?;
|
||||
f.sync_data()?;
|
||||
f.write_all(&data).map_err(|e| e.context("Unable to write to meta file"))?;
|
||||
f.sync_data().map_err(|e| e.context("Unable to sync meta file"))?;
|
||||
} else {
|
||||
bail!("Existing meta file is {}-byte; expected {}", stat.len(), FIXED_DIR_META_LEN);
|
||||
}
|
||||
@@ -194,8 +195,8 @@ impl SampleFileDir {
|
||||
FlockArg::LockExclusiveNonblock
|
||||
} else {
|
||||
FlockArg::LockSharedNonblock
|
||||
})?;
|
||||
let dir_meta = read_meta(&s.fd)?;
|
||||
}).map_err(|e| e.context(format!("unable to lock dir {}", path)))?;
|
||||
let dir_meta = read_meta(&s.fd).map_err(|e| e.context("unable to read meta file"))?;
|
||||
if !SampleFileDir::consistent(db_meta, &dir_meta) {
|
||||
let serialized =
|
||||
db_meta.write_length_delimited_to_bytes().expect("proto3->vec is infallible");
|
||||
@@ -230,7 +231,8 @@ impl SampleFileDir {
|
||||
pub(crate) fn create(path: &str, db_meta: &schema::DirMeta)
|
||||
-> Result<Arc<SampleFileDir>, Error> {
|
||||
let s = SampleFileDir::open_self(path, true)?;
|
||||
s.fd.lock(FlockArg::LockExclusiveNonblock)?;
|
||||
s.fd.lock(FlockArg::LockExclusiveNonblock)
|
||||
.map_err(|e| e.context(format!("unable to lock dir {}", path)))?;
|
||||
let old_meta = read_meta(&s.fd)?;
|
||||
|
||||
// Verify metadata. We only care that it hasn't been completely opened.
|
||||
@@ -265,8 +267,7 @@ impl SampleFileDir {
|
||||
}
|
||||
|
||||
fn open_self(path: &str, create: bool) -> Result<Arc<SampleFileDir>, Error> {
|
||||
let fd = Fd::open(path, create)
|
||||
.map_err(|e| format_err!("unable to open sample file dir {}: {}", path, e))?;
|
||||
let fd = Fd::open(path, create)?;
|
||||
Ok(Arc::new(SampleFileDir {
|
||||
fd,
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user