#!/usr/bin/env python3
# coding: UTF-8

try:
    import sys
    import importlib

    importlib.reload(sys)
    from gspylib.inspection.common import SharedFuncs
    from gspylib.inspection.common.CheckItem import BaseItem
    from gspylib.inspection.common.CheckResult import ResultStatus
except ImportError as ie:
    raise Exception("[GAUSS-52200] : Unable to import module: %s." % str(ie))

# master
MASTER_INSTANCE = 0
# standby
STANDBY_INSTANCE = 1


class CheckProcMem(BaseItem):
    def __init__(self):
        super(CheckProcMem, self).__init__(self.__class__.__name__)
        self.percentm = 0.8
        self.percentt = 0.9

    def preCheck(self):
        # check the threshold was set correctly
        if (not self.threshold.__contains__('percent_total')
                or not self.threshold.__contains__('percent_max')):
            raise Exception("threshold can not be empty")
        try:
            self.percentt = float(self.threshold['percent_total'])
            self.percentm = float(self.threshold['percent_max'])
        except TypeError as ex:
            raise Exception("conversion float contains some error:%s" % ex)

    def doCheck(self):
        cmd = "free -g | grep Mem | awk '{print $2}' 2>/dev/null"
        totalMem = SharedFuncs.runShellCmd(cmd)
        cmd = "free -g | grep Mem | awk '{print $3}' 2>/dev/null"
        usedMem = SharedFuncs.runShellCmd(cmd)
        if int(usedMem) > int(totalMem) * self.percentt:
            self.result.rst = ResultStatus.NG
            self.result.val = "Memory usage exceeded threshold"
            return
        output = self.get_inst_max_process_memory()
        if output.upper().endswith("GB"):
            maxProcessM = int(output[:-2]) * 1024 * 1024 * self.percentm
        elif output.upper().endswith("MB"):
            maxProcessM = int(output[:-2]) * 1024 * self.percentm
        elif output.upper().endswith("KB"):
            maxProcessM = int(output[:-2]) * self.percentm
        else:
            self.result.val = "Can not get the correct value of max_process_memory"
            self.result.rst = ResultStatus.NG
            return
        cmd = "ps ux | grep gaussdb | awk '{print $6}'"
        output = SharedFuncs.runShellCmd(cmd)
        for line in output.splitlines():
            procM = int(line)
            if procM > maxProcessM:
                self.result.val = "Memory usage of some gaussdb process exceeded threshold"
                self.result.rst = ResultStatus.NG
                return

        self.result.rst = ResultStatus.OK
        self.result.val = "Memory is sufficient"

    def get_inst_max_process_memory(self):
        """
        function: get datanode max_process_memory
        input: NA
        output: process memory
        """
        cmd = "show max_process_memory;"
        cnPort = None
        masterDnPort = None
        slaveDnPort = None

        self.node = self.cluster.getDbNodeByName(self.host)
        if self.node.coordinators:
            cnPort = self.node.coordinators[0].port
        masterDnlist = SharedFuncs.getMasterDnNum(self.user, self.mpprcFile)
        for datanode in self.node.datanodes:
            if datanode.instanceId in masterDnlist:
                masterDnPort = datanode.port
                break
            elif datanode.instanceType == MASTER_INSTANCE or datanode.instanceType == STANDBY_INSTANCE:
                slaveDnPort = datanode.port
                break
        if cnPort:
            output = SharedFuncs.runSqlCmd(cmd, self.user, "", cnPort, self.tmpPath, "postgres", self.mpprcFile)
        elif masterDnPort:
            output = SharedFuncs.runSqlCmd(cmd, self.user, "", masterDnPort, self.tmpPath, "postgres", self.mpprcFile)
        elif slaveDnPort:
            output = SharedFuncs.runSqlCmd(cmd, self.user, "", slaveDnPort, self.tmpPath, "postgres", self.mpprcFile,
                                           True)
        else:
            self.result.val = "There's no cn or master dn or slave dn in this node"
            self.result.rst = ResultStatus.OK
            return ""
        return output
