Skip to content

Commit 611aa92

Browse files
committed
Check PVA "put" result with plain PV.write
Since for the time being a read-only channel can only be detected by performing a put and checking the result, have to await the result even for a fire-and-forget type of write. Using a configurable timeout to prevent GUI hangups.
1 parent 40bfe09 commit 611aa92

File tree

4 files changed

+35
-18
lines changed

4 files changed

+35
-18
lines changed

core/pv/src/main/java/org/phoebus/pv/pva/PVA_PV.java

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -164,33 +164,38 @@ public VType get(final long timeout, final TimeUnit unit)
164164
@Override
165165
public void write(final Object new_value) throws Exception
166166
{
167-
// With Channel Access, there are different protocol options
168-
// for "put" vs. "put-callback".
169-
// With PVA, it is currently unclear how to distinguish between
170-
// these two. The PVA server might honor certain values in the
171-
// "request", but that is not documented as part of the protocol.
172-
// On one hand, we should 'get()' the result of the write to
173-
// receive exceptions for read-only PVs.
174-
// On the other hand, such a 'get()' could last a long time
175-
// in case some detail in the 'request' caused the PVA server
176-
// to perform a put-callback type of operation,
177-
// and a GUI calling write() expect an immediate return.
178-
179167
// Perform a disconnect check right now to alert caller
180168
// of clearly disconnected channel
181169
if (isDisconnected(read()))
182170
throw new IllegalStateException("Channel '" + getName() + "' is not connected");
183171

184172
// The channel could still disconnect in the middle of the write,
185-
// the channel may be read-only or experience other errors
186-
// that we'll only see as log messages since we don't want to
187-
// wait in 'get()' here...
188-
channel.write(name_helper.getWriteRequest(), new_value);
173+
// or experience other errors which we'll receive in the
174+
// response checked below.
175+
176+
// Perform a plain "put", not "put-callback"
177+
final Future<Void> response = channel.write(false, name_helper.getWriteRequest(), new_value);
178+
179+
// Compared to Channel Access, PVA currently offers no
180+
// information about writable vs. read-only channels.
181+
// A read-only channel will only inform us about the failed
182+
// write in the put response, for which we need to await
183+
// the return value from the PVA server.
184+
// Waiting for the response from the server, however,
185+
// can take a little time, enough to be noticeable in a GUI
186+
// that directly calls 'write' from the UI thread.
187+
// Still, there seems no alternative to waiting a little bit,
188+
// then potentially timing out.
189+
response.get(PVA_Preferences.epics_pva_write_reply_timeout_ms, TimeUnit.MILLISECONDS);
189190
}
190191

191192
@Override
192193
public Future<?> asyncWrite(final Object new_value) throws Exception
193194
{
195+
// Perform a put with completion,
196+
// i.e., process target and block until processing completes,
197+
// akin to a Channel Access put-callback.
198+
// Return the Future that can be used to await completion
194199
return channel.write(true, name_helper.getWriteRequest(), new_value);
195200
}
196201

core/pv/src/main/java/org/phoebus/pv/pva/PVA_Preferences.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ public class PVA_Preferences
4343
{
4444
private static final PVA_Preferences instance = new PVA_Preferences();
4545

46+
public static int epics_pva_write_reply_timeout_ms;
47+
4648
/** Prevent direct instantiation */
4749
private PVA_Preferences()
4850
{
@@ -76,6 +78,8 @@ public void installPreferences() throws Exception
7678
new Object[] { propname, PVA_PVFactory.class.getPackageName(), setting, value });
7779
}
7880
}
81+
82+
epics_pva_write_reply_timeout_ms = prefs.getInt("epics_pva_write_reply_timeout_ms");
7983
}
8084

8185
/** @return Singleton instance */

core/pv/src/main/resources/pv_pva_preferences.properties

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,11 @@ epics_pva_max_array_formatting
4242

4343
# TCP buffer size for sending data
4444
epics_pva_send_buffer_size
45+
46+
# Timeout used by plain "put" type of write
47+
# when checking success or failure.
48+
# Note this is not used with asyncWrite,
49+
# the "put-callback" which returns a Future
50+
# for awaiting the completion,
51+
# but only with the plain "put" that returns ASAP
52+
epics_pva_write_reply_timeout_ms=1000

core/pva/src/main/java/org/epics/pva/client/PVAChannel.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ public Future<PVAStructure> read(final String request)
241241
* @param request Request for element to write, e.g. "field(value)"
242242
* @param new_value New value: Number, String
243243
* @throws Exception on error
244-
* @return {@link Future} for awaiting completion
244+
* @return {@link Future} for awaiting completion and getting Exception in case of error
245245
* @deprecated Use {@link #write(boolean, String, Object)}
246246
*/
247247
@Deprecated
@@ -271,7 +271,7 @@ public Future<Void> write(final String request, final Object new_value) throws E
271271
* @param request Request for element to write, e.g. "field(value)"
272272
* @param new_value New value: Number, String
273273
* @throws Exception on error
274-
* @return {@link Future} for awaiting completion
274+
* @return {@link Future} for awaiting completion and getting Exception in case of error
275275
*/
276276
public Future<Void> write(final boolean completion, final String request, final Object new_value) throws Exception
277277
{

0 commit comments

Comments
 (0)