Add error tracing support in Aspect implementation
This removes the parallelization feature from the Aspect codebase as std::error::Error does not implement Send, so we cannot send the error from a child thread to a parent thread. This is clearly not an optimal implementation now, but we have hook non-aborting-error tracing support, which is more important than parallelization support, at least in this early stage of development. An issue has to be opened for re-implementing parallelization of hooks.
This commit is contained in:
parent
6c7d6c29ea
commit
a42b6a10db
1 changed files with 65 additions and 54 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use libimagerror::trace::trace_error;
|
||||||
|
|
||||||
use store::FileLockEntry;
|
use store::FileLockEntry;
|
||||||
use storeid::StoreId;
|
use storeid::StoreId;
|
||||||
use hook::Hook;
|
use hook::Hook;
|
||||||
|
@ -38,34 +40,32 @@ impl Aspect {
|
||||||
|
|
||||||
impl StoreIdAccessor for Aspect {
|
impl StoreIdAccessor for Aspect {
|
||||||
fn access(&self, id: &StoreId) -> HookResult<()> {
|
fn access(&self, id: &StoreId) -> HookResult<()> {
|
||||||
use crossbeam;
|
|
||||||
|
|
||||||
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
||||||
if !accessors.iter().all(|a| is_match!(*a, HDA::StoreIdAccess(_))) {
|
if !accessors.iter().all(|a| is_match!(*a, HDA::StoreIdAccess(_))) {
|
||||||
return Err(HE::new(HEK::AccessTypeViolation, None));
|
return Err(HE::new(HEK::AccessTypeViolation, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
let threads : Vec<HookResult<()>> = accessors
|
accessors
|
||||||
.iter()
|
.iter()
|
||||||
.map(|accessor| {
|
.fold(Ok(()), |acc, accessor| {
|
||||||
crossbeam::scope(|scope| {
|
acc.and_then(|_| {
|
||||||
scope.spawn(|| {
|
let res = match accessor {
|
||||||
match *accessor {
|
&HDA::StoreIdAccess(accessor) => accessor.access(id),
|
||||||
HDA::StoreIdAccess(accessor) => accessor.access(id),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
};
|
||||||
.map_err(|_| ()) // TODO: We're losing the error cause here
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.map(|i| i.join().map_err(|_| HE::new(HEK::HookExecutionError, None)))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
threads
|
match res {
|
||||||
.into_iter()
|
Ok(res) => Ok(res),
|
||||||
.fold(Ok(()), |acc, elem| {
|
Err(e) => {
|
||||||
acc.and_then(|a| {
|
if !e.is_aborting() {
|
||||||
elem.map(|_| a).map_err(|_| HE::new(HEK::HookExecutionError, None))
|
trace_error(&e);
|
||||||
|
// ignore error if it is not aborting, as we printed it already
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -83,52 +83,63 @@ impl MutableHookDataAccessor for Aspect {
|
||||||
return Err(HE::new(HEK::AccessTypeViolation, None));
|
return Err(HE::new(HEK::AccessTypeViolation, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
for accessor in accessors {
|
|
||||||
match accessor {
|
|
||||||
HDA::MutableAccess(accessor) => try!(accessor.access_mut(fle)),
|
|
||||||
|
|
||||||
// TODO: Naiive implementation.
|
// TODO: Naiive implementation.
|
||||||
// More sophisticated version would check whether there are _chunks_ of
|
// More sophisticated version would check whether there are _chunks_ of
|
||||||
// NonMutableAccess accessors and execute these chunks in parallel. We do not have
|
// NonMutableAccess accessors and execute these chunks in parallel. We do not have
|
||||||
// performance concerns yet, so this is okay.
|
// performance concerns yet, so this is okay.
|
||||||
HDA::NonMutableAccess(accessor) => try!(accessor.access(fle)),
|
accessors.iter().fold(Ok(()), |acc, accessor| {
|
||||||
|
acc.and_then(|_| {
|
||||||
|
let res = match accessor {
|
||||||
|
&HDA::MutableAccess(ref accessor) => accessor.access_mut(fle),
|
||||||
|
&HDA::NonMutableAccess(ref accessor) => accessor.access(fle),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
match res {
|
||||||
|
Ok(res) => Ok(res),
|
||||||
|
Err(e) => {
|
||||||
|
if !e.is_aborting() {
|
||||||
|
trace_error(&e);
|
||||||
|
// ignore error if it is not aborting, as we printed it already
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NonMutableHookDataAccessor for Aspect {
|
impl NonMutableHookDataAccessor for Aspect {
|
||||||
fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
|
fn access(&self, fle: &FileLockEntry) -> HookResult<()> {
|
||||||
use crossbeam;
|
|
||||||
|
|
||||||
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
let accessors : Vec<HDA> = self.hooks.iter().map(|h| h.accessor()).collect();
|
||||||
if !accessors.iter().all(|a| is_match!(*a, HDA::NonMutableAccess(_))) {
|
if !accessors.iter().all(|a| is_match!(*a, HDA::NonMutableAccess(_))) {
|
||||||
return Err(HE::new(HEK::AccessTypeViolation, None));
|
return Err(HE::new(HEK::AccessTypeViolation, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
let threads : Vec<HookResult<()>> = accessors
|
accessors
|
||||||
.iter()
|
.iter()
|
||||||
.map(|accessor| {
|
.fold(Ok(()), |acc, accessor| {
|
||||||
crossbeam::scope(|scope| {
|
acc.and_then(|_| {
|
||||||
scope.spawn(|| {
|
let res = match accessor {
|
||||||
match *accessor {
|
&HDA::NonMutableAccess(accessor) => accessor.access(fle),
|
||||||
HDA::NonMutableAccess(accessor) => accessor.access(fle),
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
};
|
||||||
.map_err(|_| ()) // TODO: We're losing the error cause here
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.map(|i| i.join().map_err(|_| HE::new(HEK::HookExecutionError, None)))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
threads
|
match res {
|
||||||
.into_iter()
|
Ok(res) => Ok(res),
|
||||||
.fold(Ok(()), |acc, elem| {
|
Err(e) => {
|
||||||
acc.and_then(|a| {
|
if !e.is_aborting() {
|
||||||
elem.map(|_| a).map_err(|_| HE::new(HEK::HookExecutionError, None))
|
trace_error(&e);
|
||||||
|
// ignore error if it is not aborting, as we printed it already
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue