def __init__(self, xmlname, logname, sqldir):
     self.logname = logname
     self.dispatch_config = DispatchConfig(xmlname)
     self.dispatch_log = DispatchLog(logname)
     self.search_sql = SearchSql(sqldir)
     
     self.HOST_ERROR    = 2003
     self.PASS_ERROR    = 1045
     self.DB_ERROR      = 1049
     self.CHARSET_ERROR = 2019
class DispatchTable(object):
    """
    Description:
                    初始化类
    Argument:
        xmlname: 派发目的地个个数据库的信息xml配置文件
        logname: 派发过程中日志记录的配置文件名称
        sqldir:  搜寻的sql的目录
    Return:
                    空
    """
    def __init__(self, xmlname, logname, sqldir):
        self.logname = logname
        self.dispatch_config = DispatchConfig(xmlname)
        self.dispatch_log = DispatchLog(logname)
        self.search_sql = SearchSql(sqldir)
        
        self.HOST_ERROR    = 2003
        self.PASS_ERROR    = 1045
        self.DB_ERROR      = 1049
        self.CHARSET_ERROR = 2019
    
    """
    Description:
                    解释信息
    Argument:
                    空
    Return:
                    空
    """    
    def __repr__(self):
        str = "dispatch_config:\n"
        str += self.dispatch_config.__str__()
        str += "dispatch_log:\n"
        str += self.dispatch_log.__str__()
        str += "search_sql:\n"
        str += self.search_sql.__str__()
        return str;
    
    __str__ = __repr__
    
    """
    Description:
                        加载数据:加载数据库信息、加载之前生成的派发生成日志、寻找当前目录下的sql文件
    Argument:
                        空
    Return:
                        空
    """
    def load(self):
        self.dispatch_config.read_connconfig()
        self.dispatch_log.read_log()
        self.search_sql.search_sql()
    
    """
    Description:
                        判断当前的sqlfile是否需要派发,比较上次派发日志的派发时间和当前文件最后修改时间的大小,如果大了,就表示不需要派发,小了,需要派发
    Argument:
        host:    主机IP
        dbname:  数据库名称
        sqlfile: 文件名称
    Return:
        True-need to dispatch, Fasle-need't to dispatch
    """     
    def file_is_dispatch(self, host, dbname, sqlfile):
        try:
            if (self.dispatch_log[host][dbname][sqlfile.filename].timestamp < sqlfile.last_modify_time):
                return True
            else:
                return False
        except KeyError:
                return True
    
    def sql_is_dispatch(self, host, dbname, filename, sql):
        try:
            if sql in self.dispatch_log[host][dbname][filename].keys():
                return False
            else:
                return True
        except KeyError:
                return True
    """
    Description:
                        派发表到各个数据库
    Argument:
                        空
    Return:
        
    """  
    
    def dispatch(self):
        #新建DispatchLog用来记录当前产生的日志
        dispatchlog = DispatchLog(self.logname)
        
        for (host, connconfig) in self.dispatch_config.items():                                 #遍历HOST
            hostlogconfig = HostLogConfig(host, "SUCCESS", "")                                  #初始化HOST日志
            for dbconfig in connconfig.dbconfigs:                                               #遍历HOST里面的DB
                dblogconfig = DbLogConfig(dbconfig.dbname, "SUCCESS", "")                       #初始化DB日志
                if (self.is_connect(host, dbconfig.dbname)):                                    #是否需要连接数据库
                    result = self.connect(connconfig, dbconfig)                                 #连接数据库
                    if ("SUCCESS" == result[1]):                                                #如果连接成功
                        cur = result[0].cursor()                                                #获取数据库游标
                        cur.connection.autocommit(True)                                         #设置游标为主动提交
                        for (filename, sqlfile) in self.search_sql.items():                     #遍历文件
                            filelogconfig = FileLogConfig(filename, time.time(), "SUCCESS", "") #初始化文件日志
                            if (self.file_is_dispatch(host, dbconfig.dbname, sqlfile)):              #该文件是否需要派发
                                for sql in sqlfile.sqls:
                                    sqllogconfig = SqlLogConfig(sql, "SUCCESS", "")
                                    if (self.sql_is_dispatch(host, dbconfig.dbname, filename, sql)):
                                        res = self.executesql(cur, sql);
                                        if ("ERROR" == res[0]):                                         #执行SQL语句失败
                                            #修改文件日志信息
                                            sqllogconfig.error_tag = "ERROR"
                                            sqllogconfig.error_msg = ("Mysql Error: %d %s" %(res[1], res[2]))
                                    else:
                                        #不需要派发的错误sql,需要保存到新的日志中
                                        sqllogconfig = self.dispatch_log[host][dbconfig.dbname][sqlfile.filename][sql]
                                        #即使不需要派发sql,如果文件有误,还是需要显示的
                                    if (sqllogconfig.error_tag == "ERROR"):
                                        filelogconfig.error_tag = sqllogconfig.error_tag
                                        filelogconfig.error_msg = sqllogconfig.error_msg
                                        print "host:%s dbname:%s filename:%s [%s] %s\n" %(host, dbconfig.dbname, filename, sqllogconfig.error_tag, sqllogconfig.error_msg)
                                    filelogconfig[sql] = sqllogconfig
                                if (filelogconfig.error_tag == "SUCCESS"):
                                    print "host:%s dbname:%s filename:%s [%s] %s\n" %(host, dbconfig.dbname, filename, filelogconfig.error_tag, filelogconfig.error_msg)
                            else:
                                #不需要派发的错误文件,需要保存到新的日志中
                                filelogconfig = self.dispatch_log[host][dbconfig.dbname][filename]        
                                if ("ERROR" == filelogconfig.error_tag):
                                    print "host:%s dbname:%s %s\n" %(host, dbconfig.dbname, filelogconfig.__str__())
                            #保存FILE日志到上一级DB日志
                            dblogconfig[filelogconfig.filename] = filelogconfig
                        cur.close()             #关闭游标     
                        result[0].close()       #关闭数据库连接
                    else:
                        if (result[2] == self.HOST_ERROR or result[2] == self.PASS_ERROR):              #连接错误
                            hostlogconfig.error_tag = "ERROR"
                            hostlogconfig.error_msg = "Mysql Error: (%d) %s" %(result[2], result[3])
                            print hostlogconfig
                            break;
                        elif (result[2] == self.DB_ERROR or result[2] == self.CHARSET_ERROR):           #DB错误
                            dblogconfig.error_tag = "ERROR"
                            dblogconfig.error_msg = "Mysql Error: (%d) %s" %(result[2], result[3])
                            print "host:%s %s\n" %(host, dblogconfig.__str__())
                else:
                    #原有日志中的连接有错误,需要更新到最新的日志中来
                    if ("ERROR" == self.dispatch_log[host].error_tag):                              
                        hostlogconfig.error_tag = self.dispatch_log[host].error_tag
                        hostlogconfig.error_msg = self.dispatch_log[host].error_msg
                        print hostlogconfig
                        break;
                    #原有数据库信息有错误,需要更新到最新的日志中来
                    elif ("ERROR" == self.dispatch_log[host][dbconfig.dbname].error_tag):
                        dblogconfig.error_tag = self.dispatch_log[host][dbconfig.dbname].error_tag
                        dblogconfig.error_msg = self.dispatch_log[host][dbconfig.dbname].error_msg
                        print "host:%s %s\n" %(host, dblogconfig.__str__())
                #保存DB日志到上一级的HOST日志
                hostlogconfig[dbconfig.dbname] = dblogconfig
            #保存HOST日志到上一级的Dispatch日志
            dispatchlog[host] = hostlogconfig
        #写日志
        dispatchlog.write_log()   
       
    """
    Description:
        current connection is needed; if last time's log appear error, return True, or return False
    Agument:
        host:主机名称
        dbname:数据库名称
    Return:
        if last time's log appear error, return True, or return False
    """
    def is_connect(self, host, dbname):
        try:
            if ("ERROR" == self.dispatch_log[host].error_tag or "ERROR" == self.dispatch_log[host][dbname].error_tag):
                return False
            else:
                return True
        except KeyError:
                return True
    
    """
    """
    def connect(self, connconfig, dbconfig):
        try:
            conn=MySQLdb.connect(host   =   connconfig.host,
                                 user   =   connconfig.user,
                                 passwd =   connconfig.passwd,
                                 db     =   dbconfig.dbname,
                                 port   =   connconfig.port,
                                 charset=   dbconfig.charset)
            return [conn, "SUCCESS", 0, ""]
        except MySQLdb.Error,e:
            return [None, "ERROR", e.args[0], e.args[1]]
 def dispatch(self):
     #新建DispatchLog用来记录当前产生的日志
     dispatchlog = DispatchLog(self.logname)
     
     for (host, connconfig) in self.dispatch_config.items():                                 #遍历HOST
         hostlogconfig = HostLogConfig(host, "SUCCESS", "")                                  #初始化HOST日志
         for dbconfig in connconfig.dbconfigs:                                               #遍历HOST里面的DB
             dblogconfig = DbLogConfig(dbconfig.dbname, "SUCCESS", "")                       #初始化DB日志
             if (self.is_connect(host, dbconfig.dbname)):                                    #是否需要连接数据库
                 result = self.connect(connconfig, dbconfig)                                 #连接数据库
                 if ("SUCCESS" == result[1]):                                                #如果连接成功
                     cur = result[0].cursor()                                                #获取数据库游标
                     cur.connection.autocommit(True)                                         #设置游标为主动提交
                     for (filename, sqlfile) in self.search_sql.items():                     #遍历文件
                         filelogconfig = FileLogConfig(filename, time.time(), "SUCCESS", "") #初始化文件日志
                         if (self.file_is_dispatch(host, dbconfig.dbname, sqlfile)):              #该文件是否需要派发
                             for sql in sqlfile.sqls:
                                 sqllogconfig = SqlLogConfig(sql, "SUCCESS", "")
                                 if (self.sql_is_dispatch(host, dbconfig.dbname, filename, sql)):
                                     res = self.executesql(cur, sql);
                                     if ("ERROR" == res[0]):                                         #执行SQL语句失败
                                         #修改文件日志信息
                                         sqllogconfig.error_tag = "ERROR"
                                         sqllogconfig.error_msg = ("Mysql Error: %d %s" %(res[1], res[2]))
                                 else:
                                     #不需要派发的错误sql,需要保存到新的日志中
                                     sqllogconfig = self.dispatch_log[host][dbconfig.dbname][sqlfile.filename][sql]
                                     #即使不需要派发sql,如果文件有误,还是需要显示的
                                 if (sqllogconfig.error_tag == "ERROR"):
                                     filelogconfig.error_tag = sqllogconfig.error_tag
                                     filelogconfig.error_msg = sqllogconfig.error_msg
                                     print "host:%s dbname:%s filename:%s [%s] %s\n" %(host, dbconfig.dbname, filename, sqllogconfig.error_tag, sqllogconfig.error_msg)
                                 filelogconfig[sql] = sqllogconfig
                             if (filelogconfig.error_tag == "SUCCESS"):
                                 print "host:%s dbname:%s filename:%s [%s] %s\n" %(host, dbconfig.dbname, filename, filelogconfig.error_tag, filelogconfig.error_msg)
                         else:
                             #不需要派发的错误文件,需要保存到新的日志中
                             filelogconfig = self.dispatch_log[host][dbconfig.dbname][filename]        
                             if ("ERROR" == filelogconfig.error_tag):
                                 print "host:%s dbname:%s %s\n" %(host, dbconfig.dbname, filelogconfig.__str__())
                         #保存FILE日志到上一级DB日志
                         dblogconfig[filelogconfig.filename] = filelogconfig
                     cur.close()             #关闭游标     
                     result[0].close()       #关闭数据库连接
                 else:
                     if (result[2] == self.HOST_ERROR or result[2] == self.PASS_ERROR):              #连接错误
                         hostlogconfig.error_tag = "ERROR"
                         hostlogconfig.error_msg = "Mysql Error: (%d) %s" %(result[2], result[3])
                         print hostlogconfig
                         break;
                     elif (result[2] == self.DB_ERROR or result[2] == self.CHARSET_ERROR):           #DB错误
                         dblogconfig.error_tag = "ERROR"
                         dblogconfig.error_msg = "Mysql Error: (%d) %s" %(result[2], result[3])
                         print "host:%s %s\n" %(host, dblogconfig.__str__())
             else:
                 #原有日志中的连接有错误,需要更新到最新的日志中来
                 if ("ERROR" == self.dispatch_log[host].error_tag):                              
                     hostlogconfig.error_tag = self.dispatch_log[host].error_tag
                     hostlogconfig.error_msg = self.dispatch_log[host].error_msg
                     print hostlogconfig
                     break;
                 #原有数据库信息有错误,需要更新到最新的日志中来
                 elif ("ERROR" == self.dispatch_log[host][dbconfig.dbname].error_tag):
                     dblogconfig.error_tag = self.dispatch_log[host][dbconfig.dbname].error_tag
                     dblogconfig.error_msg = self.dispatch_log[host][dbconfig.dbname].error_msg
                     print "host:%s %s\n" %(host, dblogconfig.__str__())
             #保存DB日志到上一级的HOST日志
             hostlogconfig[dbconfig.dbname] = dblogconfig
         #保存HOST日志到上一级的Dispatch日志
         dispatchlog[host] = hostlogconfig
     #写日志
     dispatchlog.write_log()