From fbd98175b2e1570586baea2d495404ef0a786219 Mon Sep 17 00:00:00 2001 From: Mike White Date: Sat, 17 Apr 2021 09:42:47 -0500 Subject: [PATCH 1/2] Add configuration to stop when dst is full --- src/plotman/_tests/manager_test.py | 3 ++- src/plotman/archive.py | 3 +-- src/plotman/configuration.py | 1 + src/plotman/manager.py | 18 ++++++++++-------- src/plotman/plot_util.py | 11 +++++++++++ src/plotman/resources/plotman.yaml | 4 ++++ 6 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/plotman/_tests/manager_test.py b/src/plotman/_tests/manager_test.py index 2f425955..a06965dc 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 17a29af0..0783cda6 100644 --- a/src/plotman/archive.py +++ b/src/plotman/archive.py @@ -121,8 +121,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 44b12c43..b6e9028a 100644 --- a/src/plotman/configuration.py +++ b/src/plotman/configuration.py @@ -69,6 +69,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 @dataclass class Plotting: diff --git a/src/plotman/manager.py b/src/plotman/manager.py index 19a45d63..97a4e5a8 100644 --- a/src/plotman/manager.py +++ b/src/plotman/manager.py @@ -84,21 +84,23 @@ def maybe_start_new_plot(dir_cfg, sched_cfg, plotting_cfg): if phases_permit_new_job(phases, d, sched_cfg, dir_cfg) ] rankable = [ (d, phases[0]) if phases else (d, (999, 999)) for (d, phases) in eligible ] - - if not eligible: + dir2ph = {d: ph for (d, ph) in dstdirs_to_youngest_phase(jobs).items() + if (d in dir_cfg.dst and plot_util.is_valid_plot_dst(d, sched_cfg))} + unused_dirs = [d for d in dir_cfg.dst + if d not in dir2ph.keys() and plot_util.is_valid_plot_dst(d, sched_cfg)] + + if not unused_dirs and not dir2ph: + wait_reason = 'no eligible dstdirs' + elif not eligible: wait_reason = 'no eligible tempdirs' else: # Plot to oldest tmpdir. tmpdir = max(rankable, key=operator.itemgetter(1))[0] - # Select the dst dir least recently selected - dir2ph = { d:ph for (d, ph) in dstdirs_to_youngest_phase(jobs).items() - if d in dir_cfg.dst } - unused_dirs = [d for d in dir_cfg.dst if d not in dir2ph.keys()] - dstdir = '' - if unused_dirs: + if unused_dirs: dstdir = random.choice(unused_dirs) else: + # Select the dst dir least recently selected dstdir = max(dir2ph, key=dir2ph.get) logfile = os.path.join( diff --git a/src/plotman/plot_util.py b/src/plotman/plot_util.py index 59ef0fad..0734887f 100644 --- a/src/plotman/plot_util.py +++ b/src/plotman/plot_util.py @@ -12,6 +12,17 @@ def df_b(d): def get_k32_plotsize(): return 108 * GB +def is_valid_plot_dst(d, sched_cfg): + return (not sched_cfg.stop_when_dst_full) or dir_can_recieve_k32(d) + +def dir_can_recieve_k32(d): + 'Determine if there is enough space for a k32 in a directory' + return enough_space_for_k32(df_b(d)) + +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/resources/plotman.yaml b/src/plotman/resources/plotman.yaml index 209ed3ad..7c9a734a 100644 --- a/src/plotman/resources/plotman.yaml +++ b/src/plotman/resources/plotman.yaml @@ -103,6 +103,10 @@ scheduling: # How often the daemon wakes to consider starting a new plot job 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 From f824ebd45b5b25b078838153fb0395da6a3a9f87 Mon Sep 17 00:00:00 2001 From: Mike White Date: Sat, 17 Apr 2021 10:28:46 -0500 Subject: [PATCH 2/2] Consider in-flight plots --- src/plotman/manager.py | 4 ++-- src/plotman/plot_util.py | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/plotman/manager.py b/src/plotman/manager.py index 97a4e5a8..ba91e8cd 100644 --- a/src/plotman/manager.py +++ b/src/plotman/manager.py @@ -85,9 +85,9 @@ def maybe_start_new_plot(dir_cfg, sched_cfg, plotting_cfg): rankable = [ (d, phases[0]) if phases else (d, (999, 999)) for (d, phases) in eligible ] dir2ph = {d: ph for (d, ph) in dstdirs_to_youngest_phase(jobs).items() - if (d in dir_cfg.dst and plot_util.is_valid_plot_dst(d, sched_cfg))} + if (d in dir_cfg.dst and plot_util.is_valid_plot_dst(d, sched_cfg, jobs))} unused_dirs = [d for d in dir_cfg.dst - if d not in dir2ph.keys() and plot_util.is_valid_plot_dst(d, sched_cfg)] + 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' diff --git a/src/plotman/plot_util.py b/src/plotman/plot_util.py index 0734887f..98aa2cc8 100644 --- a/src/plotman/plot_util.py +++ b/src/plotman/plot_util.py @@ -2,6 +2,8 @@ import os import re +from plotman import job + GB = 1_000_000_000 def df_b(d): @@ -12,12 +14,17 @@ def df_b(d): def get_k32_plotsize(): return 108 * GB -def is_valid_plot_dst(d, sched_cfg): - return (not sched_cfg.stop_when_dst_full) or dir_can_recieve_k32(d) - -def dir_can_recieve_k32(d): - 'Determine if there is enough space for a k32 in a directory' - return enough_space_for_k32(df_b(d)) +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'