feat: separate disk activity reader from disk capacity reader (#468)

This commit is contained in:
Serhiy Mytrovtsiy
2021-05-15 11:37:18 +02:00
parent 281535bc17
commit 1268891845
3 changed files with 63 additions and 48 deletions

View File

@@ -42,7 +42,7 @@ struct drive {
var size: Int64 = 1
var free: Int64 = 0
var stats: stats? = nil
var activity: stats = stats()
}
struct DiskList: value_t {
@@ -87,6 +87,7 @@ struct DiskList: value_t {
public class Disk: Module {
private let popupView: Popup = Popup()
private var activityReader: ActivityReader? = nil
private var capacityReader: CapacityReader? = nil
private var settingsView: Settings
private var selectedDisk: String = ""
@@ -101,6 +102,7 @@ public class Disk: Module {
guard self.available else { return }
self.capacityReader = CapacityReader()
self.activityReader = ActivityReader(list: &self.capacityReader!.disks)
self.selectedDisk = Store.shared.string(key: "\(self.config.name)_disk", defaultValue: self.selectedDisk)
self.capacityReader?.callbackHandler = { [unowned self] value in
@@ -110,6 +112,10 @@ public class Disk: Module {
self.readyHandler()
}
self.activityReader?.callbackHandler = { [unowned self] value in
self.capacityCallback(value)
}
self.settingsView.selectedDiskHandler = { [unowned self] value in
self.selectedDisk = value
self.capacityReader?.read()
@@ -117,13 +123,13 @@ public class Disk: Module {
self.settingsView.callback = { [unowned self] in
self.capacityReader?.read()
}
self.settingsView.setInterval = { [unowned self] value in
self.capacityReader?.setInterval(value)
}
if let reader = self.capacityReader {
self.addReader(reader)
}
if let reader = self.activityReader {
self.addReader(reader)
}
}
public override func widgetDidSet(_ type: widget_t) {
@@ -159,7 +165,7 @@ public class Disk: Module {
case let widget as Mini: widget.setValue(percentage)
case let widget as BarChart: widget.setValue([percentage])
case let widget as MemoryWidget: widget.setValue((DiskSize(free).getReadableMemory(), DiskSize(usedSpace).getReadableMemory()))
case let widget as SpeedWidget: widget.setValue(upload: d.stats?.write ?? 0, download: d.stats?.read ?? 0)
case let widget as SpeedWidget: widget.setValue(upload: d.activity.write, download: d.activity.read)
default: break
}
}

View File

@@ -35,7 +35,7 @@ internal class Popup: NSView, Popup_p {
value.list.reversed().forEach { (drive: drive) in
if let disk = self.list[drive.mediaName] {
disk.update(free: drive.free, read: drive.stats?.read, write: drive.stats?.write)
disk.update(free: drive.free, read: drive.activity.read, write: drive.activity.write)
} else {
let disk = DiskView(
NSRect(
@@ -102,7 +102,7 @@ internal class DiskView: NSView {
self.layer?.backgroundColor = isDarkMode ? NSColor(hexString: "#111111", alpha: 0.25).cgColor : NSColor(hexString: "#f5f5f5", alpha: 1).cgColor
}
public func update(free: Int64, read: Int64?, write: Int64?) {
public func update(free: Int64, read: Int64, write: Int64) {
self.nameAndBarView.update(free: free, read: read, write: write)
self.legendView.update(free: free)
}
@@ -213,7 +213,7 @@ internal class DiskNameAndBarView: NSView {
self.addSubview(view)
}
public func update(free: Int64, read: Int64?, write: Int64?) {
public func update(free: Int64, read: Int64, write: Int64) {
if (self.window?.isVisible ?? false) || !self.ready {
if self.usedBarSpace != nil {
let percentage = CGFloat(self.size - free) / CGFloat(self.size)
@@ -221,12 +221,8 @@ internal class DiskNameAndBarView: NSView {
self.usedBarSpace?.setFrameSize(NSSize(width: width, height: self.usedBarSpace!.frame.height))
}
if read != nil {
self.readState?.layer?.backgroundColor = read != 0 ? NSColor.systemBlue.cgColor : NSColor.lightGray.withAlphaComponent(0.75).cgColor
}
if write != nil {
self.writeState?.layer?.backgroundColor = write != 0 ? NSColor.systemRed.cgColor : NSColor.lightGray.withAlphaComponent(0.75).cgColor
}
self.readState?.layer?.backgroundColor = read != 0 ? NSColor.systemBlue.cgColor : NSColor.lightGray.withAlphaComponent(0.75).cgColor
self.writeState?.layer?.backgroundColor = write != 0 ? NSColor.systemRed.cgColor : NSColor.lightGray.withAlphaComponent(0.75).cgColor
self.ready = true
}

View File

@@ -17,7 +17,7 @@ import Darwin
import os.log
internal class CapacityReader: Reader<DiskList> {
private var disks: DiskList = DiskList()
internal var disks: DiskList = DiskList()
public override func read() {
let keys: [URLResourceKey] = [.volumeNameKey]
@@ -46,7 +46,6 @@ internal class CapacityReader: Reader<DiskList> {
if let path = self.disks.list[idx].path {
self.disks.list[idx].free = self.freeDiskSpaceInBytes(path)
self.driveStats(self.disks.list[idx].parent, &self.disks.list[idx].stats)
}
}
continue
@@ -145,7 +144,6 @@ internal class CapacityReader: Reader<DiskList> {
let partitionLevel = d.BSDName.filter { "0"..."9" ~= $0 }.count
if let parent = self.getDeviceIOParent(DADiskCopyIOMedia(disk), level: Int(partitionLevel)) {
d.parent = parent
self.driveStats(parent, &d.stats)
}
return d
@@ -169,37 +167,6 @@ internal class CapacityReader: Reader<DiskList> {
return parent
}
private func driveStats(_ entry: io_registry_entry_t, _ diskStats: UnsafeMutablePointer<stats?>) {
guard let props = getIOProperties(entry) else {
return
}
if let statistics = props.object(forKey: "Statistics") as? NSDictionary {
if diskStats.pointee == nil {
diskStats.initialize(to: stats())
}
let readBytes = statistics.object(forKey: "Bytes (Read)") as? Int64 ?? 0
let writeBytes = statistics.object(forKey: "Bytes (Write)") as? Int64 ?? 0
if diskStats.pointee?.readBytes != 0 {
diskStats.pointee?.read = readBytes - (diskStats.pointee?.readBytes ?? 0)
}
if diskStats.pointee?.writeBytes != 0 {
diskStats.pointee?.write = writeBytes - (diskStats.pointee?.writeBytes ?? 0)
}
diskStats.pointee?.readBytes = readBytes
diskStats.pointee?.writeBytes = writeBytes
diskStats.pointee?.readOperations = statistics.object(forKey: "Operations (Read)") as? Int64 ?? 0
diskStats.pointee?.writeOperations = statistics.object(forKey: "Operations (Read)") as? Int64 ?? 0
diskStats.pointee?.readTime = statistics.object(forKey: "Total Time (Read)") as? Int64 ?? 0
diskStats.pointee?.writeTime = statistics.object(forKey: "Total Time (Read)") as? Int64 ?? 0
}
return
}
private func freeDiskSpaceInBytes(_ path: URL) -> Int64 {
do {
if let url = URL(string: path.absoluteString) {
@@ -224,3 +191,49 @@ internal class CapacityReader: Reader<DiskList> {
return 0
}
}
internal class ActivityReader: Reader<DiskList> {
internal var disks: UnsafeMutablePointer<DiskList>? = nil
init(list: UnsafeMutablePointer<DiskList>?) {
self.disks = list
super.init()
}
override func setup() {
setInterval(1)
}
public override func read() {
guard let disks = self.disks else {
return
}
for (i, d) in disks.pointee.list.enumerated() {
guard let props = getIOProperties(d.parent) else {
return
}
if let statistics = props.object(forKey: "Statistics") as? NSDictionary {
let readBytes = statistics.object(forKey: "Bytes (Read)") as? Int64 ?? 0
let writeBytes = statistics.object(forKey: "Bytes (Write)") as? Int64 ?? 0
if disks.pointee.list[i].activity.readBytes != 0 {
disks.pointee.list[i].activity.read = readBytes - disks.pointee.list[i].activity.readBytes
}
if disks.pointee.list[i].activity.writeBytes != 0 {
disks.pointee.list[i].activity.write = writeBytes - disks.pointee.list[i].activity.writeBytes
}
disks.pointee.list[i].activity.readBytes = readBytes
disks.pointee.list[i].activity.writeBytes = writeBytes
disks.pointee.list[i].activity.readOperations = statistics.object(forKey: "Operations (Read)") as? Int64 ?? 0
disks.pointee.list[i].activity.writeOperations = statistics.object(forKey: "Operations (Read)") as? Int64 ?? 0
disks.pointee.list[i].activity.readTime = statistics.object(forKey: "Total Time (Read)") as? Int64 ?? 0
disks.pointee.list[i].activity.writeTime = statistics.object(forKey: "Total Time (Read)") as? Int64 ?? 0
}
}
self.callback(disks.pointee)
}
}