1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 import sys
21 import os
22 import re
23
24 from glue.segments import segment, segmentlist
25 from glue.ligolw import lsctables
26 from glue.ligolw import table
27 from glue.segmentdb import query_engine
28 from glue.ligolw import types as ligolwtypes
29 from six.moves import filter
30 from six.moves import map
31 from six.moves import range
32
33
34
35
36
37
38
39
40
41
42
43
45 """Returns all files in dirname and all its subdirectories whose
46 names indicate that they contain segments in the range starttime
47 to endtime"""
48
49 ret = []
50
51
52 if os.path.isfile(dirname):
53 if re.match('.*-[0-9]*-[0-9]*\.xml$', dirname):
54 return [dirname]
55 else:
56 return ret
57
58 first_four_start = starttime / 100000
59 first_four_end = endtime / 100000
60
61
62
63 file_list=os.listdir(dirname)
64 file_list.sort()
65 for filename in file_list:
66 a = re.match("\..*\.xml\..*$",filename)
67 if a != None:
68 file_list.remove(a.group(0))
69
70
71 for filename in file_list:
72 if re.match('.*-[0-9]{5}$', filename):
73 dirtime = int(filename[-5:])
74 if dirtime >= first_four_start and dirtime <= first_four_end:
75 ret += get_all_files_in_range(os.path.join(dirname,filename), starttime, endtime, pad=pad)
76 elif re.match('.*-[0-9]{4}$', filename):
77 dirtime = int(filename[-4:])
78 if dirtime >= first_four_start and dirtime <= first_four_end:
79 ret += get_all_files_in_range(os.path.join(dirname,filename), starttime, endtime, pad=pad)
80 elif re.match('.*-[0-9]*-[0-9]*\.xml$', filename):
81 file_time = int(filename.split('-')[-2])
82 if file_time >= (starttime-pad) and file_time <= (endtime+pad):
83 ret.append(os.path.join(dirname,filename))
84 elif os.path.isfile(os.path.join(dirname,filename)):
85
86 return ret
87 else:
88
89
90 ret += get_all_files_in_range(os.path.join(dirname,filename), starttime, endtime, pad=pad)
91
92 return ret
93
94
95
97 """ 1. Determine protocol"""
98 try:
99
100 if database_location.find('://') == -1:
101 msg = "Error: Please specify protocol in your --segment-url argument in the format PROTOCOL://HOST"
102 msg +="\nFor example: --segment-url https://segdb.ligo.caltech.edu"
103 msg += "\nSupported protocols include: http, https, ldbd, ldbdi"
104 msg += "\nRun with --help for usage"
105 raise ValueError(msg)
106
107
108 protocol = database_location[:database_location.find('://')].lower()
109 if protocol not in ("http","https","ldbd","ldbdi"):
110 msg = "Error: protocol %s not supported" % protocol
111 msg += "\nPlease specify correct protocol in your --segment-url argument in the format PROTOCOL://HOST"
112 msg += "\nSupported protocols include: http, https, ldbd, ldbdi"
113 msg += "\nRun with --help for usage"
114 raise ValueError(msg)
115 except ValueError as e:
116 sys.stderr.write('%s\n' % str(e))
117 sys.exit(1)
118
119 """ 2. Determine host and port"""
120 host_and_port = database_location[(len(protocol)+3):]
121 if host_and_port.find(':') < 0:
122
123 host = host_and_port
124 if protocol == 'http':
125 port = 80
126 elif protocol == 'https':
127 port = 443
128 elif protocol == 'ldbd':
129 port = 30015
130 elif protocol == 'ldbdi':
131 port = 30016
132 else:
133 host, portString = host_and_port.split(':')
134 port = int(portString)
135
136 if port == 30020:
137 sys.stderr.write("Error: PORT 30020 no longer provide segment database service\n")
138 sys.exit(1)
139
140 """ 3. Set up connection to LDBD(W)Server """
141 client = None
142 identity = "/DC=org/DC=doegrids/OU=Services/CN=ldbd/"
143
144 if protocol.startswith('http'):
145 from glue import LDBDWClient
146 if protocol == "https":
147 identity += host
148 else:
149 identity = None
150 try:
151 client = LDBDWClient.LDBDClient(host,port,protocol,identity)
152 except Exception as e:
153 sys.stderr.write("Unable to connect to LDBD Server at %s://%s:%d \n" % (protocol,host, port) + str(e))
154 sys.exit(1)
155
156 elif protocol.startswith('ldbd'):
157 from glue import LDBDClient
158 if protocol == "ldbd":
159 identity += host
160 from glue import gsiserverutils
161 else:
162 identity = None
163 try:
164 client = LDBDClient.LDBDClient(host,port,identity)
165 except Exception as e:
166 sys.stderr.write("Unable to connect to LDBD Server at %s://%s:%d\n" % (protocol,host, port) + str(e))
167 try:
168 if gsiserverutils.checkCredentials():
169 sys.stderr.write("Got the following error : \n" + str(e))
170 sys.stderr.write("Run wiht --help for usage\n")
171 except UnboundLocalError:
172 pass
173 sys.exit(1)
174
175 else:
176 raise ValueError( "invalid url for segment database" )
177
178
179 return client
180
181
182
183
184
185
186
187
188
189
190
191
193
194
195
196
197
198 if len(segdefs) == 0:
199 return [ segmentlist([]) ]
200
201
202
203
204
205 def make_clause(table, segdef):
206 ifo, name, version, start_time, end_time, start_pad, end_pad = segdef
207
208 sql = " (segment_definer.ifos = '%s' " % ifo
209 sql += "AND segment_definer.name = '%s' " % name
210 sql += "AND segment_definer.version = %s " % version
211 sql += "AND NOT (%d > %s.end_time OR %s.start_time > %d)) " % (start_time, table, table, end_time)
212
213 return sql
214
215 clauses = [make_clause(table, segdef) for segdef in segdefs]
216
217 sql = 'SELECT segment_definer.ifos, segment_definer.name, segment_definer.version, '
218 sql += ' %s.start_time, %s.end_time ' % (table, table)
219 sql += ' FROM segment_definer, %s ' % table
220 sql += ' WHERE %s.segment_def_id = segment_definer.segment_def_id AND ' % table
221
222 if engine.__class__ == query_engine.LdbdQueryEngine:
223 sql += " %s.segment_def_cdb = segment_definer.creator_db AND " % table
224
225 sql += '( ' + ' OR '.join(clauses) + ' )'
226
227 rows = engine.query(sql)
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242 results = []
243
244 for segdef in segdefs:
245 ifo, name, version, start_time, end_time, start_pad, end_pad = segdef
246
247 search_span = segment(start_time, end_time)
248 search_span_list = segmentlist([search_span])
249
250
251
252 def matches(row):
253 return ( row[0].strip() == ifo and row[1] == name and int(row[2]) == int(version)
254 and search_span.intersects(segment(row[3] + start_pad, row[4] + start_pad)) )
255
256
257 def pad_and_truncate(row_start, row_end):
258 tmp = segmentlist([segment(row_start + start_pad, row_end + end_pad)])
259
260 tmp &= search_span_list
261
262
263
264
265 if len(tmp) == 0:
266 return segment(0,0)
267 else:
268 return tmp[0]
269
270
271
272
273
274 result = segmentlist( [pad_and_truncate(row[3], row[4]) for row in rows if matches(row)] ).coalesce()
275
276
277
278
279
280 results.append(result)
281
282 return results
283
284
286 ifo, name, version, start_time, end_time, start_pad, end_pad = segdef
287
288 if version != '*':
289 return [segdef]
290
291
292 intervals = segmentlist([segment(start_time, end_time)])
293
294
295 sql = "SELECT max(version) FROM segment_definer "
296 sql += "WHERE segment_definer.ifos = '%s' " % ifo
297 sql += "AND segment_definer.name = '%s' " % name
298
299 rows = engine.query(sql)
300 try:
301 version = len(rows[0]) and rows[0][0] or 1
302 except:
303 version = None
304
305 results = []
306
307 while version > 0:
308 for interval in intervals:
309 segs = query_segments(engine, 'segment_summary', [(ifo, name, version, interval[0], interval[1], 0, 0)])
310
311 for seg in segs[0]:
312 results.append( (ifo, name, version, seg[0], seg[1], 0, 0) )
313
314 intervals.coalesce()
315 intervals -= segs[0]
316
317 version -= 1
318
319 return results
320
321
322
323
350
351
352
353
354
355
356
357
359 """Ensures that the DB represented by connection posses a segment table.
360 If not, creates one and prints a warning to stderr"""
361
362 count = connection.cursor().execute("SELECT count(*) FROM sqlite_master WHERE name='segment'").fetchone()[0]
363
364 if count == 0:
365 sys.stderr.write("WARNING: None of the loaded files contain a segment table\n")
366 theClass = lsctables.TableByName['segment']
367 statement = "CREATE TABLE IF NOT EXISTS segment (" + ", ".join(["%s %s" % (key, ligolwtypes.ToSQLiteType[theClass.validcolumns[key]]) for key in theClass.validcolumns]) + ")"
368
369 connection.cursor().execute(statement)
370
371
372
373
374
375
376
377
378
379
399
400
401
420
421
441
442
444
445 for i in range(len(segdefs)):
446 ifo, name, version, start_time, end_time, start_pad, end_pad = segdefs[i]
447
448 seg_def_id = add_to_segment_definer(doc, proc_id, ifo, name, version)
449
450 add_to_segment_summary(doc, proc_id, seg_def_id, segment_summaries[i])
451
452 if segments:
453 add_to_segment(doc, proc_id, seg_def_id, segments[i])
454
455
456
457
458
459
460
461
462
463 -def build_segment_list(engine, gps_start_time, gps_end_time, ifo, segment_name, version = None, start_pad = 0, end_pad = 0):
464 """Optains a list of segments for the given ifo, name and version between the
465 specified times. If a version is given the request is straightforward and is
466 passed on to build_segment_list_one. Otherwise more complex processing is
467 performed (not yet implemented)"""
468 if version is not None:
469 return build_segment_list_one(engine, gps_start_time, gps_end_time, ifo, segment_name, version, start_pad, end_pad)
470
471
472
473 sql = "SELECT max(version) FROM segment_definer "
474 sql += "WHERE segment_definer.ifos = '%s' " % ifo
475 sql += "AND segment_definer.name = '%s' " % segment_name
476
477 rows = engine.query(sql)
478 version = len(rows[0]) and rows[0][0] or 1
479
480 return build_segment_list_one(engine, gps_start_time, gps_end_time, ifo, segment_name, version, start_pad, end_pad)
481
482
483 -def build_segment_list_one(engine, gps_start_time, gps_end_time, ifo, segment_name, version = None, start_pad = 0, end_pad = 0):
484 """Builds a list of segments satisfying the given criteria """
485 seg_result = segmentlist([])
486 sum_result = segmentlist([])
487
488
489
490
491 sql = "SELECT segment_summary.start_time, segment_summary.end_time "
492 sql += "FROM segment_definer, segment_summary "
493 sql += "WHERE segment_summary.segment_def_id = segment_definer.segment_def_id "
494 sql += "AND segment_definer.ifos = '%s' " % ifo
495 if engine.__class__ == query_engine.LdbdQueryEngine:
496 sql += "AND segment_summary.segment_def_cdb = segment_definer.creator_db "
497 sql += "AND segment_definer.name = '%s' " % segment_name
498 sql += "AND segment_definer.version = %s " % version
499 sql += "AND NOT (%s > segment_summary.end_time OR segment_summary.start_time > %s)" % (gps_start_time, gps_end_time)
500
501 rows = engine.query(sql)
502
503 for sum_start_time, sum_end_time in rows:
504 sum_start_time = (sum_start_time < gps_start_time) and gps_start_time or sum_start_time
505 sum_end_time = (sum_end_time > gps_end_time) and gps_end_time or sum_end_time
506
507 sum_result |= segmentlist([segment(sum_start_time, sum_end_time)])
508
509
510 sql = "SELECT segment.start_time + %d, segment.end_time + %d " % (start_pad, end_pad)
511 sql += "FROM segment, segment_definer "
512 sql += "WHERE segment.segment_def_id = segment_definer.segment_def_id "
513
514 if engine.__class__ == query_engine.LdbdQueryEngine:
515 sql += "AND segment.segment_def_cdb = segment_definer.creator_db "
516 sql += "AND segment_definer.ifos = '%s' " % ifo
517 sql += "AND segment_definer.name = '%s' " % segment_name
518 sql += "AND segment_definer.version = %s " % version
519 sql += "AND NOT (%s > segment.end_time OR segment.start_time > %s)" % (gps_start_time, gps_end_time)
520
521 rows = engine.query(sql)
522
523 for seg_start_time, seg_end_time in rows:
524 seg_start_time = (seg_start_time < gps_start_time) and gps_start_time or seg_start_time
525 seg_end_time = (seg_end_time > gps_end_time) and gps_end_time or seg_end_time
526
527 seg_result |= segmentlist([segment(seg_start_time, seg_end_time)])
528
529 engine.close()
530
531 return sum_result, seg_result
532
533
534
535 -def run_query_segments(doc, proc_id, engine, gps_start_time, gps_end_time, included_segments_string, excluded_segments_string = None, write_segments = True, start_pad = 0, end_pad = 0):
536 """Runs a segment query. This was originally part of ligolw_query_segments, but now is also
537 used by ligolw_segments_from_cats.
538
539 The write_segments option is provided so callers can coalesce segments obtained over
540 sever invocations (as segments_from_cats does).
541 """
542
543 if write_segments:
544 all_ifos = {}
545
546 for ifo, segment_name, version in split_segment_ids(included_segments_string.split(',')):
547 all_ifos[ifo] = True
548
549
550 new_seg_def_id = add_to_segment_definer(doc, proc_id, ''.join(list(all_ifos.keys())), 'result', 0)
551 add_to_segment_summary(doc, proc_id, new_seg_def_id, [[gps_start_time, gps_end_time]])
552
553 result = segmentlist([])
554
555 for ifo, segment_name, version in split_segment_ids(included_segments_string.split(',')):
556 sum_segments, seg_segments = build_segment_list(engine, gps_start_time, gps_end_time, ifo, segment_name, version, start_pad, end_pad)
557 seg_def_id = add_to_segment_definer(doc, proc_id, ifo, segment_name, version)
558
559 add_to_segment_summary(doc, proc_id, seg_def_id, sum_segments)
560
561
562 result |= seg_segments
563
564
565 if excluded_segments_string:
566 excluded_segments = segmentlist([])
567
568 for ifo, segment_name, version in split_segment_ids(excluded_segments_string.split(',')):
569 sum_segments, seg_segments = build_segment_list(engine, gps_start_time, gps_end_time, ifo, segment_name, version)
570 excluded_segments |= seg_segments
571
572 result = result - excluded_segments
573
574 result.coalesce()
575
576
577 if write_segments:
578 add_to_segment(doc, proc_id, new_seg_def_id, result)
579
580 return result
581
582
583
585 """Given an array of strings of the form ifo:name and
586 ifo:name:version, returns an array of tuples of the form (ifo,
587 name, version) where version may be None"""
588
589 def split_segment_id(segment_id):
590 temp = segment_id.split(':')
591 if len(temp) == 2:
592 temp.append(None)
593 elif temp[2] == '*':
594 temp[2] = None
595 else:
596 temp[2] = int(temp[2])
597
598 return temp
599
600 return list(map(split_segment_id, segment_ids))
601