1 |
fgolf |
1.1 |
// $Id: goodrun.cc,v 1.1 2010/08/29 01:07:18 fgolf Exp $
|
2 |
|
|
|
3 |
|
|
// CINT is allowed to see this, but nothing else:
|
4 |
|
|
bool goodrun (unsigned int run, unsigned int lumi_block);
|
5 |
|
|
bool goodrun_json (unsigned int run, unsigned int lumi_block);
|
6 |
|
|
void set_goodrun_file (const char* filename);
|
7 |
|
|
void set_goodrun_file_json (const char* filename);
|
8 |
|
|
|
9 |
|
|
#ifndef __CINT__
|
10 |
|
|
|
11 |
|
|
#include <assert.h>
|
12 |
|
|
#include <stdio.h>
|
13 |
|
|
#include <string.h>
|
14 |
|
|
#include <unistd.h>
|
15 |
|
|
#include <sys/types.h>
|
16 |
|
|
#include <sys/wait.h>
|
17 |
|
|
#include <sys/stat.h>
|
18 |
|
|
#include <set>
|
19 |
|
|
#include <string>
|
20 |
|
|
|
21 |
|
|
enum file_type { TEXT, JSON };
|
22 |
|
|
|
23 |
|
|
struct run_and_lumi {
|
24 |
|
|
unsigned int run;
|
25 |
|
|
long long int lumi_min;
|
26 |
|
|
long long int lumi_max;
|
27 |
|
|
};
|
28 |
|
|
|
29 |
|
|
bool operator < (const struct run_and_lumi &r1, const struct run_and_lumi &r2)
|
30 |
|
|
{
|
31 |
|
|
return r1.run < r2.run;
|
32 |
|
|
}
|
33 |
|
|
|
34 |
|
|
typedef std::multiset<struct run_and_lumi> set_t;
|
35 |
|
|
static set_t good_runs_;
|
36 |
|
|
static bool good_runs_loaded_ = false;
|
37 |
|
|
|
38 |
|
|
static const char json_py[] =
|
39 |
|
|
"#! /usr/bin/env python \n"
|
40 |
|
|
" \n"
|
41 |
|
|
"# usage to print out good run selection for goodrun.cc: \n"
|
42 |
|
|
"# convertGoodRunsList_JSON.py <json file> \n"
|
43 |
|
|
" \n"
|
44 |
|
|
"import sys,json \n"
|
45 |
|
|
" \n"
|
46 |
|
|
"runs = json.load(open(sys.argv[1],\"r\")) \n"
|
47 |
|
|
" \n"
|
48 |
|
|
"for run in runs.keys(): \n"
|
49 |
|
|
" for lumiBlock in runs[run] : \n"
|
50 |
|
|
" if len(lumiBlock) != 2 : \n"
|
51 |
|
|
" print 'ERROR reading lumi block: run:',run,'lumiBlock:',lumiBlock \n"
|
52 |
|
|
" else: \n"
|
53 |
|
|
" # print 'run ' + str(run) + ', min lumi ' + str(lumiBlock[0]) + ', max lumi ' + str(lumiBlock[1])\n"
|
54 |
|
|
" print run,lumiBlock[0],lumiBlock[1] \n"
|
55 |
|
|
" \n";
|
56 |
|
|
//"print '' \n";
|
57 |
|
|
|
58 |
|
|
static int load_runs (const char *fname, enum file_type type)
|
59 |
|
|
{
|
60 |
|
|
good_runs_.clear();
|
61 |
|
|
FILE *file = 0;
|
62 |
|
|
switch (type) {
|
63 |
|
|
case TEXT:
|
64 |
|
|
file = fopen(fname, "r");
|
65 |
|
|
if (file == 0) {
|
66 |
|
|
perror("opening good run list");
|
67 |
|
|
return 0;
|
68 |
|
|
}
|
69 |
|
|
break;
|
70 |
|
|
case JSON:
|
71 |
|
|
{
|
72 |
|
|
// first make a temp file with the python parsing code
|
73 |
|
|
FILE *pyfile = fopen("tmp.py", "w");
|
74 |
|
|
if (pyfile == 0) {
|
75 |
|
|
perror("opening tmp file");
|
76 |
|
|
return 0;
|
77 |
|
|
}
|
78 |
|
|
fprintf(pyfile, "%s", json_py);
|
79 |
|
|
fclose(pyfile);
|
80 |
|
|
chmod("tmp.py", S_IRUSR | S_IWUSR | S_IXUSR);
|
81 |
|
|
// now execute a command to convert the JSON file to text
|
82 |
|
|
pid_t child = fork();
|
83 |
|
|
if (child == -1) {
|
84 |
|
|
perror("forking process to convert JSON good run list");
|
85 |
|
|
return 0;
|
86 |
|
|
}
|
87 |
|
|
if (child == 0) {
|
88 |
|
|
FILE *f = freopen((std::string(fname) + ".tmp").c_str(), "w", stdout);
|
89 |
|
|
if (f == 0) {
|
90 |
|
|
perror("opening good run list");
|
91 |
|
|
return 127;
|
92 |
|
|
}
|
93 |
|
|
execlp("./tmp.py", "", fname, (char *)0);
|
94 |
|
|
perror("executing JSON conversion script");
|
95 |
|
|
exit(127);
|
96 |
|
|
}
|
97 |
|
|
if (child != 0) {
|
98 |
|
|
int status;
|
99 |
|
|
waitpid(child, &status, 0);
|
100 |
|
|
if (status != 0) {
|
101 |
|
|
printf("conversion exited abnormally, consult previous errors\n");
|
102 |
|
|
return 0;
|
103 |
|
|
}
|
104 |
|
|
}
|
105 |
|
|
printf("note: converted JSON file is in %s.tmp, "
|
106 |
|
|
"please consult in case of parsing errors\n", fname);
|
107 |
|
|
file = fopen((std::string(fname) + ".tmp").c_str(), "r");
|
108 |
|
|
if (file == 0) {
|
109 |
|
|
perror("opening good run list");
|
110 |
|
|
return 0;
|
111 |
|
|
}
|
112 |
|
|
unlink("tmp.py");
|
113 |
|
|
break;
|
114 |
|
|
}
|
115 |
|
|
default:
|
116 |
|
|
break;
|
117 |
|
|
}
|
118 |
|
|
int s;
|
119 |
|
|
int line = 0;
|
120 |
|
|
do {
|
121 |
|
|
int n;
|
122 |
|
|
char buf[1024] = "";
|
123 |
|
|
// read a line from the file, not including the newline (if
|
124 |
|
|
// there is a newline)
|
125 |
|
|
s = fscanf(file, "%1024[^\n]%n", buf, &n);
|
126 |
|
|
assert(n < 1023);
|
127 |
|
|
if (s != 1) {
|
128 |
|
|
if (s != EOF) {
|
129 |
|
|
perror("reading good run list");
|
130 |
|
|
return 0;
|
131 |
|
|
} else {
|
132 |
|
|
if (ferror(file)) {
|
133 |
|
|
perror("reading good run list");
|
134 |
|
|
return 0;
|
135 |
|
|
}
|
136 |
|
|
}
|
137 |
|
|
} else if (strlen(buf) != 0 && buf[0] == '#') {
|
138 |
|
|
line++;
|
139 |
|
|
// printf("Read a comment line (line %d) from the good run list: %s\n", line, buf);
|
140 |
|
|
} else {
|
141 |
|
|
line++;
|
142 |
|
|
// printf("Read a line from the good run list: %s\n", buf);
|
143 |
|
|
unsigned int run;
|
144 |
|
|
char *pbuf = buf;
|
145 |
|
|
int s = sscanf(pbuf, " %u%n", &run, &n);
|
146 |
|
|
if (s != 1) {
|
147 |
|
|
fprintf(stderr, "Expected a run number (unsigned int)"
|
148 |
|
|
" in the first position of line %d: %s\n", line, buf);
|
149 |
|
|
assert(s == 1);
|
150 |
|
|
}
|
151 |
|
|
pbuf += n;
|
152 |
|
|
long long int lumi_min = -1;
|
153 |
|
|
long long int lumi_max = -1;
|
154 |
|
|
s = sscanf(pbuf, " %lld%n", &lumi_min, &n);
|
155 |
|
|
// if there is no lumi_min specified, that means the
|
156 |
|
|
// entire run is good
|
157 |
|
|
if (s == 1) {
|
158 |
|
|
pbuf += n;
|
159 |
|
|
s = sscanf(pbuf, " %lld%n", &lumi_max, &n);
|
160 |
|
|
if (s != 1) {
|
161 |
|
|
fprintf(stderr, "Expected a max lumi section in a lumi section range"
|
162 |
|
|
" (int) in the third position of line %d: %s\n", line, buf);
|
163 |
|
|
assert(s == 1);
|
164 |
|
|
}
|
165 |
|
|
pbuf += n;
|
166 |
|
|
}
|
167 |
|
|
char trail[1024] = "";
|
168 |
|
|
s = sscanf(pbuf, " %s", trail);
|
169 |
|
|
if (strlen(trail) != 0) {
|
170 |
|
|
fprintf(stderr, "Unexpected trailing junk (%s) on line %d: %s\n", trail, line, buf);
|
171 |
|
|
assert(s == 0);
|
172 |
|
|
}
|
173 |
|
|
// printf("Read line: run %u, min lumi %lld, max lumi %lld\n", run, lumi_min, lumi_max);
|
174 |
|
|
struct run_and_lumi new_entry = { run, lumi_min, lumi_max };
|
175 |
|
|
good_runs_.insert(new_entry);
|
176 |
|
|
}
|
177 |
|
|
// advance past the newline
|
178 |
|
|
char newlines[1024] = "";
|
179 |
|
|
s = fscanf(file, "%[ \f\n\r\t\v]", newlines);
|
180 |
|
|
if (s != -1 && strlen(newlines) != 1) {
|
181 |
|
|
fprintf(stderr, "Warning: unexpected white space following line %d\n", line);
|
182 |
|
|
// but that's just a warning
|
183 |
|
|
}
|
184 |
|
|
} while (s == 1);
|
185 |
|
|
fclose(file);
|
186 |
|
|
if (type == JSON)
|
187 |
|
|
unlink((std::string(fname) + ".tmp").c_str());
|
188 |
|
|
return line;
|
189 |
|
|
}
|
190 |
|
|
|
191 |
|
|
bool goodrun (unsigned int run, unsigned int lumi_block)
|
192 |
|
|
{
|
193 |
|
|
if (not good_runs_loaded_) {
|
194 |
|
|
int ret = load_runs("goodruns.txt", TEXT);
|
195 |
|
|
assert(ret != 0);
|
196 |
|
|
good_runs_loaded_ = true;
|
197 |
|
|
}
|
198 |
|
|
// we assume that an empty list means accept anything
|
199 |
|
|
if (good_runs_.size() == 0)
|
200 |
|
|
return true;
|
201 |
|
|
// find all blocks with this run number
|
202 |
|
|
struct run_and_lumi r_a_l = { run, 0, 0 };
|
203 |
|
|
std::pair<set_t::const_iterator, set_t::const_iterator> good_blocks =
|
204 |
|
|
good_runs_.equal_range(r_a_l);
|
205 |
|
|
for (set_t::const_iterator i = good_blocks.first;
|
206 |
|
|
i != good_blocks.second; ++i) {
|
207 |
|
|
// printf("considering run %u, min %lld, max %lld\n",
|
208 |
|
|
// i->run, i->lumi_min, i->lumi_max);
|
209 |
|
|
if (i->lumi_min <= lumi_block) {
|
210 |
|
|
if (i->lumi_max == -1 || i->lumi_max >= lumi_block)
|
211 |
|
|
return true;
|
212 |
|
|
}
|
213 |
|
|
}
|
214 |
|
|
return false;
|
215 |
|
|
}
|
216 |
|
|
|
217 |
|
|
bool goodrun_json (unsigned int run, unsigned int lumi_block)
|
218 |
|
|
{
|
219 |
|
|
if (not good_runs_loaded_) {
|
220 |
|
|
int ret = load_runs("goodruns.json", JSON);
|
221 |
|
|
assert(ret != 0);
|
222 |
|
|
good_runs_loaded_ = true;
|
223 |
|
|
}
|
224 |
|
|
// once the JSON good-run list is loaded, there's no difference
|
225 |
|
|
// between TEXT and JSON
|
226 |
|
|
return goodrun(run, lumi_block);
|
227 |
|
|
}
|
228 |
|
|
|
229 |
|
|
void set_goodrun_file (const char* filename)
|
230 |
|
|
{
|
231 |
|
|
int ret = load_runs(filename, TEXT);
|
232 |
|
|
assert(ret != 0);
|
233 |
|
|
good_runs_loaded_ = true;
|
234 |
|
|
}
|
235 |
|
|
|
236 |
|
|
void set_goodrun_file_json (const char* filename)
|
237 |
|
|
{
|
238 |
|
|
int ret = load_runs(filename, JSON);
|
239 |
|
|
assert(ret != 0);
|
240 |
|
|
good_runs_loaded_ = true;
|
241 |
|
|
}
|
242 |
|
|
|
243 |
|
|
#endif // __CUNT__
|