(#21307) Consider a missing file to be unchanged

Previously a watch file that was missing caused problems because it was always
considered changed. This modifies that behavior so that only when the file
appears is it considered changed.

In addition this pulls apart the WatchedFile class into the constituent parts: 
  * watching a particular attribute for changes
  * reading the ctime of the file
  * only looking for changes periodically
  * and deciding if a particular amount of time has elapsed

This leaves WatchedFile as a simple composition of these pieces and it is left
without tests, the individual parts are tested for their behavior.