#!/bin/python2

import sys
import mds_dump

info =\
"""Find unrecoverable chunks given the dump of MDS state and the
list of CSs considered lost. Usage:
  {0} <dump file path> [lost_cs_id ...]
To read from standard input use -- as <dump file path>
Typically it is executed on the node with running MDS by the following steps:
 1. Ensure you are the root.
 2. Find out the MDS service PID and command line arguments: ps aux | grep mdsd
 3. Stop MDS service: kill -STOP <MDS PID>
 4. Make a copy of the MDS journal directory (argument after -r command line switch):
      cp -R <MDS journal path> .
 5. Release stopped MDS service: kill -CONT <MDS PID>
 6. Execute the following:
      mdsd -X -d 2 -r $(pwd)/<MDS journal dir> 2>&1 | {0} -- [lost_cs_id ...] > <output file>
"""

bad_css = set()

def check_file(file):
	for chunk in file.chunks:
		uptd, good = 0, 0
		for node in chunk.nodes:
			if node.state == 4:
				uptd += 1
				if node.cs not in bad_css:
					good += 1
		if uptd > 0:
			if good < file.stripe_depth:
				print '[%#x] %s' % (chunk.offset, file.path)

def parse_dump(f):
	parser = mds_dump.Parser()
	parser.set_file_cb(check_file)
	return parser.parse(f)

if __name__ == '__main__':
	if len(sys.argv) < 2:
		print info.format(sys.argv[0])
		sys.exit(1)
	for cs in sys.argv[2:]:
		bad_css.add(int(cs))

	print >> sys.stderr, "Finding bad chunks given %d bad CSs ..." % len(bad_css)
	if sys.argv[1] == '--':
		res = parse_dump(sys.stdin)
	else:
		with open(sys.argv[1]) as f:
			res = parse_dump(f)
	if not res:
		print >> sys.stderr, "Dump parsing failed"
		sys.exit(-1)

	print >> sys.stderr, "done"
	sys.exit(0)
