forked from tumtumtum/gfid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgfid-mismatch
executable file
·126 lines (100 loc) · 3.8 KB
/
gfid-mismatch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#!/usr/bin/env python
# Take the outputs of `gfid-list' from many bricks and produce a list of
# inodes with mismatched gfid's.
#
# Sample invocation
# # gfid-mismatch -v gfid.1 gfid.2 gfid.3
#
# Output format:
#
# <Filename>: First set | Second set | ...
# bin/bash: gfid.2 gfid.3 | gfid.1
#
# For each mismatched file, the set of given filenames is divided into disjoint
# sets; the gfid is the same within each of these sets.
import sys
try:
from optparse import OptionParser
except ImportError:
print "Error importing 'optparse'"
def open_files(names):
"""Open all the files and return the objects in a list"""
files = []
for name in names:
try:
files.append(file(name, "r"))
except IOError, (errno, msg):
print "Cannot open file %s: %s" % (name, msg)
sys.exit(2)
return files
def all_lines_empty(lines):
for l in lines:
if l != '':
return False
return True
def is_gfid(text):
"""Return true if the text is a gfid. The validation is not strict. Anything other
than one of the *_missing strings is assumed to be a gfid"""
if not ((text == "inode_missing") or (text == "xattr_missing_key") or
(text == "xattr_missing_value")):
return True
def detect_mismatches(files, options):
line_number = 0
try:
while True:
lines = []
lines = [f.readline()[:-1] for f in files]
line_number += 1
if lines[0] == '':
if all_lines_empty(lines):
sys.exit(0)
else:
print "Error on line %d: One of the files ends prematurely." % line_number
sys.exit(3)
gfid = {}
pieces = lines[0].split(" ", 1)
name = pieces[1]
if is_gfid(pieces[0]):
gfid[pieces[0]] = [files[0].name]
i = 0
for l in lines:
if l == '':
if all_lines_empty(lines):
sys.exit(0)
else:
print "Error on line %d: One of the files ends prematurely." % line_number
sys.exit(3)
pieces = l.split(" ", 1)
if pieces[1] != name:
print "Error on line %d: file name is not same in all files." % line_number
for (l, f) in zip(lines, files):
print "\t%s: %s" % (f.name, l.split(" ", 1)[1])
sys.exit(3)
if is_gfid(pieces[0]):
if gfid.has_key(pieces[0]) and files[i].name not in gfid[pieces[0]]:
gfid[pieces[0]].append(files[i].name)
else:
gfid[pieces[0]] = [files[i].name]
i += 1
if len(gfid) > 1:
# We have found more than one unique gfid
if options.verbose:
print "%s: %s" % (name, " | ".join([" ".join(f) for f in gfid.values()]))
else:
print name
except IndexError:
print "Error on line %d: One of the files is not in the proper format." % line_number
sys.exit(3)
def main():
usage = "usage: %prog [options] <gfid-file-1> <gfid-file-2> ..."
parser = OptionParser(usage=usage)
parser.add_option("-v", "--verbose", action="store_true", dest="verbose",
default=False,
help="Show details of the mismatch by dividing the files into disjoint sets with the gfid being the same within each set")
(options, args) = parser.parse_args()
if (len(args) < 1):
parser.error("No filenames specified")
files = open_files(args)
detect_mismatches(files, options)
if __name__ == "__main__":
main()