blob: 600bcfa4e839ef111696687227dd359497ba2799 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
@startuml
skinparam titleFontSize 24
skinparam defaultFontSize 16
title NFSTrace: libwatch class diagram
abstract class AbstractProtocol #Aquamarine {
+ commandsAmount: const std::size_t
+ name: const std::string
+ AbstractProtocol(name: const std::string&, commandsAmount: std::size_t)
+ {abstract} commandName(std::size_t commandId): const char * = 0
}
class NFSv3Protocol #Aquamarine {
+ NFSv3Protocol()
+ {abstract} commandName(std::size_t commandId): const char *
}
class NFSv4Protocol #Aquamarine {
+ NFSv4Protocol()
+ {abstract} commandName(std::size_t commandId): const char *
}
AbstractProtocol <|-- NFSv3Protocol
AbstractProtocol <|-- NFSv4Protocol
class CommandsStatistics {
+ commands: std::vector<std::size_t>
}
class WatchAnalyzer {
- _userGUI: UserGUI
- _protocols: std::vector<AbstractProtocol*>
+ {abstract} onCommand(): void
+ {abstract} onUnixSignal(): void
}
class UserGUI << thread >> {
- _isRunning: std::atomic<bool>
- _shouldRefresh: std::atomic<bool>
- _statisticsMutex: std::mutex
- _statisticsContainer: std::unordered_map<AbstractProtocol*, CommandsStatistics>
- _activeProtocol: AbstractProtocol&
- _mainWindow: MainWindow
- _headerWindow: HeaderWindow
- _statisticsWindow: StatisticsWindow
+ UserGUI(protocols: std::vector<AbstractProtocol *>&)
+ incrementCommand(protocol: const AbstractProtocol&, commandId: std::size_t)
+ refresh()
- run()
- selectProtocol(protocol: const ActiveProtocol&)
}
note right of UserGUI
<b>_statisticsContainer/_statisticsMutex</b>
are used to thread-safely pass statistics from
analyzer's thread to GUI's one;
<b>run()</b> is a thread-function where GUI is to
be created/[re-]drawn/destroyed, keyboard events are to
be handled and incoming statistics delta is to be applied;
<b>selectProtocol()</b> is to be called internally when
a user changes active protocol;
<b>incrementCommand()</b> is to be called from analyzer
to update statistics on command detection;
<b>refresh()</b> is to be called from analyzer
to completely redraw GUI (e.g. on SIGCONT) -
this method just sets <b>_shouldRefresh</b> to <b>true</b>
but actual refresh is made in <b>run()</b>.
end note
class MainWindow #Khaki {
- _handle: WINDOW*
}
class HeaderWindow #Khaki {
- _handle: WINDOW*
- _activeProtocol: const AbstractProtocol&
+ HeaderWindow(protocols: std::vector<AbstractProtocol *>&, activeProtocol: const AbstractProtocol&)
+ selectProtocol(protocol: const AbstractProtocol&)
+ refresh()
}
class StatisticsWindow #Khaki {
- _handle: WINDOW*
- _activeProtocol: const AbstractProtocol&
- _statisticsContainer: const CommandsStatistics&
- _scrollOffsets: std::unordered_map<AbstractProtocol*, std::size_t>
+ StatisticsWindow(activeProtocol: const AbstractProtocol&, statisticsContainer: const CommandsStatistics&)
+ selectProtocol(protocol: const AbstractProtocol&)
+ update()
+ scroll(increment: int)
+ refresh()
}
note top of StatisticsWindow
<b>selectProtocol()</b> is to be called when a protocol is changed;
<b>update()</b> is to be called to update statistics data;
<b>scroll()</b> is to be called to scroll statistics data;
<b>refresh()</b> is to be called to completely redraw window.
end note
WatchAnalyzer "1" *-- "1" UserGUI
WatchAnalyzer "1" *-- "*" AbstractProtocol
UserGUI "1" *-- "*" AbstractProtocol
UserGUI "1" *-- "1" MainWindow
UserGUI "1" *-- "1" HeaderWindow
UserGUI "1" *-- "1" StatisticsWindow
UserGUI "1" *-- "*" CommandsStatistics
HeaderWindow "1" o-- "1" AbstractProtocol
StatisticsWindow "1" o-- "1" CommandsStatistics
StatisticsWindow "1" o-- "1" AbstractProtocol
@enduml
|