Profiles, Locks, Mergers and Acquisitions

First note that problems with locks can actually exist without profiles.

Second note that the locking mechanism used by Mozilla is flawed:

  1. Create a profile victim.
  2. Create a profile attacker.

In the attacker profile, change all the paths to match the victim profile.

You can share:

  1. Cache
  2. Bookmarks
  3. Mail

You can not share the following in this fashion:

  1. Cookies
  2. History
  3. Preferences
  4. Profile Lock

OK, so what would happen if you did this?

you could have two running applications corrupting bookmarks, cache and mail.

The Profile Lock only protects (D-F) because it lives in the same directory as them and their locations aren't configurable.

So really, what should be done about this?

Well, the lock should be split.

It turns out that we're sort of doing this already with the Mozilla 1.5 proposal, your Mail profile lock (Gm) will protect a set ACF and your Browser profile lock (Gb) will protect a set ABDEF. Does this split prevent two profiles from tripping over any A, B or C? No, of course not, only a per directory lock would do that.

About locks in Mozilla

Currently profiles aren't really cross platform, but suppose we actually fix them so that at least preferences use relative file paths when possible. What happens if you use a profile on windows, BeOS, Linux, and Mac OS X? It turns out that the name of the profile lock isn't the same. So while the windows lock will protect you from another Mozilla-w32 process it might not protect you from a Mozilla-Mac OS X process.

More pressing concerns in profile land.

The Linux profile lock marks a profile with an IP address and a PID. So what happens if your system crashes, is configured with DHCP and gets a different IP address the next time it runs? Well, in today's world you'd have to find the lock file and kill it.

Can we do better than that?

Well, perhaps we can ping the IP address listed in the lock file.

Ping

If it's down then we can make the somewhat unsafe but probably relatively reasonable assertion that the profile is available.

Are there any restrictions to this approach?

We should probably only do it if the lock is somewhat stale (5+ minutes).

Why?

Well, why not?
suppose your computer actually did crash, it'd take it some time to boot and some time for the profile using application to load and some time to connect to this network storage device. Plus you don't need to write changes to the profile immediately so letting the user use the profile and storing data in memory for the remaining minutes wouldn't be such a big deal. In the event that the computer doesn't respond to pings but does update the profile data the application could write a file 'noicmp' to indicate that the ICMP test doesn't work.

So what happens today when a user runs into a profile lock?

Mozilla tosses up a dialog saying that the profile is locked and refuses to let you use it.

That's great. What's wrong with this picture?

  1. It tosses up a dialog
  2. The dialog does not offer a recourse
  3. The user is blocked from doing stuff which the user expects to be able to do

That doesn't sound very nice. What did n4 (4xp) do?

Netscape 4 tossed up a dialog which indicated that you could use the profile readonly if you continued.

ReadOnly

Why is this better?
Instead of 1, 2 and 3, n4 did 1 and did the opposite of 2 and 3.

The dialog told the user how to use the data and the user was allowed to use the data.

Was it perfect?

Probably not.

Is it better than Mozilla/5?

Certainly.

What are locks

In computer science a lock is supposed to be used for the shortest duration possible to maintain integrity with a balancing factor that requires you to consider the cost of acquiring the lock.

Does the current architecture honor those concerns?

Not really. The profile data lock is acquired early and held for as long as possible. It isn't really released until the user quits or selects to use a new profile and therefore its associated lock.

Would it be possible to limit the duration of locks so that if you left your computer for a while and the power failed before you came back, your data would be saved and there wouldn't be a lock to contend with?

Sleeping Gracefully

It should be possible to do this.
What would the application have to do?
It would have to detect that the user isn't using it and flush profile data to disk. Then it would need to release the lock and be prepared to contend with another process for the lock in the event that the user actually switches to another computer and starts to use the now available profile.

Sleeping gracefully is unfortunately very much dependent on another concept, what should happen if the user does manage to make changes to two copies of profile data and one instance of the program notices.

Let's look at sharing your bookmarks file.

Netscape 4 and earlier allowed you to choose your bookmarks file location using manage bookmarks, file, open. It turns out that users actually would change their bookmarks files while their browser was open. So what did Netscape 4 do about this?

Detecting External Changes

Netscape 4 would detect that the file was changed, probably by checking the file's date/time-stamp and size. When it detected a change it would ask you whether you wanted to load the new bookmarks file or keep the one you were using.
What does Mozilla/5 do if the user changes the bookmarks file while Mozilla is open?
Nothing :), the changes will be clobbered when Mozilla quits. There isn't any code to check for this case.

So things improved from Mozilla/5 to Mozilla/4... oh wait, whoops... Right... What should have happened in the evolution from Mozilla/4 to Mozilla/5 was instead of dropping the feature, it should have been improved.

How could you improve it?

In addition to offering to delete the current/new file, you could offer to merge the two, or import the new bookmarks.
| Someone asked today how to reload bookmarks, i believe one would do this:
| Components.classes["@mozilla.org/browser/bookmarks-service;1"].
|           getService(Components.interfaces.nsIObserver).
|           observe(0, "profile-after-change", "")

Could the approach of detecting changes to Bookmarks on disk and responding to them be applied to anything else?

Yes :), you can merge/replace cookies, permissions (cookperm.txt), and history.

You can't easily merge changes to preferences, cache or mail.

In my experience w/ n4 mail, mailnews tended to only keep things open if it was really using them. Also changes to mail folders tend to either be simple line changes or append operations, things which wouldn't usually disturb other applications (except summaries/indexes).

Would it be possible to merge changes to preferences?

Yes, but it probably isn't worth it, although at least detecting changes to the preferences file would probably be a good idea.

What about the cache directory?

Necko's cache is very sensitive, it's so sensitive that if Mozilla/5 crashes, necko will blow away the cache directory the next time it launches because it doesn't trust that the cache will be consistent enough to be used safely.

So is there any locking that could help the cache directory?

There are two things which might help.
  1. Monitoring the cache directory for changes made by another application.
    -If something else changes the cache then it isn't locked well enough and something should stop treating it as if it has a write lock.
  2. Implementing support for a readonly cache directory and perhaps a secondary cache directory.
    -If you do decide that the cache directory is being used by someone else you have pretty much three choices.
  1. Ignore that fact and proceed as if nothing's wrong, knowing full well that something bad will happen. :)
  2. Stop writing to the cache, but continue using the cache as a cache of old data because it's there.
  3. Finding some other place to cache stuff (a temp directory or ram)
Mozilla/5 does something like A, except that it doesn't even check to make sure that no one is using the directory. Obviously B and C are better, although they would require coding.
Are there uses for a readonly cache?
Yes.
Are there uses for a secondary cache?
Sure, whenever one wants to cache things and the primary cache is readonly.

Would you need to implement it right away in order to use a readonly cache?

No, it could be implemented later.

Putting it all together

So if a profile started running in a readonly mode, ala n4, how could we improve the behavior?

A thread could be started to monitor the lockfile(s). If the lock becomes available, the thread would capture the lock and then figure out what files need to be reconciled. At some point, the UI thread would inform the user that it can now write to the profile directory, and offer the user the opportunity to reconcile files or run readonly permanently.