Repository: ESMCI/cime

Issue:
CIME should error gracefully if a required file is 0 size after write or before read.

Recently, a user had not known they were up against their quota and env_run.xml in the casedir had size 0 after completion of a run.  When trying to do "case.submit" again, a cryptic error message resulted (see below).

Shouldn't the creation or overwrite of env_run.xml have triggered an error if it was size 0?  Or should its size be checked before trying to read?   I'm not sure if a quota error will generate the same signal as physically filling the filesystem.

(I feel like multiple parts of the system (CIME and model) are bad at recognizing out-of-space issues).

./case.submit
Traceback (most recent call last):
  File "./case.submit", line 108, in <module>
    _main_func(__doc__)
  File "./case.submit", line 102, in _main_func
    with Case(caseroot, read_only=False) as case:
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/case/case.py", line 95, in __init__
    self.read_xml()
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/case/case.py", line 203, in read_xml
    self._env_entryid_files.append(EnvRun(self._caseroot, components=components, read_only=self._force_read_only))
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/XML/env_run.py", line 19, in __init__
    EnvBase.__init__(self, case_root, infile, schema=schema, read_only=read_only)
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/XML/env_base.py", line 21, in __init__
    EntryID.__init__(self, fullpath, schema=schema, read_only=read_only)
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/XML/entry_id.py", line 17, in __init__
    GenericXML.__init__(self, infile, schema, read_only=read_only)
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/XML/generic_xml.py", line 64, in __init__
    self.read(infile, schema)
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/XML/generic_xml.py", line 102, in read
    self.read_fd(fd)
  File "/gpfs/fs1/home/user/cryo/e3sm_repos/maint-1.2.20210610/E3SM/cime/scripts/Tools/../../scripts/lib/CIME/XML/generic_xml.py", line 127, in read_fd
    self.tree = ET.parse(fd)
  File "/lcrc/soft/climate/e3sm-unified/base/envs/e3sm_unified_1.5.0_nompi/lib/python3.8/xml/etree/ElementTree.py", line 1202, in parse
    tree.parse(source, parser)
  File "/lcrc/soft/climate/e3sm-unified/base/envs/e3sm_unified_1.5.0_nompi/lib/python3.8/xml/etree/ElementTree.py", line 595, in parse
    self._root = parser._parse_whole(source)
xml.etree.ElementTree.ParseError: no element found: line 1, column 0


Discussion:
This [line](https://github.com/ESMCI/cime/blob/master/scripts/lib/CIME/XML/generic_xml.py#L62) could be modified to add a test that the file size is > 0.

Resolving patch:
diff --git a/scripts/lib/CIME/XML/generic_xml.py b/scripts/lib/CIME/XML/generic_xml.py
--- a/scripts/lib/CIME/XML/generic_xml.py
+++ b/scripts/lib/CIME/XML/generic_xml.py
@@ -59,7 +59,7 @@ def __init__(self, infile=None, schema=None, root_name_override=None, root_attri
         if infile is None:
             return
 
-        if os.path.isfile(infile) and os.access(infile, os.R_OK):
+        if os.path.isfile(infile) and os.access(infile, os.R_OK) and os.stat(infile).st_size > 0:
             # If file is defined and exists, read it
             self.read(infile, schema)
         else:


Test patch: