Skip to content

Commit 85b1721

Browse files
authored
Merge pull request #2866 from pared/2473
remote: s3: adjust jobs number basing on file descriptors number
2 parents 032d094 + ab54847 commit 85b1721

File tree

3 files changed

+48
-9
lines changed

3 files changed

+48
-9
lines changed

dvc/main.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Main entry point for dvc CLI."""
22
from __future__ import unicode_literals
33

4+
import errno
45
import logging
56

67
from dvc import analytics
@@ -64,6 +65,10 @@ def main(argv=None):
6465
"unicode is not supported in DVC for Python 2 "
6566
"(end-of-life January 1, 2020), please upgrade to Python 3"
6667
)
68+
elif isinstance(exc, OSError) and exc.errno == errno.EMFILE:
69+
logger.exception(
70+
"too many open files, please increase your `ulimit`"
71+
)
6772
else:
6873
logger.exception("unexpected error")
6974
ret = 255

dvc/remote/base.py

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
from __future__ import unicode_literals
2+
3+
import errno
4+
25
from dvc.utils.compat import basestring, FileNotFoundError, str, urlparse
36

47
import itertools
@@ -516,6 +519,16 @@ def _save(self, path_info, checksum):
516519
return
517520
self._save_file(path_info, checksum)
518521

522+
def _handle_transfer_exception(
523+
self, from_info, to_info, exception, operation
524+
):
525+
if isinstance(exception, OSError) and exception.errno == errno.EMFILE:
526+
raise exception
527+
528+
msg = "failed to {} '{}' to '{}'".format(operation, from_info, to_info)
529+
logger.exception(msg)
530+
return 1
531+
519532
def upload(self, from_info, to_info, name=None, no_progress_bar=False):
520533
if not hasattr(self, "_upload"):
521534
raise RemoteActionNotImplemented("upload", self.scheme)
@@ -537,10 +550,10 @@ def upload(self, from_info, to_info, name=None, no_progress_bar=False):
537550
name=name,
538551
no_progress_bar=no_progress_bar,
539552
)
540-
except Exception:
541-
msg = "failed to upload '{}' to '{}'"
542-
logger.exception(msg.format(from_info, to_info))
543-
return 1 # 1 fail
553+
except Exception as e:
554+
return self._handle_transfer_exception(
555+
from_info, to_info, e, "upload"
556+
)
544557

545558
return 0
546559

@@ -614,10 +627,10 @@ def _download_file(
614627
self._download(
615628
from_info, tmp_file, name=name, no_progress_bar=no_progress_bar
616629
)
617-
except Exception:
618-
msg = "failed to download '{}' to '{}'"
619-
logger.exception(msg.format(from_info, to_info))
620-
return 1 # 1 fail
630+
except Exception as e:
631+
return self._handle_transfer_exception(
632+
from_info, to_info, e, "download"
633+
)
621634

622635
move(tmp_file, to_info, mode=file_mode)
623636

tests/func/test_remote.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1+
import errno
12
import os
23
import shutil
34

45
import configobj
6+
import pytest
57
from mock import patch
68

79
from dvc.config import Config
810
from dvc.main import main
911
from dvc.path_info import PathInfo
10-
from dvc.remote import RemoteLOCAL
12+
from dvc.remote import RemoteLOCAL, RemoteConfig
1113
from dvc.remote.base import RemoteBASE
14+
from dvc.utils.compat import fspath
1215
from tests.basic_env import TestDvc
1316
from tests.remotes import get_local_url, get_local_storagepath
1417

@@ -253,3 +256,21 @@ def unreliable_upload(self, from_file, to_info, name=None, **kwargs):
253256
def get_last_exc(caplog):
254257
_, exc, _ = caplog.records[-2].exc_info
255258
return exc
259+
260+
261+
def test_raise_on_too_many_open_files(tmp_dir, dvc, tmp_path_factory, mocker):
262+
storage = tmp_path_factory.mktemp("test_remote_base")
263+
remote_config = RemoteConfig(dvc.config)
264+
remote_config.add("local_remote", fspath(storage), default=True)
265+
266+
tmp_dir.dvc_gen({"file": "file content"})
267+
268+
mocker.patch.object(
269+
RemoteLOCAL,
270+
"_upload",
271+
side_effect=OSError(errno.EMFILE, "Too many open files"),
272+
)
273+
274+
with pytest.raises(OSError) as e:
275+
dvc.push()
276+
assert e.errno == errno.EMFILE

0 commit comments

Comments
 (0)