Skip to content

Commit 00225a6

Browse files
committed
gufi_query_dsi wrapper script
1 parent ff426f1 commit 00225a6

File tree

2 files changed

+225
-0
lines changed

2 files changed

+225
-0
lines changed

contrib/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ endif()
125125
set(USEFUL
126126
canned_queries.sh
127127
gentrace.py
128+
gufi_query_dsi
128129
hashes.py
129130
longitudinal_snapshot.py
130131
trace_anonymizer.py
@@ -134,6 +135,8 @@ foreach(file ${USEFUL})
134135
configure_file("${file}" "${file}" @ONLY)
135136
endforeach()
136137

138+
install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/gufi_query_dsi" DESTINATION bin COMPONENT Server)
139+
137140
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
138141
add_subdirectory(debug)
139142
endif()

contrib/gufi_query_dsi

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
#!/usr/bin/env @PYTHON_INTERPRETER@
2+
# This file is part of GUFI, which is part of MarFS, which is released
3+
# under the BSD license.
4+
#
5+
#
6+
# Copyright (c) 2017, Los Alamos National Security (LANS), LLC
7+
# All rights reserved.
8+
#
9+
# Redistribution and use in source and binary forms, with or without modification,
10+
# are permitted provided that the following conditions are met:
11+
#
12+
# 1. Redistributions of source code must retain the above copyright notice, this
13+
# list of conditions and the following disclaimer.
14+
#
15+
# 2. Redistributions in binary form must reproduce the above copyright notice,
16+
# this list of conditions and the following disclaimer in the documentation and/or
17+
# other materials provided with the distribution.
18+
#
19+
# 3. Neither the name of the copyright holder nor the names of its contributors
20+
# may be used to endorse or promote products derived from this software without
21+
# specific prior written permission.
22+
#
23+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24+
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26+
# IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27+
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28+
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29+
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30+
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
31+
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32+
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33+
#
34+
#
35+
# From Los Alamos National Security, LLC:
36+
# LA-CC-15-039
37+
#
38+
# Copyright (c) 2017, Los Alamos National Security, LLC All rights reserved.
39+
# Copyright 2017. Los Alamos National Security, LLC. This software was produced
40+
# under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National
41+
# Laboratory (LANL), which is operated by Los Alamos National Security, LLC for
42+
# the U.S. Department of Energy. The U.S. Government has rights to use,
43+
# reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR LOS
44+
# ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
45+
# ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is
46+
# modified to produce derivative works, such modified software should be
47+
# clearly marked, so as not to confuse it with the version available from
48+
# LANL.
49+
#
50+
# THIS SOFTWARE IS PROVIDED BY LOS ALAMOS NATIONAL SECURITY, LLC AND CONTRIBUTORS
51+
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
52+
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53+
# ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL SECURITY, LLC OR
54+
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
55+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
56+
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
59+
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
60+
# OF SUCH DAMAGE.
61+
62+
63+
64+
import argparse
65+
import os
66+
import subprocess
67+
import sys
68+
69+
import gufi_common
70+
71+
class Q_Args:
72+
def __init__(self, val):
73+
parts = val.split()
74+
if len(parts) != 5:
75+
raise ValueError("Input string should be 5 space separated strings")
76+
self.template_path, self.template_attach_name, self.basename, self.table, self.view = parts
77+
78+
def forward(self):
79+
# the template and the matching external database files must have the same table name and schema to UNION on
80+
return ['-Q', self.basename, self.table, '{0}.{1}'.format(self.template_attach_name, self.table), self.view]
81+
82+
def __repr__(self):
83+
return '({0})'.format(' '.join(self.forward()[1:]))
84+
85+
EXAMPLE = '''
86+
Example Usage:
87+
gufi_query_dsi \\
88+
-Q "templatel.db template1 db1.db table ext1" \\
89+
-Q "template2.db template2 db2.db table ext2" \\
90+
-E "SELECT col1, col2 FROM evrpentries LEFT JOIN ext1 ON (evrpentries.name == ext1.name) AND (evrpentries.type == ext1.type) LEFT JOIN ext2 ON (evrpentries.name == ext2.name) AND (evrpentries.type == ext2.type);" \\
91+
index
92+
93+
The first argument to -Q should be the full path to a globally
94+
accessible SQLite3 file that provides a schema templates for
95+
matching on in queries (e.g. name, type, inode). The table used
96+
should be empty but does not have to be.
97+
98+
The second argument is the name of the template db file's attach
99+
name.
100+
101+
The third argument to -Q should be the basename of the SQLite3
102+
file in the current directory to look for. The comparison done is
103+
an exact string match.
104+
105+
The fourth argument is the table name that must be avaialble in
106+
both the template db as well as the current directory's external
107+
database and must have the same schema.
108+
109+
The fifth argument is the name that should be (left) joined with
110+
'e' variants of tables and views.
111+
112+
Multiple '-Q's may be used.
113+
'''
114+
115+
def parse_args(argv):
116+
parser = argparse.ArgumentParser(
117+
'gufi_query_dsi', description='GUFI Query DSI Wrapper',
118+
formatter_class=argparse.RawDescriptionHelpFormatter,
119+
epilog=EXAMPLE)
120+
121+
parser.add_argument('--version', '-v',
122+
action='version',
123+
version=os.path.basename(os.path.realpath(__file__)) + ' @GUFI_VERSION@')
124+
parser.add_argument('--verbose', '-V', action='store_true',
125+
help='Show the gufi_query being executed')
126+
127+
# gufi_query flags
128+
parser.add_argument('-d', type=gufi_common.get_char, dest='delim',
129+
metavar='char', default='|',
130+
help='output column separator')
131+
parser.add_argument('-x', action='store_true',
132+
help='pull in xattrs when querying')
133+
parser.add_argument('-I', type=str,
134+
metavar='SQL',
135+
help='gufi_query -I')
136+
parser.add_argument('-T', type=str,
137+
metavar='SQL',
138+
help='gufi_query -T')
139+
parser.add_argument('-S', type=str,
140+
metavar='SQL',
141+
help='gufi_query -S')
142+
parser.add_argument('-E', type=str,
143+
metavar='SQL',
144+
help='gufi_query -E')
145+
146+
# positional arg
147+
parser.add_argument('index', type=str,
148+
help='starting directory of GUFI tree')
149+
150+
# -Q
151+
parser.add_argument('-Q', type=Q_Args,
152+
metavar='template-path template-attach-name basename table view',
153+
default=[], action='append',
154+
help='attach external databases in current directory for querying')
155+
156+
# extra args
157+
parser.add_argument('--gufi_query', type=str,
158+
metavar='path', default="gufi_query",
159+
help='path of gufi_query executable')
160+
161+
parser.add_argument('--threads', '-n', type=int,
162+
metavar='n', default=1,
163+
help='number of threads to run with')
164+
165+
parser.add_argument('--dry-run', action='store_true',
166+
help='set up command to run but do not run')
167+
168+
return parser.parse_args(argv[1:])
169+
170+
def run(argv):
171+
args = parse_args(argv)
172+
173+
I = []
174+
Q = []
175+
for q in args.Q:
176+
# set up external db templates
177+
I += ['ATTACH \'file:{0}?mode=ro\' AS {1}'.format(q.template_path, q.template_attach_name)]
178+
Q += q.forward()
179+
180+
# then run original -I
181+
if args.I:
182+
I += [args.I]
183+
184+
cmd = [
185+
args.gufi_query,
186+
'-n', str(args.threads),
187+
'-d', args.delim,
188+
]
189+
190+
if args.x is True:
191+
cmd += ['-x']
192+
193+
cmd += Q
194+
195+
if len(I) > 0:
196+
cmd += ['-I', '; '.join(I) + ';']
197+
198+
if args.T:
199+
cmd += ['-T', args.T]
200+
201+
if args.S:
202+
cmd += ['-S', args.S]
203+
204+
if args.E:
205+
cmd += ['-E', args.E]
206+
207+
cmd += [
208+
args.index,
209+
]
210+
211+
if args.verbose:
212+
gufi_common.print_query(cmd)
213+
214+
if args.dry_run:
215+
return 0
216+
217+
query = subprocess.Popen(cmd) # pylint: disable=consider-using-with
218+
query.communicate() # block until query finishes
219+
return query.returncode
220+
221+
if __name__ == '__main__':
222+
sys.exit(run(sys.argv))

0 commit comments

Comments
 (0)