#!/usr/bin/python2.6 -tt
# -*- coding: utf-8 -*-

#    Copyright (C) 2010  Matthias Urlichs <matthias@urlichs.de>
#
#    This program may be distributed under the terms of the GNU GPLv3.
#
## This file is formatted with tabs.
## Do NOT introduce leading spaces.

from __future__ import absolute_import

BLOCKSIZE = 4096


from twisted.internet import reactor
from twisted.python import log
from twisted.spread import pb

from sqlmix.twisted import DbPool
import sqlfuse as sf
from sqlfuse import tracers,tracer_info,trace, ManholeEnv
from sqlfuse.main import SqlFuse
from sqlfuse.options import options
from twistfuse.handler import Handler
import sys
import twist

from signal import signal,SIGUSR1,SIGUSR2,SIGTERM,SIGINT

tracer_info['fuse']="Log low-level FUSE request/responses"
tracer_info['profile']="Log profiling start/stop (enabled)"
tracers.add('profile')
tracer_info['db']="Log database calls"

if __debug__:
	tracer_info['osthread']="Low-level thread tracing"
	import threading

def main():
	usage = """
sqlmount /path -o option...: mount a file hierarchy from a SQL database.
""" 

	opt = options("opt") # (,usage=usage)
	global fs
	fs = SqlFuse(test=opt.test)
	sf.NAME(opt.node)

	if opt.debug:
		if opt.debug == 'help':
			print >>sys.stderr,"""\
Debug flags:
"""
			w=0
			for s in tracer_info:
				if w < len(s): w = len(s)
			for s,t in sorted(tracer_info.items()):
				print(s + " "*(2+w-len(s)) + t)
			print >>sys.stderr,"""\

Turn off flags with a prepended '-'. Separate multiple flags with slashes ('/').
"""
			# TODO: use debug=foo+bar-baz-quux instead.
			sys.exit(1)
		for s in opt.debug.split("/"):
			if (s[1:] if s.startswith('-') else s) not in tracer_info:
				print >>sys.stderr,"%s: '%s': unknown debug option.\nTo print a list: debug=help." % (sys.argv[0],s)
				sys.exit(1)
			if s.startswith("-"):
				tracers.discard(s[1:])
			else:
				tracers.add(s)
		if "*" in tracers or "db" in tracers:
			from sqlmix import twisted as dbt
			dbt._DEBUG = opt.node or True
		if "osthread" in tracers:
			threading._VERBOSE = True

	def startup():
		signal(SIGINT,fs.do_umount)
		signal(SIGTERM,fs.do_umount)
		db = DbPool(dbtye=opt.dbtype,host=opt.host,port=opt.port,database=opt.database,username=opt.username,password=opt.password)
		d = fs.init_db(db, opt.node)
		def did_init(r):
			global h
			args = {}
			if '*' not in tracers and 'fuse' not in tracers:
				args['logfile'] = None
			else:
				args['logprefix'] = opt.node
			h = Handler(**args)
			return h.mount(fs,opt.mountpoint)
		def did_init2(r):
			return fs.init(opt)
		d.addCallback(did_init)
		d.addCallback(did_init2)
		def did_error(e):
			trace('error',"%s",e)
			global h
			if h is not None:
				h.umount()
			reactor.stop()
		d.addErrback(did_error)
	reactor.callWhenRunning(startup)

	if opt.profile:
		trace('',"Enabled profiling. Start/stop with SIGUSR1/2.")
		try:
			import cProfile as profile
		except Exception:
			import profile
		p = profile.Profile()
		reactor.callWhenRunning(p.disable)
		def pen():
			trace('profile',"Starting profiling.")
			p.enable()
		def pdis():
			trace('profile',"Stopped profiling, dumping to '%s'",opt.profile)
			p.dump_stats(opt.profile)
			p.disable()
			p.clear()
		signal(SIGUSR1,pen)
		signal(SIGUSR2,pdis)
		ManholeEnv['prof_start'] = pen
		ManholeEnv['prof_stop'] = pdis
		ManholeEnv['profiler'] = p

		p.runcall(reactor.run)
	else:
		reactor.run()

	global h
	if h is not None:
		h.umount(True)
	#fs.destroy()

if __name__ == '__main__':
	main()

