diff --git a/src/lib/entry.rs b/src/lib/entry.rs index 640497f60..de5d32e44 100644 --- a/src/lib/entry.rs +++ b/src/lib/entry.rs @@ -1,9 +1,10 @@ // use serde_json::{Error, Value}; use super::proto_v1::Entry as ProtoEntry; -use error::SchemaError; +use error::{OperationError, SchemaError}; use filter::{Filter, FilterValid}; use modify::{Modify, ModifyInvalid, ModifyList, ModifyValid}; use schema::{SchemaAttribute, SchemaClass, SchemaReadTransaction}; +use server::{QueryServerReadTransaction, QueryServerWriteTransaction}; use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut}; use std::collections::BTreeMap; use std::collections::HashMap; @@ -152,26 +153,42 @@ impl Entry { } // FIXME: Can we consume protoentry? - pub fn from(e: &ProtoEntry) -> Self { + pub fn from(e: &ProtoEntry, qs: &QueryServerWriteTransaction) -> Result { // Why not the trait? In the future we may want to extend // this with server aware functions for changes of the // incoming data. - Entry { + + // Somehow we need to take the tree of e attrs, and convert + // all ref types to our types ... + + let map2: Result>, OperationError> = e + .attrs + .iter() + .map(|(k, v)| { + let nv: Result, _> = v.iter().map(|vr| qs.clone_value(&k, vr)).collect(); + match nv { + Ok(mut nvi) => { + nvi.sort_unstable(); + Ok((k.clone(), nvi)) + } + Err(e) => Err(e), + } + }) + .collect(); + + let x = match map2 { + Ok(v) => v, + Err(e) => return Err(e), + }; + + Ok(Entry { // For now, we do a straight move, and we sort the incoming data // sets so that BST works. state: EntryNew, valid: EntryInvalid, id: None, - attrs: e - .attrs - .iter() - .map(|(k, v)| { - let mut nv = v.clone(); - nv.sort_unstable(); - (k.clone(), nv) - }) - .collect(), - } + attrs: x, + }) } } diff --git a/src/lib/event.rs b/src/lib/event.rs index e282bc0b1..09502af84 100644 --- a/src/lib/event.rs +++ b/src/lib/event.rs @@ -62,9 +62,7 @@ impl SearchResult { pub struct SearchEvent { pub internal: bool, pub filter: Filter, - // TODO: Remove this - class: (), // String - // TODO: Add list of attributes to request + // TODO: Add list of attributes to request } impl SearchEvent { @@ -76,7 +74,6 @@ impl SearchEvent { Ok(f) => Ok(SearchEvent { internal: false, filter: Filter::new_ignore_hidden(f), - class: (), }), Err(e) => Err(e), } @@ -87,7 +84,6 @@ impl SearchEvent { SearchEvent { internal: false, filter: filter, - class: (), } } @@ -99,7 +95,6 @@ impl SearchEvent { Ok(f) => Ok(SearchEvent { filter: Filter::new_recycled(f), internal: false, - class: (), }), Err(e) => Err(e), } @@ -109,7 +104,6 @@ impl SearchEvent { SearchEvent { internal: false, filter: Filter::new_recycled(filter), - class: (), } } @@ -118,7 +112,6 @@ impl SearchEvent { SearchEvent { internal: false, filter: Filter::new_ignore_hidden(filter), - class: (), } } @@ -126,7 +119,6 @@ impl SearchEvent { SearchEvent { internal: true, filter: filter, - class: (), } } } @@ -146,14 +138,21 @@ pub struct CreateEvent { // FIXME: Should this actually be in createEvent handler? impl CreateEvent { - pub fn from_request(request: CreateRequest) -> Self { - CreateEvent { - // From ProtoEntry -> Entry - // What is the correct consuming iterator here? Can we - // even do that? - internal: false, - // TODO: Transform references here. - entries: request.entries.iter().map(|e| Entry::from(e)).collect(), + pub fn from_request( + request: CreateRequest, + qs: &QueryServerWriteTransaction, + ) -> Result { + let rentries: Result, _> = + request.entries.iter().map(|e| Entry::from(e, qs)).collect(); + match rentries { + Ok(entries) => Ok(CreateEvent { + // From ProtoEntry -> Entry + // What is the correct consuming iterator here? Can we + // even do that? + internal: false, + entries: entries, + }), + Err(e) => Err(e), } } @@ -202,7 +201,6 @@ impl DeleteEvent { ) -> Result { match Filter::from_rw(&request.filter, qs) { Ok(f) => Ok(DeleteEvent { - // TODO: Transform references here. filter: Filter::new_ignore_hidden(f), internal: false, }), @@ -239,13 +237,14 @@ impl ModifyEvent { qs: &QueryServerWriteTransaction, ) -> Result { match Filter::from_rw(&request.filter, qs) { - Ok(f) => Ok(ModifyEvent { - // TODO: Transform references here. - filter: Filter::new_ignore_hidden(f), - // TODO: Transform references here. - modlist: ModifyList::from(&request.modlist), - internal: false, - }), + Ok(f) => match ModifyList::from(&request.modlist, qs) { + Ok(m) => Ok(ModifyEvent { + filter: Filter::new_ignore_hidden(f), + modlist: m, + internal: false, + }), + Err(e) => Err(e), + }, Err(e) => Err(e), } @@ -333,7 +332,6 @@ impl ReviveRecycledEvent { ) -> Result { match Filter::from_rw(&request.filter, qs) { Ok(f) => Ok(ReviveRecycledEvent { - // TODO: Transform references here (in theory should be none though) filter: Filter::new_recycled(f), internal: false, }), diff --git a/src/lib/filter.rs b/src/lib/filter.rs index 0a309fb1e..9ac7ce1c6 100644 --- a/src/lib/filter.rs +++ b/src/lib/filter.rs @@ -196,70 +196,44 @@ impl Filter { // monomorphise on the trait to call clone_value. An option is to make a fn that // takes "clone_value(t, a, v) instead, but that may have a similar issue. pub fn from_ro(f: &ProtoFilter, qs: &QueryServerTransaction) -> Result { - match f { - ProtoFilter::Eq(a, v) => match qs.clone_value(a, v) { - Ok(vc) => Ok(Filter::Eq(a.clone(), vc)), - Err(e) => Err(e), - }, - ProtoFilter::Sub(a, v) => match qs.clone_value(a, v) { - Ok(vc) => Ok(Filter::Sub(a.clone(), vc)), - Err(e) => Err(e), - }, - ProtoFilter::Pres(a) => Ok(Filter::Pres(a.clone())), - ProtoFilter::Or(l) => { - let inner: Result, _> = l.iter().map(|f| Self::from_ro(f, qs)).collect(); - match inner { - Ok(lc) => Ok(Filter::Or(lc)), - Err(e) => Err(e), - } - } - ProtoFilter::And(l) => { - let inner: Result, _> = l.iter().map(|f| Self::from_ro(f, qs)).collect(); - match inner { - Ok(lc) => Ok(Filter::And(lc)), - Err(e) => Err(e), - } - } - ProtoFilter::AndNot(l) => match Self::from_ro(l, qs) { - Ok(f) => Ok(Filter::AndNot(Box::new(f))), - Err(e) => Err(e), - }, - } + Ok(match f { + ProtoFilter::Eq(a, v) => Filter::Eq(a.clone(), qs.clone_value(a, v)?), + ProtoFilter::Sub(a, v) => Filter::Sub(a.clone(), qs.clone_value(a, v)?), + ProtoFilter::Pres(a) => Filter::Pres(a.clone()), + ProtoFilter::Or(l) => Filter::Or( + l.iter() + .map(|f| Self::from_ro(f, qs)) + .collect::, _>>()?, + ), + ProtoFilter::And(l) => Filter::And( + l.iter() + .map(|f| Self::from_ro(f, qs)) + .collect::, _>>()?, + ), + ProtoFilter::AndNot(l) => Filter::AndNot(Box::new(Self::from_ro(l, qs)?)), + }) } pub fn from_rw( f: &ProtoFilter, qs: &QueryServerWriteTransaction, ) -> Result { - match f { - ProtoFilter::Eq(a, v) => match qs.clone_value(a, v) { - Ok(vc) => Ok(Filter::Eq(a.clone(), vc)), - Err(e) => Err(e), - }, - ProtoFilter::Sub(a, v) => match qs.clone_value(a, v) { - Ok(vc) => Ok(Filter::Sub(a.clone(), vc)), - Err(e) => Err(e), - }, - ProtoFilter::Pres(a) => Ok(Filter::Pres(a.clone())), - ProtoFilter::Or(l) => { - let inner: Result, _> = l.iter().map(|f| Self::from_rw(f, qs)).collect(); - match inner { - Ok(lc) => Ok(Filter::Or(lc)), - Err(e) => Err(e), - } - } - ProtoFilter::And(l) => { - let inner: Result, _> = l.iter().map(|f| Self::from_rw(f, qs)).collect(); - match inner { - Ok(lc) => Ok(Filter::And(lc)), - Err(e) => Err(e), - } - } - ProtoFilter::AndNot(l) => match Self::from_rw(l, qs) { - Ok(f) => Ok(Filter::AndNot(Box::new(f))), - Err(e) => Err(e), - }, - } + Ok(match f { + ProtoFilter::Eq(a, v) => Filter::Eq(a.clone(), qs.clone_value(a, v)?), + ProtoFilter::Sub(a, v) => Filter::Sub(a.clone(), qs.clone_value(a, v)?), + ProtoFilter::Pres(a) => Filter::Pres(a.clone()), + ProtoFilter::Or(l) => Filter::Or( + l.iter() + .map(|f| Self::from_rw(f, qs)) + .collect::, _>>()?, + ), + ProtoFilter::And(l) => Filter::And( + l.iter() + .map(|f| Self::from_rw(f, qs)) + .collect::, _>>()?, + ), + ProtoFilter::AndNot(l) => Filter::AndNot(Box::new(Self::from_rw(l, qs)?)), + }) } } diff --git a/src/lib/modify.rs b/src/lib/modify.rs index a4e0bf0a8..f733324b9 100644 --- a/src/lib/modify.rs +++ b/src/lib/modify.rs @@ -1,8 +1,9 @@ use proto_v1::Modify as ProtoModify; use proto_v1::ModifyList as ProtoModifyList; -use error::SchemaError; +use error::{OperationError, SchemaError}; use schema::{SchemaAttribute, SchemaReadTransaction}; +use server::{QueryServerReadTransaction, QueryServerWriteTransaction}; // Should this be std? use std::slice; @@ -23,12 +24,12 @@ pub enum Modify { } impl Modify { - pub fn from(m: &ProtoModify) -> Self { - match m { - ProtoModify::Present(a, v) => Modify::Present(a.clone(), v.clone()), - ProtoModify::Removed(a, v) => Modify::Removed(a.clone(), v.clone()), + pub fn from(m: &ProtoModify, qs: &QueryServerWriteTransaction) -> Result { + Ok(match m { + ProtoModify::Present(a, v) => Modify::Present(a.clone(), qs.clone_value(a, v)?), + ProtoModify::Removed(a, v) => Modify::Removed(a.clone(), qs.clone_value(a, v)?), ProtoModify::Purged(a) => Modify::Purged(a.clone()), - } + }) } } @@ -70,11 +71,18 @@ impl ModifyList { self.mods.push(modify) } - pub fn from(ml: &ProtoModifyList) -> Self { + pub fn from( + ml: &ProtoModifyList, + qs: &QueryServerWriteTransaction, + ) -> Result { // For each ProtoModify, do a from. - ModifyList { - valid: ModifyInvalid, - mods: ml.mods.iter().map(|pm| Modify::from(pm)).collect(), + let inner: Result, _> = ml.mods.iter().map(|pm| Modify::from(pm, qs)).collect(); + match inner { + Ok(m) => Ok(ModifyList { + valid: ModifyInvalid, + mods: m, + }), + Err(e) => Err(e), } } diff --git a/src/lib/proto_v1_actors.rs b/src/lib/proto_v1_actors.rs index f1e5dfd2a..a72b26e49 100644 --- a/src/lib/proto_v1_actors.rs +++ b/src/lib/proto_v1_actors.rs @@ -167,12 +167,18 @@ impl Handler for QueryServerV1 { fn handle(&mut self, msg: CreateRequest, _: &mut Self::Context) -> Self::Result { let mut audit = AuditScope::new("create"); let res = audit_segment!(&mut audit, || { - let crt = CreateEvent::from_request(msg); + let qs_write = self.qs.write(); + + let crt = match CreateEvent::from_request(msg, &qs_write) { + Ok(c) => c, + Err(e) => { + audit_log!(audit, "Failed to begin create: {:?}", e); + return Err(e); + } + }; audit_log!(audit, "Begin create event {:?}", crt); - let qs_write = self.qs.write(); - qs_write .create(&mut audit, &crt) .and_then(|_| qs_write.commit(&mut audit).map(|_| OperationResponse {}))