Support lockContent in more special remotes. This allows dropping content from a special remote when the only copies are in other special remotes, without needing to set mincopies to 0 and risk losing content.
(All the easy ones, eg read-only special remotes, are implemented already.)
It might be possible for an external remote to lock content, but it would be a tricky extension to the protocol, since lockContent needs to keep it locked while running another action. There would need to be separate actions for locking and unlocking.
If this were implemented in git-annex, and some special remote program didn't used to support it, and implemented REMOVE w/o checking a lock, then making that program support lockContent would run the risk of a mixture of the old and new version being in use for the same remote, which could result in data loss.
To avoid that, the author of the special remote would need to either a) always do lock checking from the beginning or b) wait long enough or document well enough to be sure that situation never happens.
Maybe this second part is not a problem actually? Analysis follows:
There are 2 git-annex instances A and B, and 2 special remotes X and Y. A is using the old program that does not support locking, B uses the new program that does. Both X and Y have a copy of an object.
If A is dropping from X, it will not trust Y to satisfy mincopies, since A cannot lockContent Y. So it will not drop from X.
If B is dropping from Y, it can lockContent X, and so the drop succeeds.
It seems it's ok for B to trust lockContent X, even though A does not check if X is locked when dropping from it. Because A will not drop from X unless it's able to satisfy mincopies by locking the content somewhere else. --Joey
directory could use fcntl locking
This would need a transition, because dropping from directory first needs to support checking for locks. Only after we're sure that any git-annex binaries that might be in use on a machine do that is it safe for lockContent to take the lock. So git-annex would need to be released with the first change, then wait several months or years before making the second change.
Update: See analysis above, should also apply here.
Also, the directory might be on a filesystem that does not support locking, with various failure modes. And unlike a git-annex repo, there's nowhere in a directory special remote to record information about locking problems with it. Getting this right seems hard..
If lockContent throws an exception, that remote is treated the same as if it did not support lockContent, so if these problems can be differentiated from a failure to lock at all, can just throw an exception. But need to avoid lockContent succeeding in any case where removeKey will not be prevented from removing the content.
S3 has an object lock feature, I don't know if it would be usable for this.
It would need a transition, with dropKey first failing when the object lock was in place, and then once that git-annex was in use everywhere, lockContent setting the object lock.
Update: See analysis above, should also apply here.
(S3 with versioning=yes already supports lockContent.)
adb could use some shell trick perhaps.. But it would depend on doing locking in /sdcard, which seems likely to be a massive ball of POSIX incompliance and pain.
Maybe, can implement lockContent with the existing protocol? To lock a key, use
TRANSFER STORE
to store a lockfile to the remote, with the lockfile's key derived from the key being locked, and the lockfile's content storing details like when was the lock set and by whom. Before anyREMOVE
request, git-annex would useCHECKPRESENT
on the lockfile key, and not count the key as present if the lockfile key exists.Or, simpler, just store one special key into the remote indicating "prevent all removals by git-annex instances other than this one" before doing a series of removals, and
REMOVE
the key when removals end.TRANSFER STORE
is not specified to fail if the key is already stored, so not usable for locking.lockContent
, before dropping content from a remote, could temporarily untrust it, sync thegit-annex
branch, then -- only if the sync succeeds -- drop the content, then restore the trust level and sync again?Both of these ideas above seem to suffer from race conditions, which lockContent needs to prevent. lockContent needs the remote to support an actual exclusive locking operation.
Do you have an external special remote that could actually support that?
"lockContent needs the remote to support an actual exclusive locking operation. Do you have an external special remote that could actually support that?" -- I do, the DNAnexus special remote. But it'd better if
git-annex
itself handled locking, so that one didn't have to trust each external remote's implementation. Locking for a remote doesn't have to be done through the remote itself; it can be done through another remote for which git-annex has built-in locking support. Doing it through the git remote itself seems simplest."ideas above seem to suffer from race conditions" -- what is the race condition for syncing through the git-annex branch? If two people try to push to git-annex branch one will fail, and require a pull first. Let's say people P1 and P2 try to drop a file from remotes R1 and R2. They both cloned the repo from git remote G. P1's git-annex marks R1 untrusted on the git-annex branch, and pushes that branch to G. P2's git-annex marks R2 untrusted on the git-annex branch, and tries to push that branch to G, but fails, so has to pull first. Then P2's git-annex sees that R1 is now untrusted, and refuses to drop from R2. P1's git-annex finishes the drop from R1, then restores R1's trust level.
This does require there to be a shared git remote G, but that's often the case. Maybe the URL of G could be stored in the remotes R1/R2 as contents of a special key?
Nothing really prevents G from accepting both pushes and merging them, resulging in both R1 and R2 being untrusted, but P2 not seeing in time that R2 is untrusted.
Nothing prevents G from letting the push from P2 overwrite the branch that was earlier pushed from P1.
Nothing assues P1 and P2 that they are actually talking to the same git repository and not a split brain situation that normally presents as a single git repository.
The above are all maybe unlikely, but it would be hard to rule them all out. A perhaps more likely case is, what if some other process on P2 happens to pull from G just before P2 modifies the git-annex branch? Then P2's push will not fail. That kind of race is probably what I was thinking of.
Doing locking via another git-annex remote is an interesting idea. That would involve having an empty dummy object file for some derived key stored in the git-annex remote, and lock that object file.
It seems that, to avoid situations that drop both copies of an object stored in 2 such special remotes, dropping the object from the special remote would need to entail first dropping the dummy object file from the git-annex remote, and only when that succeeds can the object be safely dropped from the special remote. And this implies that, in order to store the object in the special remote, the dummy object file first has to be stored in the git-annex remote.
But operation on the git-annex remote are not atomic with operations on the special remote. So I do not think it is possible to avoid all races.
For example, let's have two objects A and B in two special remotes (2 copies of the content of the same key) and two corresponding dummy objects A' and B' in a git-annex remote. You are dropping A, so you first lock B', then remove A', and finally remove A. I am dropping B, so I first lock A', then remove B', and finally remove B.
Seems safe, right -- either you remove A' before I can lock it and my drop fails, or I lock A' before you can remove it, and your drop fails. But.. There's a third actor, Mallory. Mallory thinks that A does not contain the object yet, and he's going to helpfully fix that. He decides he will first store A' in the git-annex remote, then store A.
Then, this sequence of events could occur:
It certainly must be possible to use a git-annex remote to handle locking for special remotes, after all if you inverted control and had that git-annex repository communicating to the user's reposities and telling them when to delete from the special remote, that would be race safe.
But it seems that the usual git-annex remote operations are not sufficient to do it. It would need some new operations tailored to support it.