Skip to content

Commit 5c541dc

Browse files
committed
always validate in get path
1 parent bb1c60b commit 5c541dc

File tree

3 files changed

+29
-87
lines changed

3 files changed

+29
-87
lines changed

src/tracked_struct.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ where
333333
// which means the interned key could exist but `struct_map` not yet have
334334
// been updated).
335335

336-
match self.struct_map.update(current_revision, id) {
336+
match self.struct_map.update(zalsa, id) {
337337
Update::Current(r) => {
338338
// All inputs up to this point were previously
339339
// observed to be green and this struct was already
@@ -378,8 +378,7 @@ where
378378
///
379379
/// If the struct has not been created in this revision.
380380
pub fn lookup_struct<'db>(&'db self, db: &'db dyn Database, id: Id) -> C::Struct<'db> {
381-
let current_revision = db.zalsa().current_revision();
382-
self.struct_map.get(current_revision, id)
381+
self.struct_map.get(db.zalsa(), id)
383382
}
384383

385384
/// Deletes the given entities. This is used after a query `Q` executes and we can compare

src/tracked_struct/struct_map.rs

Lines changed: 25 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -100,22 +100,11 @@ where
100100
}
101101

102102
pub fn validate(&self, current_revision: Revision, id: Id) {
103-
Self::validate_in_map(&self.map, current_revision, id)
104-
}
105-
106-
pub fn validate_in_map(
107-
map: &FxDashMap<Id, Alloc<Value<C>>>,
108-
current_revision: Revision,
109-
id: Id,
110-
) {
111-
let mut data = map.get_mut(&id).unwrap();
103+
let mut data = self.map.get_mut(&id).unwrap();
112104

113105
// UNSAFE: We never permit `&`-access in the current revision until data.created_at
114106
// has been updated to the current revision (which we check below).
115107
let data = unsafe { data.as_mut() };
116-
117-
// Never update a struct twice in the same revision.
118-
assert!(data.created_at <= current_revision);
119108
data.created_at = current_revision;
120109
}
121110

@@ -126,7 +115,7 @@ where
126115
///
127116
/// * If the value is not present in the map.
128117
/// * If the value is already updated in this revision.
129-
pub fn update(&self, current_revision: Revision, id: Id) -> Update<'_, C> {
118+
pub fn update(&self, zalsa: &Zalsa, id: Id) -> Update<'_, C> {
130119
let mut data = self.map.get_mut(&id).unwrap();
131120

132121
// UNSAFE: We never permit `&`-access in the current revision until data.created_at
@@ -156,9 +145,10 @@ where
156145
//
157146
// For this reason, we just return `None` in this case, ensuring that the calling
158147
// code cannot violate that `&`-reference.
148+
let current_revision = zalsa.current_revision();
159149
if data_ref.created_at == current_revision {
160150
drop(data);
161-
return Update::Current(Self::get_from_map(&self.map, current_revision, id));
151+
return Update::Current(Self::get_from_map(&self.map, zalsa, id));
162152
}
163153

164154
data_ref.created_at = current_revision;
@@ -171,64 +161,25 @@ where
171161
///
172162
/// * If the value is not present in the map.
173163
/// * If the value has not been updated in this revision.
174-
pub fn get(&self, current_revision: Revision, id: Id) -> C::Struct<'_> {
175-
Self::get_from_map(&self.map, current_revision, id)
164+
pub fn get(&self, zalsa: &Zalsa, id: Id) -> C::Struct<'_> {
165+
Self::get_from_map(&self.map, zalsa, id)
176166
}
177167

178168
/// Helper function, provides shared functionality for [`StructMapView`][]
179169
///
180170
/// # Panics
181171
///
182172
/// * If the value is not present in the map.
183-
/// * If the value has not been updated in this revision.
184-
fn get_from_map(
185-
map: &FxDashMap<Id, Alloc<Value<C>>>,
186-
current_revision: Revision,
187-
id: Id,
188-
) -> C::Struct<'_> {
189-
let data = map.get(&id).unwrap();
190-
191-
// UNSAFE: We permit `&`-access in the current revision once data.created_at
192-
// has been updated to the current revision (which we check below).
193-
let data_ref: &Value<C> = unsafe { data.as_ref() };
194-
195-
// Before we drop the lock, check that the value has
196-
// been updated in this revision. This is what allows us to return a Struct
197-
let created_at = data_ref.created_at;
198-
assert!(
199-
created_at == current_revision,
200-
"access to tracked struct from previous revision"
201-
);
202-
203-
// Unsafety clause:
204-
//
205-
// * Value will not be updated again in this revision,
206-
// and revision will not change so long as runtime is shared
207-
// * We only remove values from the map when we have `&mut self`
208-
unsafe { C::struct_from_raw(data.as_raw()) }
209-
}
210-
211-
/// Lookup an existing tracked struct from the map, maybe validating it to current revision.
212-
///
213-
/// Validates to current revision if the struct was last created/validated in a revision that
214-
/// is still current for the struct's durability. That is, if the struct is HIGH durability
215-
/// (created by a HIGH durability query) and was created in R2, and we are now at R3 but no
216-
/// HIGH durability input has changed since R2, the struct is still valid and we can validate
217-
/// it to R3.
218-
///
219-
/// # Panics
220-
///
221-
/// * If the value is not present in the map.
222-
/// * If the value has not been updated in the last-changed revision for its durability.
223-
fn get_and_validate_last_changed<'db>(
224-
map: &'db FxDashMap<Id, Alloc<Value<C>>>,
173+
/// * If the value has not been updated since last-modified revision for its durability.
174+
fn get_from_map<'a>(
175+
map: &'a FxDashMap<Id, Alloc<Value<C>>>,
225176
zalsa: &Zalsa,
226177
id: Id,
227-
) -> C::Struct<'db> {
228-
let data = map.get(&id).unwrap();
178+
) -> C::Struct<'a> {
179+
let mut data = map.get_mut(&id).unwrap();
229180

230181
// UNSAFE: We permit `&`-access in the current revision once data.created_at
231-
// has been updated to the current revision (which we ensure below).
182+
// has been updated to the current revision (which we check below).
232183
let data_ref: &Value<C> = unsafe { data.as_ref() };
233184

234185
// Before we drop the lock, check that the value has been updated in the most recent
@@ -237,25 +188,24 @@ where
237188
let last_changed = zalsa.last_changed_revision(data_ref.durability);
238189
assert!(
239190
created_at >= last_changed,
240-
"access to tracked struct from obsolete revision"
191+
"access to tracked struct from previous revision"
241192
);
242193

194+
// Validate in current revision, if needed.
195+
let current_revision = zalsa.current_revision();
196+
if created_at < current_revision {
197+
// UNSAFE: We never permit `&`-access in the current revision until data.created_at
198+
// has been updated to the current revision (which we check below).
199+
let data = unsafe { data.as_mut() };
200+
data.created_at = current_revision;
201+
}
202+
243203
// Unsafety clause:
244204
//
245205
// * Value will not be updated again in this revision,
246206
// and revision will not change so long as runtime is shared
247207
// * We only remove values from the map when we have `&mut self`
248-
let ret = unsafe { C::struct_from_raw(data.as_raw()) };
249-
250-
drop(data);
251-
252-
// Validate in current revision, if necessary.
253-
let current_revision = zalsa.current_revision();
254-
if last_changed < current_revision {
255-
Self::validate_in_map(map, current_revision, id);
256-
}
257-
258-
ret
208+
unsafe { C::struct_from_raw(data.as_raw()) }
259209
}
260210

261211
/// Remove the entry for `id` from the map.
@@ -288,12 +238,8 @@ where
288238
///
289239
/// * If the value is not present in the map.
290240
/// * If the value has not been updated in this revision.
291-
pub fn get(&self, current_revision: Revision, id: Id) -> C::Struct<'_> {
292-
StructMap::get_from_map(&self.map, current_revision, id)
293-
}
294-
295-
pub fn get_and_validate_last_changed<'db>(&'db self, zalsa: &Zalsa, id: Id) -> C::Struct<'db> {
296-
StructMap::get_and_validate_last_changed(&self.map, zalsa, id)
241+
pub fn get(&self, zalsa: &Zalsa, id: Id) -> C::Struct<'_> {
242+
StructMap::get_from_map(&self.map, zalsa, id)
297243
}
298244
}
299245

src/tracked_struct/tracked_field.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ where
4747
/// The caller is responible for selecting the appropriate element.
4848
pub fn field<'db>(&'db self, db: &'db dyn Database, id: Id) -> &'db C::Fields<'db> {
4949
let zalsa_local = db.zalsa_local();
50-
let current_revision = db.zalsa().current_revision();
51-
let data = self.struct_map.get(current_revision, id);
50+
let data = self.struct_map.get(db.zalsa(), id);
5251
let data = C::deref_struct(data);
5352
let changed_at = data.revisions[self.field_index];
5453

@@ -84,9 +83,7 @@ where
8483
revision: crate::Revision,
8584
) -> bool {
8685
let id = input.unwrap();
87-
let data = self
88-
.struct_map
89-
.get_and_validate_last_changed(db.zalsa(), id);
86+
let data = self.struct_map.get(db.zalsa(), id);
9087
let data = C::deref_struct(data);
9188
let field_changed_at = data.revisions[self.field_index];
9289
field_changed_at > revision

0 commit comments

Comments
 (0)