Skip to content

Commit 55f747b

Browse files
committed
Additional documentation for the baton.
1 parent 16bc12e commit 55f747b

4 files changed

Lines changed: 203 additions & 0 deletions

File tree

docs/developer/hyperion/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Documentation specific for the Hyperion module within MX-Bluesky
1313
:maxdepth: 1
1414

1515
reference/readme
16+
reference/baton
1617
reference/param-hierarchy
1718
reference/coordinate-systems
1819
deploying-hyperion
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Hyperion Baton
2+
==============
3+
4+
The Hyperion baton is controlled by two PVs; these are described under `Special PVs`_
5+
6+
An approximate outline of how the various baton workflows operates is outlined in the flowcharts below:
7+
8+
.. image:: ../../../images/417717258-afbd813c-8941-445c-9fdf-255c167453cf.png
9+
10+
.. _Special PVs: ../../../user/hyperion/pvs.html
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
@startuml
2+
title GDA Baton Management
3+
4+
package Server {
5+
class Thread
6+
class JythonServerThread extends Thread {
7+
authorisationLevel: int
8+
int getAuthorisationLevel()
9+
}
10+
11+
interface IBatonManager {
12+
ClientDetails getClientInformation((myJSFIdentifier)
13+
boolean requestBaton(uniqueIdentifier)
14+
void returnBaton((uniqueIdentifier)
15+
void assignBaton(myJSFIdentifier, indexOfReceiver, indexOfPasser)
16+
boolean isBatonHeld()
17+
boolean amIBatonHolder(myJSFIdentifier)
18+
int effectiveAuthorisationLevelOf(uniqueId)
19+
void addFacade(uniqueId, info: ClientDetails)
20+
void removeFacade(uniqueId)
21+
}
22+
23+
class BatonManager implements IBatonManager {
24+
useBaton = true
25+
useRBAC = true
26+
firstClientTakesBaton = true
27+
batonHolder: String
28+
facadeNames: Map<String, ClientInfo>
29+
leaseHolders: Map<String, Long>
30+
}
31+
32+
note "Each client has a facade name aka uniqueId aka jsfIdentifier\n\
33+
There is a LeaseRefresher that periodically sends a BatonLeaseRenewRequest\n\
34+
to all clients, any interaction with the BatonManager extends the lease.\n\n\
35+
On first client registration, if firstClientTakesBaton is true then it will\n\
36+
assume the baton if it is not the server or an automated client." as batonManagerNote
37+
38+
BatonManager .. batonManagerNote
39+
40+
41+
interface IJythonServerNotifier {
42+
void notifyServer(source, data)
43+
}
44+
interface LocalJython
45+
class JythonServer implements LocalJython {
46+
batonManager: BatonManager
47+
}
48+
49+
note "JythonServer registers a client with the BatonManager via forwarding of addFacade()\n\
50+
The authorisationLevel is determined by asking the Authoriser" as jythonServerNote
51+
52+
JythonServer .. jythonServerNote
53+
54+
interface Authoriser {
55+
int getAuthorisationLevel(username)
56+
int getDefaultPermissions(username)
57+
isLocalStaff(username)
58+
}
59+
60+
class FileAuthoriser implements Authoriser
61+
note "Gets the permissions from user_permissions.xml" as fileAuthoriserNote
62+
FileAuthoriser .. fileAuthoriserNote
63+
class LdapAuthoriser extends FileAuthoriser
64+
class SingleFileAuthoriser implements Authoriser
65+
note "Authorisation method is determined by gda.gui.AcquisitionGUI.authorisationMethod" as authoriserNote
66+
67+
Authoriser .. authoriserNote
68+
69+
together {
70+
class UDCBatonHandler {
71+
runner: IUDCRunner
72+
}
73+
interface IUDCRunner
74+
class GDAUDCRunner implements IUDCRunner
75+
class HyperionUDCRunner implements IUDCRunner
76+
}
77+
78+
note "\
79+
Creates the UDC Client by calling getUnattendedClientFacade() during configuration.\n\
80+
Creates the UDC Runner according to the gda.mx.udc.hyperion.enable property.\
81+
" as udcBatonHandlerNote
82+
UDCBatonHandler .. udcBatonHandlerNote
83+
84+
class Device {
85+
protectionLevel: int
86+
}
87+
class DeviceInterceptor
88+
note "DeviceInterceptor is an interceptor on specific methods of Device, if the current thread\n\
89+
has an authorisationLevel below the protectionLevel of the device, and\n\
90+
the call is made from Jython the method call throws AccessDeniedException." as deviceNote
91+
Device .. deviceNote
92+
93+
94+
95+
class UDCCompleteEvent
96+
97+
}
98+
99+
package Common {
100+
together {
101+
class BatonChanged
102+
class BatonRequested
103+
class BatonLeaseRenewRequest
104+
}
105+
106+
interface Jython {
107+
boolean amIBatonHolder(myJSFIdentifier)
108+
int addFacade(jsfIdentifier, hostname, username, fullName, visitId)
109+
boolean isBatonHeld()
110+
}
111+
112+
class ClientInfo {
113+
index: int
114+
userId: String
115+
fullName: String
116+
hostname: String
117+
authorisationLevel: int
118+
visitID: String
119+
120+
boolean isServer()
121+
boolean isAutomatedUser()
122+
}
123+
note "isServer and isAutomatedUser are determined by the authorisationLevel" as clientInfoNote
124+
ClientInfo .. clientInfoNote
125+
126+
class ClientDetails extends ClientInfo {
127+
hasBaton: boolean
128+
}
129+
130+
interface IAuthorisationHolder {
131+
int getAuthorisationLevel()
132+
int getAuthorisationLevelAtRegistration()
133+
}
134+
135+
interface IBatonStateProvider {
136+
boolean amIBatonHolder()
137+
boolean isBatonHeld()
138+
void addBatonChangedObserver(observer)
139+
void deleteBatonChangedObserver(observer)
140+
}
141+
note "Access is enforced in the client via calls to amIBatonHolder()" as iBatonStateProviderNote
142+
143+
class JythonServerFacade implements IBatonStateProvider, IAuthorisationHolder {
144+
commandServer: Jython
145+
visitID: String
146+
{static} JythonServerFacade getUnattendedClientFacade()
147+
}
148+
}
149+
150+
package Client {
151+
class ApplicationWorkbenchAdvisor
152+
note "ApplicationWorkbenchAdvisor receives the BatonLeaseRenewRequest and uses IBatonStateProvider\n\
153+
to renew the lease by calling amIBatonHolder()" as applicationWorkbenchAdvisorNote
154+
}
155+
156+
'Server -up-> Common
157+
'Common -up[hidden]-> Client
158+
ApplicationWorkbenchAdvisor ..[norank] applicationWorkbenchAdvisorNote
159+
160+
ApplicationWorkbenchAdvisor --down> IBatonStateProvider
161+
162+
IBatonStateProvider .. iBatonStateProviderNote
163+
LocalJython -up-|> Jython
164+
LocalJython --|> IJythonServerNotifier
165+
166+
JythonServerFacade o-> Jython
167+
JythonServer o->BatonManager
168+
JythonServer --> Authoriser
169+
170+
JythonServer --> JythonServerThread
171+
172+
BatonChanged --> UDCBatonHandler : handles
173+
BatonRequested --> UDCBatonHandler : handles
174+
UDCCompleteEvent --> UDCBatonHandler : handles
175+
176+
UDCBatonHandler -[norank]-> JythonServerFacade
177+
UDCBatonHandler o-> IUDCRunner
178+
BatonManager -up-> BatonChanged : fires
179+
BatonManager -up-> BatonRequested : fires
180+
BatonManager -up-> BatonLeaseRenewRequest : fires
181+
GDAUDCRunner -[norank]-> UDCCompleteEvent : fires
182+
BatonManager *-[norank]-> ClientInfo
183+
184+
UDCCompleteEvent --> GDAUDCRunner : handles
185+
HyperionUDCRunner --> UDCCompleteEvent : fires
186+
187+
DeviceInterceptor --> Device
188+
DeviceInterceptor --> JythonServerThread
189+
190+
BatonManager -up-> IJythonServerNotifier
191+
192+
@enduml
213 KB
Loading

0 commit comments

Comments
 (0)