<commit_before>from elixir import (Field, Unicode, Integer, Entity, Boolean,
        using_table_options, ManyToOne, session)
from elixir.events import after_insert
from sqlalchemy import UniqueConstraint
import uuid
import socket
import json

from astral.exceptions import NetworkError
from astral.models.base import BaseEntityMixin
from astral.models.event import Event
from astral.api.client import NodeAPI
from astral.conf import settings

import logging
log = logging.getLogger(__name__)


class Node(BaseEntityMixin, Entity):
    ip_address = Field(Unicode(15), nullable=False)
    uuid = Field(Integer, nullable=False, unique=True)
    port = Field(Integer, nullable=False)
    supernode = Field(Boolean, nullable=False, default=False)
    primary_supernode = ManyToOne('Node')
    rtt = Field(Integer)
    upstream = Field(Integer)
    downstream = Field(Integer)

    using_table_options(UniqueConstraint('ip_address', 'port'))

    API_FIELDS = ['ip_address', 'uuid', 'port', 'supernode',]
    RTT_STEP = 0.2
    BANDWIDTH_STEP = 0.2

    def __init__(self, *args, **kwargs):
        if not kwargs.get('uuid'):
            kwargs['uuid'] = settings.UUID_OVERRIDE or uuid.getnode()
            log.info("Using %s for this node's unique ID", kwargs['uuid'])

        if not kwargs.get('ip_address'):
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                s.connect((settings.ASTRAL_WEBSERVER, 80))
            except socket.gaierror, e:
                log.debug("Couldn't connect to the Astral webserver: %s", e)
                kwargs['ip_address'] = '127.0.0.1'
            else:
                kwargs['ip_address'] = s.getsockname()
            log.info("Using %s for this node's IP address", kwargs['ip_address'])

        if not kwargs.get('port'):
            kwargs['port'] = settings.PORT
            log.info("Using %s for this node's API port", kwargs['port'])
        return super(Node, self).__init__(*args, **kwargs)

    @classmethod
    def from_dict(cls, data):
        node = Node.get_by(uuid=data['uuid'])
        # TODO if we get ourselves back and should be a supernode, need to
        # update ourselves
        # TODO argh, ths makes running on one machine tough. need to be able to
        # override uuid for testing.
        if not node:
            node = cls(ip_address=data['ip_address'], uuid=data['uuid'],
                    port=data['port'], supernode=data.get('supernode', False))
            if 'primary_supernode' in data:
                node.primary_supernode = Node.get_by(
                        uuid=data['primary_supernode'])
        return node

    def update_rtt(self):
        sampled_rtt = NodeAPI(self.uri()).ping()
        self.rtt = self._weighted_average(self.rtt, self.RTT_STEP, sampled_rtt)
        return self.rtt

    def update_downstream(self):
        byte_count, transfer_time = NodeAPI(self.uri()).downstream_check()
        self.downstream = self._weighted_average(self.downstream,
                self.BANDWIDTH_STEP, byte_count / transfer_time)
        return self.downstream

    def update_upstream(self):
        byte_count, transfer_time = NodeAPI(self.uri()).upstream_check()
        self.upstream = self._weighted_average(self.upstream,<commit_msg>Fix supernode attribute name when constructing from JSON.<commit_after>from elixir import (Field, Unicode, Integer, Entity, Boolean,
        using_table_options, ManyToOne, session)
from elixir.events import after_insert
from sqlalchemy import UniqueConstraint
import uuid
import socket
import json

from astral.exceptions import NetworkError
from astral.models.base import BaseEntityMixin
from astral.models.event import Event
from astral.api.client import NodeAPI
from astral.conf import settings

import logging
log = logging.getLogger(__name__)


class Node(BaseEntityMixin, Entity):
    ip_address = Field(Unicode(15), nullable=False)
    uuid = Field(Integer, nullable=False, unique=True)
    port = Field(Integer, nullable=False)
    supernode = Field(Boolean, nullable=False, default=False)
    primary_supernode = ManyToOne('Node')
    rtt = Field(Integer)
    upstream = Field(Integer)
    downstream = Field(Integer)

    using_table_options(UniqueConstraint('ip_address', 'port'))

    API_FIELDS = ['ip_address', 'uuid', 'port', 'supernode',]
    RTT_STEP = 0.2
    BANDWIDTH_STEP = 0.2

    def __init__(self, *args, **kwargs):
        if not kwargs.get('uuid'):
            kwargs['uuid'] = settings.UUID_OVERRIDE or uuid.getnode()
            log.info("Using %s for this node's unique ID", kwargs['uuid'])

        if not kwargs.get('ip_address'):
            try:
                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                s.connect((settings.ASTRAL_WEBSERVER, 80))
            except socket.gaierror, e:
                log.debug("Couldn't connect to the Astral webserver: %s", e)
                kwargs['ip_address'] = '127.0.0.1'
            else:
                kwargs['ip_address'] = s.getsockname()
            log.info("Using %s for this node's IP address", kwargs['ip_address'])

        if not kwargs.get('port'):
            kwargs['port'] = settings.PORT
            log.info("Using %s for this node's API port", kwargs['port'])
        return super(Node, self).__init__(*args, **kwargs)

    @classmethod
    def from_dict(cls, data):
        node = Node.get_by(uuid=data['uuid'])
        # TODO if we get ourselves back and should be a supernode, need to
        # update ourselves
        # TODO argh, ths makes running on one machine tough. need to be able to
        # override uuid for testing.
        if not node:
            node = cls(ip_address=data['ip_address'], uuid=data['uuid'],
                    port=data['port'], supernode=data.get('supernode', False))
            if 'primary_supernode_uuid' in data:
                node.primary_supernode = Node.get_by(
                        uuid=data['primary_supernode_uuid'])
        return node

    def update_rtt(self):
        sampled_rtt = NodeAPI(self.uri()).ping()
        self.rtt = self._weighted_average(self.rtt, self.RTT_STEP, sampled_rtt)
        return self.rtt

    def update_downstream(self):
        byte_count, transfer_time = NodeAPI(self.uri()).downstream_check()
        self.downstream = self._weighted_average(self.downstream,
                self.BANDWIDTH_STEP, byte_count / transfer_time)
        return self.downstream

    def update_upstream(self):
        byte_count, transfer_time = NodeAPI(self.uri()).upstream_check()
        self.upstream = self._weighted_average(self.upstream,
{'fraction_non_alphanumeric': 0.1088404480775053, 'fraction_numerical': 0.004238570996064184, 'mean_word_length': 2.8660035108250437, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2446116', 'n_tokens_mistral': 2002, 'n_tokens_neox': 1940, 'n_words': 486}