This is mostly just brainpuke right now...
This is just a way to cut down on disk writes, which should give decent browsing speedups. Right now we write the whole file. That's bad, and it affects performance (less so now that writing that file was moved off the main thread).
Unlike the change to Password Manager, mozStorage here will only be used for writing to disk. We'll still be keeping all of the data we have in memory.
Methods That Will Need to Change
For the most part changes will be minor - mostly just marking state as dirty. Writing the file is where things will get most complicated. More on that later.
Database Related Methodology
This needs to be done well. I wasn't entirely happy with how Password Manager ended up. It works, but parts can be cleaner (for example, storing schema as strings is kinda dumb... oops) & we don't need everything (e.g. there are a limited number of statements we'll need to create). Unlike Password Manager we need to make sure we do a clean shutdown.
We'll have to keep track of state for each tab & window. These states should be independent (e.g. a dirty tab doesn't imply a dirty window). This state (obviously) shouldn't be stored in the DB, so it will have to be filtered out of the object on write.
nsSessionStartup will also need to be changed. We won't be able to just parse a JSON string and setState. We may want to move the reading of the database into nsSessionStore so it's consolidated.
Closing Tabs / Windows
This isn't as easy as marking state "deleted". Since we're not writing changes immediately, we'll have to keep track of what rows in the DB need to be deleted. Since the schema should include primary keys (I know we already make unique ids for windows, not sure about tabs), we can just put those ids in an array for the next write.
Writing the File
There are a few cases to consider:
- When state is "dirty", UPDATE
- When state is "new", INSERT
- If we keep the ids in an array as mentioned above, we can just loop over them & DELETE.
- Writing the root object each time shouldn't be too bad. All that we keep is selectedWindow, state, and lastUpdate.
- Will need to be de-normalized. It wouldn't be efficient to do 3NF for the data we're handling. There's just too much with a good amount of variability that it's just not worth it.
- I'm thinking just a basic window-||-----O<-tab relationship & another table for root properties (_closedWindows, state, lastupdate, etc)
- Closed tabs (window._closedTabs) will probably be a column in the windows table. We would just store the whole object here instead of keeping each tab as a separate entry in the tabs table (and having some isClosed marker).
We'll probably have to vacuum this database fairly frequently. "...frequent inserts, updates, and deletes can cause the information in the database to become fragmented..." (SQLite VACUUM). Places doesn't vacuum as of yet (and neither do other heavy hitters like Mail.app), so it might not actually be too big of an issue. A large database kept across sessions could become a problem though. Should probably ignore the potential problem & see what happens with Firefox/Projects/App-wide_Database_Vacuum.
- Do we want to read from sessionstore.js if sessionstore.sqlite isn't there (could be handy).
- Changes to schema will most likely cause issues.
- Sessions used with 3.7 (assuming this happens for that) won't be compatible with previous versions. Right now I think sessions created with a newer version of Firefox will still run on older ones.