gstlal 1.13.0
Loading...
Searching...
No Matches
gstlal_dagfile_rerun_relatives
1#!/usr/bin/env python3
2#
3# Copyright (C) 2019 Kipp Cannon
4#
5# This program is free software; you can redistribute it and/or modify it
6# under the terms of the GNU General Public License as published by the
7# Free Software Foundation; either version 3 of the License, or (at your
8# option) any later version.
9#
10# This program is distributed in the hope that it will be useful, but
11# WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13# Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19
20#
21# =============================================================================
22#
23# Preamble
24#
25# =============================================================================
26#
27
28
29from __future__ import print_function
30from optparse import OptionParser
31import sys
32
33
34from gstlal import __version__, __date__
35from gstlal import dagfile
36
37__author__ = "Kipp Cannon <kipp.cannon@ligo.org>"
38
39
40#
41# =============================================================================
42#
43# Command Line
44#
45# =============================================================================
46#
47
48
49def parse_command_line():
50 parser = OptionParser(
51 version = "Name: %%prog\n%s" % __version__,
52 usage = "%prog [options] node1 [node2 ...] <old_dag >new_dag",
53 description = "%prog constructs a DAG to re-run relatives of DAG nodes named on the command line. The scenario this is intended to address is the situation in which one or more of the parents of a job malfunction but exit with a success code (0). This can occur, for example, during a filesystem malfunction, where the job believes it wrote its output files to disk successfully, it exits with a success code, but the files never show up on the server. Because the job exited with a success code, dagman marks it done, and submitting the rescue DAG will not retry the job. This tool can be used to automate the process of rerunning one or more selected jobs, as well as their ancestor and/or descendent graphs. The old DAG is read from stdin. The new one is written to stdout."
54 )
55 parser.add_option("--themselves", "-t", action = "store_true", help = "Rerun the named nodes.")
56 parser.add_option("--ancestors-of", "-a", action = "store_true", help = "Rerun the ancestors of the named nodes.")
57 parser.add_option("--descendants-of", "-d", action = "store_true", help = "Rerun the descendents of the named nodes.")
58 parser.add_option("--verbose", "-v", action = "store_true", help = "Be verbose.")
59 options, nodenames = parser.parse_args()
60
61 #
62 # check that there's something to do
63 #
64
65 if not (options.themselves or options.ancestors_of or options.descendants_of):
66 raise ValueError("nothing to do!")
67 if options.ancestors_of and options.descendants_of and not options.themselves:
68 raise ValueError("cowardly refusing to rerun both the parents and children of the named nodes without also rerunning the named nodes themselves. must include --themselves when both --ancestors-of and --descendants-of have been selected.")
69
70 #
71 # uniqueify the node names
72 #
73
74 nodenames = set(nodenames)
75
76 #
77 # done
78 #
79
80 return options, nodenames
81
82
83#
84# =============================================================================
85#
86# Process DAG
87#
88# =============================================================================
89#
90
91
92#
93# command line
94#
95
96
97options, nodenames = parse_command_line()
98
99
100#
101# read original dag from stdin
102#
103
104
105if options.verbose:
106 def progress(f, n, done):
107 print("reading original dag from stdin ... %d lines\r" % n, end=' ', file=sys.stderr)
108 if done:
109 print(file=sys.stderr)
110else:
111 progress = None
112dag = dagfile.DAG.parse(sys.stdin, progress = progress)
113if not nodenames.issubset(set(dag.nodes)):
114 raise ValueError("node(s) %s not found in dag" % ", ".join(sorted(nodenames - set(dag.nodes))))
115
116
117#
118# extract graph
119#
120
121
122if options.verbose:
123 print("extracting graph ...", file=sys.stderr)
124names_to_rerun = set()
125if options.ancestors_of:
126 names_to_rerun |= dag.get_all_parent_names(nodenames)
127if options.descendants_of:
128 names_to_rerun |= dag.get_all_child_names(nodenames)
129if options.themselves:
130 names_to_rerun |= nodenames
131assert names_to_rerun # must not be empty
132dag = dagfile.DAG.select_nodes_by_name(dag, names_to_rerun)
133
134
135#
136# set nodes to not done
137#
138
139
140if options.verbose:
141 print("setting job states to not-done ...", file=sys.stderr)
142for nodename, node in dag.nodes.items():
143 node.done = False
144
145
146#
147# write new dag to stdout
148#
149
150
151if options.verbose:
152 def progress(f, n, done):
153 print("writing new dag to stdout ... %d lines\r" % n, end=' ', file=sys.stderr)
154 if done:
155 print(file=sys.stderr)
156else:
157 progress = None
158dag.write(sys.stdout, progress = progress)