From 281bbbed2eb1b6d81cbf3ef3462e6048a2fa7138 Mon Sep 17 00:00:00 2001 From: Rafael Steil Date: Tue, 18 May 2021 09:31:27 -0400 Subject: [PATCH] [Custom Patch] Check dstdir available space before starting new plot Reference: https://github.com/ericaltendorf/plotman/pull/122 --- src/plotman/_tests/manager_test.py | 3 ++- src/plotman/archive.py | 3 +-- src/plotman/configuration.py | 1 + src/plotman/manager.py | 19 +++++++++++-------- src/plotman/plot_util.py | 18 ++++++++++++++++++ src/plotman/plotman.py | 2 +- src/plotman/resources/plotman.yaml | 4 ++++ 7 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/plotman/_tests/manager_test.py b/src/plotman/_tests/manager_test.py index 43a3f78e..8e6a1535 100755 --- a/src/plotman/_tests/manager_test.py +++ b/src/plotman/_tests/manager_test.py @@ -14,7 +14,8 @@ def sched_cfg(): polling_time_s=2, tmpdir_stagger_phase_major=3, tmpdir_stagger_phase_minor=0, - tmpdir_max_jobs=3 + tmpdir_max_jobs=3, + stop_when_dst_full=False ) @pytest.fixture diff --git a/src/plotman/archive.py b/src/plotman/archive.py index 641ae1d1..35ac5a40 100644 --- a/src/plotman/archive.py +++ b/src/plotman/archive.py @@ -159,8 +159,7 @@ def archive(dir_cfg, all_jobs): return(False, 'No free archive dirs found.') archdir = '' - available = [(d, space) for (d, space) in archdir_freebytes.items() if - space > 1.2 * plot_util.get_k32_plotsize()] + available = [(d, space) for (d, space) in archdir_freebytes.items() if plot_util.enough_space_for_k32(space)] if len(available) > 0: index = min(dir_cfg.archive.index, len(available) - 1) (archdir, freespace) = sorted(available)[index] diff --git a/src/plotman/configuration.py b/src/plotman/configuration.py index f081e75d..5b00d0b2 100644 --- a/src/plotman/configuration.py +++ b/src/plotman/configuration.py @@ -92,6 +92,7 @@ class Scheduling: tmpdir_stagger_phase_major: int tmpdir_stagger_phase_minor: int tmpdir_stagger_phase_limit: int = 1 # If not explicit, "tmpdir_stagger_phase_limit" will default to 1 + stop_when_dst_full: bool = False @attr.frozen class Plotting: diff --git a/src/plotman/manager.py b/src/plotman/manager.py index 8c418f35..b5333768 100644 --- a/src/plotman/manager.py +++ b/src/plotman/manager.py @@ -90,21 +90,24 @@ def maybe_start_new_plot(dir_cfg, sched_cfg, plotting_cfg): rankable = [ (d, phases[0]) if phases else (d, job.Phase(known=False)) for (d, phases) in eligible ] - if not eligible: + # Select the dst dir least recently selected + dst_dir = dir_cfg.get_dst_directories() + + dir2ph = { d:ph for (d, ph) in dstdirs_to_youngest_phase(jobs).items() + if d in dst_dir and ph is not None and plot_util.is_valid_plot_dst(d, sched_cfg, jobs)} + unused_dirs = [d for d in dst_dir if d not in dir2ph.keys() and plot_util.is_valid_plot_dst(d, sched_cfg, jobs)] + + if not unused_dirs and not dir2ph: + wait_reason = 'no eligible dstdirs' + elif not eligible: wait_reason = 'no eligible tempdirs (%ds/%ds)' % (youngest_job_age, global_stagger) else: # Plot to oldest tmpdir. tmpdir = max(rankable, key=operator.itemgetter(1))[0] - - # Select the dst dir least recently selected - dst_dir = dir_cfg.get_dst_directories() + if dir_cfg.dst_is_tmp(): dstdir = tmpdir else: - dir2ph = { d:ph for (d, ph) in dstdirs_to_youngest_phase(jobs).items() - if d in dst_dir and ph is not None} - unused_dirs = [d for d in dst_dir if d not in dir2ph.keys()] - dstdir = '' if unused_dirs: dstdir = random.choice(unused_dirs) else: diff --git a/src/plotman/plot_util.py b/src/plotman/plot_util.py index bbdf1bed..31336224 100644 --- a/src/plotman/plot_util.py +++ b/src/plotman/plot_util.py @@ -3,6 +3,8 @@ import re import shutil +from plotman import job + GB = 1_000_000_000 def df_b(d): @@ -13,6 +15,22 @@ def df_b(d): def get_k32_plotsize(): return 108 * GB +def is_valid_plot_dst(d, sched_cfg, all_jobs): + if sched_cfg.stop_when_dst_full: + space = df_b(d) + # Subtract space for current jobs which will be moved to the dir + # Note: This is underestimates the free space available when a + # job is in phase 4 since the plot is partially moved to dst, + # once phase 4 is complete a new plot will eventually kick off + jobs_to_dstdir = job.job_phases_for_dstdir(d, all_jobs) + space -= len(jobs_to_dstdir) * get_k32_plotsize() + return enough_space_for_k32(space) + return True + +def enough_space_for_k32(b): + 'Determine if there is enough space for a k32 given a number of free bytes' + return b > 1.2 * get_k32_plotsize() + def human_format(num, precision): magnitude = 0 while abs(num) >= 1000: diff --git a/src/plotman/plotman.py b/src/plotman/plotman.py index 326fb0c8..69bfdefc 100755 --- a/src/plotman/plotman.py +++ b/src/plotman/plotman.py @@ -171,7 +171,7 @@ def main(): csv_exporter.export(logfilenames, args.save_to) else: - jobs = Job.get_running_jobs(cfg.directories.log()) + jobs = Job.get_running_jobs(cfg.directories.log) # Status report if args.cmd == 'status': diff --git a/src/plotman/resources/plotman.yaml b/src/plotman/resources/plotman.yaml index 060989b8..af09ae6d 100644 --- a/src/plotman/resources/plotman.yaml +++ b/src/plotman/resources/plotman.yaml @@ -113,6 +113,10 @@ scheduling: # How often the daemon wakes to consider starting a new plot job, in seconds. polling_time_s: 20 + # Stop initiating new plots when a dst is full, default to False since + # archiving job should move other plots before plotting is completed + stop_when_dst_full: False + # Plotting parameters. These are pass-through parameters to chia plots create. # See documentation at