jack-ullery / AppAnvil

Graphical user interface for the AppArmor security module (in-progress)
GNU General Public License v3.0
17 stars 12 forks source link

Improve Log parsing performance #41

Closed jack-ullery closed 2 years ago

jack-ullery commented 2 years ago

Description

Since there can be a large number of AppArmor logs on a system, we should prioritize performance when parsing them.

Previously, parsing the logs would be an O (n log(n) ) operation. These changes improve it to an O( n ) operation.

Change 1 - Do not store LogTableEntry structs in the database

Previously, we would store the LogTableEntry structs in the database, so that we could retrieve them when a log is selected. Adding a single log to the DB takes O ( log(n) ) time according to the implementation for std::map, where n is the number of logs with a constant number for AppArmor profiles. However, this was functionality was not used as of #39.

Instead of storing a LogTableEntry struct in the database for each profile, we instead store an integer for the number of Logs parsed for each Profile. Now, adding a single log takes constant time, assuming the number of Profiles is constant.

Change 2 - Use cursor when parsing logs

journalctl can provide a cursor when parsing logs on multiple calls. It will only print logs that occurred after the cursor, if you provide one. I made changes for a few classes to take advantage of this functionality.

Now ConsoleThread will remember the cursor every time it gets a batch of logs, and use that cursor the next time it queries for logs. This ensures that duplicate logs are do not returned by CommandCaller, which lowers the amount of logs parsed when refreshing tabs.

Change 3 - Update unit tests to reflect changes

These changes involved modifying Database, AppArmorCaller, and LogAdapter. The unit tests needed to be rewritten to reflect these changes. I also removed the DatabaseMock class, because it has not been necessary since #37.