Compare commits

...

6 Commits

Author SHA1 Message Date
Hemna 026dc6e376 syncronize the add for StatsStore 2024-04-11 22:55:01 -04:00
Hemna f59b65d13c Lock on stats for PacketList 2024-04-11 22:24:02 -04:00
Hemna 5ff62c9bdf Fixed PacketList maxlen
This patch removes the MutableMapping from PacketList
and fixes the code that keeps the max packets in the internal
dict.
2024-04-11 21:40:43 -04:00
Hemna 5fa4eaf909 Fixed a problem with the webchat tab notification
Somehow the hidden div for the webchat interface's
tab notification was removed.  this patch adds it back in
so the user knows that they have message(s) for a tab that
isn't selected
2024-04-11 18:11:05 -04:00
Hemna f34120c2df Another fix for ACK packets 2024-04-11 17:28:47 -04:00
Hemna 3bef1314f8 Fix issue not tracking RX Ack packets for stats
This patch updates the RX tracking for packets.  Every
packet we get into the rx thread, we now will track
every packet we RX so the stats are acurate.
2024-04-11 16:54:46 -04:00
5 changed files with 28 additions and 29 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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+'&nbsp;&nbsp;';
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');