Add modify and entry transformers

This commit is contained in:
William Brown 2019-03-17 13:24:06 +10:00
parent 6b4256cd98
commit f858e6b5c4
5 changed files with 113 additions and 110 deletions

View file

@ -1,9 +1,10 @@
// use serde_json::{Error, Value}; // use serde_json::{Error, Value};
use super::proto_v1::Entry as ProtoEntry; use super::proto_v1::Entry as ProtoEntry;
use error::SchemaError; use error::{OperationError, SchemaError};
use filter::{Filter, FilterValid}; use filter::{Filter, FilterValid};
use modify::{Modify, ModifyInvalid, ModifyList, ModifyValid}; use modify::{Modify, ModifyInvalid, ModifyList, ModifyValid};
use schema::{SchemaAttribute, SchemaClass, SchemaReadTransaction}; use schema::{SchemaAttribute, SchemaClass, SchemaReadTransaction};
use server::{QueryServerReadTransaction, QueryServerWriteTransaction};
use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut}; use std::collections::btree_map::{Iter as BTreeIter, IterMut as BTreeIterMut};
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::collections::HashMap; use std::collections::HashMap;
@ -152,26 +153,42 @@ impl Entry<EntryInvalid, EntryNew> {
} }
// FIXME: Can we consume protoentry? // FIXME: Can we consume protoentry?
pub fn from(e: &ProtoEntry) -> Self { pub fn from(e: &ProtoEntry, qs: &QueryServerWriteTransaction) -> Result<Self, OperationError> {
// Why not the trait? In the future we may want to extend // Why not the trait? In the future we may want to extend
// this with server aware functions for changes of the // this with server aware functions for changes of the
// incoming data. // incoming data.
Entry {
// Somehow we need to take the tree of e attrs, and convert
// all ref types to our types ...
let map2: Result<BTreeMap<String, Vec<String>>, OperationError> = e
.attrs
.iter()
.map(|(k, v)| {
let nv: Result<Vec<_>, _> = 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 // For now, we do a straight move, and we sort the incoming data
// sets so that BST works. // sets so that BST works.
state: EntryNew, state: EntryNew,
valid: EntryInvalid, valid: EntryInvalid,
id: None, id: None,
attrs: e attrs: x,
.attrs })
.iter()
.map(|(k, v)| {
let mut nv = v.clone();
nv.sort_unstable();
(k.clone(), nv)
})
.collect(),
}
} }
} }

View file

@ -62,9 +62,7 @@ impl SearchResult {
pub struct SearchEvent { pub struct SearchEvent {
pub internal: bool, pub internal: bool,
pub filter: Filter<FilterInvalid>, pub filter: Filter<FilterInvalid>,
// TODO: Remove this // TODO: Add list of attributes to request
class: (), // String
// TODO: Add list of attributes to request
} }
impl SearchEvent { impl SearchEvent {
@ -76,7 +74,6 @@ impl SearchEvent {
Ok(f) => Ok(SearchEvent { Ok(f) => Ok(SearchEvent {
internal: false, internal: false,
filter: Filter::new_ignore_hidden(f), filter: Filter::new_ignore_hidden(f),
class: (),
}), }),
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -87,7 +84,6 @@ impl SearchEvent {
SearchEvent { SearchEvent {
internal: false, internal: false,
filter: filter, filter: filter,
class: (),
} }
} }
@ -99,7 +95,6 @@ impl SearchEvent {
Ok(f) => Ok(SearchEvent { Ok(f) => Ok(SearchEvent {
filter: Filter::new_recycled(f), filter: Filter::new_recycled(f),
internal: false, internal: false,
class: (),
}), }),
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -109,7 +104,6 @@ impl SearchEvent {
SearchEvent { SearchEvent {
internal: false, internal: false,
filter: Filter::new_recycled(filter), filter: Filter::new_recycled(filter),
class: (),
} }
} }
@ -118,7 +112,6 @@ impl SearchEvent {
SearchEvent { SearchEvent {
internal: false, internal: false,
filter: Filter::new_ignore_hidden(filter), filter: Filter::new_ignore_hidden(filter),
class: (),
} }
} }
@ -126,7 +119,6 @@ impl SearchEvent {
SearchEvent { SearchEvent {
internal: true, internal: true,
filter: filter, filter: filter,
class: (),
} }
} }
} }
@ -146,14 +138,21 @@ pub struct CreateEvent {
// FIXME: Should this actually be in createEvent handler? // FIXME: Should this actually be in createEvent handler?
impl CreateEvent { impl CreateEvent {
pub fn from_request(request: CreateRequest) -> Self { pub fn from_request(
CreateEvent { request: CreateRequest,
// From ProtoEntry -> Entry qs: &QueryServerWriteTransaction,
// What is the correct consuming iterator here? Can we ) -> Result<Self, OperationError> {
// even do that? let rentries: Result<Vec<_>, _> =
internal: false, request.entries.iter().map(|e| Entry::from(e, qs)).collect();
// TODO: Transform references here. match rentries {
entries: request.entries.iter().map(|e| Entry::from(e)).collect(), 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<Self, OperationError> { ) -> Result<Self, OperationError> {
match Filter::from_rw(&request.filter, qs) { match Filter::from_rw(&request.filter, qs) {
Ok(f) => Ok(DeleteEvent { Ok(f) => Ok(DeleteEvent {
// TODO: Transform references here.
filter: Filter::new_ignore_hidden(f), filter: Filter::new_ignore_hidden(f),
internal: false, internal: false,
}), }),
@ -239,13 +237,14 @@ impl ModifyEvent {
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
match Filter::from_rw(&request.filter, qs) { match Filter::from_rw(&request.filter, qs) {
Ok(f) => Ok(ModifyEvent { Ok(f) => match ModifyList::from(&request.modlist, qs) {
// TODO: Transform references here. Ok(m) => Ok(ModifyEvent {
filter: Filter::new_ignore_hidden(f), filter: Filter::new_ignore_hidden(f),
// TODO: Transform references here. modlist: m,
modlist: ModifyList::from(&request.modlist), internal: false,
internal: false, }),
}), Err(e) => Err(e),
},
Err(e) => Err(e), Err(e) => Err(e),
} }
@ -333,7 +332,6 @@ impl ReviveRecycledEvent {
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
match Filter::from_rw(&request.filter, qs) { match Filter::from_rw(&request.filter, qs) {
Ok(f) => Ok(ReviveRecycledEvent { Ok(f) => Ok(ReviveRecycledEvent {
// TODO: Transform references here (in theory should be none though)
filter: Filter::new_recycled(f), filter: Filter::new_recycled(f),
internal: false, internal: false,
}), }),

View file

@ -196,70 +196,44 @@ impl Filter<FilterInvalid> {
// monomorphise on the trait to call clone_value. An option is to make a fn that // 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. // takes "clone_value(t, a, v) instead, but that may have a similar issue.
pub fn from_ro(f: &ProtoFilter, qs: &QueryServerTransaction) -> Result<Self, OperationError> { pub fn from_ro(f: &ProtoFilter, qs: &QueryServerTransaction) -> Result<Self, OperationError> {
match f { Ok(match f {
ProtoFilter::Eq(a, v) => match qs.clone_value(a, v) { ProtoFilter::Eq(a, v) => Filter::Eq(a.clone(), qs.clone_value(a, v)?),
Ok(vc) => Ok(Filter::Eq(a.clone(), vc)), ProtoFilter::Sub(a, v) => Filter::Sub(a.clone(), qs.clone_value(a, v)?),
Err(e) => Err(e), ProtoFilter::Pres(a) => Filter::Pres(a.clone()),
}, ProtoFilter::Or(l) => Filter::Or(
ProtoFilter::Sub(a, v) => match qs.clone_value(a, v) { l.iter()
Ok(vc) => Ok(Filter::Sub(a.clone(), vc)), .map(|f| Self::from_ro(f, qs))
Err(e) => Err(e), .collect::<Result<Vec<_>, _>>()?,
}, ),
ProtoFilter::Pres(a) => Ok(Filter::Pres(a.clone())), ProtoFilter::And(l) => Filter::And(
ProtoFilter::Or(l) => { l.iter()
let inner: Result<Vec<_>, _> = l.iter().map(|f| Self::from_ro(f, qs)).collect(); .map(|f| Self::from_ro(f, qs))
match inner { .collect::<Result<Vec<_>, _>>()?,
Ok(lc) => Ok(Filter::Or(lc)), ),
Err(e) => Err(e), ProtoFilter::AndNot(l) => Filter::AndNot(Box::new(Self::from_ro(l, qs)?)),
} })
}
ProtoFilter::And(l) => {
let inner: Result<Vec<_>, _> = 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),
},
}
} }
pub fn from_rw( pub fn from_rw(
f: &ProtoFilter, f: &ProtoFilter,
qs: &QueryServerWriteTransaction, qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> { ) -> Result<Self, OperationError> {
match f { Ok(match f {
ProtoFilter::Eq(a, v) => match qs.clone_value(a, v) { ProtoFilter::Eq(a, v) => Filter::Eq(a.clone(), qs.clone_value(a, v)?),
Ok(vc) => Ok(Filter::Eq(a.clone(), vc)), ProtoFilter::Sub(a, v) => Filter::Sub(a.clone(), qs.clone_value(a, v)?),
Err(e) => Err(e), ProtoFilter::Pres(a) => Filter::Pres(a.clone()),
}, ProtoFilter::Or(l) => Filter::Or(
ProtoFilter::Sub(a, v) => match qs.clone_value(a, v) { l.iter()
Ok(vc) => Ok(Filter::Sub(a.clone(), vc)), .map(|f| Self::from_rw(f, qs))
Err(e) => Err(e), .collect::<Result<Vec<_>, _>>()?,
}, ),
ProtoFilter::Pres(a) => Ok(Filter::Pres(a.clone())), ProtoFilter::And(l) => Filter::And(
ProtoFilter::Or(l) => { l.iter()
let inner: Result<Vec<_>, _> = l.iter().map(|f| Self::from_rw(f, qs)).collect(); .map(|f| Self::from_rw(f, qs))
match inner { .collect::<Result<Vec<_>, _>>()?,
Ok(lc) => Ok(Filter::Or(lc)), ),
Err(e) => Err(e), ProtoFilter::AndNot(l) => Filter::AndNot(Box::new(Self::from_rw(l, qs)?)),
} })
}
ProtoFilter::And(l) => {
let inner: Result<Vec<_>, _> = 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),
},
}
} }
} }

View file

@ -1,8 +1,9 @@
use proto_v1::Modify as ProtoModify; use proto_v1::Modify as ProtoModify;
use proto_v1::ModifyList as ProtoModifyList; use proto_v1::ModifyList as ProtoModifyList;
use error::SchemaError; use error::{OperationError, SchemaError};
use schema::{SchemaAttribute, SchemaReadTransaction}; use schema::{SchemaAttribute, SchemaReadTransaction};
use server::{QueryServerReadTransaction, QueryServerWriteTransaction};
// Should this be std? // Should this be std?
use std::slice; use std::slice;
@ -23,12 +24,12 @@ pub enum Modify {
} }
impl Modify { impl Modify {
pub fn from(m: &ProtoModify) -> Self { pub fn from(m: &ProtoModify, qs: &QueryServerWriteTransaction) -> Result<Self, OperationError> {
match m { Ok(match m {
ProtoModify::Present(a, v) => Modify::Present(a.clone(), v.clone()), ProtoModify::Present(a, v) => Modify::Present(a.clone(), qs.clone_value(a, v)?),
ProtoModify::Removed(a, v) => Modify::Removed(a.clone(), v.clone()), ProtoModify::Removed(a, v) => Modify::Removed(a.clone(), qs.clone_value(a, v)?),
ProtoModify::Purged(a) => Modify::Purged(a.clone()), ProtoModify::Purged(a) => Modify::Purged(a.clone()),
} })
} }
} }
@ -70,11 +71,18 @@ impl ModifyList<ModifyInvalid> {
self.mods.push(modify) self.mods.push(modify)
} }
pub fn from(ml: &ProtoModifyList) -> Self { pub fn from(
ml: &ProtoModifyList,
qs: &QueryServerWriteTransaction,
) -> Result<Self, OperationError> {
// For each ProtoModify, do a from. // For each ProtoModify, do a from.
ModifyList { let inner: Result<Vec<_>, _> = ml.mods.iter().map(|pm| Modify::from(pm, qs)).collect();
valid: ModifyInvalid, match inner {
mods: ml.mods.iter().map(|pm| Modify::from(pm)).collect(), Ok(m) => Ok(ModifyList {
valid: ModifyInvalid,
mods: m,
}),
Err(e) => Err(e),
} }
} }

View file

@ -167,12 +167,18 @@ impl Handler<CreateRequest> for QueryServerV1 {
fn handle(&mut self, msg: CreateRequest, _: &mut Self::Context) -> Self::Result { fn handle(&mut self, msg: CreateRequest, _: &mut Self::Context) -> Self::Result {
let mut audit = AuditScope::new("create"); let mut audit = AuditScope::new("create");
let res = audit_segment!(&mut audit, || { 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); audit_log!(audit, "Begin create event {:?}", crt);
let qs_write = self.qs.write();
qs_write qs_write
.create(&mut audit, &crt) .create(&mut audit, &crt)
.and_then(|_| qs_write.commit(&mut audit).map(|_| OperationResponse {})) .and_then(|_| qs_write.commit(&mut audit).map(|_| OperationResponse {}))