Feature #3448

Updated by Tom Clegg over 6 years ago

This statistic is needed to ensure a grace period (equal to permission signature TTL) after writing a block, during which the block is not eligible for garbage collection.
* Data manager needs to know this timestamp (via storage server's @GET /@ index method) in order to get a more accurate picture of which blocks it will be able to delete.
* Storage server itself needs to check this timestamp when performing @DELETE@ requests, to catch race conditions (if a client PUT a new copy of a block 10 seconds ago, after data manager decided 20 seconds ago that the block was a good candidate for deletion, the storage server should refuse to delete it).


* Use Probably makes the most sense to use mtime (@touch(1)@, godoc syscall → @syscall.Utimes()@?) ("touch") to store timestamps. This makes it easy for an admin to inspect state using the usual filesystem tools.
** @Volume@ and @UnixVolume@ should grow an UpdateTimestamp method.
** GetBlock() in handlers.go should accept an additional argument indicating whether it should also perform an "update timestamp" operation before considering its "Get" operation successful.
* Readonly cases: volumes are dangerous: timestamps can't get updated, so clients won't get a grace period. The safest option is to err on the side of excessive replication: when PUTting a block that already exists on the volume, if the timestamp cannot be updated, consider that a failure and try the next volume.
* In @DELETE@, check the mtime of each file before deleting it. If it's newer than permission signature TTL, don't delete. There's a race condition here too, so use mutexes get a volume lock around {check timestamp; delete file} and around {update timestamp during PUT}. If there's a race, "update timestamp" will fail ENOENT and the PUT operation should either retry the current volume once (which would involve writing) or just give up and move on to the next volume.
** Wrap each of the {check timestamp; delete file} and {update timestamp} operations with {open file with mode "a+" and Flock(LOCK_EX) it}
** (Considered using an in-process lock like the -serialize-io mechanism, but that doesn't guard against accidental misconfigurations where multiple keepstore processes point at the same mount point.)
* UnixVolume's Index method already reports modtime. Yay!