8 Commits

Author SHA1 Message Date
Scott Lamb
1bd5c8aafe Sanify sample directory references.
Before, I had a gross hardcoded path in moonfire-db.cc + a hacky
Recording::sample_file_path (which is StrCat(sample_file_dir, "/", uuid),
essentially). Now, things expect to take a File* to the sample file directory
and use openat(2). Several things had to change in the process:

* RealFileSlice now takes a File* dir.
* File has an Open that returns an fd (for RealFileSlice's benefit).
* BuildMp4 now is in WebInterface rather than MoonfireDatabase. The latter
  only manages the SQLite database, so it shouldn't know anything about the
  sample file directory.
2016-01-31 22:41:30 -08:00
Scott Lamb
699ffe7777 Expanded, reasonably efficient SQL operations.
* Schema revisions. The most dramatic is the addition of a covering index on
  (camera_id, start_time_90k) that avoids the need to make sparse accesses
  into the recording table (where the desired data is intermixed with both
  the large blobs and rows from other cameras). A query over a year's data
  previously took many seconds (6+ even in a form without the video_index)
  and now is roughly 10X faster. Queries for a couple weeks now should be
  unnoticeably fast.

  Other changes to shrink the rows, such as duration_90k instead of
  end_time_90k (more compact varint encoding) and video_sample_entry_id
  (typically 1 byte) instead of video_sample_entry_sha1 (20 bytes).
  And more CHECK constraints for good measure.

* Caching of expensive computations and logic to keep them up to date.
  The top-level web view previously went through the entire recording table,
  which was even slower. Now it is served from a small map in RAM.

* Expanded the scope of operations to cover (hopefully) everything needed for
  recording into the SQLite database.

* Added tests of MoonfireDatabase. These are basic tests that don't
  exercise a lot of error cases, but at least they exist.

The main MoonfireDatabase functionality still missing is support for quickly
seeing what calendar days have data over the full timespan of a camera. This
is more data to compute and cache.
2016-01-24 17:57:46 -08:00
Scott Lamb
b9d6526492 Optimize the SQLite query for building .mp4s.
On my laptop, with a month's data, a test query would take 0.1 to 0.2 seconds
before. Now it takes 0.001 to 0.004 seconds.

I improved this by creating and taking advantage of an index on start time.
It's a little more complicated than that because the desired timespan is
specified in terms of a recording's start and end time, not start time alone.
I defined a maximum duration of a recording (5 minutes) and specified this
with an extra condition in the query so that the end time can be used to
narrow the valid range of start times.

"explain query plan select ..." output confirms it's using the index with
both > and < comparisons:

0|0|0|SEARCH TABLE recording USING INDEX recording_start_time_90k (start_time_90k>? AND start_time_90k<?)
0|1|1|SEARCH TABLE video_sample_entry USING INDEX sqlite_autoindex_video_sample_entry_1 (sha1=?)

I also refactored ListMp4Recordings out of BuildMp4File to make the measurement
easier.
2016-01-17 01:14:29 -08:00
Scott Lamb
40cd983355 Web interface to the new SQLite schema.
This is almost certain to have performance problems with large databases,
but it's a useful starting point.

No tests yet. It shouldn't be too hard to add some for moonfire-db.h, but
I'm impatient to fake up enough data to check on the performance and see
what needs to change there first.
2016-01-16 22:54:16 -08:00
Scott Lamb
84406a8123 Add a fast path to Mp4SampleTablePieces::Init.
This avoids iteration through the video index for the "interior" recordings of
a virtual file. This takes generating the size of a ~8-hour / 15 fps file from
about 60 ms to about 10 ms. I expect better savings on a Raspberry Pi 2, for
longer records, and for higher frame rates. The total time here can be
significant; one one ~day-long recording on the Pi, it was several seconds.
I'm optimistic this will help with that.

It'd also be possible to optimize DecodeVar32 (perhaps by unrolling the loop)
but better to remove a call than to optimize one.

To add the fast path, we need a new field "video_sync_samples" in the
recording table to calculate the length of the stss table. Storage cost should
be minimal; I think typically two bytes in SQLite's record format (serial type
1, value < 128), described here: <https://www.sqlite.org/fileformat2.html>.
2016-01-14 15:41:45 -08:00
Scott Lamb
85b7027803 Logic for generating .mp4 virtual files.
This is still pretty rough. For example, there's no test coverage of virtual
files based on multiple recordings. The etag and last modified code are stubs.
And various other conditions aren't tested at all. But it does appear to work
in a test that does a round-trip from a .mp4 file, so it should be a decent
starting point.
2016-01-11 00:17:56 -08:00
Scott Lamb
48d0473a4c Small helper for writing sample files safely.
Handles partial writes + checksumming.
2016-01-09 17:16:55 -08:00
Scott Lamb
60988f0646 Add sample index codec; fix schema doc. 2016-01-05 11:01:36 -08:00