mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-01-15 00:35:03 -05:00
avoid heap allocation reading uuid from sqlite
As described here: https://github.com/jgallagher/rusqlite/issues/158#issuecomment-277884643
This commit is contained in:
parent
5d727a9c83
commit
13c6af45a1
32
src/db.rs
32
src/db.rs
@ -190,6 +190,16 @@ const LIST_RECORDINGS_BY_ID_SQL: &'static str = r#"
|
|||||||
recording.composite_id
|
recording.composite_id
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
|
struct FromSqlUuid(Uuid);
|
||||||
|
|
||||||
|
impl rusqlite::types::FromSql for FromSqlUuid {
|
||||||
|
fn column_result(value: rusqlite::types::ValueRef) -> rusqlite::types::FromSqlResult<Self> {
|
||||||
|
let uuid = Uuid::from_bytes(value.as_blob()?)
|
||||||
|
.map_err(|e| rusqlite::types::FromSqlError::Other(Box::new(e)))?;
|
||||||
|
Ok(FromSqlUuid(uuid))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A concrete box derived from a ISO/IEC 14496-12 section 8.5.2 VisualSampleEntry box. Describes
|
/// A concrete box derived from a ISO/IEC 14496-12 section 8.5.2 VisualSampleEntry box. Describes
|
||||||
/// the codec, width, height, etc.
|
/// the codec, width, height, etc.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -449,13 +459,6 @@ impl Camera {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a uuid from the given SQLite row and column index.
|
|
||||||
fn get_uuid<I: rusqlite::RowIndex>(row: &rusqlite::Row, i: I) -> Result<Uuid, Error> {
|
|
||||||
// TODO: avoid this extra allocation+copy into a Vec<u8>.
|
|
||||||
// See <https://github.com/jgallagher/rusqlite/issues/158>.
|
|
||||||
Ok(Uuid::from_bytes(row.get_checked::<_, Vec<u8>>(i)?.as_slice())?)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initializes the recordings associated with the given camera.
|
/// Initializes the recordings associated with the given camera.
|
||||||
fn init_recordings(conn: &mut rusqlite::Connection, camera_id: i32, camera: &mut Camera)
|
fn init_recordings(conn: &mut rusqlite::Connection, camera_id: i32, camera: &mut Camera)
|
||||||
-> Result<(), Error> {
|
-> Result<(), Error> {
|
||||||
@ -966,8 +969,9 @@ impl LockedDatabase {
|
|||||||
let mut rows = stmt.query_named(&[(":composite_id", &composite_id)])?;
|
let mut rows = stmt.query_named(&[(":composite_id", &composite_id)])?;
|
||||||
if let Some(row) = rows.next() {
|
if let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
|
let uuid: FromSqlUuid = row.get_checked(0)?;
|
||||||
let r = Arc::new(RecordingPlayback{
|
let r = Arc::new(RecordingPlayback{
|
||||||
sample_file_uuid: get_uuid(&row, 0)?,
|
sample_file_uuid: uuid.0,
|
||||||
video_index: row.get_checked(1)?,
|
video_index: row.get_checked(1)?,
|
||||||
});
|
});
|
||||||
cache.insert(composite_id, r.clone());
|
cache.insert(composite_id, r.clone());
|
||||||
@ -983,7 +987,8 @@ impl LockedDatabase {
|
|||||||
let mut rows = stmt.query_named(&[])?;
|
let mut rows = stmt.query_named(&[])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
reserved.push(get_uuid(&row, 0)?);
|
let uuid: FromSqlUuid = row.get_checked(0)?;
|
||||||
|
reserved.push(uuid.0);
|
||||||
}
|
}
|
||||||
Ok(reserved)
|
Ok(reserved)
|
||||||
}
|
}
|
||||||
@ -1002,10 +1007,11 @@ impl LockedDatabase {
|
|||||||
let start = recording::Time(row.get_checked(2)?);
|
let start = recording::Time(row.get_checked(2)?);
|
||||||
let duration = recording::Duration(row.get_checked(3)?);
|
let duration = recording::Duration(row.get_checked(3)?);
|
||||||
let composite_id: i64 = row.get_checked(0)?;
|
let composite_id: i64 = row.get_checked(0)?;
|
||||||
|
let uuid: FromSqlUuid = row.get_checked(1)?;
|
||||||
let should_continue = f(ListOldestSampleFilesRow{
|
let should_continue = f(ListOldestSampleFilesRow{
|
||||||
recording_id: composite_id as i32,
|
recording_id: composite_id as i32,
|
||||||
camera_id: (composite_id >> 32) as i32,
|
camera_id: (composite_id >> 32) as i32,
|
||||||
uuid: get_uuid(&row, 1)?,
|
uuid: uuid.0,
|
||||||
time: start .. start + duration,
|
time: start .. start + duration,
|
||||||
sample_file_bytes: row.get_checked(4)?,
|
sample_file_bytes: row.get_checked(4)?,
|
||||||
});
|
});
|
||||||
@ -1078,10 +1084,10 @@ impl LockedDatabase {
|
|||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let id = row.get_checked(0)?;
|
let id = row.get_checked(0)?;
|
||||||
let uuid = get_uuid(&row, 1)?;
|
let uuid: FromSqlUuid = row.get_checked(1)?;
|
||||||
self.state.cameras_by_id.insert(id, Camera{
|
self.state.cameras_by_id.insert(id, Camera{
|
||||||
id: id,
|
id: id,
|
||||||
uuid: uuid,
|
uuid: uuid.0,
|
||||||
short_name: row.get_checked(2)?,
|
short_name: row.get_checked(2)?,
|
||||||
description: row.get_checked(3)?,
|
description: row.get_checked(3)?,
|
||||||
host: row.get_checked(4)?,
|
host: row.get_checked(4)?,
|
||||||
@ -1096,7 +1102,7 @@ impl LockedDatabase {
|
|||||||
days: BTreeMap::new(),
|
days: BTreeMap::new(),
|
||||||
next_recording_id: row.get_checked(10)?,
|
next_recording_id: row.get_checked(10)?,
|
||||||
});
|
});
|
||||||
self.state.cameras_by_uuid.insert(uuid, id);
|
self.state.cameras_by_uuid.insert(uuid.0, id);
|
||||||
}
|
}
|
||||||
info!("Loaded {} cameras", self.state.cameras_by_id.len());
|
info!("Loaded {} cameras", self.state.cameras_by_id.len());
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
Reference in New Issue
Block a user