From 57dc6fe99b8b9f55ea093b2f39f73e54b7269255 Mon Sep 17 00:00:00 2001 From: Zachary Prince Date: Wed, 11 Sep 2024 21:03:47 -0600 Subject: [PATCH] Getting syncdbAfterWrite working (#1857) Co-authored-by: John Stilley <1831479+john-science@users.noreply.github.com> --- armi/bookkeeping/db/database3.py | 11 +++++ .../db/tests/test_databaseInterface.py | 49 +++++++++++++++++++ doc/release/0.4.rst | 1 + 3 files changed, 61 insertions(+) diff --git a/armi/bookkeeping/db/database3.py b/armi/bookkeeping/db/database3.py index 4e3b021d6..320fb6cba 100644 --- a/armi/bookkeeping/db/database3.py +++ b/armi/bookkeeping/db/database3.py @@ -33,6 +33,7 @@ """ import collections import copy +import gc import io import itertools import os @@ -683,8 +684,18 @@ def syncToSharedFolder(self): """ runLog.extra("Copying DB to shared working directory.") self.h5db.flush() + + # Close the h5 file so it can be copied + self.h5db.close() + self.h5db = None shutil.copy(self._fullPath, self._fileName) + # Garbage collect so we don't have multiple databases hanging around in memory + gc.collect() + + # Reload the file in append mode and continue on our merry way + self.h5db = h5py.File(self._fullPath, "r+") + def load( self, cycle, diff --git a/armi/bookkeeping/db/tests/test_databaseInterface.py b/armi/bookkeeping/db/tests/test_databaseInterface.py index 664ed1931..b1542dfa7 100644 --- a/armi/bookkeeping/db/tests/test_databaseInterface.py +++ b/armi/bookkeeping/db/tests/test_databaseInterface.py @@ -194,6 +194,55 @@ def test_timeNodeLoop_tightCoupling(self): self.o._timeNodeLoop(0, 0) self.assertTrue(self.dbi._db.hasTimeStep(0, 0)) + def test_syncDbAfterWrite(self): + """ + Test to ensure that the fast-path database is copied to working + directory at every time node when ``syncDbAfterWrite`` is ``True``. + """ + r = self.r + + self.o.cs["syncDbAfterWrite"] = True + self.o.cs["burnSteps"] = 2 # make test insensitive to burn steps + + self.dbi.interactBOL() + self.assertFalse(os.path.exists(self.dbi.database.fileName)) + + # Go through a few time nodes to ensure appending is working + for timeNode in range(self.o.cs["burnSteps"]): + r.p.cycle = 0 + r.p.timeNode = timeNode + self.dbi.interactEveryNode(r.p.cycle, r.p.timeNode) + + # The file should have been copied to working directory + self.assertTrue(os.path.exists(self.dbi.database.fileName)) + + # The copied file should have the newest time node + with Database3(self.dbi.database.fileName, "r") as db: + for tn in range(timeNode + 1): + self.assertTrue(db.hasTimeStep(r.p.cycle, tn)) + + # The in-memory database should have been reloaded properly + for tn in range(timeNode + 1): + self.assertTrue(self.dbi.database.hasTimeStep(r.p.cycle, tn)) + + # Make sure EOL runs smoothly + self.dbi.interactEOL() + self.assertTrue(os.path.exists(self.dbi.database.fileName)) + + def test_noSyncDbAfterWrite(self): + """ + Test to ensure that the fast-path database is NOT copied to working + directory at every time node when ``syncDbAfterWrite`` is ``False``. + """ + self.o.cs["syncDbAfterWrite"] = False + + self.dbi.interactBOL() + self.assertFalse(os.path.exists(self.dbi.database.fileName)) + self.dbi.interactEveryNode(0, 0) + self.assertFalse(os.path.exists(self.dbi.database.fileName)) + self.dbi.interactEOL() + self.assertTrue(os.path.exists(self.dbi.database.fileName)) + class TestDatabaseWriter(unittest.TestCase): def setUp(self): diff --git a/doc/release/0.4.rst b/doc/release/0.4.rst index 35e3c1eaf..16a35ebbb 100644 --- a/doc/release/0.4.rst +++ b/doc/release/0.4.rst @@ -26,6 +26,7 @@ Bug Fixes --------- #. Fixed ``DerivedShape.getArea`` for ``cold=True``. (`PR#1831 `_) #. Fixed error parsing command line integers in ``ReportsEntryPoint``. (`PR#1824 `_) +#. Fixed ``PermissionError`` when using ``syncDbAfterWrite``. (`PR#1857 `_) #. Fixed ``MpiDirectoryChanger``. (`PR#1853 `_) #. Changed data type of ``thKernel`` setting from ``bool`` to ``str`` in ``ThermalHydraulicsPlugin``. (`PR#1855 `_) #. TBD