Currently only one instance of dvc could run in a particular repo
because of the `.dvc/lock`. That gets furstrating when you are running
some long-running command and blocked from doing anything else.
This PR solved that issue for `dvc run` by releasing the repo lock
while running the command. To protect against conflicts, we now use
rwlock, which keeps the list of readers and writers for particular
paths. The process looks like this:
1) aquire read locks for deps;
2) aquire write locks for outs;
3) release repo lock;
4) run cmd;
5) aquire repo lock;
6) release write locks for outs;
7) release read locks for outs;
We also take rwlocks for operations such as `import`, `add` and `checkout`
to ensure that we won't hit the same files that are being used by
another `dvc run` in the background.
We don't aquire rwlocks for the stage file itself, as we don't really
care about anyone overwriting a stage file, as there is a very little
difference here between parallel runs and sequential runs that overwrite
the same stage file.
Next steps might be to release repo lock on `import`(when dowloading
stuff) and when computing checksums or copying files.
Fixes#755
* master:
address @efiop's suggestions
s3: add support for top level empty directories
remote: http: calculate length basing on response and not head call
test: remote: http: clear test file name
HTTPError: reformat error message
Update dvc/remote/http.py
remote: http: rename http error, refactor test
remote: http: raise exception when download response with error status code
Support GDrive as remote
setup: don't forget contextlib2
remote: refactor ssh ask password code
remote: protect all remote client/session creation code with locks
test: refactor & remove redundant test fixtures
NoRemoteInExternalRepoError: dont pass cause of exception
perf: optimize cache listing for local, ssh and hdfs
remote: small .save_info()/.get_checksum() cleanup