###############################################################################
#
# The MIT License (MIT)
#
# Copyright (c) typedef int GmbH
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
###############################################################################

import pprint
import uuid

import numpy as np

import flatbuffers

from zlmdb import table, MapTimestampUuidFlatBuffers
from txaio import time_ns

import MNodeLog as MNodeLogGen


class _MNodeLogGen(MNodeLogGen.MNodeLog):
    """
    Expand methods on the class code generated by flatc.

    FIXME: come up with a PR for flatc to generated this stuff automatically.
    """

    @classmethod
    def GetRootAsMNodeLog(cls, buf, offset):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
        x = _MNodeLogGen()
        x.Init(buf, n + offset)
        return x

    def NodeIdAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off : _off + _len]
        return None

    def RunIdAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off : _off + _len]
        return None


class MNodeLog(object):
    def __init__(self, from_fbs=None):
        self._from_fbs = from_fbs

        # uint64
        self._timestamp = None

        # node_id: [uint8] (uuid);
        self._node_id = None

        # run_id: [uint8] (uuid);
        self._run_id = None

        # state: MNodeState;
        self._state = None

        # ended: uint64;
        self._ended = None

        # session: uint64;
        self._session = None

        # sent: uint64;
        self._sent = None

        # seq: uint64;
        self._seq = None

        # routers: uint16;
        self._routers = None

        # containers: uint16;
        self._containers = None

        # guests: uint16;
        self._guests = None

        # proxies: uint16;
        self._proxies = None

        # xbr_marketmakers: uint16;
        self._marketmakers = None

        # CF node system statistics
        self._cpu_ctx_switches = None
        self._cpu_freq = None
        self._cpu_guest = None
        self._cpu_guest_nice = None
        self._cpu_idle = None
        self._cpu_interrupts = None
        self._cpu_iotwait = None
        self._cpu_irq = None
        self._cpu_nice = None
        self._cpu_soft_interrupts = None
        self._cpu_softirq = None
        self._cpu_steal = None
        self._cpu_system = None
        self._cpu_user = None
        self._disk_busy_time = None
        self._disk_read_bytes = None
        self._disk_read_count = None
        self._disk_read_merged_count = None
        self._disk_read_time = None
        self._disk_write_bytes = None
        self._disk_write_count = None
        self._disk_write_merged_count = None
        self._disk_write_time = None
        self._memory_active = None
        self._memory_available = None
        self._memory_buffers = None
        self._memory_cached = None
        self._memory_free = None
        self._memory_inactive = None
        self._memory_percent = None
        self._memory_shared = None
        self._memory_slab = None
        self._memory_total = None
        self._memory_used = None
        self._network_bytes_recv = None
        self._network_bytes_sent = None
        self._network_connection_af_inet = None
        self._network_connection_af_inet6 = None
        self._network_connection_af_unix = None
        self._network_dropin = None
        self._network_dropout = None
        self._network_errin = None
        self._network_errout = None
        self._network_packets_recv = None
        self._network_packets_sent = None

    @staticmethod
    def parse(node_id, heartbeat):
        assert isinstance(node_id, uuid.UUID)
        assert type(heartbeat) == dict
        assert "timestamp" in heartbeat and type(heartbeat["timestamp"]) == int

        obj = MNodeLog()
        obj._timestamp = np.datetime64(time_ns(), "ns")
        obj._node_id = node_id
        obj._run_id = uuid.UUID(bytes=b"\0" * 16)
        obj._state = heartbeat.get("state", None)
        obj._ended = (
            np.datetime64(heartbeat["ended"], "ns")
            if heartbeat.get("ended", None)
            else None
        )
        obj._session = heartbeat.get("session", None)
        obj._sent = (
            np.datetime64(heartbeat["timestamp"], "ns")
            if heartbeat.get("timestamp", None)
            else None
        )
        obj._seq = heartbeat.get("seq", None)

        workers = heartbeat.get("workers", {})
        obj._routers = workers.get("router", None)
        obj._containers = workers.get("container", None)
        obj._guests = workers.get("guest", None)
        obj._proxies = workers.get("proxy", None)
        obj._marketmakers = workers.get("xbrmm", None)

        system = heartbeat.get("system", {})
        system_cpu = system.get("cpu", {})
        system_net = system.get("network", {})
        system_mem = system.get("memory", {})
        system_dsk = system.get("disk", {})

        obj._cpu_ctx_switches = system_cpu.get("ctx_switches", None)
        obj._cpu_freq = system_cpu.get("freq", None)
        obj._cpu_guest = system_cpu.get("guest", None)
        obj._cpu_guest_nice = system_cpu.get("guest_nice", None)
        obj._cpu_idle = system_cpu.get("idle", None)
        obj._cpu_interrupts = system_cpu.get("interrupts", None)
        obj._cpu_iotwait = system_cpu.get("iotwait", None)
        obj._cpu_irq = system_cpu.get("irq", None)
        obj._cpu_nice = system_cpu.get("nice", None)
        obj._cpu_soft_interrupts = system_cpu.get("soft_interrupts", None)
        obj._cpu_softirq = system_cpu.get("softirq", None)
        obj._cpu_steal = system_cpu.get("steal", None)
        obj._cpu_system = system_cpu.get("system", None)
        obj._cpu_user = system_cpu.get("user", None)

        obj._network_bytes_recv = system_net.get("bytes_recv", None)
        obj._network_bytes_sent = system_net.get("bytes_sent", None)
        obj._network_packets_recv = system_net.get("packets_recv", None)
        obj._network_packets_sent = system_net.get("packets_sent", None)
        obj._network_dropin = system_net.get("dropin", None)
        obj._network_dropout = system_net.get("dropout", None)
        obj._network_errin = system_net.get("errin", None)
        obj._network_errout = system_net.get("errout", None)

        connection = system_net.get("connection", {})
        obj._network_connection_af_inet = connection.get("AF_INET", None)
        obj._network_connection_af_inet6 = connection.get("AF_INET6", None)
        obj._network_connection_af_unix = connection.get("AF_UNIX", None)

        obj._memory_active = system_mem.get("active", None)
        obj._memory_available = system_mem.get("available", None)
        obj._memory_buffers = system_mem.get("buffers", None)
        obj._memory_cached = system_mem.get("cached", None)
        obj._memory_free = system_mem.get("free", None)
        obj._memory_inactive = system_mem.get("inactive", None)
        obj._memory_percent = system_mem.get("percent", None)
        obj._memory_shared = system_mem.get("shared", None)
        obj._memory_slab = system_mem.get("slab", None)
        obj._memory_total = system_mem.get("total", None)
        obj._memory_used = system_mem.get("used", None)

        obj._disk_busy_time = system_dsk.get("busy_time", None)
        obj._disk_read_bytes = system_dsk.get("read_bytes", None)
        obj._disk_read_count = system_dsk.get("read_count", None)
        obj._disk_read_merged_count = system_dsk.get("read_merged_count", None)
        obj._disk_read_time = system_dsk.get("read_time", None)
        obj._disk_write_bytes = system_dsk.get("write_bytes", None)
        obj._disk_write_count = system_dsk.get("write_count", None)
        obj._disk_write_merged_count = system_dsk.get("write_merged_count", None)
        obj._disk_write_time = system_dsk.get("write_time", None)

        return obj

    def marshal(self):
        obj = {
            "timestamp": self.timestamp,
            "node_id": str(self.node_id),
            "run_id": str(self.run_id),
            "state": self.state,
            "ended": self.ended,
            "session": self.session,
            "sent": self.sent,
            "seq": self.seq,
            "workers": {
                "router": self.routers,
                "container": self.containers,
                "guest": self.guests,
                "proxy": self.proxies,
                "xbrmm": self.marketmakers,
            },
            "cpu": {
                "ctx_switches": self.cpu_ctx_switches,
                "freq": self.cpu_freq,
                "guest": self.cpu_guest,
                "guest_nice": self.cpu_guest_nice,
                "idle": self.cpu_idle,
                "interrupts": self.cpu_interrupts,
                "iotwait": self.cpu_iotwait,
                "irq": self.cpu_irq,
                "nice": self.cpu_nice,
                "soft_interrupts": self.cpu_soft_interrupts,
                "softirq": self.cpu_softirq,
                "steal": self.cpu_steal,
                "system": self.cpu_system,
                "user": self.cpu_user,
            },
            "memory": {
                "active": self.memory_active,
                "available": self.memory_available,
                "buffers": self.memory_buffers,
                "cached": self.memory_cached,
                "free": self.memory_free,
                "inactive": self.memory_inactive,
                "percent": self.memory_percent,
                "shared": self.memory_shared,
                "slab": self.memory_slab,
                "total": self.memory_total,
                "used": self.memory_used,
            },
            "disk": {
                "busy_time": self.disk_busy_time,
                "read_bytes": self.disk_read_bytes,
                "read_count": self.disk_read_count,
                "read_merged_count": self.disk_read_merged_count,
                "read_time": self.disk_read_time,
                "write_bytes": self.disk_write_bytes,
                "write_count": self.disk_write_count,
                "write_merged_count": self.disk_write_merged_count,
                "write_time": self.disk_write_time,
            },
            "network": {
                "bytes_recv": self.network_bytes_recv,
                "bytes_sent": self.network_bytes_sent,
                "connection": {
                    "AF_INET": self.network_connection_af_inet,
                    "AF_INET6": self.network_connection_af_inet6,
                    "UNIX": self.network_connection_af_unix,
                },
                "dropin": self.network_dropin,
                "dropout": self.network_dropout,
                "errin": self.network_errin,
                "errout": self.network_errout,
                "packets_recv": self.network_packets_recv,
                "packets_sent": self.network_packets_sent,
            },
        }
        return obj

    def __str__(self):
        return "\n{}\n".format(pprint.pformat(self.marshal()))

    @property
    def timestamp(self):
        if self._timestamp is None and self._from_fbs:
            self._timestamp = np.datetime64(self._from_fbs.Timestamp(), "ns")
        return self._timestamp

    @timestamp.setter
    def timestamp(self, value):
        assert value is None or isinstance(value, np.datetime64)
        self._timestamp = value

    @property
    def node_id(self):
        if self._node_id is None and self._from_fbs:
            if self._from_fbs.NodeIdLength():
                _node_id = self._from_fbs.NodeIdAsBytes()
                self._node_id = uuid.UUID(bytes=_node_id.tobytes())
        return self._node_id

    @node_id.setter
    def node_id(self, value):
        assert value is None or isinstance(value, uuid.UUID)
        self._node_id = value

    @property
    def run_id(self):
        if self._run_id is None and self._from_fbs:
            if self._from_fbs.RunIdLength():
                _run_id = self._from_fbs.RunIdAsBytes()
                self._run_id = uuid.UUID(bytes=_run_id.tobytes())
        return self._run_id

    @run_id.setter
    def run_id(self, value):
        assert value is None or isinstance(value, uuid.UUID)
        self._run_id = value

    @property
    def state(self):
        if self._state is None and self._from_fbs:
            self._state = self._from_fbs.State()
        return self._state

    @state.setter
    def state(self, value):
        assert value is None or type(value) == int
        self._state = value

    @property
    def ended(self):
        if self._ended is None and self._from_fbs:
            self._ended = np.datetime64(self._from_fbs.Ended(), "ns")
        return self._ended

    @ended.setter
    def ended(self, value):
        assert value is None or isinstance(value, np.datetime64)
        self._ended = value

    @property
    def session(self):
        if self._session is None and self._from_fbs:
            self._session = self._from_fbs.Session()
        return self._session

    @session.setter
    def session(self, value):
        assert value is None or type(value) == int
        self._session = value

    @property
    def sent(self):
        if self._sent is None and self._from_fbs:
            self._sent = np.datetime64(self._from_fbs.Sent(), "ns")
        return self._sent

    @sent.setter
    def sent(self, value):
        assert value is None or isinstance(value, np.datetime64)
        self._sent = value

    @property
    def seq(self):
        if self._seq is None and self._from_fbs:
            self._seq = self._from_fbs.Seq()
        return self._seq

    @seq.setter
    def seq(self, value):
        assert value is None or type(value) == int
        self._seq = value

    @property
    def routers(self):
        if self._routers is None and self._from_fbs:
            self._routers = self._from_fbs.Routers()
        return self._routers

    @routers.setter
    def routers(self, value):
        assert value is None or type(value) == int
        self._routers = value

    @property
    def containers(self):
        if self._containers is None and self._from_fbs:
            self._containers = self._from_fbs.Containers()
        return self._containers

    @containers.setter
    def containers(self, value):
        assert value is None or type(value) == int
        self._containers = value

    @property
    def guests(self):
        if self._guests is None and self._from_fbs:
            self._guests = self._from_fbs.Guests()
        return self._guests

    @guests.setter
    def guests(self, value):
        assert value is None or type(value) == int
        self._guests = value

    @property
    def proxies(self):
        if self._proxies is None and self._from_fbs:
            self._proxies = self._from_fbs.Proxies()
        return self._proxies

    @proxies.setter
    def proxies(self, value):
        assert value is None or type(value) == int
        self._proxies = value

    @property
    def marketmakers(self):
        if self._marketmakers is None and self._from_fbs:
            self._marketmakers = self._from_fbs.Marketmakers()
        return self._marketmakers

    @marketmakers.setter
    def marketmakers(self, value):
        assert value is None or type(value) == int
        self._marketmakers = value

    @property
    def cpu_ctx_switches(self):
        if self._cpu_ctx_switches is None and self._from_fbs:
            self._cpu_ctx_switches = self._from_fbs.CpuCtxSwitches()
        return self._cpu_ctx_switches

    @cpu_ctx_switches.setter
    def cpu_ctx_switches(self, value):
        assert value is None or type(value) == int
        self._cpu_ctx_switches = value

    @property
    def cpu_freq(self):
        if self._cpu_freq is None and self._from_fbs:
            self._cpu_freq = self._from_fbs.CpuFreq()
        return self._cpu_freq

    @cpu_freq.setter
    def cpu_freq(self, value):
        assert value is None or type(value) == float
        self._cpu_freq = value

    @property
    def cpu_guest(self):
        if self._cpu_guest is None and self._from_fbs:
            self._cpu_guest = self._from_fbs.CpuGuest()
        return self._cpu_guest

    @cpu_guest.setter
    def cpu_guest(self, value):
        assert value is None or type(value) == float
        self._cpu_guest = value

    @property
    def cpu_guest_nice(self):
        if self._cpu_guest_nice is None and self._from_fbs:
            self._cpu_guest_nice = self._from_fbs.CpuGuestNice()
        return self._cpu_guest_nice

    @cpu_guest_nice.setter
    def cpu_guest_nice(self, value):
        assert value is None or type(value) == float
        self._cpu_guest_nice = value

    @property
    def cpu_idle(self):
        if self._cpu_idle is None and self._from_fbs:
            self._cpu_idle = self._from_fbs.CpuIdle()
        return self._cpu_idle

    @cpu_idle.setter
    def cpu_idle(self, value):
        assert value is None or type(value) == float
        self._cpu_idle = value

    @property
    def cpu_interrupts(self):
        if self._cpu_interrupts is None and self._from_fbs:
            self._cpu_interrupts = self._from_fbs.CpuInterrupts()
        return self._cpu_interrupts

    @cpu_interrupts.setter
    def cpu_interrupts(self, value):
        assert value is None or type(value) == int
        self._cpu_interrupts = value

    @property
    def cpu_iotwait(self):
        if self._cpu_iotwait is None and self._from_fbs:
            self._cpu_iotwait = self._from_fbs.CpuIowait()
        return self._cpu_iotwait

    @cpu_iotwait.setter
    def cpu_iotwait(self, value):
        assert value is None or type(value) == float
        self._cpu_iotwait = value

    @property
    def cpu_irq(self):
        if self._cpu_irq is None and self._from_fbs:
            self._cpu_irq = self._from_fbs.CpuIrq()
        return self._cpu_irq

    @cpu_irq.setter
    def cpu_irq(self, value):
        assert value is None or type(value) == float
        self._cpu_irq = value

    @property
    def cpu_nice(self):
        if self._cpu_nice is None and self._from_fbs:
            self._cpu_nice = self._from_fbs.CpuNice()
        return self._cpu_nice

    @cpu_nice.setter
    def cpu_nice(self, value):
        assert value is None or type(value) == float
        self._cpu_nice = value

    @property
    def cpu_soft_interrupts(self):
        if self._cpu_soft_interrupts is None and self._from_fbs:
            self._cpu_soft_interrupts = self._from_fbs.CpuSoftInterrupts()
        return self._cpu_soft_interrupts

    @cpu_soft_interrupts.setter
    def cpu_soft_interrupts(self, value):
        assert value is None or type(value) == int
        self._cpu_soft_interrupts = value

    @property
    def cpu_softirq(self):
        if self._cpu_softirq is None and self._from_fbs:
            self._cpu_softirq = self._from_fbs.CpuSoftirq()
        return self._cpu_softirq

    @cpu_softirq.setter
    def cpu_softirq(self, value):
        assert value is None or type(value) == float
        self._cpu_softirq = value

    @property
    def cpu_steal(self):
        if self._cpu_steal is None and self._from_fbs:
            self._cpu_steal = self._from_fbs.CpuSteal()
        return self._cpu_steal

    @cpu_steal.setter
    def cpu_steal(self, value):
        assert value is None or type(value) == float
        self._cpu_steal = value

    @property
    def cpu_system(self):
        if self._cpu_system is None and self._from_fbs:
            self._cpu_system = self._from_fbs.CpuSystem()
        return self._cpu_system

    @cpu_system.setter
    def cpu_system(self, value):
        assert value is None or type(value) == float
        self._cpu_system = value

    @property
    def cpu_user(self):
        if self._cpu_user is None and self._from_fbs:
            self._cpu_user = self._from_fbs.CpuUser()
        return self._cpu_user

    @cpu_user.setter
    def cpu_user(self, value):
        assert value is None or type(value) == float
        self._cpu_user = value

    @property
    def network_bytes_recv(self):
        if self._network_bytes_recv is None and self._from_fbs:
            self._network_bytes_recv = self._from_fbs.NetworkBytesRecv()
        return self._network_bytes_recv

    @network_bytes_recv.setter
    def network_bytes_recv(self, value):
        assert value is None or type(value) == int
        self._network_bytes_recv = value

    @property
    def network_bytes_sent(self):
        if self._network_bytes_sent is None and self._from_fbs:
            self._network_bytes_sent = self._from_fbs.NetworkBytesSent()
        return self._network_bytes_sent

    @network_bytes_sent.setter
    def network_bytes_sent(self, value):
        assert value is None or type(value) == int
        self._network_bytes_sent = value

    @property
    def network_connection_af_inet(self):
        if self._network_connection_af_inet is None and self._from_fbs:
            self._network_connection_af_inet = self._from_fbs.NetworkConnectionAfInet()
        return self._network_connection_af_inet

    @network_connection_af_inet.setter
    def network_connection_af_inet(self, value):
        assert value is None or type(value) == int
        self._network_connection_af_inet = value

    @property
    def network_connection_af_inet6(self):
        if self._network_connection_af_inet6 is None and self._from_fbs:
            self._network_connection_af_inet6 = (
                self._from_fbs.NetworkConnectionAfInet6()
            )
        return self._network_connection_af_inet6

    @network_connection_af_inet6.setter
    def network_connection_af_inet6(self, value):
        assert value is None or type(value) == int
        self._network_connection_af_inet6 = value

    @property
    def network_connection_af_unix(self):
        if self._network_connection_af_unix is None and self._from_fbs:
            self._network_connection_af_unix = self._from_fbs.NetworkConnectionAfUnix()
        return self._network_connection_af_unix

    @network_connection_af_unix.setter
    def network_connection_af_unix(self, value):
        assert value is None or type(value) == int
        self._network_connection_af_unix = value

    @property
    def network_dropin(self):
        if self._network_dropin is None and self._from_fbs:
            self._network_dropin = self._from_fbs.NetworkDropin()
        return self._network_dropin

    @network_dropin.setter
    def network_dropin(self, value):
        assert value is None or type(value) == int
        self._network_dropin = value

    @property
    def network_dropout(self):
        if self._network_dropout is None and self._from_fbs:
            self._network_dropout = self._from_fbs.NetworkDropout()
        return self._network_dropout

    @network_dropout.setter
    def network_dropout(self, value):
        assert value is None or type(value) == int
        self._network_dropout = value

    @property
    def network_errin(self):
        if self._network_errin is None and self._from_fbs:
            self._network_errin = self._from_fbs.NetworkErrin()
        return self._network_errin

    @network_errin.setter
    def network_errin(self, value):
        assert value is None or type(value) == int
        self._network_errin = value

    @property
    def network_errout(self):
        if self._network_errout is None and self._from_fbs:
            self._network_errout = self._from_fbs.NetworkErrout()
        return self._network_errout

    @network_errout.setter
    def network_errout(self, value):
        assert value is None or type(value) == int
        self._network_errout = value

    @property
    def network_packets_recv(self):
        if self._network_packets_recv is None and self._from_fbs:
            self._network_packets_recv = self._from_fbs.NetworkPacketsRecv()
        return self._network_packets_recv

    @network_packets_recv.setter
    def network_packets_recv(self, value):
        assert value is None or type(value) == int
        self._network_packets_recv = value

    @property
    def network_packets_sent(self):
        if self._network_packets_sent is None and self._from_fbs:
            self._network_packets_sent = self._from_fbs.NetworkPacketsSent()
        return self._network_packets_sent

    @network_packets_sent.setter
    def network_packets_sent(self, value):
        assert value is None or type(value) == int
        self._network_packets_sent = value

    @property
    def memory_active(self):
        if self._memory_active is None and self._from_fbs:
            self._memory_active = self._from_fbs.MemoryActive()
        return self._memory_active

    @memory_active.setter
    def memory_active(self, value):
        assert value is None or type(value) == int
        self._memory_active = value

    @property
    def memory_available(self):
        if self._memory_available is None and self._from_fbs:
            self._memory_available = self._from_fbs.MemoryAvailable()
        return self._memory_available

    @memory_available.setter
    def memory_available(self, value):
        assert value is None or type(value) == int
        self._memory_available = value

    @property
    def memory_buffers(self):
        if self._memory_buffers is None and self._from_fbs:
            self._memory_buffers = self._from_fbs.MemoryBuffers()
        return self._memory_buffers

    @memory_buffers.setter
    def memory_buffers(self, value):
        assert value is None or type(value) == int
        self._memory_buffers = value

    @property
    def memory_cached(self):
        if self._memory_cached is None and self._from_fbs:
            self._memory_cached = self._from_fbs.MemoryCached()
        return self._memory_cached

    @memory_cached.setter
    def memory_cached(self, value):
        assert value is None or type(value) == int
        self._memory_cached = value

    @property
    def memory_free(self):
        if self._memory_free is None and self._from_fbs:
            self._memory_free = self._from_fbs.MemoryFree()
        return self._memory_free

    @memory_free.setter
    def memory_free(self, value):
        assert value is None or type(value) == int
        self._memory_free = value

    @property
    def memory_inactive(self):
        if self._memory_inactive is None and self._from_fbs:
            self._memory_inactive = self._from_fbs.MemoryInactive()
        return self._memory_inactive

    @memory_inactive.setter
    def memory_inactive(self, value):
        assert value is None or type(value) == int
        self._memory_inactive = value

    @property
    def memory_percent(self):
        if self._memory_percent is None and self._from_fbs:
            self._memory_percent = self._from_fbs.MemoryPercent()
        return self._memory_percent

    @memory_percent.setter
    def memory_percent(self, value):
        assert value is None or type(value) == float
        self._memory_percent = value

    @property
    def memory_shared(self):
        if self._memory_shared is None and self._from_fbs:
            self._memory_shared = self._from_fbs.MemoryShared()
        return self._memory_shared

    @memory_shared.setter
    def memory_shared(self, value):
        assert value is None or type(value) == int
        self._memory_shared = value

    @property
    def memory_slab(self):
        if self._memory_slab is None and self._from_fbs:
            self._memory_slab = self._from_fbs.MemorySlab()
        return self._memory_slab

    @memory_slab.setter
    def memory_slab(self, value):
        assert value is None or type(value) == int
        self._memory_slab = value

    @property
    def memory_total(self):
        if self._memory_total is None and self._from_fbs:
            self._memory_total = self._from_fbs.MemoryTotal()
        return self._memory_total

    @memory_total.setter
    def memory_total(self, value):
        assert value is None or type(value) == int
        self._memory_total = value

    @property
    def memory_used(self):
        if self._memory_used is None and self._from_fbs:
            self._memory_used = self._from_fbs.MemoryUsed()
        return self._memory_used

    @memory_used.setter
    def memory_used(self, value):
        assert value is None or type(value) == int
        self._memory_used = value

    @property
    def disk_busy_time(self):
        if self._disk_busy_time is None and self._from_fbs:
            self._disk_busy_time = self._from_fbs.DiskBusyTime()
        return self._disk_busy_time

    @disk_busy_time.setter
    def disk_busy_time(self, value):
        assert value is None or type(value) == int
        self._disk_busy_time = value

    @property
    def disk_read_bytes(self):
        if self._disk_read_bytes is None and self._from_fbs:
            self._disk_read_bytes = self._from_fbs.DiskReadBytes()
        return self._disk_read_bytes

    @disk_read_bytes.setter
    def disk_read_bytes(self, value):
        assert value is None or type(value) == int
        self._disk_read_bytes = value

    @property
    def disk_read_count(self):
        if self._disk_read_count is None and self._from_fbs:
            self._disk_read_count = self._from_fbs.DiskReadCount()
        return self._disk_read_count

    @disk_read_count.setter
    def disk_read_count(self, value):
        assert value is None or type(value) == int
        self._disk_read_count = value

    @property
    def disk_read_merged_count(self):
        if self._disk_read_merged_count is None and self._from_fbs:
            self._disk_read_merged_count = self._from_fbs.DiskReadMergedCount()
        return self._disk_read_merged_count

    @disk_read_merged_count.setter
    def disk_read_merged_count(self, value):
        assert value is None or type(value) == int
        self._disk_read_merged_count = value

    @property
    def disk_read_time(self):
        if self._disk_read_time is None and self._from_fbs:
            self._disk_read_time = self._from_fbs.DiskReadTime()
        return self._disk_read_time

    @disk_read_time.setter
    def disk_read_time(self, value):
        assert value is None or type(value) == int
        self._disk_read_time = value

    @property
    def disk_write_bytes(self):
        if self._disk_write_bytes is None and self._from_fbs:
            self._disk_write_bytes = self._from_fbs.DiskWriteBytes()
        return self._disk_write_bytes

    @disk_write_bytes.setter
    def disk_write_bytes(self, value):
        assert value is None or type(value) == int
        self._disk_write_bytes = value

    @property
    def disk_write_count(self):
        if self._disk_write_count is None and self._from_fbs:
            self._disk_write_count = self._from_fbs.DiskWriteCount()
        return self._disk_write_count

    @disk_write_count.setter
    def disk_write_count(self, value):
        assert value is None or type(value) == int
        self._disk_write_count = value

    @property
    def disk_write_merged_count(self):
        if self._disk_write_merged_count is None and self._from_fbs:
            self._disk_write_merged_count = self._from_fbs.DiskWriteMergedCount()
        return self._disk_write_merged_count

    @disk_write_merged_count.setter
    def disk_write_merged_count(self, value):
        assert value is None or type(value) == int
        self._disk_write_merged_count = value

    @property
    def disk_write_time(self):
        if self._disk_write_time is None and self._from_fbs:
            self._disk_write_time = self._from_fbs.DiskWriteTime()
        return self._disk_write_time

    @disk_write_time.setter
    def disk_write_time(self, value):
        assert value is None or type(value) == int
        self._disk_write_time = value

    @staticmethod
    def cast(buf):
        assert type(buf) in [bytes, bytearray], "bytes expected, got {}".format(
            type(buf)
        )
        return MNodeLog(_MNodeLogGen.GetRootAsMNodeLog(buf, 0))

    def build(self, builder):
        node_id = self.node_id.bytes if self.node_id else None
        if node_id:
            node_id = builder.CreateString(node_id)

        run_id = self.run_id.bytes if self.run_id else None
        if run_id:
            run_id = builder.CreateString(run_id)

        MNodeLogGen.MNodeLogStart(builder)

        if self.timestamp:
            MNodeLogGen.MNodeLogAddTimestamp(builder, int(self.timestamp))

        if node_id:
            MNodeLogGen.MNodeLogAddNodeId(builder, node_id)

        if run_id:
            MNodeLogGen.MNodeLogAddRunId(builder, run_id)

        if self.state:
            MNodeLogGen.MNodeLogAddState(builder, self.state)

        if self.ended:
            MNodeLogGen.MNodeLogAddEnded(builder, int(self.ended))

        if self.session:
            MNodeLogGen.MNodeLogAddSession(builder, self.session)

        if self.sent:
            MNodeLogGen.MNodeLogAddSent(builder, int(self.sent))

        if self.seq:
            MNodeLogGen.MNodeLogAddSeq(builder, self.seq)

        if self.routers:
            MNodeLogGen.MNodeLogAddRouters(builder, self.routers)

        if self.containers:
            MNodeLogGen.MNodeLogAddContainers(builder, self.containers)

        if self.guests:
            MNodeLogGen.MNodeLogAddGuests(builder, self.guests)

        if self.proxies:
            MNodeLogGen.MNodeLogAddProxies(builder, self.proxies)

        if self.marketmakers:
            MNodeLogGen.MNodeLogAddMarketmakers(builder, self.marketmakers)

        if self.cpu_ctx_switches:
            MNodeLogGen.MNodeLogAddCpuCtxSwitches(builder, self.cpu_ctx_switches)

        if self.cpu_freq:
            MNodeLogGen.MNodeLogAddCpuFreq(builder, self.cpu_freq)

        if self.cpu_guest:
            MNodeLogGen.MNodeLogAddCpuGuest(builder, self.cpu_guest)

        if self.cpu_guest_nice:
            MNodeLogGen.MNodeLogAddCpuGuestNice(builder, self.cpu_guest_nice)

        if self.cpu_idle:
            MNodeLogGen.MNodeLogAddCpuIdle(builder, self.cpu_idle)

        if self.cpu_interrupts:
            MNodeLogGen.MNodeLogAddCpuInterrupts(builder, self.cpu_interrupts)

        if self.cpu_iotwait:
            MNodeLogGen.MNodeLogAddCpuIowait(builder, self.cpu_iotwait)

        if self.cpu_irq:
            MNodeLogGen.MNodeLogAddCpuIrq(builder, self.cpu_irq)

        if self.cpu_nice:
            MNodeLogGen.MNodeLogAddCpuNice(builder, self.cpu_nice)

        if self.cpu_soft_interrupts:
            MNodeLogGen.MNodeLogAddCpuSoftInterrupts(builder, self.cpu_soft_interrupts)

        if self.cpu_softirq:
            MNodeLogGen.MNodeLogAddCpuSoftirq(builder, self.cpu_softirq)

        if self.cpu_steal:
            MNodeLogGen.MNodeLogAddCpuSteal(builder, self.cpu_steal)

        if self.cpu_system:
            MNodeLogGen.MNodeLogAddCpuSystem(builder, self.cpu_system)

        if self.cpu_user:
            MNodeLogGen.MNodeLogAddCpuUser(builder, self.cpu_user)

        if self.network_bytes_recv:
            MNodeLogGen.MNodeLogAddNetworkBytesRecv(builder, self.network_bytes_recv)

        if self.network_bytes_sent:
            MNodeLogGen.MNodeLogAddNetworkBytesSent(builder, self.network_bytes_sent)

        if self.network_connection_af_inet:
            MNodeLogGen.MNodeLogAddNetworkConnectionAfInet(
                builder, self.network_connection_af_inet
            )

        if self.network_connection_af_inet6:
            MNodeLogGen.MNodeLogAddNetworkConnectionAfInet6(
                builder, self.network_connection_af_inet6
            )

        if self.network_connection_af_unix:
            MNodeLogGen.MNodeLogAddNetworkConnectionAfUnix(
                builder, self.network_connection_af_unix
            )

        if self.network_dropin:
            MNodeLogGen.MNodeLogAddNetworkDropin(builder, self.network_dropin)

        if self.network_dropout:
            MNodeLogGen.MNodeLogAddNetworkDropout(builder, self.network_dropout)

        if self.network_errin:
            MNodeLogGen.MNodeLogAddNetworkErrin(builder, self.network_errin)

        if self.network_errout:
            MNodeLogGen.MNodeLogAddNetworkErrout(builder, self.network_errout)

        if self.network_packets_recv:
            MNodeLogGen.MNodeLogAddNetworkPacketsRecv(
                builder, self.network_packets_recv
            )

        if self.network_packets_sent:
            MNodeLogGen.MNodeLogAddNetworkPacketsSent(
                builder, self.network_packets_sent
            )

        if self.memory_active:
            MNodeLogGen.MNodeLogAddMemoryActive(builder, self.memory_active)

        if self.memory_available:
            MNodeLogGen.MNodeLogAddMemoryAvailable(builder, self.memory_available)

        if self.memory_buffers:
            MNodeLogGen.MNodeLogAddMemoryBuffers(builder, self.memory_buffers)

        if self.memory_cached:
            MNodeLogGen.MNodeLogAddMemoryCached(builder, self.memory_cached)

        if self.memory_free:
            MNodeLogGen.MNodeLogAddMemoryFree(builder, self.memory_free)

        if self.memory_inactive:
            MNodeLogGen.MNodeLogAddMemoryInactive(builder, self.memory_inactive)

        if self.memory_percent:
            MNodeLogGen.MNodeLogAddMemoryPercent(builder, self.memory_percent)

        if self.memory_shared:
            MNodeLogGen.MNodeLogAddMemoryShared(builder, self.memory_shared)

        if self.memory_slab:
            MNodeLogGen.MNodeLogAddMemorySlab(builder, self.memory_slab)

        if self.memory_total:
            MNodeLogGen.MNodeLogAddMemoryTotal(builder, self.memory_total)

        if self.memory_used:
            MNodeLogGen.MNodeLogAddMemoryUsed(builder, self.memory_used)

        if self.disk_busy_time:
            MNodeLogGen.MNodeLogAddDiskBusyTime(builder, self.disk_busy_time)

        if self.disk_read_bytes:
            MNodeLogGen.MNodeLogAddDiskReadBytes(builder, self.disk_read_bytes)

        if self.disk_read_count:
            MNodeLogGen.MNodeLogAddDiskReadCount(builder, self.disk_read_count)

        if self.disk_read_merged_count:
            MNodeLogGen.MNodeLogAddDiskReadMergedCount(
                builder, self.disk_read_merged_count
            )

        if self.disk_read_time:
            MNodeLogGen.MNodeLogAddDiskReadTime(builder, self.disk_read_time)

        if self.disk_write_bytes:
            MNodeLogGen.MNodeLogAddDiskWriteBytes(builder, self.disk_write_bytes)

        if self.disk_write_count:
            MNodeLogGen.MNodeLogAddDiskWriteCount(builder, self.disk_write_count)

        if self.disk_write_merged_count:
            MNodeLogGen.MNodeLogAddDiskWriteMergedCount(
                builder, self.disk_write_merged_count
            )

        if self.disk_write_time:
            MNodeLogGen.MNodeLogAddDiskWriteTime(builder, self.disk_write_time)

        final = MNodeLogGen.MNodeLogEnd(builder)

        return final


@table("256a071f-5aeb-47f3-8786-97cd8281bdb7", build=MNodeLog.build, cast=MNodeLog.cast)
class MNodeLogs(MapTimestampUuidFlatBuffers):
    pass


class Schema(object):
    mnode_logs = None

    def __init__(self, db):
        self.db = db

    @staticmethod
    def attach(db):
        schema = Schema(db)

        schema.mnode_logs = db.attach_table(MNodeLogs)

        return schema
