mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-02-24 11:59:15 -05:00
NLL-inspired simplifications to db.rs
* remove intermediate bool from adjust_day. * rewrite LockedDatabase::list_aggregate_recordings. I started by collapsing the flush into the first part of the if, in a similar way to adjust_day. But then I refactored more and ended up with a structure that probably would have been allowed with the old lexical borrow checker. I think it's more readable, and it does 1 btree operation per row where before it did 2 or 3.
This commit is contained in:
parent
699ec87968
commit
0b0f4ec9ed
105
db/db.rs
105
db/db.rs
@ -166,6 +166,27 @@ pub struct ListAggregatedRecordingsRow {
|
|||||||
pub growing: bool,
|
pub growing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ListAggregatedRecordingsRow {
|
||||||
|
fn from(row: ListRecordingsRow) -> Self {
|
||||||
|
let recording_id = row.id.recording();
|
||||||
|
let uncommitted = (row.flags & RecordingFlags::Uncommitted as i32) != 0;
|
||||||
|
let growing = (row.flags & RecordingFlags::Growing as i32) != 0;
|
||||||
|
ListAggregatedRecordingsRow {
|
||||||
|
time: row.start .. recording::Time(row.start.0 + row.duration_90k as i64),
|
||||||
|
ids: recording_id .. recording_id+1,
|
||||||
|
video_samples: row.video_samples as i64,
|
||||||
|
video_sync_samples: row.video_sync_samples as i64,
|
||||||
|
sample_file_bytes: row.sample_file_bytes as i64,
|
||||||
|
video_sample_entry_id: row.video_sample_entry_id,
|
||||||
|
stream_id: row.id.stream(),
|
||||||
|
run_start_id: recording_id - row.run_offset,
|
||||||
|
open_id: row.open_id,
|
||||||
|
first_uncommitted: if uncommitted { Some(recording_id) } else { None },
|
||||||
|
growing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Select fields from the `recordings_playback` table. Retrieve with `with_recording_playback`.
|
/// Select fields from the `recordings_playback` table. Retrieve with `with_recording_playback`.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RecordingPlayback<'a> {
|
pub struct RecordingPlayback<'a> {
|
||||||
@ -454,13 +475,10 @@ fn adjust_day(day: StreamDayKey, delta: StreamDayValue,
|
|||||||
match m.entry(day) {
|
match m.entry(day) {
|
||||||
Entry::Vacant(e) => { e.insert(delta); },
|
Entry::Vacant(e) => { e.insert(delta); },
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
let remove = {
|
let v = e.get_mut();
|
||||||
let v = e.get_mut();
|
v.recordings += delta.recordings;
|
||||||
v.recordings += delta.recordings;
|
v.duration += delta.duration;
|
||||||
v.duration += delta.duration;
|
if v.recordings == 0 {
|
||||||
v.recordings == 0
|
|
||||||
};
|
|
||||||
if remove {
|
|
||||||
e.remove_entry();
|
e.remove_entry();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1124,58 +1142,43 @@ impl LockedDatabase {
|
|||||||
self.list_recordings_by_time(stream_id, desired_time, &mut |row| {
|
self.list_recordings_by_time(stream_id, desired_time, &mut |row| {
|
||||||
let recording_id = row.id.recording();
|
let recording_id = row.id.recording();
|
||||||
let run_start_id = recording_id - row.run_offset;
|
let run_start_id = recording_id - row.run_offset;
|
||||||
let needs_flush = if let Some(a) = aggs.get(&run_start_id) {
|
|
||||||
let new_dur = a.time.end - a.time.start +
|
|
||||||
recording::Duration(row.duration_90k as i64);
|
|
||||||
a.ids.end != recording_id || row.video_sample_entry_id != a.video_sample_entry_id ||
|
|
||||||
new_dur >= forced_split
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
if needs_flush {
|
|
||||||
let a = aggs.remove(&run_start_id).expect("needs_flush when agg is None");
|
|
||||||
f(&a)?;
|
|
||||||
}
|
|
||||||
let uncommitted = (row.flags & RecordingFlags::Uncommitted as i32) != 0;
|
let uncommitted = (row.flags & RecordingFlags::Uncommitted as i32) != 0;
|
||||||
let growing = (row.flags & RecordingFlags::Growing as i32) != 0;
|
let growing = (row.flags & RecordingFlags::Growing as i32) != 0;
|
||||||
use std::collections::btree_map::Entry;
|
use std::collections::btree_map::Entry;
|
||||||
match aggs.entry(run_start_id) {
|
match aggs.entry(run_start_id) {
|
||||||
Entry::Occupied(mut e) => {
|
Entry::Occupied(mut e) => {
|
||||||
let a = e.get_mut();
|
let a = e.get_mut();
|
||||||
if a.time.end != row.start {
|
let new_dur = a.time.end - a.time.start +
|
||||||
bail!("stream {} recording {} ends at {}; {} starts at {}; expected same",
|
recording::Duration(row.duration_90k as i64);
|
||||||
stream_id, a.ids.end - 1, a.time.end, row.id, row.start);
|
let needs_flush =
|
||||||
|
a.ids.end != recording_id ||
|
||||||
|
row.video_sample_entry_id != a.video_sample_entry_id ||
|
||||||
|
new_dur >= forced_split;
|
||||||
|
if needs_flush { // flush then start a new entry.
|
||||||
|
f(a)?;
|
||||||
|
*a = ListAggregatedRecordingsRow::from(row);
|
||||||
|
} else { // append.
|
||||||
|
if a.time.end != row.start {
|
||||||
|
bail!("stream {} recording {} ends at {} but {} starts at {}",
|
||||||
|
stream_id, a.ids.end - 1, a.time.end, row.id, row.start);
|
||||||
|
}
|
||||||
|
if a.open_id != row.open_id {
|
||||||
|
bail!("stream {} recording {} has open id {} but {} has {}",
|
||||||
|
stream_id, a.ids.end - 1, a.open_id, row.id, row.open_id);
|
||||||
|
}
|
||||||
|
a.time.end.0 += row.duration_90k as i64;
|
||||||
|
a.ids.end = recording_id + 1;
|
||||||
|
a.video_samples += row.video_samples as i64;
|
||||||
|
a.video_sync_samples += row.video_sync_samples as i64;
|
||||||
|
a.sample_file_bytes += row.sample_file_bytes as i64;
|
||||||
|
if uncommitted {
|
||||||
|
a.first_uncommitted = a.first_uncommitted.or(Some(recording_id));
|
||||||
|
}
|
||||||
|
a.growing = growing;
|
||||||
}
|
}
|
||||||
if a.open_id != row.open_id {
|
|
||||||
bail!("stream {} recording {} has open id {}; {} has {}; expected same",
|
|
||||||
stream_id, a.ids.end - 1, a.open_id, row.id, row.open_id);
|
|
||||||
}
|
|
||||||
a.time.end.0 += row.duration_90k as i64;
|
|
||||||
a.ids.end = recording_id + 1;
|
|
||||||
a.video_samples += row.video_samples as i64;
|
|
||||||
a.video_sync_samples += row.video_sync_samples as i64;
|
|
||||||
a.sample_file_bytes += row.sample_file_bytes as i64;
|
|
||||||
if uncommitted {
|
|
||||||
a.first_uncommitted = a.first_uncommitted.or(Some(recording_id));
|
|
||||||
}
|
|
||||||
a.growing = growing;
|
|
||||||
},
|
},
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => { e.insert(ListAggregatedRecordingsRow::from(row)); },
|
||||||
e.insert(ListAggregatedRecordingsRow {
|
}
|
||||||
time: row.start .. recording::Time(row.start.0 + row.duration_90k as i64),
|
|
||||||
ids: recording_id .. recording_id+1,
|
|
||||||
video_samples: row.video_samples as i64,
|
|
||||||
video_sync_samples: row.video_sync_samples as i64,
|
|
||||||
sample_file_bytes: row.sample_file_bytes as i64,
|
|
||||||
video_sample_entry_id: row.video_sample_entry_id,
|
|
||||||
stream_id,
|
|
||||||
run_start_id,
|
|
||||||
open_id: row.open_id,
|
|
||||||
first_uncommitted: if uncommitted { Some(recording_id) } else { None },
|
|
||||||
growing,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
for a in aggs.values() {
|
for a in aggs.values() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user