Accelerator Independent Data Access / PVAccess 2.0
AIDA-PVA is the latest version of the AIDA framework. Built on top of EPICS 7 it enables client applications to programmatically access and manage any device or database on the SLAC Network using simple channel names.
Loading...
Searching...
No Matches
AIDASLCBPMBUFF_SERVER.c
Go to the documentation of this file.
1/** @file
2 * @brief Buffered BPM Acquisition Native Provider implementation.
3 * **MEMBER**=SLCLIBS:AIDA_PVALIB
4 * **ATTRIBUTES**=JNI,LIBR_NOGLOBAL
5 */
6#include "aida_pva.h"
7#include "AIDASLCBPMBUFF_SERVER.h"
8
9static int
10acquireBuffAcqData(JNIEnv* env, int* rows, int nDevices, DEVICE_NAME_TS* deviceNames, char* dGroupName,
11 int bpmd,
12 int nrpos, int timeout);
13static int getBuffAcqData(JNIEnv* env,
14 char** namesData,
15 float* xData, float* yData, float* tmitData, unsigned long* pulseIdData,
16 int2u* statsData, int2u* goodMeasData);
17static int endAcquireBuffAcq(JNIEnv* env);
18static int checkArguments(JNIEnv* env, int bpmd, int nrpos, int nDevices);
19
20// API Stubs
21VERSION("1.0.0")
40
41/**
42 * Initialise the service
43 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
44 * @throws ServerInitialisationException if the service fails to initialise
45 */
46void aidaServiceInit(JNIEnv* env)
47{
48 vmsstat_t status;
49
50 if (!$VMS_STATUS_SUCCESS(status = init("AIDA_SLCBPMBUFF", true))) {
51 aidaThrow(env, status, SERVER_INITIALISATION_EXCEPTION, "while initializing Buffered BPM service");
52 return;
53 }
54
55 DPSLCBUFF_SETMODE();
56
57 printf("AIDA-PVA Buffered BPM Acquisition Provider\n");
58}
59
60/**
61 * Get a table of data
62 * Parameters:
63 * BPMD: Integer Bpm Measurement Definition number
64 * NRPOS: number of pulses. Default is 1
65 * BPMS: json. List of BPMs to read
66 * ["BPMS:LI02:501", "BPMS:DR12:334"]
67 * DEVS: json. List of devices to read
68 * Note: cannot specify both BPMS and DEVS
69 *
70 * @param env to be used to throw exceptions using aidaThrow() and aidaThrowNonOsException()
71 * @param uri the uri
72 * @param arguments the arguments
73 * @return the table
74 */
75Table aidaRequestTable(JNIEnv* env, const char* uri, Arguments arguments)
76{
78
79 // Get arguments
80 int bpmd = BPMD_ROGUE, nrpos = NRPOS_DEFAULT, nDevices = 0, timeout = 3;
81 unsigned int nBpms = 0, nDevs = 0;
82 char** bpms = NULL, ** devices = NULL;
83 DEVICE_NAME_TS deviceNames[MAX_DGRP_BPMS];
84 TO_DGROUP(dGroupName, uri)
85
86 if (ascanf(env, &arguments, "%d %od %osa %osa %od",
87 "bpmd", &bpmd,
88 "nrpos", &nrpos,
89 "bpms", &bpms, &nBpms,
90 "devs", &devices, &nDevs,
91 "timeout", &timeout
92 )) {
94 }
95 TRACK_MEMORY(bpms)
96 TRACK_MEMORY(devices)
97
98 if (nBpms && nDevs) {
99 // Only one or the other not both
100 aidaThrowNonOsException(env, UNABLE_TO_GET_DATA_EXCEPTION, "Specify either DEVS or BPMS argument but not both");
103 } else if (nBpms) {
104 for (int i = 0; i < nBpms; i++) {
105 if (pmuFromDeviceName(env, bpms[i],
106 deviceNames[i].prim_s._a,
107 deviceNames[i].micr_s._a,
108 &deviceNames[i].unit_s._i)) {
111 }
112 }
113 nDevices += nBpms;
114 bpms = NULL;
115 } else if (nDevs) {
116 for (int i = 0; i < nDevs; i++) {
117 if (pmuFromDeviceName(env, devices[i],
118 deviceNames[i].prim_s._a,
119 deviceNames[i].micr_s._a,
120 &deviceNames[i].unit_s._i)) {
123 }
124 }
125 nDevices += nDevs;
126 devices = NULL;
127 }
129
130 // Check arguments
131 if (checkArguments(env, bpmd, nrpos, nDevices)) {
133 }
134
135 // Acquire Data
136 int rows;
137 if (acquireBuffAcqData(env, &rows, nDevices, &deviceNames[0], dGroupName, bpmd, nrpos, timeout)) {
139 }
140
141 // No rows
142 if (!rows) {
143 aidaThrowNonOsException(env, UNABLE_TO_GET_DATA_EXCEPTION, "No rows were retrieved for your query");
145 }
146
147 if (rows > MAX_DGRP_BPMS * MAX_BUFF_MEAS) {
148 aidaThrowNonOsException(env, UNABLE_TO_GET_DATA_EXCEPTION, "Too many rows returned by this query");
150 }
151
152 // To hold data
153 char* namesData[rows + 1];
154 float xData[rows + 1], yData[rows + 1], tmitData[rows + 1];
155 unsigned long pulseIdData[rows + 1];
156 int2u statsData[rows + 1], goodMeasData[rows + 1];
157
158 // Get Buffered Data
159 if (getBuffAcqData(env, namesData, xData, yData, tmitData, pulseIdData, statsData, goodMeasData)) {
161 }
162
163 // Make and output table
164 Table table = tableCreate(env, rows, 7);
166 tableAddStringColumn(env, &table, namesData);
168 tableAddColumn(env, &table, AIDA_INTEGER_TYPE, pulseIdData, false);
170 tableAddColumn(env, &table, AIDA_FLOAT_TYPE, xData, false);
172 tableAddColumn(env, &table, AIDA_FLOAT_TYPE, yData, false);
174 tableAddColumn(env, &table, AIDA_FLOAT_TYPE, tmitData, false);
176 tableAddColumn(env, &table, AIDA_SHORT_TYPE, statsData, false);
178 tableAddColumn(env, &table, AIDA_SHORT_TYPE, goodMeasData, false);
179
180 endAcquireBuffAcq(env);
181
182 // All read successfully
183 return table;
184}
185
186/**
187 * Check arguments
188 * @param env
189 * @param bpmd
190 * @param nrpos
191 * @param nDevices
192 * @return
193 */
194static int checkArguments(JNIEnv* env, int bpmd, int nrpos, int nDevices)
195{
196 // Check that required param, bpmd, is valid.
197 if (bpmd < BPMD_MIN || bpmd > BPMD_MAX) {
199 "BPMD param is required and must be be between 1..9999");
200 return EXIT_FAILURE;
201 }
202
203 // Check n is valid
204 if (nrpos < NRPOS_MIN || nrpos > NRPOS_MAX) {
206 "NRPOS, the number of pulse to acquire, must be between 1..2800");
207 return EXIT_FAILURE;
208 }
209
210 // Check devices given
211 if (nDevices <= 0) {
212 aidaThrowNonOsException(env, UNABLE_TO_GET_DATA_EXCEPTION, "No devices to acquire were received");
213 return EXIT_FAILURE;
214 }
215 return EXIT_SUCCESS;
216}
217
218/**
219 * Acquire Buffered Data and return the number of readings returned
220 *
221 * @param env
222 * @param nDevices
223 * @param deviceNames
224 * @param dGroupName
225 * @param bpmd
226 * @param nrpos
227 * @return
228 */
229static int
230acquireBuffAcqData(JNIEnv* env, int* rows, int nDevices, DEVICE_NAME_TS* deviceNames, char* dGroupName,
231 int bpmd,
232 int nrpos, int timeout)
233{
234 vmsstat_t status;
235
236 // Initialise acquisition
237 if (!$VMS_STATUS_SUCCESS(status = DPSLCBUFF_ACQINIT(nDevices, nrpos))) {
238 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "while initializing Buffered BPM Acquisition");
239 return EXIT_FAILURE;
240 }
241
242 // Acquire BPM values
243 status = DPSLCBUFF_ACQ_WITH_TIMEOUT(nDevices, deviceNames, dGroupName, bpmd, nrpos, timeout);
244 if (!$VMS_STATUS_SUCCESS(status)) {
245 endAcquireBuffAcq(env);
246 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "while making Buffered Data acquisition");
247 return EXIT_FAILURE;
248 }
249
250 *rows = (int)DPSLCBUFF_GETTABLEMROWS();
251 return EXIT_SUCCESS;
252}
253
254/**
255 * Get the Buffered Data
256 *
257 * @param env
258 * @param namesData
259 * @param xData
260 * @param yData
261 * @param tmitData
262 * @param pulseIdData
263 * @param statsData
264 * @param goodMeasData
265 * @return
266 */
267static int
268getBuffAcqData(JNIEnv* env,
269 char** namesData,
270 float* xData, float* yData, float* tmitData,
271 unsigned long* pulseIdData, int2u* statsData, int2u* goodMeasData)
272{
273 int4u nNames, nPulseId, nXdata, nYdata, ntmit, nstats, ngoodmeas;
274
275 if (!(nNames = DPSLCBUFF_GETNAMES(namesData)) ||
276 !(nPulseId = DPSLCBUFF_GETPULSEIDS(pulseIdData)) ||
277 !(nXdata = DPSLCBUFF_GETXS(xData)) ||
278 !(nYdata = DPSLCBUFF_GETYS(yData)) ||
279 !(ntmit = DPSLCBUFF_GETTMITS(tmitData)) ||
280 !(nstats = DPSLCBUFF_GETSTATS(statsData)) ||
281 !(ngoodmeas = DPSLCBUFF_GETGOODMEASES(goodMeasData))
282 ) {
283 endAcquireBuffAcq(env);
284 aidaThrowNonOsException(env, UNABLE_TO_GET_DATA_EXCEPTION, "reading Buffered values");
285 return EXIT_FAILURE;
286 }
287
288 // If rows are not homogenous
289 if (!(nNames == nPulseId && nPulseId == nXdata && nXdata == nYdata && nYdata == ntmit && ntmit == nstats
290 && nstats == ngoodmeas)) {
291 endAcquireBuffAcq(env);
292 aidaThrowNonOsException(env, UNABLE_TO_GET_DATA_EXCEPTION, "non-homologous vectors of data returned");
293 return EXIT_FAILURE;
294 }
295
296 return EXIT_SUCCESS;
297}
298
299/**
300 * End Buffered data acquisition
301 *
302 * @param env
303 * @return
304 */
305static int endAcquireBuffAcq(JNIEnv* env)
306{
307 vmsstat_t status = 0;
308
309 // Terminate the acquisition
310 if (!$VMS_STATUS_SUCCESS(status = DPSLCBUFF_ACQTERM())) {
311 aidaThrow(env, status, UNABLE_TO_GET_DATA_EXCEPTION, "while terminating Buffered Data acquisition");
312 return EXIT_FAILURE;
313 }
314 return EXIT_SUCCESS;
315}
316
REQUEST_STUB_BOOLEAN REQUEST_STUB_BYTE REQUEST_STUB_SHORT REQUEST_STUB_INTEGER REQUEST_STUB_LONG REQUEST_STUB_FLOAT REQUEST_STUB_DOUBLE REQUEST_STUB_STRING REQUEST_STUB_BOOLEAN_ARRAY REQUEST_STUB_BYTE_ARRAY REQUEST_STUB_SHORT_ARRAY REQUEST_STUB_INTEGER_ARRAY REQUEST_STUB_LONG_ARRAY REQUEST_STUB_FLOAT_ARRAY REQUEST_STUB_DOUBLE_ARRAY REQUEST_STUB_STRING_ARRAY SET_STUB_VOID SET_STUB_TABLE void aidaServiceInit(JNIEnv *env)
Initialise the service.
Table aidaRequestTable(JNIEnv *env, const char *uri, Arguments arguments)
Get a table of data Parameters: BPMD: Integer Bpm Measurement Definition number NRPOS: number of puls...
The Header File for the AIDA-PVA Module functions.
#define REQUEST_STUB_BYTE
aidaRequestByte API Stub
Definition: aida_pva_api.h:259
#define VERSION(_version)
Use this macro to define the version of the provider.
Definition: aida_pva_api.h:40
#define REQUEST_STUB_INTEGER
aidaRequestInteger API Stub
Definition: aida_pva_api.h:269
#define REQUEST_STUB_LONG_ARRAY
aidaRequestLongArray API Stub
Definition: aida_pva_api.h:326
#define REQUEST_STUB_SHORT
aidaRequestShort API Stub
Definition: aida_pva_api.h:264
#define REQUEST_STUB_INTEGER_ARRAY
aidaRequestIntegerArray API Stub
Definition: aida_pva_api.h:321
#define SET_STUB_VOID
aidaSetValue API stub
Definition: aida_pva_api.h:361
#define REQUEST_STUB_LONG
aidaRequestLong API Stub
Definition: aida_pva_api.h:274
#define REQUEST_STUB_STRING
aidaRequestString API Stub
Definition: aida_pva_api.h:289
#define REQUEST_STUB_DOUBLE
aidaRequestDouble API Stub
Definition: aida_pva_api.h:284
#define REQUEST_STUB_SHORT_ARRAY
aidaRequestShortArray API Stub
Definition: aida_pva_api.h:316
#define REQUEST_STUB_BYTE_ARRAY
aidaRequestByteArray API Stub
Definition: aida_pva_api.h:311
#define RETURN_NULL_TABLE
Return an empty table response.
Definition: aida_pva_api.h:380
#define REQUEST_STUB_BOOLEAN
aidaRequestBoolean API Stub
Definition: aida_pva_api.h:253
#define SET_STUB_TABLE
aidaSetValueWithResponse API stub
Definition: aida_pva_api.h:370
#define REQUEST_STUB_FLOAT_ARRAY
aidaRequestFloatArray API Stub
Definition: aida_pva_api.h:331
#define REQUEST_STUB_DOUBLE_ARRAY
aidaRequestDoubleArray API Stub
Definition: aida_pva_api.h:336
#define REQUEST_STUB_BOOLEAN_ARRAY
aidaRequestBooleanArray API Stub
Definition: aida_pva_api.h:306
#define REQUEST_STUB_FLOAT
aidaRequestFloat API Stub
Definition: aida_pva_api.h:279
#define REQUEST_STUB_STRING_ARRAY
aidaRequestStringArray API stub
Definition: aida_pva_api.h:342
#define SERVER_INITIALISATION_EXCEPTION
Use this string to signal Server Initialisation Exceptions in aidaThrow()
#define ON_EXCEPTION_RETURN_(_r)
Check to see if an exception has been raised, and return the given return value.
#define UNABLE_TO_GET_DATA_EXCEPTION
Use this string to signal Exceptions when trying to Get Data in aidaThrow()
#define TRACK_ALLOCATED_MEMORY
Create tracking variables so that memory can be freed with FREE_MEMORY macro.
#define FREE_MEMORY
Free any allocated memory.
#define TRACK_MEMORY(_ptr)
Register this newly allocated memory so that it will be freed by FREE_MEMORY.
void aidaThrow(JNIEnv *env, vmsstat_t status, char *exception, const char *message)
To log any exceptions and throw back to java.
vmsstat_t init(const char *processName, bool initMessageServices)
Call standalone_init()
void aidaThrowNonOsException(JNIEnv *env, char *exception, const char *message)
To log any non-OS exceptions and throw back to java.
int pmuFromDeviceName(JNIEnv *env, char *device, char *primary, char *micro, int4u *unit)
Get primary, micro and unit from a device name.
@ AIDA_FLOAT_TYPE
Represents a float.
@ AIDA_INTEGER_TYPE
Represents an integer.
@ AIDA_SHORT_TYPE
Represents a short.
void tableAddStringColumn(JNIEnv *env, Table *table, char **data)
Add a String column to the given Table.
int ascanf(JNIEnv *env, Arguments *arguments, const char *formatString,...)
ascanf(), avscanf()
Table tableCreate(JNIEnv *env, int rows, int columns)
Make a Table for return to client.
void tableAddColumn(JNIEnv *env, Table *table, Type type, void *data, bool ieeeFormat)
Add a column of arbitrary type to a Table.
#define TO_DGROUP(_var, _uri)
Get a display group name from the provided uri and store it in the given variable name.
Definition: aida_pva_uri.h:69
An Arguments structure stores all of the arguments passed from the request to the Native Channel Prov...
Table structure.