<commit_before>import json
import time
import threading
from websocket_server import WebsocketServer


class Publisher(object):
    MIN_SEND_GAP_S = 0.1

    def __init__(self):
        self.frame = ""
        self.last_sent_frame = ""
        self.next_time_to_send = 0
        self.lock = threading.RLock()
        self.timer = None
        self.ws_server = WebsocketServer(9999, host="0.0.0.0")

        def send_to_client(client, server):
            with self.lock:
                server.send_message(client, self.frame)

        self.ws_server.set_fn_new_client(send_to_client)
        t = threading.Thread(target=self.ws_server.run_forever)
        t.daemon = True
        t.start()

    def build_graph(self, mon):
        nodes = []
        for cs in mon.cs.itervalues():
            nodes.append({"name": cs.name, "load": (100*cs.active_jobs)/cs.maxjobs})

        links = []
        for job in mon.jobs.itervalues():
            if job.host_id == 0:
                continue
            c, s = mon.cs[job.client_id], mon.cs[job.host_id]
            links.append({"source": c.name, "target": s.name, "value": 10})

        frame = {
            "timestamp": 0,
            "index": 0,
            "nodes": nodes,
            "links": links,
        }

        return json.dumps(frame)

    def publish(self, mon):
        with self.lock:
            self.frame = self.build_graph(mon)
            self.notify()

    def notify(self):
        now = time.time()
        with self.lock:
            if self.frame == self.last_sent_frame:
                # Frame hasn't changed, don't resend.
                return<commit_msg>Disambiguate between cs with same name.  (Should really do this using IDs).<commit_after>import json
import time
import threading
from websocket_server import WebsocketServer


class Publisher(object):
    MIN_SEND_GAP_S = 0.1

    def __init__(self):
        self.frame = ""
        self.last_sent_frame = ""
        self.next_time_to_send = 0
        self.lock = threading.RLock()
        self.timer = None
        self.ws_server = WebsocketServer(9999, host="0.0.0.0")

        def send_to_client(client, server):
            with self.lock:
                server.send_message(client, self.frame)

        self.ws_server.set_fn_new_client(send_to_client)
        t = threading.Thread(target=self.ws_server.run_forever)
        t.daemon = True
        t.start()

    def build_graph(self, mon):
        nodes = []
        used_names = {}
        def get_name(cs):
            if cs.id in used_names.iterkeys():
                return used_names[cs.id]

            name = cs.name
            ix = 0
            while name in used_names.itervalues():
                ix += 1
                name = cs.name + "({0})".format(ix)

            used_names[cs.id] = name
            return name

        for cs in mon.cs.itervalues():
            nodes.append({"name": get_name(cs), "load": (100*cs.active_jobs)/cs.maxjobs})

        links = []
        for job in mon.jobs.itervalues():
            if job.host_id not in mon.cs or job.client_id not in mon.cs:
                continue
            c, s = mon.cs[job.client_id], mon.cs[job.host_id]
            links.append({"source": get_name(c), "target": get_name(s), "value": 10})

        frame = {
            "timestamp": 0,
            "index": 0,
            "nodes": nodes,
            "links": links,
        }

        return json.dumps(frame)

    def publish(self, mon):
        with self.lock:
            self.frame = self.build_graph(mon)
            self.notify()

    def notify(self):
        now = time.time()
        with self.lock:
            if self.frame == self.last_sent_frame:
                # Frame hasn't changed, don't resend.
                return
{'fraction_non_alphanumeric': 0.11515957446808511, 'fraction_numerical': 0.010638297872340425, 'mean_word_length': 1.7492690058479532, 'pattern_counts': {'":': 18, '<': 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': '563022', 'n_tokens_mistral': 1225, 'n_tokens_neox': 1152, 'n_words': 253}