Skip to content

Commit 302b1fb

Browse files
author
kasemir
committed
PVA ServerPV support for changing the write permissions
1 parent 889d79d commit 302b1fb

File tree

1 file changed

+33
-14
lines changed

1 file changed

+33
-14
lines changed

core/pva/src/main/java/org/epics/pva/server/ServerPV.java

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
import static org.epics.pva.PVASettings.logger;
1111

1212
import java.util.BitSet;
13-
import java.util.Map.Entry;
1413
import java.util.concurrent.ConcurrentHashMap;
1514
import java.util.concurrent.ConcurrentHashMap.KeySetView;
15+
import java.util.concurrent.atomic.AtomicBoolean;
1616
import java.util.concurrent.atomic.AtomicInteger;
1717
import java.util.logging.Level;
1818

19+
import org.epics.pva.common.AccessRightsChange;
1920
import org.epics.pva.common.PVAHeader;
2021
import org.epics.pva.data.PVAString;
2122
import org.epics.pva.data.PVAStructure;
@@ -74,9 +75,12 @@ public class ServerPV implements AutoCloseable
7475
/** Handler for write access. May be READONLY_WRITE_HANDLER */
7576
private final WriteEventHandler write_handler;
7677

77-
/** Map of TCP handlers,
78-
* i.e. TCP connections to clients that access this PV,
79-
* by client ID
78+
/** Is the PV writable? */
79+
private final AtomicBoolean writable;
80+
81+
/** Map of TCP handlers and client IDs.
82+
* PV has one server ID.
83+
* Client ID is provided by client for each TCP connection.
8084
*/
8185
private final ConcurrentHashMap<ServerTCPHandler, Integer> cid_by_client = new ConcurrentHashMap<>();
8286

@@ -96,6 +100,7 @@ public class ServerPV implements AutoCloseable
96100
this.data = data.cloneData();
97101
rpc = DEFAULT_RPC_SERVICE;
98102
this.write_handler = write_handler;
103+
writable = new AtomicBoolean(write_handler != READONLY_WRITE_HANDLER);
99104
}
100105

101106
/** Create PV for handling RPC calls
@@ -110,6 +115,7 @@ public class ServerPV implements AutoCloseable
110115
this.data = RPC_SERVICE_VALUE;
111116
this.rpc = rpc;
112117
write_handler = READONLY_WRITE_HANDLER;
118+
writable = new AtomicBoolean(false);
113119
}
114120

115121

@@ -131,7 +137,7 @@ public int getSID()
131137
*/
132138
void addClient(final ServerTCPHandler tcp, final int cid)
133139
{
134-
// A client should create a PV just once.
140+
// Each client should create a PV just once.
135141
// If client creates PV several times, we only track the last CID
136142
// and issue a warning.
137143
final Integer other = cid_by_client.put(tcp, cid);
@@ -226,9 +232,26 @@ PVAStructure getData()
226232
}
227233
}
228234

229-
boolean isWritable()
235+
/** @return Is the PV writable? */
236+
public boolean isWritable()
237+
{
238+
return writable.get();
239+
}
240+
241+
/** Update write access
242+
*
243+
* To enable write access, PV must have been created with {@link WriteEventHandler}
244+
*
245+
* @param writable Should the PV be writable?
246+
*/
247+
public void setWritable(final boolean writable)
230248
{
231-
return write_handler != READONLY_WRITE_HANDLER;
249+
if (write_handler != READONLY_WRITE_HANDLER && this.writable.compareAndSet(!writable, writable))
250+
{
251+
logger.log(Level.FINE, () -> "Update ACL " + this + (writable ? " to writable" : " to read-only"));
252+
cid_by_client.forEach((tcp, cid) ->
253+
tcp.submit((version, buffer) -> AccessRightsChange.encode(buffer, cid, writable)));
254+
}
232255
}
233256

234257
/** Notification that a client wrote to the PV
@@ -256,18 +279,14 @@ PVAStructure call(final PVAStructure parameters) throws Exception
256279
@Override
257280
public void close()
258281
{
259-
for (Entry<ServerTCPHandler, Integer> client : cid_by_client.entrySet())
260-
{
261-
final ServerTCPHandler tcp = client.getKey();
262-
final int cid = client.getValue();
282+
cid_by_client.forEach((tcp, cid) ->
263283
tcp.submit( (version, buffer) ->
264-
{
284+
{ // Send CMD_DESTROY_CHANNEL for this PV to all clients
265285
logger.log(Level.FINE, () -> "Sending destroy channel command for SID " + sid + ", CID " + cid);
266286
PVAHeader.encodeMessageHeader(buffer, PVAHeader.FLAG_SERVER, PVAHeader.CMD_DESTROY_CHANNEL, 4+4);
267287
buffer.putInt(sid);
268288
buffer.putInt(cid);
269-
});
270-
}
289+
}));
271290

272291
server.deletePV(this);
273292
}

0 commit comments

Comments
 (0)