1 |
// $Id: goodrun.cc,v 1.1 2010/09/02 01:18:56 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__
|