mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2024-12-26 07:05:56 -05:00
upgrade rusqlite, bump required Rust to 1.33
The new rusqlite requires the transpose_result feature, stabilized in this Rust version.
This commit is contained in:
parent
3668c69d4b
commit
b629fe6ac1
@ -23,7 +23,7 @@ matrix:
|
|||||||
script:
|
script:
|
||||||
- ci/script-rust.sh
|
- ci/script-rust.sh
|
||||||
- language: rust
|
- language: rust
|
||||||
rust: 1.32.0
|
rust: 1.33.0
|
||||||
script:
|
script:
|
||||||
- ci/script-rust.sh
|
- ci/script-rust.sh
|
||||||
- language: node_js
|
- language: node_js
|
||||||
|
29
Cargo.lock
generated
29
Cargo.lock
generated
@ -432,6 +432,16 @@ name = "fake-simd"
|
|||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fallible-iterator"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fallible-streaming-iterator"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -700,7 +710,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
version = "0.11.1"
|
version = "0.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
"cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -892,7 +902,7 @@ dependencies = [
|
|||||||
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"protobuf 2.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"protobuf 2.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rusqlite 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rusqlite 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -940,7 +950,7 @@ dependencies = [
|
|||||||
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
"reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rusqlite 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rusqlite 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -1508,12 +1518,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rusqlite"
|
name = "rusqlite"
|
||||||
version = "0.16.0"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libsqlite3-sys 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libsqlite3-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2292,6 +2305,8 @@ dependencies = [
|
|||||||
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2"
|
||||||
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1"
|
||||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
|
"checksum fallible-iterator 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||||
|
"checksum fallible-streaming-iterator 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||||
"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa"
|
"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa"
|
||||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||||
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
|
||||||
@ -2321,7 +2336,7 @@ dependencies = [
|
|||||||
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
|
||||||
"checksum libc 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "a844cabbd5a77e60403a58af576f0a1baa83c3dd2670be63e615bd24fc58b82d"
|
"checksum libc 0.2.57 (registry+https://github.com/rust-lang/crates.io-index)" = "a844cabbd5a77e60403a58af576f0a1baa83c3dd2670be63e615bd24fc58b82d"
|
||||||
"checksum libpasta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31a3bd8a4714af6f88d2cd850b016ad4567770f88fa3cf0571ec197591362f99"
|
"checksum libpasta 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "31a3bd8a4714af6f88d2cd850b016ad4567770f88fa3cf0571ec197591362f99"
|
||||||
"checksum libsqlite3-sys 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3567bc1a0c84e2c0d71eeb4a1f08451babf7843babd733158777d9c686dad9f3"
|
"checksum libsqlite3-sys 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e310445ab028c374b9efaaed4b7a52a14e3b8ad5a1351b4bbd46dec03ffce717"
|
||||||
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
|
||||||
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
|
"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
|
||||||
"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff"
|
"checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff"
|
||||||
@ -2398,7 +2413,7 @@ dependencies = [
|
|||||||
"checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50"
|
"checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50"
|
||||||
"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c"
|
"checksum ring 0.14.6 (registry+https://github.com/rust-lang/crates.io-index)" = "426bc186e3e95cac1e4a4be125a4aca7e84c2d616ffc02244eef36e2a60a093c"
|
||||||
"checksum rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37473170aedbe66ffa3ad3726939ba677d83c646ad4fd99e5b4bc38712f45ec"
|
"checksum rpassword 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37473170aedbe66ffa3ad3726939ba677d83c646ad4fd99e5b4bc38712f45ec"
|
||||||
"checksum rusqlite 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6381ddfe91dbb659b4b132168da15985bc84162378cf4fcdc4eb99c857d063e2"
|
"checksum rusqlite 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "700720c977deb8b91c9d881dcbe3309c254d414078ca3856ea6647e569be3b66"
|
||||||
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
"checksum rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f76d05d3993fd5f4af9434e8e436db163a12a9d40e1a58a726f27a01dfd12a2a"
|
||||||
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
|
||||||
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
|
||||||
|
@ -43,7 +43,7 @@ parking_lot = { version = "0.8", features = [] }
|
|||||||
reffers = "0.5.1"
|
reffers = "0.5.1"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
ring = "0.14.6"
|
ring = "0.14.6"
|
||||||
rusqlite = "0.16"
|
rusqlite = "0.18"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
smallvec = "0.6"
|
smallvec = "0.6"
|
||||||
|
@ -28,7 +28,7 @@ openssl = "0.10"
|
|||||||
parking_lot = { version = "0.7", features = [] }
|
parking_lot = { version = "0.7", features = [] }
|
||||||
protobuf = "2.0"
|
protobuf = "2.0"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
rusqlite = "0.16"
|
rusqlite = "0.18"
|
||||||
smallvec = "0.6"
|
smallvec = "0.6"
|
||||||
tempdir = "0.3"
|
tempdir = "0.3"
|
||||||
time = "0.1"
|
time = "0.1"
|
||||||
|
59
db/auth.rs
59
db/auth.rs
@ -347,18 +347,17 @@ impl State {
|
|||||||
user
|
user
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = row.get(0)?;
|
||||||
let id = row.get_checked(0)?;
|
let name: String = row.get(1)?;
|
||||||
let name: String = row.get_checked(1)?;
|
|
||||||
state.users_by_id.insert(id, User {
|
state.users_by_id.insert(id, User {
|
||||||
id,
|
id,
|
||||||
username: name.clone(),
|
username: name.clone(),
|
||||||
flags: row.get_checked(2)?,
|
flags: row.get(2)?,
|
||||||
password_hash: row.get_checked(3)?,
|
password_hash: row.get(3)?,
|
||||||
password_id: row.get_checked(4)?,
|
password_id: row.get(4)?,
|
||||||
password_failure_count: row.get_checked(5)?,
|
password_failure_count: row.get(5)?,
|
||||||
unix_uid: row.get_checked(6)?,
|
unix_uid: row.get(6)?,
|
||||||
dirty: false,
|
dirty: false,
|
||||||
});
|
});
|
||||||
state.users_by_name.insert(name, id);
|
state.users_by_name.insert(name, id);
|
||||||
@ -693,39 +692,35 @@ fn lookup_session(conn: &Connection, hash: &SessionHash) -> Result<Session, Erro
|
|||||||
session_id_hash = ?
|
session_id_hash = ?
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[&&hash.0[..]])?;
|
let mut rows = stmt.query(&[&&hash.0[..]])?;
|
||||||
let row = match rows.next() {
|
let row = rows.next()?.ok_or_else(|| format_err!("no such session"))?;
|
||||||
None => bail!("no such session"),
|
let creation_addr: FromSqlIpAddr = row.get(8)?;
|
||||||
Some(Err(e)) => return Err(e.into()),
|
let revocation_addr: FromSqlIpAddr = row.get(11)?;
|
||||||
Some(Ok(r)) => r,
|
let last_use_addr: FromSqlIpAddr = row.get(16)?;
|
||||||
};
|
|
||||||
let creation_addr: FromSqlIpAddr = row.get_checked(8)?;
|
|
||||||
let revocation_addr: FromSqlIpAddr = row.get_checked(11)?;
|
|
||||||
let last_use_addr: FromSqlIpAddr = row.get_checked(16)?;
|
|
||||||
Ok(Session {
|
Ok(Session {
|
||||||
user_id: row.get_checked(0)?,
|
user_id: row.get(0)?,
|
||||||
seed: row.get_checked(1)?,
|
seed: row.get(1)?,
|
||||||
flags: row.get_checked(2)?,
|
flags: row.get(2)?,
|
||||||
domain: row.get_checked(3)?,
|
domain: row.get(3)?,
|
||||||
description: row.get_checked(4)?,
|
description: row.get(4)?,
|
||||||
creation_password_id: row.get_checked(5)?,
|
creation_password_id: row.get(5)?,
|
||||||
creation: Request {
|
creation: Request {
|
||||||
when_sec: row.get_checked(6)?,
|
when_sec: row.get(6)?,
|
||||||
user_agent: row.get_checked(7)?,
|
user_agent: row.get(7)?,
|
||||||
addr: creation_addr.0,
|
addr: creation_addr.0,
|
||||||
},
|
},
|
||||||
revocation: Request {
|
revocation: Request {
|
||||||
when_sec: row.get_checked(9)?,
|
when_sec: row.get(9)?,
|
||||||
user_agent: row.get_checked(10)?,
|
user_agent: row.get(10)?,
|
||||||
addr: revocation_addr.0,
|
addr: revocation_addr.0,
|
||||||
},
|
},
|
||||||
revocation_reason: row.get_checked(12)?,
|
revocation_reason: row.get(12)?,
|
||||||
revocation_reason_detail: row.get_checked(13)?,
|
revocation_reason_detail: row.get(13)?,
|
||||||
last_use: Request {
|
last_use: Request {
|
||||||
when_sec: row.get_checked(14)?,
|
when_sec: row.get(14)?,
|
||||||
user_agent: row.get_checked(15)?,
|
user_agent: row.get(15)?,
|
||||||
addr: last_use_addr.0,
|
addr: last_use_addr.0,
|
||||||
},
|
},
|
||||||
use_count: row.get_checked(17)?,
|
use_count: row.get(17)?,
|
||||||
dirty: false,
|
dirty: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
52
db/check.rs
52
db/check.rs
@ -59,14 +59,13 @@ 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(&[] as &[&ToSql])?;
|
let mut rows = dir_stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
|
||||||
let mut meta = schema::DirMeta::default();
|
let mut meta = schema::DirMeta::default();
|
||||||
let dir_id: i32 = row.get_checked(0)?;
|
let dir_id: i32 = row.get(0)?;
|
||||||
let dir_path: String = row.get_checked(1)?;
|
let dir_path: String = row.get(1)?;
|
||||||
let dir_uuid: FromSqlUuid = row.get_checked(2)?;
|
let dir_uuid: FromSqlUuid = row.get(2)?;
|
||||||
let open_id = row.get_checked(3)?;
|
let open_id = row.get(3)?;
|
||||||
let open_uuid: FromSqlUuid = row.get_checked(4)?;
|
let open_uuid: FromSqlUuid = row.get(4)?;
|
||||||
meta.db_uuid.extend_from_slice(&db_uuid.as_bytes()[..]);
|
meta.db_uuid.extend_from_slice(&db_uuid.as_bytes()[..]);
|
||||||
meta.dir_uuid.extend_from_slice(&dir_uuid.0.as_bytes()[..]);
|
meta.dir_uuid.extend_from_slice(&dir_uuid.0.as_bytes()[..]);
|
||||||
{
|
{
|
||||||
@ -79,9 +78,8 @@ pub fn run(conn: &rusqlite::Connection, opts: &Options) -> Result<(), Error> {
|
|||||||
let _dir = dir::SampleFileDir::open(&dir_path, &meta)?;
|
let _dir = dir::SampleFileDir::open(&dir_path, &meta)?;
|
||||||
let mut streams = read_dir(&dir_path, opts)?;
|
let mut streams = read_dir(&dir_path, opts)?;
|
||||||
let mut rows = garbage_stmt.query(&[&dir_id])?;
|
let mut rows = garbage_stmt.query(&[&dir_id])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = CompositeId(row.get(0)?);
|
||||||
let id = CompositeId(row.get_checked(0)?);
|
|
||||||
let s = streams.entry(id.stream()).or_insert_with(Stream::default);
|
let s = streams.entry(id.stream()).or_insert_with(Stream::default);
|
||||||
s.entry(id.recording()).or_insert_with(Recording::default).garbage_row = true;
|
s.entry(id.recording()).or_insert_with(Recording::default).garbage_row = true;
|
||||||
}
|
}
|
||||||
@ -95,10 +93,9 @@ pub fn run(conn: &rusqlite::Connection, opts: &Options) -> Result<(), Error> {
|
|||||||
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(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let stream_id = row.get(0)?;
|
||||||
let stream_id = row.get_checked(0)?;
|
let dir_id = row.get(1)?;
|
||||||
let dir_id = row.get_checked(1)?;
|
|
||||||
let stream = match streams_by_dir.get_mut(&dir_id) {
|
let stream = match streams_by_dir.get_mut(&dir_id) {
|
||||||
None => Stream::default(),
|
None => Stream::default(),
|
||||||
Some(d) => d.remove(&stream_id).unwrap_or_else(Stream::default),
|
Some(d) => d.remove(&stream_id).unwrap_or_else(Stream::default),
|
||||||
@ -224,15 +221,14 @@ fn compare_stream(conn: &rusqlite::Connection, stream_id: i32, opts: &Options,
|
|||||||
composite_id between ? and ?
|
composite_id between ? and ?
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[&start.0, &end.0])?;
|
let mut rows = stmt.query(&[&start.0, &end.0])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = CompositeId(row.get(0)?);
|
||||||
let id = CompositeId(row.get_checked(0)?);
|
|
||||||
let s = RecordingSummary {
|
let s = RecordingSummary {
|
||||||
flags: row.get_checked(1)?,
|
flags: row.get(1)?,
|
||||||
bytes: row.get_checked::<_, i64>(2)? as u64,
|
bytes: row.get::<_, i64>(2)? as u64,
|
||||||
duration: row.get_checked(3)?,
|
duration: row.get(3)?,
|
||||||
video_samples: row.get_checked(4)?,
|
video_samples: row.get(4)?,
|
||||||
video_sync_samples: row.get_checked(5)?,
|
video_sync_samples: row.get(5)?,
|
||||||
};
|
};
|
||||||
stream.entry(id.recording())
|
stream.entry(id.recording())
|
||||||
.or_insert_with(Recording::default)
|
.or_insert_with(Recording::default)
|
||||||
@ -252,10 +248,9 @@ fn compare_stream(conn: &rusqlite::Connection, stream_id: i32, opts: &Options,
|
|||||||
composite_id between ? and ?
|
composite_id between ? and ?
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[&start.0, &end.0])?;
|
let mut rows = stmt.query(&[&start.0, &end.0])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = CompositeId(row.get(0)?);
|
||||||
let id = CompositeId(row.get_checked(0)?);
|
let video_index: Vec<u8> = row.get(1)?;
|
||||||
let video_index: Vec<u8> = row.get_checked(1)?;
|
|
||||||
let s = match summarize_index(&video_index) {
|
let s = match summarize_index(&video_index) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -280,9 +275,8 @@ fn compare_stream(conn: &rusqlite::Connection, stream_id: i32, opts: &Options,
|
|||||||
composite_id between ? and ?
|
composite_id between ? and ?
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[&start.0, &end.0])?;
|
let mut rows = stmt.query(&[&start.0, &end.0])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = CompositeId(row.get(0)?);
|
||||||
let id = CompositeId(row.get_checked(0)?);
|
|
||||||
stream.entry(id.recording())
|
stream.entry(id.recording())
|
||||||
.or_insert_with(Recording::default)
|
.or_insert_with(Recording::default)
|
||||||
.integrity_row = true;
|
.integrity_row = true;
|
||||||
|
84
db/db.rs
84
db/db.rs
@ -587,11 +587,10 @@ fn init_recordings(conn: &mut rusqlite::Connection, stream_id: i32, camera: &Cam
|
|||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query_named(&[(":stream_id", &stream_id)])?;
|
let mut rows = stmt.query_named(&[(":stream_id", &stream_id)])?;
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let start = recording::Time(row.get(0)?);
|
||||||
let start = recording::Time(row.get_checked(0)?);
|
let duration = recording::Duration(row.get(1)?);
|
||||||
let duration = recording::Duration(row.get_checked(1)?);
|
let bytes = row.get(2)?;
|
||||||
let bytes = row.get_checked(2)?;
|
|
||||||
stream.add_recording(start .. start + duration, bytes);
|
stream.add_recording(start .. start + duration, bytes);
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
@ -1277,9 +1276,8 @@ impl LockedDatabase {
|
|||||||
trace!("cache miss for recording {}", id);
|
trace!("cache miss for recording {}", id);
|
||||||
let mut stmt = self.conn.prepare_cached(GET_RECORDING_PLAYBACK_SQL)?;
|
let mut stmt = self.conn.prepare_cached(GET_RECORDING_PLAYBACK_SQL)?;
|
||||||
let mut rows = stmt.query_named(&[(":composite_id", &id.0)])?;
|
let mut rows = stmt.query_named(&[(":composite_id", &id.0)])?;
|
||||||
if let Some(row) = rows.next() {
|
if let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let video_index: VideoIndex = row.get(0)?;
|
||||||
let video_index: VideoIndex = row.get_checked(0)?;
|
|
||||||
let result = f(&RecordingPlayback { video_index: &video_index.0[..] });
|
let result = f(&RecordingPlayback { video_index: &video_index.0[..] });
|
||||||
cache.insert(id.0, video_index.0);
|
cache.insert(id.0, video_index.0);
|
||||||
return result;
|
return result;
|
||||||
@ -1325,24 +1323,23 @@ impl LockedDatabase {
|
|||||||
video_sample_entry
|
video_sample_entry
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = row.get(0)?;
|
||||||
let id = row.get_checked(0)?;
|
|
||||||
let mut sha1 = [0u8; 20];
|
let mut sha1 = [0u8; 20];
|
||||||
let sha1_vec: Vec<u8> = row.get_checked(1)?;
|
let sha1_vec: Vec<u8> = row.get(1)?;
|
||||||
if sha1_vec.len() != 20 {
|
if sha1_vec.len() != 20 {
|
||||||
bail!("video sample entry id {} has sha1 {} of wrong length", id, sha1_vec.len());
|
bail!("video sample entry id {} has sha1 {} of wrong length", id, sha1_vec.len());
|
||||||
}
|
}
|
||||||
sha1.copy_from_slice(&sha1_vec);
|
sha1.copy_from_slice(&sha1_vec);
|
||||||
let data: Vec<u8> = row.get_checked(5)?;
|
let data: Vec<u8> = row.get(5)?;
|
||||||
|
|
||||||
self.video_sample_entries_by_id.insert(id, Arc::new(VideoSampleEntry {
|
self.video_sample_entries_by_id.insert(id, Arc::new(VideoSampleEntry {
|
||||||
id: id as i32,
|
id: id as i32,
|
||||||
width: row.get_checked::<_, i32>(2)? as u16,
|
width: row.get::<_, i32>(2)? as u16,
|
||||||
height: row.get_checked::<_, i32>(3)? as u16,
|
height: row.get::<_, i32>(3)? as u16,
|
||||||
sha1,
|
sha1,
|
||||||
data,
|
data,
|
||||||
rfc6381_codec: row.get_checked(4)?,
|
rfc6381_codec: row.get(4)?,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
info!("Loaded {} video sample entries",
|
info!("Loaded {} video sample entries",
|
||||||
@ -1365,12 +1362,11 @@ impl LockedDatabase {
|
|||||||
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(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = row.get(0)?;
|
||||||
let id = row.get_checked(0)?;
|
let dir_uuid: FromSqlUuid = row.get(2)?;
|
||||||
let dir_uuid: FromSqlUuid = row.get_checked(2)?;
|
let open_id: Option<u32> = row.get(3)?;
|
||||||
let open_id: Option<u32> = row.get_checked(3)?;
|
let open_uuid: Option<FromSqlUuid> = row.get(4)?;
|
||||||
let open_uuid: Option<FromSqlUuid> = row.get_checked(4)?;
|
|
||||||
let last_complete_open = match (open_id, open_uuid) {
|
let last_complete_open = match (open_id, open_uuid) {
|
||||||
(Some(id), Some(uuid)) => Some(Open { id, uuid: uuid.0, }),
|
(Some(id), Some(uuid)) => Some(Open { id, uuid: uuid.0, }),
|
||||||
(None, None) => None,
|
(None, None) => None,
|
||||||
@ -1379,7 +1375,7 @@ impl LockedDatabase {
|
|||||||
self.sample_file_dirs_by_id.insert(id, SampleFileDir {
|
self.sample_file_dirs_by_id.insert(id, SampleFileDir {
|
||||||
id,
|
id,
|
||||||
uuid: dir_uuid.0,
|
uuid: dir_uuid.0,
|
||||||
path: row.get_checked(1)?,
|
path: row.get(1)?,
|
||||||
dir: None,
|
dir: None,
|
||||||
last_complete_open,
|
last_complete_open,
|
||||||
garbage_needs_unlink: raw::list_garbage(&self.conn, id)?,
|
garbage_needs_unlink: raw::list_garbage(&self.conn, id)?,
|
||||||
@ -1407,18 +1403,17 @@ impl LockedDatabase {
|
|||||||
camera;
|
camera;
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = row.get(0)?;
|
||||||
let id = row.get_checked(0)?;
|
let uuid: FromSqlUuid = row.get(1)?;
|
||||||
let uuid: FromSqlUuid = row.get_checked(1)?;
|
|
||||||
self.cameras_by_id.insert(id, Camera {
|
self.cameras_by_id.insert(id, Camera {
|
||||||
id: id,
|
id: id,
|
||||||
uuid: uuid.0,
|
uuid: uuid.0,
|
||||||
short_name: row.get_checked(2)?,
|
short_name: row.get(2)?,
|
||||||
description: row.get_checked(3)?,
|
description: row.get(3)?,
|
||||||
host: row.get_checked(4)?,
|
host: row.get(4)?,
|
||||||
username: row.get_checked(5)?,
|
username: row.get(5)?,
|
||||||
password: row.get_checked(6)?,
|
password: row.get(6)?,
|
||||||
streams: Default::default(),
|
streams: Default::default(),
|
||||||
});
|
});
|
||||||
self.cameras_by_uuid.insert(uuid.0, id);
|
self.cameras_by_uuid.insert(uuid.0, id);
|
||||||
@ -1446,26 +1441,25 @@ impl LockedDatabase {
|
|||||||
stream;
|
stream;
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = row.get(0)?;
|
||||||
let id = row.get_checked(0)?;
|
let type_: String = row.get(1)?;
|
||||||
let type_: String = row.get_checked(1)?;
|
|
||||||
let type_ = StreamType::parse(&type_).ok_or_else(
|
let type_ = StreamType::parse(&type_).ok_or_else(
|
||||||
|| format_err!("no such stream type {}", type_))?;
|
|| format_err!("no such stream type {}", type_))?;
|
||||||
let camera_id = row.get_checked(2)?;
|
let camera_id = row.get(2)?;
|
||||||
let c = self
|
let c = self
|
||||||
.cameras_by_id
|
.cameras_by_id
|
||||||
.get_mut(&camera_id)
|
.get_mut(&camera_id)
|
||||||
.ok_or_else(|| format_err!("missing camera {} for stream {}",
|
.ok_or_else(|| format_err!("missing camera {} for stream {}",
|
||||||
camera_id, id))?;
|
camera_id, id))?;
|
||||||
let flush_if_sec = row.get_checked(6)?;
|
let flush_if_sec = row.get(6)?;
|
||||||
self.streams_by_id.insert(id, Stream {
|
self.streams_by_id.insert(id, Stream {
|
||||||
id,
|
id,
|
||||||
type_,
|
type_,
|
||||||
camera_id,
|
camera_id,
|
||||||
sample_file_dir_id: row.get_checked(3)?,
|
sample_file_dir_id: row.get(3)?,
|
||||||
rtsp_path: row.get_checked(4)?,
|
rtsp_path: row.get(4)?,
|
||||||
retain_bytes: row.get_checked(5)?,
|
retain_bytes: row.get(5)?,
|
||||||
flush_if_sec,
|
flush_if_sec,
|
||||||
range: None,
|
range: None,
|
||||||
sample_file_bytes: 0,
|
sample_file_bytes: 0,
|
||||||
@ -1474,8 +1468,8 @@ impl LockedDatabase {
|
|||||||
bytes_to_add: 0,
|
bytes_to_add: 0,
|
||||||
duration: recording::Duration(0),
|
duration: recording::Duration(0),
|
||||||
days: BTreeMap::new(),
|
days: BTreeMap::new(),
|
||||||
next_recording_id: row.get_checked(7)?,
|
next_recording_id: row.get(7)?,
|
||||||
record: row.get_checked(8)?,
|
record: row.get(8)?,
|
||||||
uncommitted: VecDeque::new(),
|
uncommitted: VecDeque::new(),
|
||||||
synced_recordings: 0,
|
synced_recordings: 0,
|
||||||
on_live_segment: Vec::new(),
|
on_live_segment: Vec::new(),
|
||||||
@ -1815,12 +1809,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'",
|
||||||
&[] as &[&ToSql], |row| row.get_checked(0))?;
|
&[] as &[&ToSql], |row| row.get(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", &[] as &[&ToSql],
|
Ok(Some(conn.query_row_and_then("select max(id) from version", &[] as &[&ToSql],
|
||||||
|row| row.get_checked(0))?))
|
|row| row.get(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
|
||||||
|
56
db/raw.rs
56
db/raw.rs
@ -147,29 +147,28 @@ pub(crate) fn list_recordings_by_id(
|
|||||||
fn list_recordings_inner(mut rows: rusqlite::Rows,
|
fn list_recordings_inner(mut rows: rusqlite::Rows,
|
||||||
f: &mut FnMut(db::ListRecordingsRow) -> Result<(), Error>)
|
f: &mut FnMut(db::ListRecordingsRow) -> Result<(), Error>)
|
||||||
-> Result<(), Error> {
|
-> Result<(), Error> {
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
|
||||||
f(db::ListRecordingsRow {
|
f(db::ListRecordingsRow {
|
||||||
id: CompositeId(row.get_checked(0)?),
|
id: CompositeId(row.get(0)?),
|
||||||
run_offset: row.get_checked(1)?,
|
run_offset: row.get(1)?,
|
||||||
flags: row.get_checked(2)?,
|
flags: row.get(2)?,
|
||||||
start: recording::Time(row.get_checked(3)?),
|
start: recording::Time(row.get(3)?),
|
||||||
duration_90k: row.get_checked(4)?,
|
duration_90k: row.get(4)?,
|
||||||
sample_file_bytes: row.get_checked(5)?,
|
sample_file_bytes: row.get(5)?,
|
||||||
video_samples: row.get_checked(6)?,
|
video_samples: row.get(6)?,
|
||||||
video_sync_samples: row.get_checked(7)?,
|
video_sync_samples: row.get(7)?,
|
||||||
video_sample_entry_id: row.get_checked(8)?,
|
video_sample_entry_id: row.get(8)?,
|
||||||
open_id: row.get_checked(9)?,
|
open_id: row.get(9)?,
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
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", &[] as &[&ToSql], |row| -> Result<Uuid, Error> {
|
Ok(conn.query_row("select uuid from meta", &[] as &[&ToSql], |row| -> rusqlite::Result<Uuid> {
|
||||||
let uuid: FromSqlUuid = row.get_checked(0)?;
|
let uuid: FromSqlUuid = row.get(0)?;
|
||||||
Ok(uuid.0)
|
Ok(uuid.0)
|
||||||
})?
|
})?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inserts the specified recording (for from `try_flush` only).
|
/// Inserts the specified recording (for from `try_flush` only).
|
||||||
@ -313,8 +312,8 @@ pub(crate) fn get_range(conn: &rusqlite::Connection, stream_id: i32)
|
|||||||
// The minimum is straightforward, taking advantage of the start_time_90k index.
|
// The minimum is straightforward, taking advantage of the start_time_90k index.
|
||||||
let mut stmt = conn.prepare_cached(STREAM_MIN_START_SQL)?;
|
let mut stmt = conn.prepare_cached(STREAM_MIN_START_SQL)?;
|
||||||
let mut rows = stmt.query_named(&[(":stream_id", &stream_id)])?;
|
let mut rows = stmt.query_named(&[(":stream_id", &stream_id)])?;
|
||||||
let min_start = match rows.next() {
|
let min_start = match rows.next()? {
|
||||||
Some(row) => recording::Time(row?.get_checked(0)?),
|
Some(row) => recording::Time(row.get(0)?),
|
||||||
None => return Ok(None),
|
None => return Ok(None),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -325,10 +324,9 @@ pub(crate) fn get_range(conn: &rusqlite::Connection, stream_id: i32)
|
|||||||
let mut stmt = conn.prepare_cached(STREAM_MAX_START_SQL)?;
|
let mut stmt = conn.prepare_cached(STREAM_MAX_START_SQL)?;
|
||||||
let mut rows = stmt.query_named(&[(":stream_id", &stream_id)])?;
|
let mut rows = stmt.query_named(&[(":stream_id", &stream_id)])?;
|
||||||
let mut maxes_opt = None;
|
let mut maxes_opt = None;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let row_start = recording::Time(row.get(0)?);
|
||||||
let row_start = recording::Time(row.get_checked(0)?);
|
let row_duration: i64 = row.get(1)?;
|
||||||
let row_duration: i64 = row.get_checked(1)?;
|
|
||||||
let row_end = recording::Time(row_start.0 + row_duration);
|
let row_end = recording::Time(row_start.0 + row_duration);
|
||||||
let maxes = match maxes_opt {
|
let maxes = match maxes_opt {
|
||||||
None => row_start .. row_end,
|
None => row_start .. row_end,
|
||||||
@ -353,9 +351,8 @@ pub(crate) fn list_garbage(conn: &rusqlite::Connection, dir_id: i32)
|
|||||||
let mut stmt = conn.prepare_cached(
|
let mut 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 = stmt.query(&[&dir_id])?;
|
let mut rows = stmt.query(&[&dir_id])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
garbage.insert(CompositeId(row.get(0)?));
|
||||||
garbage.insert(CompositeId(row.get_checked(0)?));
|
|
||||||
}
|
}
|
||||||
Ok(garbage)
|
Ok(garbage)
|
||||||
}
|
}
|
||||||
@ -370,13 +367,12 @@ pub(crate) fn list_oldest_recordings(conn: &rusqlite::Connection, start: Composi
|
|||||||
(":start", &start.0),
|
(":start", &start.0),
|
||||||
(":end", &CompositeId::new(start.stream() + 1, 0).0),
|
(":end", &CompositeId::new(start.stream() + 1, 0).0),
|
||||||
])?;
|
])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
|
||||||
let should_continue = f(db::ListOldestRecordingsRow {
|
let should_continue = f(db::ListOldestRecordingsRow {
|
||||||
id: CompositeId(row.get_checked(0)?),
|
id: CompositeId(row.get(0)?),
|
||||||
start: recording::Time(row.get_checked(1)?),
|
start: recording::Time(row.get(1)?),
|
||||||
duration: row.get_checked(2)?,
|
duration: row.get(2)?,
|
||||||
sample_file_bytes: row.get_checked(3)?,
|
sample_file_bytes: row.get(3)?,
|
||||||
});
|
});
|
||||||
if !should_continue {
|
if !should_continue {
|
||||||
break;
|
break;
|
||||||
|
@ -54,7 +54,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), &[] as &[&ToSql],
|
let actual = conn.query_row(&format!("pragma journal_mode = {}", requested), &[] as &[&ToSql],
|
||||||
|row| row.get_checked::<_, String>(0))??;
|
|row| row.get::<_, String>(0))?;
|
||||||
info!("...database now in journal_mode {} (requested {}).", actual, requested);
|
info!("...database now in journal_mode {} (requested {}).", actual, requested);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ 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", &[] as &[&ToSql],
|
conn.query_row("select max(id) from version", &[] as &[&ToSql],
|
||||||
|row| row.get_checked(0))??;
|
|row| row.get(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);
|
||||||
|
@ -144,9 +144,8 @@ fn fill_recording(tx: &rusqlite::Transaction) -> Result<HashMap<i32, CameraState
|
|||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = select.query(&[] as &[&ToSql])?;
|
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 camera_id: i32 = row.get(0)?;
|
||||||
let camera_id: i32 = row.get_checked(0)?;
|
|
||||||
let camera_state = camera_state.entry(camera_id).or_insert_with(|| {
|
let camera_state = camera_state.entry(camera_id).or_insert_with(|| {
|
||||||
CameraState{
|
CameraState{
|
||||||
current_run: None,
|
current_run: None,
|
||||||
@ -155,17 +154,17 @@ fn fill_recording(tx: &rusqlite::Transaction) -> Result<HashMap<i32, CameraState
|
|||||||
});
|
});
|
||||||
let composite_id = ((camera_id as i64) << 32) | (camera_state.next_recording_id as i64);
|
let composite_id = ((camera_id as i64) << 32) | (camera_state.next_recording_id as i64);
|
||||||
camera_state.next_recording_id += 1;
|
camera_state.next_recording_id += 1;
|
||||||
let sample_file_bytes: i32 = row.get_checked(1)?;
|
let sample_file_bytes: i32 = row.get(1)?;
|
||||||
let start_time_90k: i64 = row.get_checked(2)?;
|
let start_time_90k: i64 = row.get(2)?;
|
||||||
let duration_90k: i32 = row.get_checked(3)?;
|
let duration_90k: i32 = row.get(3)?;
|
||||||
let local_time_delta_90k: i64 = row.get_checked(4)?;
|
let local_time_delta_90k: i64 = row.get(4)?;
|
||||||
let video_samples: i32 = row.get_checked(5)?;
|
let video_samples: i32 = row.get(5)?;
|
||||||
let video_sync_samples: i32 = row.get_checked(6)?;
|
let video_sync_samples: i32 = row.get(6)?;
|
||||||
let video_sample_entry_id: i32 = row.get_checked(7)?;
|
let video_sample_entry_id: i32 = row.get(7)?;
|
||||||
let sample_file_uuid: db::FromSqlUuid = row.get_checked(8)?;
|
let sample_file_uuid: db::FromSqlUuid = row.get(8)?;
|
||||||
let sample_file_sha1: Vec<u8> = row.get_checked(9)?;
|
let sample_file_sha1: Vec<u8> = row.get(9)?;
|
||||||
let video_index: Vec<u8> = row.get_checked(10)?;
|
let video_index: Vec<u8> = row.get(10)?;
|
||||||
let old_id: i32 = row.get_checked(11)?;
|
let old_id: i32 = row.get(11)?;
|
||||||
let trailing_zero = has_trailing_zero(&video_index).unwrap_or_else(|e| {
|
let trailing_zero = has_trailing_zero(&video_index).unwrap_or_else(|e| {
|
||||||
warn!("recording {}/{} (sample file {}, formerly recording {}) has corrupt \
|
warn!("recording {}/{} (sample file {}, formerly recording {}) has corrupt \
|
||||||
video_index: {}",
|
video_index: {}",
|
||||||
@ -218,18 +217,17 @@ fn fill_camera(tx: &rusqlite::Transaction, camera_state: HashMap<i32, CameraStat
|
|||||||
: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(&[] as &[&ToSql])?;
|
let mut rows = select.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id: i32 = row.get(0)?;
|
||||||
let id: i32 = row.get_checked(0)?;
|
let uuid: Vec<u8> = row.get(1)?;
|
||||||
let uuid: Vec<u8> = row.get_checked(1)?;
|
let short_name: String = row.get(2)?;
|
||||||
let short_name: String = row.get_checked(2)?;
|
let description: String = row.get(3)?;
|
||||||
let description: String = row.get_checked(3)?;
|
let host: String = row.get(4)?;
|
||||||
let host: String = row.get_checked(4)?;
|
let username: String = row.get(5)?;
|
||||||
let username: String = row.get_checked(5)?;
|
let password: String = row.get(6)?;
|
||||||
let password: String = row.get_checked(6)?;
|
let main_rtsp_path: String = row.get(7)?;
|
||||||
let main_rtsp_path: String = row.get_checked(7)?;
|
let sub_rtsp_path: String = row.get(8)?;
|
||||||
let sub_rtsp_path: String = row.get_checked(8)?;
|
let retain_bytes: i64 = row.get(9)?;
|
||||||
let retain_bytes: i64 = row.get_checked(9)?;
|
|
||||||
insert.execute_named(&[
|
insert.execute_named(&[
|
||||||
(":id", &id),
|
(":id", &id),
|
||||||
(":uuid", &uuid),
|
(":uuid", &uuid),
|
||||||
|
@ -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;
|
||||||
"#, &[] as &[&ToSql], |r| r.get_checked(0))??;
|
"#, &[] as &[&ToSql], |r| r.get(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?;
|
||||||
@ -330,9 +330,8 @@ fn verify_dir_contents(sample_file_path: &str, tx: &rusqlite::Transaction) -> Re
|
|||||||
{
|
{
|
||||||
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(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let uuid: crate::db::FromSqlUuid = row.get(0)?;
|
||||||
let uuid: crate::db::FromSqlUuid = row.get_checked(0)?;
|
|
||||||
if !files.remove(&uuid.0) {
|
if !files.remove(&uuid.0) {
|
||||||
bail!("{} is missing from dir {}!", uuid.0, sample_file_path);
|
bail!("{} is missing from dir {}!", uuid.0, sample_file_path);
|
||||||
}
|
}
|
||||||
@ -341,9 +340,8 @@ 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(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let uuid: crate::db::FromSqlUuid = row.get(0)?;
|
||||||
let uuid: crate::db::FromSqlUuid = row.get_checked(0)?;
|
|
||||||
files.remove(&uuid.0);
|
files.remove(&uuid.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,14 +367,13 @@ fn fix_video_sample_entry(tx: &rusqlite::Transaction) -> Result<(), Error> {
|
|||||||
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(&[] as &[&ToSql])?;
|
let mut rows = select.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let data: Vec<u8> = row.get(4)?;
|
||||||
let data: Vec<u8> = row.get_checked(4)?;
|
|
||||||
insert.execute_named(&[
|
insert.execute_named(&[
|
||||||
(":id", &row.get_checked::<_, i32>(0)?),
|
(":id", &row.get::<_, i32>(0)?),
|
||||||
(":sha1", &row.get_checked::<_, Vec<u8>>(1)?),
|
(":sha1", &row.get::<_, Vec<u8>>(1)?),
|
||||||
(":width", &row.get_checked::<_, i32>(2)?),
|
(":width", &row.get::<_, i32>(2)?),
|
||||||
(":height", &row.get_checked::<_, i32>(3)?),
|
(":height", &row.get::<_, i32>(3)?),
|
||||||
(":rfc6381_codec", &rfc6381_codec_from_sample_entry(&data)?),
|
(":rfc6381_codec", &rfc6381_codec_from_sample_entry(&data)?),
|
||||||
(":data", &data),
|
(":data", &data),
|
||||||
])?;
|
])?;
|
||||||
|
@ -58,11 +58,11 @@ fn open_sample_file_dir(tx: &rusqlite::Transaction) -> Result<Arc<dir::SampleFil
|
|||||||
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
|
||||||
"#, &[] as &[&ToSql], |row| {
|
"#, &[] as &[&ToSql], |row| {
|
||||||
(row.get_checked(0).unwrap(),
|
Ok((row.get(0)?,
|
||||||
row.get_checked(1).unwrap(),
|
row.get(1)?,
|
||||||
row.get_checked(2).unwrap(),
|
row.get(2)?,
|
||||||
row.get_checked(3).unwrap(),
|
row.get(3)?,
|
||||||
row.get_checked(4).unwrap())
|
row.get(4)?))
|
||||||
})?;
|
})?;
|
||||||
let mut meta = schema::DirMeta::default();
|
let mut meta = schema::DirMeta::default();
|
||||||
meta.db_uuid.extend_from_slice(&db_uuid.0.as_bytes()[..]);
|
meta.db_uuid.extend_from_slice(&db_uuid.0.as_bytes()[..]);
|
||||||
@ -85,10 +85,9 @@ pub fn run(_args: &super::Args, tx: &rusqlite::Transaction) -> Result<(), Error>
|
|||||||
recording_playback
|
recording_playback
|
||||||
"#)?;
|
"#)?;
|
||||||
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
let mut rows = stmt.query(&[] as &[&ToSql])?;
|
||||||
while let Some(row) = rows.next() {
|
while let Some(row) = rows.next()? {
|
||||||
let row = row?;
|
let id = db::CompositeId(row.get(0)?);
|
||||||
let id = db::CompositeId(row.get_checked(0)?);
|
let sample_file_uuid: FromSqlUuid = row.get(1)?;
|
||||||
let sample_file_uuid: FromSqlUuid = row.get_checked(1)?;
|
|
||||||
let from_path = get_uuid_pathname(sample_file_uuid.0);
|
let from_path = get_uuid_pathname(sample_file_uuid.0);
|
||||||
let to_path = get_id_pathname(id);
|
let to_path = get_id_pathname(id);
|
||||||
let r = unsafe { dir::renameat(&d.fd, from_path.as_ptr(), &d.fd, to_path.as_ptr()) };
|
let r = unsafe { dir::renameat(&d.fd, from_path.as_ptr(), &d.fd, to_path.as_ptr()) };
|
||||||
|
@ -45,7 +45,7 @@ all non-Rust dependencies:
|
|||||||
pkgconf \
|
pkgconf \
|
||||||
tzdata
|
tzdata
|
||||||
|
|
||||||
Next, you need Rust 1.32+ and Cargo. The easiest way to install them is by
|
Next, you need Rust 1.33+ and Cargo. The easiest way to install them is by
|
||||||
following the instructions at [rustup.rs](https://www.rustup.rs/).
|
following the instructions at [rustup.rs](https://www.rustup.rs/).
|
||||||
|
|
||||||
Finally, building the UI requires [yarn](https://yarnpkg.com/en/).
|
Finally, building the UI requires [yarn](https://yarnpkg.com/en/).
|
||||||
|
@ -40,7 +40,7 @@ fi
|
|||||||
NODE_MIN_VERSION="8"
|
NODE_MIN_VERSION="8"
|
||||||
YARN_MIN_VERSION="1.0"
|
YARN_MIN_VERSION="1.0"
|
||||||
CARGO_MIN_VERSION="0.2"
|
CARGO_MIN_VERSION="0.2"
|
||||||
RUSTC_MIN_VERSION="1.32"
|
RUSTC_MIN_VERSION="1.33"
|
||||||
FFMPEG_MIN_VERSION="55.1.101"
|
FFMPEG_MIN_VERSION="55.1.101"
|
||||||
FFMPEG_RELEASE_VERSION="3.4"
|
FFMPEG_RELEASE_VERSION="3.4"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user