mirror of https://github.com/craigerl/aprsd.git
Compare commits
6 Commits
94f36e0aad
...
026dc6e376
Author | SHA1 | Date |
---|---|---|
Hemna | 026dc6e376 | |
Hemna | f59b65d13c | |
Hemna | 5ff62c9bdf | |
Hemna | 5fa4eaf909 | |
Hemna | f34120c2df | |
Hemna | 3bef1314f8 |
|
@ -1,5 +1,4 @@
|
|||
from collections import OrderedDict
|
||||
from collections.abc import MutableMapping
|
||||
import logging
|
||||
import threading
|
||||
|
||||
|
@ -14,7 +13,7 @@ CONF = cfg.CONF
|
|||
LOG = logging.getLogger("APRSD")
|
||||
|
||||
|
||||
class PacketList(MutableMapping, objectstore.ObjectStoreMixin):
|
||||
class PacketList(objectstore.ObjectStoreMixin):
|
||||
_instance = None
|
||||
lock = threading.Lock()
|
||||
_total_rx: int = 0
|
||||
|
@ -57,10 +56,15 @@ class PacketList(MutableMapping, objectstore.ObjectStoreMixin):
|
|||
self._add(packet)
|
||||
|
||||
def _add(self, packet):
|
||||
if packet.key in self.data["packets"]:
|
||||
self.data["packets"].move_to_end(packet.key)
|
||||
elif len(self.data["packets"]) == self.maxlen:
|
||||
self.data["packets"].popitem(last=False)
|
||||
self.data["packets"][packet.key] = packet
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
def copy(self):
|
||||
return self.d.copy()
|
||||
return self.data.copy()
|
||||
|
||||
@property
|
||||
def maxlen(self):
|
||||
|
@ -68,25 +72,9 @@ class PacketList(MutableMapping, objectstore.ObjectStoreMixin):
|
|||
|
||||
@wrapt.synchronized(lock)
|
||||
def find(self, packet):
|
||||
return self.get(packet.key)
|
||||
|
||||
def __getitem__(self, key):
|
||||
# self.d.move_to_end(key)
|
||||
return self.data["packets"][key]
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key in self.data["packets"]:
|
||||
self.data["packets"].move_to_end(key)
|
||||
elif len(self.data["packets"]) == self.maxlen:
|
||||
self.data["packets"].popitem(last=False)
|
||||
self.data["packets"][key] = value
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self.data["packets"][key]
|
||||
|
||||
def __iter__(self):
|
||||
return self.data["packets"].__iter__()
|
||||
return self.data["packets"][packet.key]
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
def __len__(self):
|
||||
return len(self.data["packets"])
|
||||
|
||||
|
@ -98,13 +86,13 @@ class PacketList(MutableMapping, objectstore.ObjectStoreMixin):
|
|||
def total_tx(self):
|
||||
return self._total_tx
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
def stats(self, serializable=False) -> dict:
|
||||
stats = {
|
||||
"total_tracked": self.total_tx() + self.total_rx(),
|
||||
"rx": self.total_rx(),
|
||||
"tx": self.total_tx(),
|
||||
"total_tracked": self._total_rx + self._total_rx,
|
||||
"rx": self._total_rx,
|
||||
"tx": self._total_tx,
|
||||
"types": self.data["types"],
|
||||
"packets": self.data["packets"],
|
||||
}
|
||||
|
||||
return stats
|
||||
|
|
|
@ -96,6 +96,7 @@ class APRSDDupeRXThread(APRSDRXThread):
|
|||
packet = self._client.decode_packet(*args, **kwargs)
|
||||
# LOG.debug(raw)
|
||||
packet_log.log(packet)
|
||||
pkt_list = packets.PacketList()
|
||||
|
||||
if isinstance(packet, packets.AckPacket):
|
||||
# We don't need to drop AckPackets, those should be
|
||||
|
@ -106,7 +107,6 @@ class APRSDDupeRXThread(APRSDRXThread):
|
|||
# For RF based APRS Clients we can get duplicate packets
|
||||
# So we need to track them and not process the dupes.
|
||||
found = False
|
||||
pkt_list = packets.PacketList()
|
||||
try:
|
||||
# Find the packet in the list of already seen packets
|
||||
# Based on the packet.key
|
||||
|
@ -157,6 +157,7 @@ class APRSDProcessPacketThread(APRSDThread):
|
|||
"""We got an ack for a message, no need to resend it."""
|
||||
ack_num = packet.msgNo
|
||||
LOG.debug(f"Got ack for message {ack_num}")
|
||||
packets.PacketList().rx(packet)
|
||||
pkt_tracker = packets.PacketTrack()
|
||||
pkt_tracker.remove(ack_num)
|
||||
|
||||
|
@ -164,6 +165,7 @@ class APRSDProcessPacketThread(APRSDThread):
|
|||
"""We got a reject message for a packet. Stop sending the message."""
|
||||
ack_num = packet.msgNo
|
||||
LOG.debug(f"Got REJECT for message {ack_num}")
|
||||
packets.PacketList().rx(packet)
|
||||
pkt_tracker = packets.PacketTrack()
|
||||
pkt_tracker.remove(ack_num)
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import threading
|
|||
import time
|
||||
|
||||
from oslo_config import cfg
|
||||
import wrapt
|
||||
|
||||
from aprsd.stats import collector
|
||||
from aprsd.threads import APRSDThread
|
||||
|
@ -18,6 +19,10 @@ class StatsStore(objectstore.ObjectStoreMixin):
|
|||
lock = threading.Lock()
|
||||
data = {}
|
||||
|
||||
@wrapt.synchronized(lock)
|
||||
def add(self, stats: dict):
|
||||
self.data = stats
|
||||
|
||||
|
||||
class APRSDStatsStoreThread(APRSDThread):
|
||||
"""Save APRSD Stats to disk periodically."""
|
||||
|
@ -32,7 +37,7 @@ class APRSDStatsStoreThread(APRSDThread):
|
|||
if self.loop_count % self.save_interval == 0:
|
||||
stats = collector.Collector().collect()
|
||||
ss = StatsStore()
|
||||
ss.data = stats
|
||||
ss.add(stats)
|
||||
ss.save()
|
||||
|
||||
time.sleep(1)
|
||||
|
|
|
@ -70,8 +70,8 @@ class ObjectStoreMixin:
|
|||
"""Save any queued to disk?"""
|
||||
if not CONF.enable_save:
|
||||
return
|
||||
save_filename = self._save_filename()
|
||||
if len(self) > 0:
|
||||
save_filename = self._save_filename()
|
||||
LOG.info(
|
||||
f"{self.__class__.__name__}::Saving"
|
||||
f" {len(self)} entries to disk at "
|
||||
|
@ -83,7 +83,7 @@ class ObjectStoreMixin:
|
|||
LOG.debug(
|
||||
"{} Nothing to save, flushing old save file '{}'".format(
|
||||
self.__class__.__name__,
|
||||
self._save_filename(),
|
||||
save_filename,
|
||||
),
|
||||
)
|
||||
self.flush()
|
||||
|
|
|
@ -313,6 +313,7 @@ function create_callsign_tab(callsign, active=false) {
|
|||
//item_html += '<button onClick="callsign_select(\''+callsign+'\');" callsign="'+callsign+'" class="nav-link '+active_str+'" id="'+tab_id+'" data-bs-toggle="tab" data-bs-target="#'+tab_content+'" type="button" role="tab" aria-controls="'+callsign+'" aria-selected="true">';
|
||||
item_html += '<button onClick="callsign_select(\''+callsign+'\');" callsign="'+callsign+'" class="nav-link position-relative '+active_str+'" id="'+tab_id+'" data-bs-toggle="tab" data-bs-target="#'+tab_content+'" type="button" role="tab" aria-controls="'+callsign+'" aria-selected="true">';
|
||||
item_html += callsign+' ';
|
||||
item_html += '<span id="'+tab_notify_id+'" class="position-absolute top-0 start-80 translate-middle badge bg-danger border border-light rounded-pill visually-hidden">0</span>';
|
||||
item_html += '<span onclick="delete_tab(\''+callsign+'\');">×</span>';
|
||||
item_html += '</button></li>'
|
||||
|
||||
|
@ -407,6 +408,9 @@ function append_message(callsign, msg, msg_html) {
|
|||
tab_notify_id = tab_notification_id(callsign, true);
|
||||
// get the current count of notifications
|
||||
count = parseInt($(tab_notify_id).text());
|
||||
if (isNaN(count)) {
|
||||
count = 0;
|
||||
}
|
||||
count += 1;
|
||||
$(tab_notify_id).text(count);
|
||||
$(tab_notify_id).removeClass('visually-hidden');
|
||||
|
|
Loading…
Reference in New Issue