mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-01-13 07:53:22 -05:00
Merge branch 'master' into auth
This commit is contained in:
commit
4f87c16c31
451
Cargo.lock
generated
451
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -38,11 +38,11 @@ moonfire-db = { path = "db" }
|
|||||||
moonfire-ffmpeg = { path = "ffmpeg" }
|
moonfire-ffmpeg = { path = "ffmpeg" }
|
||||||
mylog = { git = "https://github.com/scottlamb/mylog" }
|
mylog = { git = "https://github.com/scottlamb/mylog" }
|
||||||
openssl = "0.10"
|
openssl = "0.10"
|
||||||
parking_lot = { version = "0.6", features = [] }
|
parking_lot = { version = "0.7", features = [] }
|
||||||
reffers = "0.5.1"
|
reffers = "0.5.1"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
ring = "0.12.1"
|
ring = "0.12.1"
|
||||||
rusqlite = "0.14"
|
rusqlite = "0.15"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
@ -51,14 +51,14 @@ time = "0.1"
|
|||||||
tokio = "0.1.8"
|
tokio = "0.1.8"
|
||||||
tokio-signal = "0.2"
|
tokio-signal = "0.2"
|
||||||
url = "1.4"
|
url = "1.4"
|
||||||
uuid = { version = "0.6", features = ["serde", "std", "v4"] }
|
uuid = { version = "0.7", features = ["serde", "std", "v4"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
reqwest = "0.9.5"
|
reqwest = "0.9.5"
|
||||||
tempdir = "0.3"
|
tempdir = "0.3"
|
||||||
|
|
||||||
[dependencies.cursive]
|
[dependencies.cursive]
|
||||||
version = "0.9"
|
version = "0.10"
|
||||||
#default-features = false
|
#default-features = false
|
||||||
#features = ["termion-backend"]
|
#features = ["termion-backend"]
|
||||||
|
|
||||||
|
@ -14,5 +14,5 @@ path = "lib.rs"
|
|||||||
failure = "0.1.1"
|
failure = "0.1.1"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
parking_lot = { version = "0.6", features = [] }
|
parking_lot = { version = "0.7", features = [] }
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
|
@ -23,10 +23,10 @@ lru-cache = "0.1"
|
|||||||
moonfire-base = { path = "../base" }
|
moonfire-base = { path = "../base" }
|
||||||
mylog = { git = "https://github.com/scottlamb/mylog" }
|
mylog = { git = "https://github.com/scottlamb/mylog" }
|
||||||
openssl = "0.10"
|
openssl = "0.10"
|
||||||
parking_lot = { version = "0.6", features = [] }
|
parking_lot = { version = "0.7", features = [] }
|
||||||
protobuf = "2.0"
|
protobuf = "2.0"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
rusqlite = "0.14"
|
rusqlite = "0.15"
|
||||||
tempdir = "0.3"
|
tempdir = "0.3"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
uuid = { version = "0.6", features = ["std", "v4"] }
|
uuid = { version = "0.7", features = ["std", "v4"] }
|
||||||
|
@ -34,7 +34,7 @@ use failure::Error;
|
|||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use libpasta;
|
use libpasta;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use rusqlite::{self, Connection, Transaction};
|
use rusqlite::{self, Connection, Transaction, types::ToSql};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
@ -343,7 +343,7 @@ impl State {
|
|||||||
from
|
from
|
||||||
user
|
user
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
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)?;
|
||||||
@ -594,7 +594,7 @@ impl State {
|
|||||||
let addr = req.addr_buf();
|
let addr = req.addr_buf();
|
||||||
let addr: Option<&[u8]> = addr.as_ref().map(|a| a.as_ref());
|
let addr: Option<&[u8]> = addr.as_ref().map(|a| a.as_ref());
|
||||||
stmt.execute(&[
|
stmt.execute(&[
|
||||||
&req.when_sec,
|
&req.when_sec as &ToSql,
|
||||||
&req.user_agent,
|
&req.user_agent,
|
||||||
&addr,
|
&addr,
|
||||||
&(reason as i32),
|
&(reason as i32),
|
||||||
|
@ -36,7 +36,7 @@ use failure::Error;
|
|||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use raw;
|
use raw;
|
||||||
use recording;
|
use recording;
|
||||||
use rusqlite;
|
use rusqlite::{self, types::ToSql};
|
||||||
use schema;
|
use schema;
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -57,7 +57,7 @@ pub fn run(conn: &rusqlite::Connection, opts: &Options) -> Result<(), Error> {
|
|||||||
"#)?;
|
"#)?;
|
||||||
let mut garbage_stmt = conn.prepare_cached(
|
let mut garbage_stmt = conn.prepare_cached(
|
||||||
"select composite_id from garbage where sample_file_dir_id = ?")?;
|
"select composite_id from garbage where sample_file_dir_id = ?")?;
|
||||||
let mut rows = dir_stmt.query(&[])?;
|
let mut rows = dir_stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let mut meta = schema::DirMeta::default();
|
let mut meta = schema::DirMeta::default();
|
||||||
@ -93,7 +93,7 @@ pub fn run(conn: &rusqlite::Connection, opts: &Options) -> Result<(), Error> {
|
|||||||
let mut stmt = conn.prepare(r#"
|
let mut stmt = conn.prepare(r#"
|
||||||
select id, sample_file_dir_id from stream where sample_file_dir_id is not null
|
select id, sample_file_dir_id from stream where sample_file_dir_id is not null
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let stream_id = row.get_checked(0)?;
|
let stream_id = row.get_checked(0)?;
|
||||||
|
29
db/db.rs
29
db/db.rs
@ -62,7 +62,7 @@ use openssl::hash;
|
|||||||
use parking_lot::{Mutex,MutexGuard};
|
use parking_lot::{Mutex,MutexGuard};
|
||||||
use raw;
|
use raw;
|
||||||
use recording::{self, TIME_UNITS_PER_SEC};
|
use recording::{self, TIME_UNITS_PER_SEC};
|
||||||
use rusqlite;
|
use rusqlite::{self, types::ToSql};
|
||||||
use schema;
|
use schema;
|
||||||
use std::collections::{BTreeMap, VecDeque};
|
use std::collections::{BTreeMap, VecDeque};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -101,7 +101,7 @@ pub struct FromSqlUuid(pub Uuid);
|
|||||||
|
|
||||||
impl rusqlite::types::FromSql for FromSqlUuid {
|
impl rusqlite::types::FromSql for FromSqlUuid {
|
||||||
fn column_result(value: rusqlite::types::ValueRef) -> rusqlite::types::FromSqlResult<Self> {
|
fn column_result(value: rusqlite::types::ValueRef) -> rusqlite::types::FromSqlResult<Self> {
|
||||||
let uuid = Uuid::from_bytes(value.as_blob()?)
|
let uuid = Uuid::from_slice(value.as_blob()?)
|
||||||
.map_err(|e| rusqlite::types::FromSqlError::Other(Box::new(e)))?;
|
.map_err(|e| rusqlite::types::FromSqlError::Other(Box::new(e)))?;
|
||||||
Ok(FromSqlUuid(uuid))
|
Ok(FromSqlUuid(uuid))
|
||||||
}
|
}
|
||||||
@ -881,7 +881,7 @@ impl LockedDatabase {
|
|||||||
let mut stmt = tx.prepare_cached(
|
let mut stmt = tx.prepare_cached(
|
||||||
r"update open set duration_90k = ?, end_time_90k = ? where id = ?")?;
|
r"update open set duration_90k = ?, end_time_90k = ? where id = ?")?;
|
||||||
let rows = stmt.execute(&[
|
let rows = stmt.execute(&[
|
||||||
&(recording::Time::new(clocks.monotonic()) - self.open_monotonic).0,
|
&(recording::Time::new(clocks.monotonic()) - self.open_monotonic).0 as &ToSql,
|
||||||
&recording::Time::new(clocks.realtime()).0,
|
&recording::Time::new(clocks.realtime()).0,
|
||||||
&o.id,
|
&o.id,
|
||||||
])?;
|
])?;
|
||||||
@ -1002,7 +1002,7 @@ impl LockedDatabase {
|
|||||||
update sample_file_dir set last_complete_open_id = ? where id = ?
|
update sample_file_dir set last_complete_open_id = ? where id = ?
|
||||||
"#)?;
|
"#)?;
|
||||||
for &id in in_progress.keys() {
|
for &id in in_progress.keys() {
|
||||||
if stmt.execute(&[&o.id, &id])? != 1 {
|
if stmt.execute(&[&o.id as &ToSql, &id])? != 1 {
|
||||||
bail!("unable to update dir {}", id);
|
bail!("unable to update dir {}", id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1260,7 +1260,7 @@ impl LockedDatabase {
|
|||||||
from
|
from
|
||||||
video_sample_entry
|
video_sample_entry
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
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)?;
|
||||||
@ -1300,7 +1300,7 @@ impl LockedDatabase {
|
|||||||
from
|
from
|
||||||
sample_file_dir d left join open o on (d.last_complete_open_id = o.id);
|
sample_file_dir d left join open o on (d.last_complete_open_id = o.id);
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
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)?;
|
||||||
@ -1342,7 +1342,7 @@ impl LockedDatabase {
|
|||||||
from
|
from
|
||||||
camera;
|
camera;
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
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)?;
|
||||||
@ -1381,7 +1381,7 @@ impl LockedDatabase {
|
|||||||
from
|
from
|
||||||
stream;
|
stream;
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
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)?;
|
||||||
@ -1486,7 +1486,7 @@ impl LockedDatabase {
|
|||||||
self.conn.execute(r#"
|
self.conn.execute(r#"
|
||||||
insert into sample_file_dir (path, uuid, last_complete_open_id)
|
insert into sample_file_dir (path, uuid, last_complete_open_id)
|
||||||
values (?, ?, ?)
|
values (?, ?, ?)
|
||||||
"#, &[&path, &uuid_bytes, &o.id])?;
|
"#, &[&path as &ToSql, &uuid_bytes, &o.id])?;
|
||||||
let id = self.conn.last_insert_rowid() as i32;
|
let id = self.conn.last_insert_rowid() as i32;
|
||||||
use ::std::collections::btree_map::Entry;
|
use ::std::collections::btree_map::Entry;
|
||||||
let e = self.sample_file_dirs_by_id.entry(id);
|
let e = self.sample_file_dirs_by_id.entry(id);
|
||||||
@ -1731,7 +1731,7 @@ impl LockedDatabase {
|
|||||||
/// Note this doesn't set journal options, so that it can be used on in-memory databases for
|
/// Note this doesn't set journal options, so that it can be used on in-memory databases for
|
||||||
/// test code.
|
/// test code.
|
||||||
pub fn init(conn: &mut rusqlite::Connection) -> Result<(), Error> {
|
pub fn init(conn: &mut rusqlite::Connection) -> Result<(), Error> {
|
||||||
conn.execute("pragma foreign_keys = on", &[])?;
|
conn.execute("pragma foreign_keys = on", &[] as &[&ToSql])?;
|
||||||
let tx = conn.transaction()?;
|
let tx = conn.transaction()?;
|
||||||
tx.execute_batch(include_str!("schema.sql"))?;
|
tx.execute_batch(include_str!("schema.sql"))?;
|
||||||
{
|
{
|
||||||
@ -1750,11 +1750,12 @@ pub fn init(conn: &mut rusqlite::Connection) -> Result<(), Error> {
|
|||||||
pub fn get_schema_version(conn: &rusqlite::Connection) -> Result<Option<i32>, Error> {
|
pub fn get_schema_version(conn: &rusqlite::Connection) -> Result<Option<i32>, Error> {
|
||||||
let ver_tables: i32 = conn.query_row_and_then(
|
let ver_tables: i32 = conn.query_row_and_then(
|
||||||
"select count(*) from sqlite_master where name = 'version'",
|
"select count(*) from sqlite_master where name = 'version'",
|
||||||
&[], |row| row.get_checked(0))?;
|
&[] as &[&ToSql], |row| row.get_checked(0))?;
|
||||||
if ver_tables == 0 {
|
if ver_tables == 0 {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
Ok(Some(conn.query_row_and_then("select max(id) from version", &[], |row| row.get_checked(0))?))
|
Ok(Some(conn.query_row_and_then("select max(id) from version", &[] as &[&ToSql],
|
||||||
|
|row| row.get_checked(0))?))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The recording database. Abstracts away SQLite queries. Also maintains in-memory state
|
/// The recording database. Abstracts away SQLite queries. Also maintains in-memory state
|
||||||
@ -1791,7 +1792,7 @@ impl<C: Clocks + Clone> Database<C> {
|
|||||||
/// Creates the database from a caller-supplied SQLite connection.
|
/// Creates the database from a caller-supplied SQLite connection.
|
||||||
pub fn new(clocks: C, conn: rusqlite::Connection,
|
pub fn new(clocks: C, conn: rusqlite::Connection,
|
||||||
read_write: bool) -> Result<Database<C>, Error> {
|
read_write: bool) -> Result<Database<C>, Error> {
|
||||||
conn.execute("pragma foreign_keys = on", &[])?;
|
conn.execute("pragma foreign_keys = on", &[] as &[&ToSql])?;
|
||||||
{
|
{
|
||||||
let ver = get_schema_version(&conn)?.ok_or_else(|| format_err!(
|
let ver = get_schema_version(&conn)?.ok_or_else(|| format_err!(
|
||||||
"no such table: version. \
|
"no such table: version. \
|
||||||
@ -1821,7 +1822,7 @@ impl<C: Clocks + Clone> Database<C> {
|
|||||||
let mut stmt = conn.prepare(" insert into open (uuid, start_time_90k) values (?, ?)")?;
|
let mut stmt = conn.prepare(" insert into open (uuid, start_time_90k) values (?, ?)")?;
|
||||||
let uuid = Uuid::new_v4();
|
let uuid = Uuid::new_v4();
|
||||||
let uuid_bytes = &uuid.as_bytes()[..];
|
let uuid_bytes = &uuid.as_bytes()[..];
|
||||||
stmt.execute(&[&uuid_bytes, &real.0])?;
|
stmt.execute(&[&uuid_bytes as &ToSql, &real.0])?;
|
||||||
Some(Open {
|
Some(Open {
|
||||||
id: conn.last_insert_rowid() as u32,
|
id: conn.last_insert_rowid() as u32,
|
||||||
uuid,
|
uuid,
|
||||||
|
@ -34,7 +34,7 @@ use db::{self, CompositeId, FromSqlUuid};
|
|||||||
use failure::{Error, ResultExt};
|
use failure::{Error, ResultExt};
|
||||||
use fnv::FnvHashSet;
|
use fnv::FnvHashSet;
|
||||||
use recording;
|
use recording;
|
||||||
use rusqlite;
|
use rusqlite::{self, types::ToSql};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ fn list_recordings_inner(mut rows: rusqlite::Rows,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_db_uuid(conn: &rusqlite::Connection) -> Result<Uuid, Error> {
|
pub(crate) fn get_db_uuid(conn: &rusqlite::Connection) -> Result<Uuid, Error> {
|
||||||
conn.query_row("select uuid from meta", &[], |row| -> Result<Uuid, Error> {
|
conn.query_row("select uuid from meta", &[] as &[&ToSql], |row| -> Result<Uuid, Error> {
|
||||||
let uuid: FromSqlUuid = row.get_checked(0)?;
|
let uuid: FromSqlUuid = row.get_checked(0)?;
|
||||||
Ok(uuid.0)
|
Ok(uuid.0)
|
||||||
})?
|
})?
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
use db;
|
use db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use rusqlite;
|
use rusqlite::{self, types::ToSql};
|
||||||
|
|
||||||
mod v0_to_v1;
|
mod v0_to_v1;
|
||||||
mod v1_to_v2;
|
mod v1_to_v2;
|
||||||
@ -52,7 +52,7 @@ pub struct Args<'a> {
|
|||||||
|
|
||||||
fn set_journal_mode(conn: &rusqlite::Connection, requested: &str) -> Result<(), Error> {
|
fn set_journal_mode(conn: &rusqlite::Connection, requested: &str) -> Result<(), Error> {
|
||||||
assert!(!requested.contains(';')); // quick check for accidental sql injection.
|
assert!(!requested.contains(';')); // quick check for accidental sql injection.
|
||||||
let actual = conn.query_row(&format!("pragma journal_mode = {}", requested), &[],
|
let actual = conn.query_row(&format!("pragma journal_mode = {}", requested), &[] as &[&ToSql],
|
||||||
|row| row.get_checked::<_, String>(0))??;
|
|row| row.get_checked::<_, String>(0))??;
|
||||||
info!("...database now in journal_mode {} (requested {}).", actual, requested);
|
info!("...database now in journal_mode {} (requested {}).", actual, requested);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -68,7 +68,8 @@ pub fn run(args: &Args, conn: &mut rusqlite::Connection) -> Result<(), Error> {
|
|||||||
{
|
{
|
||||||
assert_eq!(upgraders.len(), db::EXPECTED_VERSION as usize);
|
assert_eq!(upgraders.len(), db::EXPECTED_VERSION as usize);
|
||||||
let old_ver =
|
let old_ver =
|
||||||
conn.query_row("select max(id) from version", &[], |row| row.get_checked(0))??;
|
conn.query_row("select max(id) from version", &[] as &[&ToSql],
|
||||||
|
|row| row.get_checked(0))??;
|
||||||
if old_ver > db::EXPECTED_VERSION {
|
if old_ver > db::EXPECTED_VERSION {
|
||||||
bail!("Database is at version {}, later than expected {}",
|
bail!("Database is at version {}, later than expected {}",
|
||||||
old_ver, db::EXPECTED_VERSION);
|
old_ver, db::EXPECTED_VERSION);
|
||||||
@ -84,7 +85,7 @@ pub fn run(args: &Args, conn: &mut rusqlite::Connection) -> Result<(), Error> {
|
|||||||
tx.execute(r#"
|
tx.execute(r#"
|
||||||
insert into version (id, unix_time, notes)
|
insert into version (id, unix_time, notes)
|
||||||
values (?, cast(strftime('%s', 'now') as int32), ?)
|
values (?, cast(strftime('%s', 'now') as int32), ?)
|
||||||
"#, &[&(ver + 1), &UPGRADE_NOTES])?;
|
"#, &[&(ver + 1) as &ToSql, &UPGRADE_NOTES])?;
|
||||||
tx.commit()?;
|
tx.commit()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,7 +94,7 @@ pub fn run(args: &Args, conn: &mut rusqlite::Connection) -> Result<(), Error> {
|
|||||||
// compiles the SQLite3 amalgamation with -DSQLITE_DEFAULT_FOREIGN_KEYS=1). Ensure it's
|
// compiles the SQLite3 amalgamation with -DSQLITE_DEFAULT_FOREIGN_KEYS=1). Ensure it's
|
||||||
// always on. Note that our foreign keys are immediate rather than deferred, so we have to
|
// always on. Note that our foreign keys are immediate rather than deferred, so we have to
|
||||||
// be careful about the order of operations during the upgrade.
|
// be careful about the order of operations during the upgrade.
|
||||||
conn.execute("pragma foreign_keys = on", &[])?;
|
conn.execute("pragma foreign_keys = on", &[] as &[&ToSql])?;
|
||||||
|
|
||||||
// WAL is the preferred journal mode for normal operation; it reduces the number of syncs
|
// WAL is the preferred journal mode for normal operation; it reduces the number of syncs
|
||||||
// without compromising safety.
|
// without compromising safety.
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
use db;
|
use db;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use recording;
|
use recording;
|
||||||
use rusqlite;
|
use rusqlite::{self, types::ToSql};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error> {
|
pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error> {
|
||||||
@ -141,7 +141,7 @@ fn fill_recording(tx: &rusqlite::Transaction) -> Result<HashMap<i32, CameraState
|
|||||||
insert into recording_playback values (:composite_id, :sample_file_uuid, :sample_file_sha1,
|
insert into recording_playback values (:composite_id, :sample_file_uuid, :sample_file_sha1,
|
||||||
:video_index)
|
:video_index)
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = select.query(&[])?;
|
let mut rows = select.query(&[] as &[&ToSql])?;
|
||||||
let mut camera_state: HashMap<i32, CameraState> = HashMap::new();
|
let mut camera_state: HashMap<i32, CameraState> = HashMap::new();
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
@ -216,7 +216,7 @@ fn fill_camera(tx: &rusqlite::Transaction, camera_state: HashMap<i32, CameraStat
|
|||||||
insert into camera values (:id, :uuid, :short_name, :description, :host, :username, :password,
|
insert into camera values (:id, :uuid, :short_name, :description, :host, :username, :password,
|
||||||
:main_rtsp_path, :sub_rtsp_path, :retain_bytes, :next_recording_id)
|
:main_rtsp_path, :sub_rtsp_path, :retain_bytes, :next_recording_id)
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = select.query(&[])?;
|
let mut rows = select.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let id: i32 = row.get_checked(0)?;
|
let id: i32 = row.get_checked(0)?;
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
use dir;
|
use dir;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
use libc;
|
use libc;
|
||||||
use rusqlite;
|
use rusqlite::{self, types::ToSql};
|
||||||
use schema::DirMeta;
|
use schema::DirMeta;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
@ -122,7 +122,7 @@ pub fn run(args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
|||||||
tx.execute(r#"
|
tx.execute(r#"
|
||||||
insert into sample_file_dir (path, uuid, last_complete_open_id)
|
insert into sample_file_dir (path, uuid, last_complete_open_id)
|
||||||
values (?, ?, ?)
|
values (?, ?, ?)
|
||||||
"#, &[&sample_file_path, &dir_uuid_bytes, &open_id])?;
|
"#, &[&sample_file_path as &ToSql, &dir_uuid_bytes, &open_id])?;
|
||||||
|
|
||||||
tx.execute_batch(r#"
|
tx.execute_batch(r#"
|
||||||
drop table reserved_sample_files;
|
drop table reserved_sample_files;
|
||||||
@ -298,7 +298,7 @@ fn verify_dir_contents(sample_file_path: &str, tx: &rusqlite::Transaction) -> Re
|
|||||||
from
|
from
|
||||||
(select count(*) as c from recording) a,
|
(select count(*) as c from recording) a,
|
||||||
(select count(*) as c from reserved_sample_files) b;
|
(select count(*) as c from reserved_sample_files) b;
|
||||||
"#, &[], |r| r.get_checked(0))??;
|
"#, &[] as &[&ToSql], |r| r.get_checked(0))??;
|
||||||
let mut files = ::fnv::FnvHashSet::with_capacity_and_hasher(n as usize, Default::default());
|
let mut files = ::fnv::FnvHashSet::with_capacity_and_hasher(n as usize, Default::default());
|
||||||
for e in fs::read_dir(sample_file_path)? {
|
for e in fs::read_dir(sample_file_path)? {
|
||||||
let e = e?;
|
let e = e?;
|
||||||
@ -320,7 +320,7 @@ fn verify_dir_contents(sample_file_path: &str, tx: &rusqlite::Transaction) -> Re
|
|||||||
Ok(u) => u,
|
Ok(u) => u,
|
||||||
Err(_) => bail!("unexpected file {:?} in {:?}", f, sample_file_path),
|
Err(_) => bail!("unexpected file {:?} in {:?}", f, sample_file_path),
|
||||||
};
|
};
|
||||||
if s != uuid.hyphenated().to_string() { // non-canonical form.
|
if s != uuid.to_hyphenated_ref().to_string() { // non-canonical form.
|
||||||
bail!("unexpected file {:?} in {:?}", f, sample_file_path);
|
bail!("unexpected file {:?} in {:?}", f, sample_file_path);
|
||||||
}
|
}
|
||||||
files.insert(uuid);
|
files.insert(uuid);
|
||||||
@ -329,7 +329,7 @@ fn verify_dir_contents(sample_file_path: &str, tx: &rusqlite::Transaction) -> Re
|
|||||||
// Iterate through the database and check that everything has a matching file.
|
// Iterate through the database and check that everything has a matching file.
|
||||||
{
|
{
|
||||||
let mut stmt = tx.prepare(r"select sample_file_uuid from recording_playback")?;
|
let mut stmt = tx.prepare(r"select sample_file_uuid from recording_playback")?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let uuid: ::db::FromSqlUuid = row.get_checked(0)?;
|
let uuid: ::db::FromSqlUuid = row.get_checked(0)?;
|
||||||
@ -340,7 +340,7 @@ fn verify_dir_contents(sample_file_path: &str, tx: &rusqlite::Transaction) -> Re
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut stmt = tx.prepare(r"select uuid from reserved_sample_files")?;
|
let mut stmt = tx.prepare(r"select uuid from reserved_sample_files")?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let uuid: ::db::FromSqlUuid = row.get_checked(0)?;
|
let uuid: ::db::FromSqlUuid = row.get_checked(0)?;
|
||||||
@ -368,7 +368,7 @@ fn fix_video_sample_entry(tx: &rusqlite::Transaction) -> Result<(), Error> {
|
|||||||
let mut insert = tx.prepare(r#"
|
let mut insert = tx.prepare(r#"
|
||||||
insert into video_sample_entry values (:id, :sha1, :width, :height, :rfc6381_codec, :data)
|
insert into video_sample_entry values (:id, :sha1, :width, :height, :rfc6381_codec, :data)
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = select.query(&[])?;
|
let mut rows = select.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let data: Vec<u8> = row.get_checked(4)?;
|
let data: Vec<u8> = row.get_checked(4)?;
|
||||||
|
@ -40,7 +40,7 @@ use schema;
|
|||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use rusqlite;
|
use rusqlite::{self, types::ToSql};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
/// Opens the sample file dir.
|
/// Opens the sample file dir.
|
||||||
@ -57,7 +57,7 @@ fn open_sample_file_dir(tx: &rusqlite::Transaction) -> Result<Arc<dir::SampleFil
|
|||||||
sample_file_dir s
|
sample_file_dir s
|
||||||
join open o on (s.last_complete_open_id = o.id)
|
join open o on (s.last_complete_open_id = o.id)
|
||||||
cross join meta m
|
cross join meta m
|
||||||
"#, &[], |row| {
|
"#, &[] as &[&ToSql], |row| {
|
||||||
(row.get_checked(0).unwrap(),
|
(row.get_checked(0).unwrap(),
|
||||||
row.get_checked(1).unwrap(),
|
row.get_checked(1).unwrap(),
|
||||||
row.get_checked(2).unwrap(),
|
row.get_checked(2).unwrap(),
|
||||||
@ -84,7 +84,7 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
|||||||
from
|
from
|
||||||
recording_playback
|
recording_playback
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next() {
|
||||||
let row = row?;
|
let row = row?;
|
||||||
let id = db::CompositeId(row.get_checked(0)?);
|
let id = db::CompositeId(row.get_checked(0)?);
|
||||||
@ -124,7 +124,8 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
|||||||
/// Gets a pathname for a sample file suitable for passing to open or unlink.
|
/// Gets a pathname for a sample file suitable for passing to open or unlink.
|
||||||
fn get_uuid_pathname(uuid: Uuid) -> [libc::c_char; 37] {
|
fn get_uuid_pathname(uuid: Uuid) -> [libc::c_char; 37] {
|
||||||
let mut buf = [0u8; 37];
|
let mut buf = [0u8; 37];
|
||||||
write!(&mut buf[..36], "{}", uuid.hyphenated()).expect("can't format uuid to pathname buf");
|
write!(&mut buf[..36], "{}", uuid.to_hyphenated_ref())
|
||||||
|
.expect("can't format uuid to pathname buf");
|
||||||
|
|
||||||
// libc::c_char seems to be i8 on some platforms (Linux/arm) and u8 on others (Linux/amd64).
|
// libc::c_char seems to be i8 on some platforms (Linux/arm) and u8 on others (Linux/amd64).
|
||||||
unsafe { mem::transmute::<[u8; 37], [libc::c_char; 37]>(buf) }
|
unsafe { mem::transmute::<[u8; 37], [libc::c_char; 37]>(buf) }
|
||||||
|
@ -142,7 +142,7 @@ fn press_test(siv: &mut Cursive, t: db::StreamType) {
|
|||||||
format!("{} stream at {}:\n\n{}", t.as_str(), url, description))
|
format!("{} stream at {}:\n\n{}", t.as_str(), url, description))
|
||||||
.title("Stream test succeeded")
|
.title("Stream test succeeded")
|
||||||
.dismiss_button("Back"));
|
.dismiss_button("Back"));
|
||||||
}));
|
})).unwrap();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user