##############################################################################
#
#                        Crossbar.io FX
#     Copyright (C) Crossbar.io Technologies GmbH. All rights reserved.
#
##############################################################################

import pprint
import uuid

import numpy as np

import flatbuffers

from zlmdb import table, MapTimestampUuidFlatBuffers, MapTimestampUuidStringFlatBuffers, time_ns

from .gen.log import MNodeLog as MNodeLogGen
from .gen.log import MWorkerLog as MWorkerLogGen


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 MrealmIdAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10))
        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(12))
        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

        # PK: uint64
        self._timestamp = None

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

        # period: uint32;
        self._period = None

        # mrealm_id: [uint8] (uuid);
        self._mrealm_id = None

        # state: MNodeState;
        self._state = None

        # session: uint64;
        self._session = None

        # sent: uint64;
        self._sent = None

        # seq: uint64;
        self._seq = None

        # controllers: uint16;
        self._controllers = 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

        # hostmonitors: uint16;
        self._hostmonitors = 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(mrealm_id, 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._mrealm_id = mrealm_id
        obj._node_id = node_id
        obj._timestamp = np.datetime64(time_ns(), 'ns')
        obj._period = heartbeat.get('period', None)
        obj._state = heartbeat.get('state', 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._controllers = workers.get('controller', None)
        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)
        obj._hostmonitors = workers.get('hostmonitor', 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': int(self.timestamp) if self.timestamp else None,
            'period': self.period,
            'mrealm_id': str(self.mrealm_id) if self.mrealm_id else None,
            'node_id': str(self.node_id) if self.node_id else None,
            'state': self.state,
            'session': self.session,
            'sent': self.sent,
            'seq': self.seq,
            'workers': {
                'controller': self.controllers,
                'router': self.routers,
                'container': self.containers,
                'guest': self.guests,
                'proxy': self.proxies,
                'xbrmm': self.marketmakers,
                'hostmonitor': self.hostmonitors,
            },
            '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 period(self):
        if self._period is None and self._from_fbs:
            self._period = self._from_fbs.Period()
        return self._period

    @period.setter
    def period(self, value):
        assert value is None or type(value) == int
        self._period = 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=bytes(_node_id))
        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 mrealm_id(self):
        if self._mrealm_id is None and self._from_fbs:
            if self._from_fbs.MrealmIdLength():
                _mrealm_id = self._from_fbs.MrealmIdAsBytes()
                if _mrealm_id:
                    _mrealm_id = bytes(_mrealm_id)
                    assert type(_mrealm_id) == bytes, 'mrealm_id must be binary, was "{}"'.format(type(_mrealm_id))
                    assert len(_mrealm_id) == 16, 'mrealm_id must have length 16, was {} / {}: {}'.format(len(_mrealm_id), self._from_fbs.MrealmIdLength(), _mrealm_id)
                    self._mrealm_id = uuid.UUID(bytes=_mrealm_id)
        return self._mrealm_id

    @mrealm_id.setter
    def mrealm_id(self, value):
        assert value is None or isinstance(value, uuid.UUID)
        self._mrealm_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 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 controllers(self):
        if self._controllers is None and self._from_fbs:
            self._controllers = self._from_fbs.Controllers()
        return self._controllers

    @controllers.setter
    def controllers(self, value):
        assert value is None or type(value) == int
        self._controllers = 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 hostmonitors(self):
        if self._hostmonitors is None and self._from_fbs:
            self._hostmonitors = self._from_fbs.Hostmonitors()
        return self._hostmonitors

    @hostmonitors.setter
    def hostmonitors(self, value):
        assert value is None or type(value) == int
        self._hostmonitors = 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):
        return MNodeLog(_MNodeLogGen.GetRootAsMNodeLog(buf, 0))

    def build(self, builder):

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

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

        MNodeLogGen.MNodeLogStart(builder)

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

        if self.period:
            MNodeLogGen.MNodeLogAddPeriod(builder, int(self.period))

        if mrealm_id:
            MNodeLogGen.MNodeLogAddMrealmId(builder, mrealm_id)

        if node_id:
            MNodeLogGen.MNodeLogAddNodeId(builder, node_id)

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

        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.controllers:
            MNodeLogGen.MNodeLogAddControllers(builder, self.controllers)

        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.hostmonitors:
            MNodeLogGen.MNodeLogAddHostmonitors(builder, self.hostmonitors)

        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):
    """
    Persisted managed node heartbeat log records.

    Map :class:`zlmdb.MapTimestampUuidFlatBuffers` from ``(timestamp, node_id)`` to :class:`crossbarfx.cfxdb.logs.MNodeLog`
    """


class _MWorkerLogGen(MWorkerLogGen.MWorkerLog):
    """
    Expand methods on the class code generated by flatc.

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

    @classmethod
    def GetRootAsMWorkerLog(cls, buf, offset):
        n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset)
        x = _MWorkerLogGen()
        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 MrealmIdAsBytes(self):
        o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(12))
        if o != 0:
            _off = self._tab.Vector(o)
            _len = self._tab.VectorLen(o)
            return memoryview(self._tab.Bytes)[_off:_off+_len]
        return None


class MWorkerLog(object):

    WORKER_TYPES = {
        '': 0,
        'router': 1,
        'container': 2,
        'guest': 3,
        'testee': 4,
        'proxy': 5,
        'xbrmm': 6,
        'hostmonitor': 7,
        'controller': 8,
    }
    WORKER_TYPENAMES = {
        0: '',
        1: 'router',
        2: 'container',
        3: 'guest',
        4: 'testee',
        5: 'proxy',
        6: 'xbrmm',
        7: 'hostmonitor',
        8: 'controller',
    }

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

        # PK uint64
        self._timestamp = None

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

        # PK worker_id: string;
        self._worker_id = None

        # period: uint32;
        self._period = None

        # mrealm_id: [uint8] (uuid);
        self._mrealm_id = None

        # _type: MWorkerType;
        self._type = None

        # state: MWorkerState;
        self._state = None

        # sent: uint64;
        self._sent = None

        # seq: uint64;
        self._seq = None

        # num_fds: uint32;
        self._num_fds = None

        # num_threads: uint16;
        self._num_threads = None

        # num_ctx_switches_involuntary: uint64;
        self._num_ctx_switches_involuntary = None

        # num_ctx_switches_involuntary_per_sec: uint32;
        self._num_ctx_switches_involuntary_per_sec = None

        # num_ctx_switches_voluntary: uint64;
        self._num_ctx_switches_voluntary = None

        # num_ctx_switches_voluntary_per_sec: uint32;
        self._num_ctx_switches_voluntary_per_sec = None

        # cpu_system: float;
        self._cpu_system = None

        # cpu_system_per_sec: float;
        self._cpu_system_per_sec = None

        # cpu_wait: float;
        self._cpu_wait = None

        # cpu_wait_per_sec: float;
        self._cpu_wait_per_sec = None

        # cpu_user: float;
        self._cpu_user = None

        # cpu_user_per_sec: float;
        self._cpu_user_per_sec = None

        # read_bytes: uint64;
        self._read_bytes = None

        # read_bytes_per_sec: uint64;
        self._read_bytes_per_sec = None

        # read_ios: uint64;
        self._read_ios = None

        # read_ios_per_sec: uint64;
        self._read_ios_per_sec = None

        # write_bytes: uint64;
        self._write_bytes = None

        # write_bytes_per_sec: uint64;
        self._write_bytes_per_sec = None

        # write_ios: uint64;
        self._write_ios = None

        # write_ios_per_sec: uint64;
        self._write_ios_per_sec = None

        # sent_bytes: uint64;
        self._sent_bytes = None

        # sent_bytes_per_sec: uint64;
        self._sent_bytes_per_sec = None

        # sent_ios: uint64;
        self._sent_ios = None

        # sent_ios_per_sec: uint64;
        self._sent_ios_per_sec = None

        # recv_bytes: uint64;
        self._recv_bytes = None

        # recv_bytes_per_sec: uint64;
        self._recv_bytes_per_sec = None

        # recv_ios: uint64;
        self._recv_ios = None

        # recv_ios_per_sec: uint64;
        self._recv_ios_per_sec = None

        # router_roles: uint64;
        self._router_roles = None

        # router_sessions: uint64;
        self._router_sessions = None

        # recv_call: uint64;
        self._recv_call = None

        # recv_yield: uint64;
        self._recv_yield = None

        # sent_invocation: uint64;
        self._sent_invocation = None

        # sent_result: uint64;
        self._sent_result = None

        # recv_publish: uint64;
        self._recv_publish = None

        # sent_published: uint64;
        self._sent_published = None

        # sent_event: uint64;
        self._sent_event = None

        # recv_register: uint64;
        self._recv_register = None

        # sent_registered: uint64;
        self._sent_registered = None

        # recv_subscribe: uint64;
        self._recv_subscribe = None

        # sent_subscribed: uint64;
        self._sent_subscribed = None

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

        obj = MWorkerLog()
        obj._timestamp = np.datetime64(time_ns(), 'ns')
        obj._period = heartbeat.get('period', None)
        obj._mrealm_id = mrealm_id
        obj._node_id = node_id
        obj._worker_id = worker_id
        obj._sent = np.datetime64(heartbeat['timestamp'], 'ns') if heartbeat.get('timestamp', None) else None
        obj._seq = heartbeat.get('seq', None)
        obj._type = MWorkerLog.WORKER_TYPES.get(heartbeat.get('type', None), None)
        obj._state = heartbeat.get('state', None)

        process = heartbeat.get('process', {})
        obj._num_fds = process.get('num_fds', 0)
        obj._num_threads = process.get('num_threads', 0)
        obj._num_ctx_switches_involuntary = process.get('num_ctx_switches_involuntary', 0)
        obj._num_ctx_switches_involuntary_per_sec = process.get('num_ctx_switches_involuntary_per_sec', 0)
        obj._num_ctx_switches_voluntary = process.get('num_ctx_switches_voluntary', 0)
        obj._num_ctx_switches_voluntary_per_sec = process.get('num_ctx_switches_voluntary_per_sec', 0)
        obj._cpu_system = process.get('cpu_system', 0)
        obj._cpu_system_per_sec = process.get('cpu_system_per_sec', 0)
        obj._cpu_wait = process.get('cpu_wait', 0)
        obj._cpu_wait_per_sec = process.get('cpu_wait_per_sec', 0)
        obj._cpu_user = process.get('cpu_user', 0)
        obj._cpu_user_per_sec = process.get('cpu_user_per_sec', 0)
        obj._read_bytes = process.get('read_bytes', 0)
        obj._read_bytes_per_sec = process.get('read_bytes_per_sec', 0)
        obj._read_ios = process.get('read_ios', 0)
        obj._read_ios_per_sec = process.get('read_ios_per_sec', 0)
        obj._write_bytes = process.get('write_bytes', 0)
        obj._write_bytes_per_sec = process.get('write_bytes_per_sec', 0)
        obj._write_bytes_per_sec = process.get('write_bytes_per_sec', 0)
        obj._write_ios_per_sec = process.get('write_ios_per_sec', 0)
        obj._sent_bytes = process.get('sent_bytes', 0)
        obj._sent_bytes_per_sec = process.get('sent_bytes_per_sec', 0)
        obj._sent_ios = process.get('sent_ios', 0)
        obj._sent_ios_per_sec = process.get('sent_ios_per_sec', 0)
        obj._recv_bytes = process.get('recv_bytes', 0)
        obj._recv_bytes_per_sec = process.get('recv_bytes_per_sec', 0)
        obj._recv_ios = process.get('recv_ios', 0)
        obj._recv_ios_per_sec = process.get('recv_ios_per_sec', 0)

        router = heartbeat.get('router', {})
        obj._router_roles = router.get('roles', 0)
        obj._router_sessions = router.get('sessions', 0)

        messages = router.get('messages', {})
        obj._recv_call = messages.get('call', 0)
        obj._recv_yield = messages.get('yield', 0)
        obj._sent_invocation = messages.get('invocation', 0)
        obj._sent_result = messages.get('result', 0)
        obj._recv_publish = messages.get('publish', 0)
        obj._sent_published = messages.get('published', 0)
        obj._sent_event = messages.get('event', 0)
        obj._recv_register = messages.get('register', 0)
        obj._sent_registered = messages.get('registered', 0)
        obj._recv_subscribe = messages.get('subscribe', 0)
        obj._sent_subscribed = messages.get('subscribed', 0)

        return obj

    def marshal(self):
        obj = {
            'timestamp': int(self.timestamp) if self.timestamp else None,
            'period': self.period,
            'mrealm_id': str(self.mrealm_id) if self.mrealm_id else None,
            'node_id': str(self.node_id) if self.node_id else None,
            'worker_id': self.worker_id,
            'sent': self.sent,
            'seq': self.seq,
            'type': MWorkerLog.WORKER_TYPENAMES.get(self.type, None),
            'state': self.state,
            'process': {
                'num_fds': self.num_fds,
                'num_threads': self.num_threads,
                'num_ctx_switches_involuntary': self.num_ctx_switches_involuntary,
                'num_ctx_switches_involuntary_per_sec': self.num_ctx_switches_involuntary_per_sec,
                'num_ctx_switches_voluntary': self.num_ctx_switches_voluntary,
                'num_ctx_switches_voluntary_per_sec': self.num_ctx_switches_voluntary_per_sec,
                'cpu_system': self.cpu_system,
                'cpu_system_per_sec': self.cpu_system_per_sec,
                'cpu_wait': self.cpu_wait,
                'cpu_wait_per_sec': self.cpu_wait_per_sec,
                'cpu_user': self.cpu_user,
                'cpu_user_per_sec': self.cpu_user_per_sec,
                'read_bytes': self.read_bytes,
                'read_bytes_per_sec': self.read_bytes_per_sec,
                'read_ios': self.read_ios,
                'read_ios_per_sec': self.read_ios_per_sec,
                'write_bytes': self.write_bytes,
                'write_bytes_per_sec': self.write_bytes_per_sec,
                'write_ios': self.write_ios,
                'write_ios_per_sec': self.write_ios_per_sec,
                'sent_bytes': self.sent_bytes,
                'sent_bytes_per_sec': self.sent_bytes_per_sec,
                'sent_ios': self.sent_ios,
                'sent_ios_per_sec': self.sent_ios_per_sec,
                'recv_bytes': self.recv_bytes,
                'recv_bytes_per_sec': self.recv_bytes_per_sec,
                'recv_ios': self.recv_ios,
                'recv_ios_per_sec': self.recv_ios_per_sec,
            },
        }
        if self.type == 1:
            obj['router'] = {
                'roles': self.router_roles,
                'sessions': self.router_sessions,
                'messages': {
                    'call': self.recv_call,
                    'yield': self.recv_yield,
                    'invocation': self.sent_invocation,
                    'result': self.sent_result,
                    'publish': self.recv_publish,
                    'published': self.sent_published,
                    'event': self.sent_event,
                    'register': self.recv_register,
                    'registered': self.sent_registered,
                    'subscribe': self.recv_subscribe,
                    'subscribed': self.sent_subscribed,
                }
            }
        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 mrealm_id(self):
        if self._mrealm_id is None and self._from_fbs:
            if self._from_fbs.NodeIdLength():
                _mrealm_id = self._from_fbs.MrealmIdAsBytes()
                self._mrealm_id = uuid.UUID(bytes=bytes(_mrealm_id))
        return self._mrealm_id

    @mrealm_id.setter
    def mrealm_id(self, value):
        assert value is None or isinstance(value, uuid.UUID)
        self._mrealm_id = 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=bytes(_node_id))
        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 worker_id(self):
        if self._worker_id is None and self._from_fbs:
            _worker_id = self._from_fbs.WorkerId()
            if _worker_id:
                self._worker_id = _worker_id.decode('utf8')
        return self._worker_id

    @worker_id.setter
    def worker_id(self, value):
        assert value is None or type(value) == str
        self._worker_id = value

    @property
    def period(self):
        if self._period is None and self._from_fbs:
            self._period = self._from_fbs.Period()
        return self._period

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

    @property
    def type(self):
        if self._type is None and self._from_fbs:
            self._type = self._from_fbs.Type()
        return self._type

    @type.setter
    def type(self, value):
        assert value is None or type(value) == int
        self._type = 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 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

    #### actual statistics (worker metering data attributes)

    @property
    def num_fds(self):
        if self._num_fds is None and self._from_fbs:
            self._num_fds = self._from_fbs.NumFds()
        return self._num_fds

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

    @property
    def num_threads(self):
        if self._num_threads is None and self._from_fbs:
            self._num_threads = self._from_fbs.NumThreads()
        return self._num_threads

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

    @property
    def num_ctx_switches_involuntary(self):
        if self._num_ctx_switches_involuntary is None and self._from_fbs:
            self._num_ctx_switches_involuntary = self._from_fbs.NumCtxSwitchesInvoluntary()
        return self._num_ctx_switches_involuntary

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

    @property
    def num_ctx_switches_involuntary_per_sec(self):
        if self._num_ctx_switches_involuntary_per_sec is None and self._from_fbs:
            self._num_ctx_switches_involuntary_per_sec = self._from_fbs.NumCtxSwitchesInvoluntaryPerSec()
        return self._num_ctx_switches_involuntary_per_sec

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

    @property
    def num_ctx_switches_voluntary(self):
        if self._num_ctx_switches_voluntary is None and self._from_fbs:
            self._num_ctx_switches_voluntary = self._from_fbs.NumCtxSwitchesVoluntary()
        return self._num_ctx_switches_voluntary

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

    @property
    def num_ctx_switches_voluntary_per_sec(self):
        if self._num_ctx_switches_voluntary_per_sec is None and self._from_fbs:
            self._num_ctx_switches_voluntary_per_sec = self._from_fbs.NumCtxSwitchesVoluntaryPerSec()
        return self._num_ctx_switches_voluntary_per_sec

    @num_ctx_switches_voluntary_per_sec.setter
    def num_ctx_switches_voluntary_per_sec(self, value):
        assert value is None or type(value) == int
        self._num_ctx_switches_voluntary_per_sec = 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_system_per_sec(self):
        if self._cpu_system_per_sec is None and self._from_fbs:
            self._cpu_system_per_sec = self._from_fbs.CpuSystemPerSec()
        return self._cpu_system_per_sec

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

    @property
    def cpu_wait(self):
        if self._cpu_wait is None and self._from_fbs:
            self._cpu_wait = self._from_fbs.CpuWait()
        return self._cpu_wait

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

    @property
    def cpu_wait_per_sec(self):
        if self._cpu_wait_per_sec is None and self._from_fbs:
            self._cpu_wait_per_sec = self._from_fbs.CpuWaitPerSec()
        return self._cpu_wait_per_sec

    @cpu_wait_per_sec.setter
    def cpu_wait_per_sec(self, value):
        assert value is None or type(value) == float
        self._cpu_wait_per_sec = 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 cpu_user_per_sec(self):
        if self._cpu_user_per_sec is None and self._from_fbs:
            self._cpu_user_per_sec = self._from_fbs.CpuUserPerSec()
        return self._cpu_user_per_sec

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

    @property
    def read_bytes(self):
        if self._read_bytes is None and self._from_fbs:
            self._read_bytes = self._from_fbs.ReadBytes()
        return self._read_bytes

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

    @property
    def read_bytes_per_sec(self):
        if self._read_bytes_per_sec is None and self._from_fbs:
            self._read_bytes_per_sec = self._from_fbs.ReadBytesPerSec()
        return self._read_bytes_per_sec

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

    @property
    def read_ios(self):
        if self._read_ios is None and self._from_fbs:
            self._read_ios = self._from_fbs.ReadIos()
        return self._read_ios

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

    @property
    def read_ios_per_sec(self):
        if self._read_ios_per_sec is None and self._from_fbs:
            self._read_ios_per_sec = self._from_fbs.ReadIosPerSec()
        return self._read_ios_per_sec

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

    @property
    def write_bytes(self):
        if self._write_bytes is None and self._from_fbs:
            self._write_bytes = self._from_fbs.WriteBytes()
        return self._write_bytes

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

    @property
    def write_bytes_per_sec(self):
        if self._write_bytes_per_sec is None and self._from_fbs:
            self._write_bytes_per_sec = self._from_fbs.WriteBytesPerSec()
        return self._write_bytes_per_sec

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

    @property
    def write_ios(self):
        if self._write_ios is None and self._from_fbs:
            self._write_ios = self._from_fbs.WriteIos()
        return self._write_ios

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

    @property
    def write_ios_per_sec(self):
        if self._write_ios_per_sec is None and self._from_fbs:
            self._write_ios_per_sec = self._from_fbs.WriteIosPerSec()
        return self._write_ios_per_sec

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

    @property
    def sent_bytes(self):
        if self._sent_bytes is None and self._from_fbs:
            self._sent_bytes = self._from_fbs.SentBytes()
        return self._sent_bytes

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

    @property
    def sent_bytes_per_sec(self):
        if self._sent_bytes_per_sec is None and self._from_fbs:
            self._sent_bytes_per_sec = self._from_fbs.SentBytesPerSec()
        return self._sent_bytes_per_sec

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

    @property
    def sent_ios(self):
        if self._sent_ios is None and self._from_fbs:
            self._sent_ios = self._from_fbs.SentIos()
        return self._sent_ios

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

    @property
    def sent_ios_per_sec(self):
        if self._sent_ios_per_sec is None and self._from_fbs:
            self._sent_ios_per_sec = self._from_fbs.SentIosPerSec()
        return self._sent_ios_per_sec

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

    @property
    def recv_bytes(self):
        if self._recv_bytes is None and self._from_fbs:
            self._recv_bytes = self._from_fbs.RecvBytes()
        return self._recv_bytes

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

    @property
    def recv_bytes_per_sec(self):
        if self._recv_bytes_per_sec is None and self._from_fbs:
            self._recv_bytes_per_sec = self._from_fbs.RecvBytesPerSec()
        return self._recv_bytes_per_sec

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

    @property
    def recv_ios(self):
        if self._recv_ios is None and self._from_fbs:
            self._recv_ios = self._from_fbs.RecvIos()
        return self._recv_ios

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

    @property
    def recv_ios_per_sec(self):
        if self._recv_ios_per_sec is None and self._from_fbs:
            self._recv_ios_per_sec = self._from_fbs.RecvIosPerSec()
        return self._recv_ios_per_sec

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

    @property
    def router_roles(self):
        if self._router_roles is None and self._from_fbs:
            self._router_roles = self._from_fbs.RouterRoles()
        return self._router_roles

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

    @property
    def router_sessions(self):
        if self._router_sessions is None and self._from_fbs:
            self._router_sessions = self._from_fbs.RouterSessions()
        return self._router_sessions

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

    @property
    def recv_call(self):
        if self._recv_call is None and self._from_fbs:
            self._recv_call = self._from_fbs.RecvCall()
        return self._recv_call

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

    @property
    def recv_yield(self):
        if self._recv_yield is None and self._from_fbs:
            self._recv_yield = self._from_fbs.RecvYield()
        return self._recv_yield

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

    @property
    def sent_invocation(self):
        if self._sent_invocation is None and self._from_fbs:
            self._sent_invocation = self._from_fbs.SentInvocation()
        return self._sent_invocation

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

    @property
    def sent_result(self):
        if self._sent_result is None and self._from_fbs:
            self._sent_result = self._from_fbs.SentResult()
        return self._sent_result

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

    @property
    def recv_publish(self):
        if self._recv_publish is None and self._from_fbs:
            self._recv_publish = self._from_fbs.RecvPublish()
        return self._recv_publish

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

    @property
    def sent_published(self):
        if self._sent_published is None and self._from_fbs:
            self._sent_published = self._from_fbs.SentPublished()
        return self._sent_published

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

    @property
    def sent_event(self):
        if self._sent_event is None and self._from_fbs:
            self._sent_event = self._from_fbs.SentEvent()
        return self._sent_event

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

    @property
    def recv_register(self):
        if self._recv_register is None and self._from_fbs:
            self._recv_register = self._from_fbs.RecvRegister()
        return self._recv_register

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

    @property
    def sent_registered(self):
        if self._sent_registered is None and self._from_fbs:
            self._sent_registered = self._from_fbs.SentRegistered()
        return self._sent_registered

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

    @property
    def recv_subscribe(self):
        if self._recv_subscribe is None and self._from_fbs:
            self._recv_subscribe = self._from_fbs.RecvSubscribe()
        return self._recv_subscribe

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

    @property
    def sent_subscribed(self):
        if self._sent_subscribed is None and self._from_fbs:
            self._sent_subscribed = self._from_fbs.SentSubscribed()
        return self._sent_subscribed

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

    @staticmethod
    def cast(buf):
        return MWorkerLog(_MWorkerLogGen.GetRootAsMWorkerLog(buf, 0))

    def build(self, builder):

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

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

        worker_id = None
        if self.worker_id:
            worker_id = builder.CreateString(self.worker_id)

        MWorkerLogGen.MWorkerLogStart(builder)

        if self.timestamp:
            MWorkerLogGen.MWorkerLogAddTimestamp(builder, int(self.timestamp))

        if mrealm_id:
            MWorkerLogGen.MWorkerLogAddMrealmId(builder, mrealm_id)

        if node_id:
            MWorkerLogGen.MWorkerLogAddNodeId(builder, node_id)

        if worker_id:
            MWorkerLogGen.MWorkerLogAddWorkerId(builder, worker_id)

        if self.period:
            MWorkerLogGen.MWorkerLogAddPeriod(builder, self.period)

        if self.type:
            MWorkerLogGen.MWorkerLogAddType(builder, self.type)

        if self.state:
            MWorkerLogGen.MWorkerLogAddState(builder, self.state)

        if self.sent:
            MWorkerLogGen.MWorkerLogAddSent(builder, int(self.sent))

        if self.seq:
            MWorkerLogGen.MWorkerLogAddSeq(builder, self.seq)

        if self.num_fds:
            MWorkerLogGen.MWorkerLogAddNumFds(builder, self.num_fds)

        if self.num_threads:
            MWorkerLogGen.MWorkerLogAddNumThreads(builder, self.num_threads)

        if self.num_ctx_switches_involuntary:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesInvoluntary(builder, self.num_ctx_switches_involuntary)

        if self.num_ctx_switches_involuntary_per_sec:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesInvoluntaryPerSec(builder, self.num_ctx_switches_involuntary_per_sec)

        if self.num_ctx_switches_voluntary:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesVoluntary(builder, self.num_ctx_switches_voluntary)

        if self.num_ctx_switches_voluntary_per_sec:
            MWorkerLogGen.MWorkerLogAddNumCtxSwitchesVoluntaryPerSec(builder, self.num_ctx_switches_voluntary_per_sec)

        if self.cpu_system:
            MWorkerLogGen.MWorkerLogAddCpuSystem(builder, self.cpu_system)

        if self.cpu_system_per_sec:
            MWorkerLogGen.MWorkerLogAddCpuSystemPerSec(builder, self.cpu_system_per_sec)

        if self.cpu_wait:
            MWorkerLogGen.MWorkerLogAddCpuWait(builder, self.cpu_wait)

        if self.cpu_wait_per_sec:
            MWorkerLogGen.MWorkerLogAddCpuWaitPerSec(builder, self.cpu_wait_per_sec)

        if self.cpu_user:
            MWorkerLogGen.MWorkerLogAddCpuUser(builder, self.cpu_user)

        if self.cpu_user_per_sec:
            MWorkerLogGen.MWorkerLogAddCpuUserPerSec(builder, self.cpu_user_per_sec)

        if self.read_bytes:
            MWorkerLogGen.MWorkerLogAddReadBytes(builder, self.read_bytes)

        if self.read_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddReadBytesPerSec(builder, self.read_bytes_per_sec)

        if self.read_ios:
            MWorkerLogGen.MWorkerLogAddReadIos(builder, self.read_ios)

        if self.read_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddReadIosPerSec(builder, self.read_ios_per_sec)

        if self.write_bytes:
            MWorkerLogGen.MWorkerLogAddWriteBytes(builder, self.write_bytes)

        if self.write_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddWriteBytesPerSec(builder, self.write_bytes_per_sec)

        if self.write_ios:
            MWorkerLogGen.MWorkerLogAddWriteIos(builder, self.write_ios)

        if self.write_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddWriteIosPerSec(builder, self.write_ios_per_sec)

        if self.sent_bytes:
            MWorkerLogGen.MWorkerLogAddSentBytes(builder, self.sent_bytes)

        if self.sent_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddSentBytesPerSec(builder, self.sent_bytes_per_sec)

        if self.sent_ios:
            MWorkerLogGen.MWorkerLogAddSentIos(builder, self.sent_ios)

        if self.sent_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddSentIosPerSec(builder, self.sent_ios_per_sec)

        if self.recv_bytes:
            MWorkerLogGen.MWorkerLogAddRecvBytes(builder, self.recv_bytes)

        if self.recv_bytes_per_sec:
            MWorkerLogGen.MWorkerLogAddRecvBytesPerSec(builder, self.recv_bytes_per_sec)

        if self.recv_ios:
            MWorkerLogGen.MWorkerLogAddRecvIos(builder, self.recv_ios)

        if self.recv_ios_per_sec:
            MWorkerLogGen.MWorkerLogAddRecvIosPerSec(builder, self.recv_ios_per_sec)

        if self.router_roles:
            MWorkerLogGen.MWorkerLogAddRouterRoles(builder, self.router_roles)

        if self.router_sessions:
            MWorkerLogGen.MWorkerLogAddRouterSessions(builder, self.router_sessions)

        if self.recv_call:
            MWorkerLogGen.MWorkerLogAddRecvCall(builder, self.recv_call)

        if self.recv_yield:
            MWorkerLogGen.MWorkerLogAddRecvYield(builder, self.recv_yield)

        if self.sent_invocation:
            MWorkerLogGen.MWorkerLogAddSentInvocation(builder, self.sent_invocation)

        if self.sent_result:
            MWorkerLogGen.MWorkerLogAddSentResult(builder, self.sent_result)

        if self.recv_publish:
            MWorkerLogGen.MWorkerLogAddRecvPublish(builder, self.recv_publish)

        if self.sent_published:
            MWorkerLogGen.MWorkerLogAddSentPublished(builder, self.sent_published)

        if self.sent_event:
            MWorkerLogGen.MWorkerLogAddSentEvent(builder, self.sent_event)

        if self.recv_register:
            MWorkerLogGen.MWorkerLogAddRecvRegister(builder, self.recv_register)

        if self.sent_registered:
            MWorkerLogGen.MWorkerLogAddSentRegistered(builder, self.sent_registered)

        if self.recv_subscribe:
            MWorkerLogGen.MWorkerLogAddRecvSubscribe(builder, self.recv_subscribe)

        if self.sent_subscribed:
            MWorkerLogGen.MWorkerLogAddSentSubscribed(builder, self.sent_subscribed)

        final = MWorkerLogGen.MWorkerLogEnd(builder)

        return final


@table('5ceaa500-4832-451c-adf4-4fc4968cece0', build=MWorkerLog.build, cast=MWorkerLog.cast)
class MWorkerLogs(MapTimestampUuidStringFlatBuffers):
    """
    Persisted managed node worker heartbeat log records.

    Map :class:`zlmdb.MapTimestampUuidStringFlatBuffers` from ``(timestamp, node_id, worker_id)`` to :class:`crossbarfx.cfxdb.logs.MWorkerLog`
    """


class Schema(object):

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

    # mnode_logs: MNodeLogs
    mnode_logs = None
    """
    Managed node log records.
    """

    # mworker_logs: MWorkerLogs
    mworker_logs = None
    """
    Managed node worker log records.
    """

    @staticmethod
    def attach(db):
        """
        Factory to create a schema from attaching to a database. The schema tables
        will be automatically mapped as persistant maps and attached to the
        database slots.

        :param db: zlmdb.Database
        :return: object of Schema
        """
        schema = Schema(db)

        schema.mnode_logs = db.attach_table(MNodeLogs)
        schema.mworker_logs = db.attach_table(MWorkerLogs)

        return schema
