forked from epics-base/epicsCoreJava
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpvAccessJava.html
More file actions
1615 lines (1364 loc) · 54.3 KB
/
pvAccessJava.html
File metadata and controls
1615 lines (1364 loc) · 54.3 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvAccessJava</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<div class="head">
<h1>EPICS pvAccessJava</h1>
<h2 class="nocount">Release 4.0.2, 10-Nov-2014</h2>
<dl>
<dt>Editors:</dt>
<dd>Marty Kraimer, BNL<br>
Matej Sekoranja, CosyLab</dd>
</dl>
<h2 class="nocount">Abstract</h2>
<p>pvAccessJava is the Java implementation of pvAccess, which is one of a
related set of products:<br>
<a href="http://epics-pvdata.sourceforge.net/relatedDocumentsV4.html">relatedDocumentsV4.html</a>
</p>
<h2 class="nocount">Status of this Document</h2>
<p>This is the 10-Nov-2014 version of the Java implementation of pvAccess. It
is a complete implementation of pvAccess as currently defined. </p>
</div>
<div id="toc">
<h2 class="nocount" style="page-break-before: always">Table of Contents</h2>
</div>
<div id="contents" class="contents">
<h2>Introduction</h2>
<p>This product is available via an <a
href="http://epics-pvdata.sourceforge.net/LICENSE.html">open source
license</a></p>
<p>This document is the project and package overviews for pvAccessJava. The
javaDOC is available at <a href="./html/index.html">JavaDoc</a></p>
<p>The javaDOC package overview documents for this project are not complete but
the packages of interest to people writing client code or connecting an
application that wants to start a pvAccess server is complete. What remains is
to fully document the implementation. This project overview gives a brief
description of the packages provided by this project.</p>
<p>This project implements pvAccess, which is an implementation of Channel
Access that fully supports pvData. Package <b>org.epics.pvaccess.client</b> is
of interest to anyone who wants to write client code for pvAccess and is also
of interest to anyone who wants to write a server that interfaces to other
system. The other packages are mainly of interest to those who want to
understand the internals of the implementation.</p>
<p>This project also implements client code that uses the Channel Access network
protocol to communicate with servers. It converts between the DBR ChannelAccess data and
pvData so that the client only sees pvData.</p>
<p>If your only interest is to write client code
then look at the example in the next section and then
go directly to
<b>Pachkage org.epics.pvaccess.client</b> in this document.</p>
<p>This project provides the client and server network support for the
interfaces defined in <b>org.epics.pvaccess.client</b>. The pvIOCJava provides
a local implementation of pvAccess API, which registers itself with the server
support provided by this project. Other implementations can also be
provided.</p>
<p>This package also allows the following:</p>
<ol>
<li>An application can be created that provide a pvAccess server that
provides full support for pvData.This is done by starting a local
PVDatabase, calling org.epics.pvaccess.LocalFactory.start(), and calling
org.epics.pvaccess.ServerFactory.start().</li>
<li>An extensible set of monitoring algorithms is supported. Monitoring is
defined by project pvData. pvAccess provides access to this facility. A
default set of monitoring algorithms is provided by pvData but other
algorithms can be implemented. The code that implements an algorithm must
extend org.epics.pvdata.monitor.AbstractMonitor and register with
org.epics.pvaccess.server.ChannelServer.</li>
<li>A gateway between pvAccess and other systems can be implemented.</li>
</ol>
<h2>Example</h2>
<h3>What the example does</h3>
<p>This section shows an example of issuing a channel get request. the example
is a java main program that can be executed as follows:</p>
<pre>java org.epics.pvaccess.client.example.ExampleChannelGet <channelName> <request></pre>
<p>For example if the arguments are:</p>
<pre> counter field(value)</pre>
<p>The output is:</p>
<pre>2012-09-11T12:48:44.831 Channel 'counter' created with status: StatusImpl [type=OK].
2012-09-11T12:48:45.631 Channel 'counter' CONNECTED.
2012-09-11T12:48:45.708 ChannelGet for 'counter' connected with status: StatusImpl [type=OK].
2012-09-11T12:48:45.710 getDone for 'counter' called with status: StatusImpl [type=OK].
structure
int value 1
2012-09-11T12:48:45.735 Channel 'counter' DISCONNECTED.
2012-09-11T12:48:45.736 Channel 'counter' DESTROYED. </pre>
<p>If the arguments are: </p>
<pre> counter field(value,timeStamp,alarm)</pre>
<p>The output is:</p>
<pre>2012-09-11T12:51:12.113 Channel 'counter' created with status: StatusImpl [type=OK].
2012-09-11T12:51:12.156 Channel 'counter' CONNECTED.
2012-09-11T12:51:12.163 ChannelGet for 'counter' connected with status: StatusImpl [type=OK].
2012-09-11T12:51:12.164 getDone for 'counter' called with status: StatusImpl [type=OK].
structure
int value 4
timeStamp_t timeStamp
long secondsPastEpoch 1347360671
int nanoseconds 660000000
int userTag 0
alarm_t alarm
int severity 0
int status 0
string message
2012-09-11T12:51:12.167 Channel 'counter' DISCONNECTED.
2012-09-11T12:51:12.168 Channel 'counter' DESTROYED.</pre>
<p>If the request is not given then the entire record is shown.</p>
<h3>Example Source</h3>
<h4>main:</h4>
<pre>public class ExampleChannelGet {
public static void main(String[] args) throws Throwable {
int len = args.length;
if (len == 0 || len > 2)
{
System.out.println("Usage: <channelName> <pvRequest>");
return;
}
final String channelName = args[0];
final String pvRequestString = args[1];
// initialize console logging
ConsoleLogHandler.defaultConsoleLogging(Level.INFO);
Logger logger = Logger.getLogger(ExampleChannelGet.class.getName());
logger.setLevel(Level.ALL);
// setup pvAccess client
org.epics.pvaccess.ClientFactory.start();
// get pvAccess client provider
ChannelProvider channelProvider =
ChannelProviderRegistryFactory.getChannelProviderRegistry()
.getProvider(org.epics.pvaccess.ClientFactory.PROVIDER_NAME);
//
// create channel and channelGet
//
CountDownLatch doneSignal = new CountDownLatch(1);
ChannelRequesterImpl channelRequester = new ChannelRequesterImpl(logger);
Channel channel = channelProvider.createChannel(
channelName, channelRequester, ChannelProvider.PRIORITY_DEFAULT);
ChannelGetRequester channelGetRequester = new
ChannelGetRequesterImpl(logger, channel, doneSignal);
CreateRequest createRequest = CreateRequest.create();
PVStructure pvRequest = createRequest.createRequest(pvRequestString);
if(pvRequest==null) {
String message = "createRequest failed " + createRequest.getMessage();
logger.info(message);
} else {
channel.createChannelGet(channelGetRequester,pvRequest);
// wait up-to 3 seconds for completion
if (!doneSignal.await(3, TimeUnit.SECONDS))
logger.info("Failed to get value (timeout condition).");
}
// stop pvAccess client
org.epics.pvaccess.ClientFactory.stop();
}</pre>
<p>The main routine first checks for valid arguments, initializes console
logging, creates a channel and channel get and then waits for up to 3 seconds
for response. </p>
<h4>Implementation of ChannelRequester:</h4>
<pre> static class ChannelRequesterImpl implements ChannelRequester
{
private final Logger logger;
public ChannelRequesterImpl(Logger logger)
{
this.logger = logger;
}
public String getRequesterName() {
return getClass().getName();
}
public void message(String message, MessageType messageType) {
logger.log(LoggingUtils.toLevel(messageType), message);
}
public void channelCreated(Status status, Channel channel) {
logger.info("Channel '" + channel.getChannelName() + "' created with status: " + status + ".");
}
public void channelStateChange(Channel channel, ConnectionState connectionState) {
logger.info("Channel '" + channel.getChannelName() + "' " + connectionState + ".");
}
}</pre>
<p>ChannelRequester.channelCreated method gets called when channel instance is
created. ChannelRequester.channelStateChange gets called on very channel state
change. The implementation above just logs all the information. </p>
<h4>Implementation of ChannelGetRequester:</h4>
<pre>
static class ChannelGetRequesterImpl implements ChannelGetRequester
{
private final Logger logger;
private final Channel channel;
private final CountDownLatch doneSignaler;
private volatile PVStructure pvStructure = null;
public ChannelGetRequesterImpl(Logger logger, Channel channel, CountDownLatch doneSignaler)
{
this.logger = logger;
this.channel = channel;
this.doneSignaler = doneSignaler;
}
public String getRequesterName() {
return getClass().getName();
}
public void message(String message, MessageType messageType) {
logger.log(LoggingUtils.toLevel(messageType), message);
}
public void channelGetConnect(Status status, ChannelGet channelGet,Structure structure
{
logger.info("ChannelGet for '" + channel.getChannelName() +
"' connected with status: " + status + ".");
if (status.isSuccess())
{
this.pvStructure = pvStructure;
channelGet.get(true);
}
else
doneSignaler.countDown();
}
public void getDone(Status status, PVStructure pvStructure, BitSet changedBitSet)s
{
logger.info("getDone for '" + channel.getChannelName() +
"' called with status: " + status + ".");
if (status.isSuccess())
{
System.out.println(pvStructure.toString());
}
doneSignaler.countDown();
}
}</pre>
<p>ChannelGetRequester.channelGetConnect gets called when ChannelGet request is
created on server side. Client must always check status for errors.
The implementation above issues actual get request on success by calling
"channelGet.get()".
User can always destroy a request by calling
"channelGet.destroy()".<br>
ChannelGetRequester.getDone gets called on get operation completion.
On success indicated by status parameter, pvStructure holds the latest data.</p>
<h2>User Interface Packages</h2>
<p>This section briefly describes the interfaces used by a pvAccess client and
by an application that supports a pvAccess server. It only describes how things
are connected, i.e. it does not describe pvAccess API or any of its related
interfaces because they are described in the package overview for
org.epics.pvaccess.client.</p>
<h3>org.epics.pvaccess</h3>
<p>This package provides the factories that start the client and server that
use the pvAccess network protocol to communicate between client and server.</p>
<dl>
<dt>ClientFactory</dt>
<dd>This starts the client side of the network support for pvAccess. This
is the only support that needs to be started by a stand-alone client. The
example shown in the previous section calls this.</dd>
<dt>ServerFactory</dt>
<dd>This must be started in order to allow pvAccess clients to access the
local pvAccess data source. For example the pvIOCJava (PVDatabase) can
start this.</dd>
</dl>
<p>A client normally only needs to start the channelProvider as follows:</p>
<pre>
org.epics.pvaccess.ClientFactory.start();
</pre>
<p>This starts the channelProvider that uses the pvAccess network protocol.
The name of the provider is <b>pva</b>.</p>
<p>For starting servers see package overview below for details.</p>
<h3>org.epics.ca</h3>
<p>This provides an implementation of ChannelProvider that uses the Channel Access
network protocol instead of the pvAccess network protocol.
It converts between DBR data and pvData.
It has a ClientFactory that has methods start and stop.</p>
<p>A client starts the channelProvider as follows:</p>
<pre>
org.epics.ca.ClientFactory.start();
</pre>
<p>The name of the provider is <b>ca</b>.</p>
<p>
The channelProvider implements ChannelGet, ChannelPut, ChannelArray, and Monitor.
It does not implement ChannelProcess, ChannelPutGet, or ChannelRPC.
</p>
<h3>org.epics.pvaccess.client</h3>
<p>This package provides everything required for a pvAccess client. See the
package overview for details. This section only describes how to connect to a
channel.</p>
<p>To connect to a channel a client does the following:</p>
<pre>
// get wanted channel provider
ChannelProvider channelProvider =
ChannelProviderRegistryFactory.getChannelProviderRegistry().getProvider("pva");
// connect to a channel with given name
Channel channel = channelProvider.createChannel(
"someChannel",
channelRequester,
ChannelProvider.PRIORITY_DEFAULT);
</pre>
<p>This package defines the interfaces a client uses to communicate with a
pvAccess server. This project fully implements all the interfaces. If a server
is implemented for other systems, it is OK to implement a subset of the
interfaces.
</p>
<p>Except for ChannelAccessFactory and CreateRequest, this package
contains only Java interface and enum definition.
</p>
<h2>Package org.epics.pvaccess</h2>
<h3>Overview</h3>
<p>This package provides:</p>
<dl>
<dt>Factories</dt>
<dd>ClientFactory and ServerFactory</dd>
<dt>PVAConstants</dt>
<dd>A set of constants used by the pvAccess implementation.</dd>
<dt>PVAException</dt>
<dd>A extension of Exception for pvAccess.</dd>
<dt>PVFactory</dt>
<dd>A convenience class for accessing pvData facilities.</dd>
<dt>Version</dt>
<dd>Administrative class to keep track of the version number.</dd>
</dl>
<h3>Factories</h3>
<p>Each factory has a public method:</p>
<pre> public static synchronized void start();</pre>
<p>For example the pvAccess client can be started by calling:</p>
<pre>org.epics.pvaccess.ClientFactory.start();</pre>
<p>The following factories are available:</p>
<dl>
<dt>ClientFactory</dt>
<dd>This starts the client side pvAccess API of the network support for
pvAccess. This is the only support that needs to be started by a
stand-alone client.</dd>
<dt>ServerFactory</dt>
<dd>This starts the server side pvAccess API of the network support for
pvAccess. For example the pvIOCJava can start this.</dd>
</dl>
<p>The ClientFactory has a public method:</p>
<pre>
org.epics.pvaccess.ClientFactory.stop();
</pre>
<h3>PVAConstants</h3>
<p>This defines a number of constants used by the implementation. It is not of
interest to users. Look at the source for details.</p>
<h3>PVAException</h3>
<p>This is a simple extension of the Java Exception class. It is defined so
that channel access specific exceptions can be thrown.</p>
<h3>Version</h3>
<p>This is an administrative class to keep track of the version number. See the
code for details.</p>
<h2>Package org.epics.pvaccess.client</h2>
<h3>Overview</h3>
<p>This package defines the client interfaces for pvAccess, which is a version
of channel access that fully supports structured data as defined by PVData. It
is assumed that the reader understands PVData, which is implemented by the
package "org.epics.pvdata". </p>
<p>A Channel provides a communication path between a client and a PVRecord. A
channel access server, which must reside in the same process as the PVRecord,
provides access to the record. The client and server can be part of the same
process or can be in different processes on the same network node or on
different network nodes. Channel Access provides the connection between the
client and server.</p>
<p>A client creates a channel via a call to ChannelProvider.createChannel.</p>
<p>This overview discusses:</p>
<ul>
<li>How to connect to a channel provider.</li>
<li>An overview of all the client interfaces.</li>
</ul>
<p>Many of the methods described below return or have a argument Status. This
is defined in project pvData as follows:</p>
<pre>interface Status extends Serializable {
public enum StatusType {OK,WARNING,ERROR,FATAL}
StatusType getType();
String getMessage();
String getStackDump();
boolean isOK();
boolean isSuccess();
}</pre>
<p>Unless isSuccess is true the client must realize that the request failed.
When a failure occurs, other arguments may be null.</p>
<h3>ChannelProviderRegistry, and ChannelProvider</h3>
<p>In order to connect to a channel a client must:</p>
<ol>
<li>Call ChannelProviderRegistryFactory.getChannelProviderRegistry().getProvider(String providerName) to get a
ChannelProvider.</li>
<li>Call ChannelProvider.createChannel(String channelName, ...) to create a
Channel.</li>
</ol>
<p>A client must know the channel name and the name of the channel provider.</p>
<h4>ChannelProviderRegistry</h4>
<p>Class org.epics.pvaccess.client.ChannelAccessFactory has the following
public methods:</p>
<pre>
interface ChannelProviderRegistry {
ChannelProvider getProvider(String providerName);
ChannelProvider createProvider(String providerName);
String[] getProviderNames();
}
</pre>
<p>where</p>
<dl>
<dt>getProvider</dt>
<dd>This gets the requested provider.Two providers are registered automatically:
<b>pva</b>, which uses the pvAccess network protocol, and <b>ca</b>,
which uses the Channel Access network protocol.
</dd>
<dt>createProvider</dt>
<dd>This registers a ChannelProvider. Usually user code does not call this,
e.g. it is called via code that implements the ChannelProvider interface.
</dd>
<dt>getProviderNames</dt>
<dd>Returns the names of the providers that have been created.</dd>
</dl>
<h4>ChannelProvider</h4>
<pre>interface ChannelProvider {
static final public short PRIORITY_MIN = 0;
static final public short PRIORITY_MAX = 99;
static final public short PRIORITY_LINKS_DB = PRIORITY_MAX;
static final public short PRIORITY_ARCHIVE = (PRIORITY_MAX + PRIORITY_MIN) / 2;
static final public short PRIORITY_OPI = PRIORITY_MIN;
void destroy();
String getProviderName();
ChannelFind channelFind(
String channelName,
ChannelFindRequester channelFindRequester);
ChannelFind channelList(
ChannelListRequester channelListRequester);
Channel createChannel(
String channelName,
ChannelRequester,
short priority);
Channel createChannel(
String channelName,
ChannelRequester channelRequester,
short priority,
String address);
}</pre>
<p>where</p>
<dl>
<dt>destroy</dt>
<dd>The channel provider will shutdown and remove all resources it is
using.</dd>
<dt>getProviderName</dt>
<dd>Get the name of the provider.</dd>
<dt>channelFind</dt>
<dd>Find a channel. The details are described in this section.</dd>
<dt>createChannel</dt>
<dd>Create a channel. A Channel is described in the next section.</dd>
</dl>
<h4>ChannelFind</h4>
<p>This method is to be used to by local pvAccess implementations (e.g.
pvAccess server queries pvIOCJava). A client can determine if a channel exists
without creating a channel. The client must implement a requester interface and
the implementation provides an interface that the client can use to cancel the
request. The interfaces are:</p>
<pre>
interface ChannelFindRequester {
void channelFindResult(
Status status,
ChannelFind channelFind,
boolean wasFound);
}
interface ChannelFind {
ChannelProvider getChannelProvider();
void cancelChannelFind();
} </pre>
<p>where</p>
<dl>
<dt>channelFindResult</dt>
<dd>This is called by the implementation. It may or may not get called. For
a remote call it is normally called only if the channel is found. A local
provider will usually call it immediately and report if it has the
requested channel. Thus this can be called before the channelFind method
returns.</dd>
<dt>getChannelProvider</dt>
<dd>Get the channel provider.</dd>
<dt>cancelChannelFind</dt>
<dd>Cancel the find request.</dd>
</dl>
<h3>Channel</h3>
<p>The Channel interface provides access to the services a channel access
provider implements for a channel. The principal services are: process, get,
put, putGet, RPC, array, and monitor. Each of these and some other services are
described in later sections of this package overview.</p>
<p>As described in the previous section a Channel is created via a call to the
method:</p>
<pre> ChannelProvider.createChannel(String channelName,ChannelRequester channelRequester)</pre>
<p>The caller must implement the interface:</p>
<pre>
interface ChannelRequester extends Requester {
void channelCreated(
Status status,
Channel channel);
void channelStateChange(
Channel channel,
ConnectionState connectionState);
}
</pre>
<p>where</p>
<dl>
<dt>Requester</dt>
<dd>This is defined in package org.epics.pvdata.pv. It has two methods:
getRequesterName and message.</dd>
<dt>channelCreated</dt>
<dd>This is called when a channel has been created. The argument provides
the channel unless status was not success.</dd>
<dt>channelStateChange</dt>
<dd>A channel connection state change has occurred. This is called the first
time when a channel has been created and connected to a server or
destroyed.</dd>
</dl>
<p>The Channel interface is:</p>
<pre>interface Channel extends Requester{
public enum ConnectionState {
NEVER_CONNECTED, CONNECTED, DISCONNECTED, DESTROYED
};
ChannelProvider getProvider();
String getRemoteAddress();
ConnectionState getConnectionState();
void destroy();
String getChannelName();
ChannelRequester getChannelRequester();
boolean isConnected();
AccessRights getAccessRights(PVField pvField);
void getField(GetFieldRequester requester,String subField);
ChannelProcess createChannelProcess(
ChannelProcessRequester channelProcessRequester,
PVStructure pvRequest);
ChannelGet createChannelGet(
ChannelGetRequester channelGetRequester,
PVStructure pvRequest);
ChannelPut createChannelPut(
ChannelPutRequester channelPutRequester,
PVStructure pvRequest);
ChannelPutGet createChannelPutGet(
ChannelPutGetRequester channelPutGetRequester,
PVStructure pvRequest);
ChannelRPC createChannelRPC(
ChannelRPCRequester channelRPCRequester,
PVStructure pvRequest);
ChannelArray createChannelArray(
ChannelArrayRequester channelArrayRequester,
PVStructure pvRequest);
Monitor createMonitor(
MonitorRequester MonitorRequester,
PVStructure pvRequest);
}</pre>
<p>where</p>
<dl>
<dt>getProvider</dt>
<dd>Get the provider.</dd>
<dt>getRemoteAddress</dt>
<dd>Get the network address of the server.</dd>
<dt>destroy</dt>
<dd>Destroy the channel and all resources used by the channel.</dd>
<dt>getChannelName</dt>
<dd>The name of the channel, e.g. the name if the PVRecord.</dd>
<dt>getChannelRequester</dt>
<dd>Get the channel requester. This is normally called by the
implementation rather than the client.</dd>
<dt>isConnected</dt>
<dd>Is the channel connected?</dd>
<dt>getAccessRights</dt>
<dd>Get the access rights for the channel.</dd>
</dl>
<p>The remaining methods are described in later sections of this package
overview.</p>
<p>Many of the interface described in the later sections are created via a
create call that has as one of it's arguments:
</p>
<pre> PVStructure pvRequest</pre>
See pvDataJava for a description of pvRequest.
<h3>AccessRights</h3>
<p>Access Rights are not currently implemented.</p>
<pre>enum AccessRights {
none,
read,
readWrite
}</pre>
<h3>GetField</h3>
<p>The method:</p>
<pre> Channel.getField(GetFieldRequester requester, String subField);</pre>
<p>Gets the introspection interface for the specified sub field of the record
it which the channel is connected. The subField can be null, which means get
the introspection interface for the entire record, or is of the form
"name.name..." . Thus it can be a request for any field within a record. The
requester must implement the interface:</p>
<pre>interface GetFieldRequester extends Requester {
void getDone(Status status, Field field);
}</pre>
<p>where</p>
<dl>
<dt>getDone</dt>
<dd>A getField request has finished. A null is returned if the request
fails and status contains a reason of a failure. If the request succeeds
Field is the introspection interface. </dd>
</dl>
<h3>ChannelRequest</h3>
<p>Many of the interfaces described in later sections extend the following
interface.</p>
<pre>
interface ChannelRequest extends Lockable, Destroyable {
Channel getChannel();
void cancel();
void lastRequest();
</pre>
<p>where</p>
<dl>
<dt>destroy</dt>
<dd>Destroy whatever the extended interface implements. It will free all
resources it uses.</dd>
<dt>getChannel</dt>
<dd>Get the channel instance to which this request belongs.</dd>
<dt>cancel</dt>
<dd>Cancel the current request.</dd>
<dt>lastRequest</dt>
<dd>The next request will be the last request.</dd>
</dl>
<h3>ChannelProcess</h3>
<p>A ChannelProcess is created via a call to:</p>
<pre>interface Channel extends Requester {
ChannelProcess createChannelProcess(
ChannelProcessRequester channelProcessRequester);
}</pre>
<p>The requester must implement the interface:</p>
<pre>
interface ChannelProcessRequester extends Requester {
void channelProcessConnect(
Status status,
ChannelProcess channelProcess);
void processDone(
Status status,
ChannelProcess channelProcess);
}
</pre>
<p>where</p>
<dl>
<dt>channelProcessConnect</dt>
<dd>This returns the interface for requesting that a record be processed.
Status is the result for the create request. channelProcess is null if
status is not success.</dd>
<dt>processDone</dt>
<dd>This is called when a process request is done. Status is the result for
the process request. </dd>
</dl>
<p>The following is the interface for requesting that a record be processed.</p>
<pre>interface ChannelProcess extends ChannelRequest {
void process();
}</pre>
<p>where</p>
<dl>
<dt>process</dt>
<dd>Process the record.
Another process request must not be issued until processDone is
called.</dd>
</dl>
<h3>ChannelGet</h3>
<p>A ChannelGet is created via a call to:</p>
<pre>interface Channel extends Requester {
ChannelGet createChannelGet(
ChannelGetRequester channelGetRequester,
PVStructure pvRequest);
}</pre>
<p>where</p>
<dl>
<dt>channelGetRequester</dt>
<dd>Described next.</dd>
<dt>pvRequest</dt>
<dd>This was described in a previous section. BUT for channelGet the
request string for createRequest.createRequest has the form:
"record[options]field(fieldOptions)". An example of a record options is
"process=true". The fieldOptions are as defined by pvCopy.</dd>
</dl>
<p>The requester must implement the interface.</p>
<pre>interface ChannelGetRequester extends Requester {
void channelGetConnect(
Status status,
ChannelGet channelGet,
Structure structure);
void getDone(
Status status,
ChannelGet channelGet,
PVStructure pvStructure,
BitSet bitSet);
}</pre>
<p>where</p>
<dl>
<dt>channelGetConnect</dt>
<dd>This is called if the createProcess fails or when the client request is
connected to the server. Status provides the result of the createChannel
request. If status is not success than the other arguments are null.
channelGet is the interface for requesting gets. structure is the
introspection interface for data that is returned to getDone.
</dd>
<dt>getDone</dt>
<dd>The get request is done. status provides the result of the get request.
If successful the pvStructure and bitSet contain the data returned
as a result of a get request.
bitSet shows which fields have new data. If a
bit of bitSet is set for a structure field that means that all fields of
the structure have new values. For example of bit 0 of bitSet is set then
all fields of pvStructure have new data. Note that each PVField
implements a method getFieldOffset(). this can be used with bitSet to
determine which fields have new data values. See BitSet and PVField in
org.epics.pvdata for details.
</dd>
</dl>
<p>The following is the interface for requesting data from a record.</p>
<pre>
interface ChannelGet extends ChannelRequest {
void get();
}
</pre>
<p>where</p>
<dl>
<dt>get</dt>
<dd>Get data.
Another get
request must not be issued until getDone is called.</dd>
</dl>
<h3>ChannelPut</h3>
<p>A ChannelPut is created via a call to:</p>
<pre>interface Channel extends Requester {
ChannelPut createChannelPut(
ChannelPutRequester channelPutRequester,
PVStructure pvRequest);
}</pre>
<p>where</p>
<dl>
<dt>channelPutRequester</dt>
<dd>Described next.</dd>
<dt>pvRequest</dt>
<dd>This was described in a previous section. BUT for channelPut the
request string for createRequest.createRequest has the form:
"record[options]field(fieldOptions)". An example of a record options is
"process=true". The fieldOptions are as defined by pvCopy.</dd>
</dl>
<p>The requester must implement the interface.</p>
<pre>
interface ChannelPutRequester extends Requester {
void channelPutConnect(
Status status,
ChannelPut channelPut,
Structure structure);
void putDone(
Status status,
ChannelPut channelPut);
void getDone(
Status status,
ChannelPut channelPut,
PVStructure pvStructure,
BitSet bitSet);
}</pre>
<p>where</p>
<dl>
<dt>channelPutConnect</dt>
<dd>This is called if the createChannelPut fails or when the client request
is connected to the server. Status provides the result of the
createChannelPut request. If status is not success than the other
arguments are null. channelPut is the interface for requesting puts and
gets. Structure is the introspection interface that must be used
for data that is put to the server or that is returned by a get request.
</dd>
<dt>putDone</dt>
<dd>The put request is done. status provides the result of the put request.
</dd>
<dt>getDone</dt>
<dd>The get request is done. status provides the result of the put request.
pvStructure has the data returned from the server.
bitSet to shows which fields have new data before making a put request.
If a bit of bitSet is set for a structure field that means that all
fields of the structure have new values. For example of bit 0 of bitSet
is set then all fields of pvStructure have new data. Note that each
PVField implements a method getFieldOffset(). this can be used with
bitSet to determine which fields have new data values. See BitSet and
PVField in org.epics.pvdata for details.
</dd>
</dl>
<p>The following is the interface for requesting data from a record.</p>
<pre>interface ChannelPut extends ChannelRequest {
void put(PVStructure pvPutStructure, BitSet bitSet);
void get();
}</pre>
<p>where</p>
<dl>
<dt>put</dt>
<dd>Put data.
pvPutStructure is the data to send to the server,
bitSet determines which fields are sent.
</dd>
<dt>get</dt>
<dd>Get the current data from the record. The record is never processed.
The request just gets the current values which is put into the
pvStructure returned in the call to channelPutConnect.</dd>
<dt>NOTE: Only one of put and get can be outstanding at the same time.
Another get or put must not be issued until getDone or putDone is called.</dt>
</dl>
<h3>ChannelPutGet</h3>
<p>A channelPutGet request puts data into a record, optionally processes the
record, and gets data from the record.</p>
<p>A channel putGet is created via a call to:</p>
<pre>interface Channel extends Requester {
ChannelPutGet createChannelPutGet(
ChannelPutGetRequester channelPutGetRequester,
PVStructure pvRequest);
}</pre>
<p>where</p>
<dl>
<dt>channelPutGetRequester</dt>
<dd>Described next.</dd>
<dt>pvRequest</dt>
<dd>This was described in a previous section. BUT for channelPutGet the
request string for createRequest.createRequest has the form:
"record[...]putField(fieldOptions)getField(fieldOptions)". An
example of a record options is "process=true". The fieldOptions are as
defined by pvCopy.</dd>
</dl>
<p>The requester must implement the interface.</p>
<pre>
interface ChannelPutGetRequester extends Requester
{
void channelPutGetConnect(
Status status,
ChannelPutGet channelPutGet,
Structure putStructure,
Structure getStructure);
void putGetDone(
Status status,
ChannelPutGet channelPutGet,
PVStructure getPVStructure,
BitSet getBitSet);
void getPutDone(
Status status,
ChannelPutGet channelPutGet,
PVStructure putPVStructure,
BitSet putBitSet);
void getGetDone(
Status status,