1 saw 1.1 /*-----------------------------------------------------------------------------
2 * Copyright (c) 1994 Southeastern Universities Research Association,
3 * Continuous Electron Beam Accelerator Facility
4 *
5 * This software was developed under a United States Government license
6 * described in the NOTICE file included as part of this distribution.
7 *
8 * Stephen A. Wood, 12000 Jefferson Ave., Newport News, VA 23606
9 * Email: saw@cebaf.gov Tel: (804) 249-7367 Fax: (804) 249-5800
10 *-----------------------------------------------------------------------------
11 *
12 * Description:
13 * Routines used by a client to retrieve CTP variables
14 *
15 * Author: Stephen Wood, CEBAF Hall C
16 *
17 * Revision History:
18 * $Log: thClient.c,v $
19 * Revision 1.4 1995/08/03 13:50:52 saw
20 * Add SGI compatibility
21 *
22 saw 1.1 * Revision 1.3 1994/11/07 14:09:42 saw
23 * Bug fixes in thGetList_test and callback server code.
24 *
25 * Revision 1.2 1994/10/17 17:07:28 saw
26 * Add thGetList_test and the callback service davar_readmultiple_test_cb_1
27 *
28 * Revision 1.1 1994/09/27 19:19:09 saw
29 * Initial revision
30 *
31 */
32 #include <stdio.h>
33 #include <string.h>
34 #include <rpc/rpc.h>
35 #include "daVar.h"
36 #include "daVarRpc.h"
37 #include "cfortran.h"
38
39 long thCreateList(); /* Move to some include file */
40 long thAddToList(long handle, char *pattern);
41 long thRemoveFromList(long handle, char *pattern);
42 long thGetList(long handle, CLIENT *clnt);
43 saw 1.1 long thGetList_test(long handle, CLIENT *clnt, char *test_condition,
44 int max_time_wait, int max_event_wait);
45 long thPrintList(long handle);
46
47 FCALLSCFUN0(LONG,thCreateList,THCRLIST,thcrlist);
48 FCALLSCFUN2(LONG,thAddToList,THADDLIST,thaddlist,LONG,STRING);
49 FCALLSCFUN2(LONG,thRemoveFromList,THREMLIST,thremlist,LONG,STRING);
50 #ifdef __osf__
51 FCALLSCFUN2(LONG,thGetList,THGETLIST,thgetlist,LONG,PVOID);
52 FCALLSCFUN5(LONG,thGetList_test,THCGETLIST,thcgetlist,LONG,PVOID,STRING,INT,INT);
53 #else
54 FCALLSCFUN2(LONG,thGetList,THGETLIST,thgetlist,LONG,LONG);
55 FCALLSCFUN5(LONG,thGetList_test,THCGETLIST,thcgetlist,LONG,LONG,STRING,INT,INT);
56 #endif
57 FCALLSCFUN1(LONG,thPrintList,THPRTLIST,thprtlist,LONG);
58 /* Don't really understand the following. What about ultrix */
59 #if !defined(__ultrix__) && !defined(linux)
60 #ifndef __osf__
61 FCALLSCFUN4(LONG,clnt_create,CLNT_CREATE,clnt_create,STRING,LONG,LONG,STRING);
62 #endif
63 #else
64 saw 1.1 FCALLSCFUN4(LONG,clnt_create,CLNT_CREATE_,clnt_create_,STRING,LONG,LONG,STRING);
65 #endif
66
67 struct thNameNode {
68 char *name;
69 struct thNameNode *next;
70 };
71 typedef struct thNameNode thNameNode;
72
73 struct thNameList {
74 thNameNode *namehead;
75 int nnames; /* Number of names in list */
76 int rpc_made;
77 NAMELIST rpc; /* List in form for RPC argument */
78 };
79 typedef struct thNameList thNameList;
80
81 TESTNAMELIST *pending_arg=0;
82 int pending_flag=0;
83 int callback_result;
84
85 saw 1.1 long thCreateList(){
86 /* Create a handle for a list of variables */
87 thNameList *list;
88
89 list = (thNameList *) malloc(sizeof(thNameList));;
90 list->namehead = 0;
91 list->nnames = 0;
92 list->rpc_made = 0;
93 list->rpc.NAMELIST_len = 0;
94 list->rpc.NAMELIST_val = 0;
95 return((long) list);
96 }
97 long thAddToList(long handle, char *pattern)
98 /* Add registered variables to a list of variables to get from a server
99 Return the number of variables added
100 Should we check for duplicates? Not now. No harm in duplicates.
101 thRemoveFromList will remove all duplicates though. */
102 {
103 thNameList *list;
104 thNameNode *next,*this;
105 char **vlist; /* List of characters matching pattern */
106 saw 1.1 int count; /* Number of variables being added */
107 int i;
108
109 list = (thNameList *) handle;
110 daVarList(pattern,&vlist,&count);
111 for(i=0;i<count;i++) {
112 next = list->namehead; /* The current list */
113 this = list->namehead = (thNameNode *) malloc(sizeof(thNameNode)); /* New name */
114 this->name = (char *) malloc(strlen(vlist[i])+1);
115 strcpy(this->name,vlist[i]);
116 this->next = next; /* Attach rest of list */
117 }
118 list->nnames += count; /* Perhaps I should just count when needed ? */
119 list->rpc_made = 0; /* RPC format list now out of date. */
120 return(list->nnames);
121 }
122 long thRemoveFromList(long handle, char *pattern)
123 {
124 thNameList *list;
125 thNameNode *this,**thisp;
126 char **vlist; /* List of characters matching pattern */
127 saw 1.1 int count; /* Number of variables being removed */
128 int nremove;
129 int i;
130
131 list = (thNameList *) handle;
132 daVarList(pattern,&vlist,&count);
133 nremove = 0;
134 for(i=0;i<count;i++) {
135 this = list->namehead; /* Start of list */
136 thisp = &list->namehead; /* Pointer to next field of previous name */
137 while(this) {
138 if(strcasecmp(this->name,vlist[i])==0) { /* Remove matching string */
139 *thisp = this->next;
140 free(this->name);
141 free(this);
142 this = *thisp;
143 nremove++;
144 } else {
145 thisp = &(this->next);
146 this = this->next;
147 }
148 saw 1.1 }
149 }
150 list->nnames -= nremove; /* Perhaps I should just count when needed ? */
151 return(list->nnames);
152 }
153 long thPrintList(long handle)
154 /* For debugging */
155 {
156 thNameList *list;
157 thNameNode *next,*this;
158 int count;
159
160 list = (thNameList *) handle;
161 this = list->namehead;
162 printf("Variables attached to handle %d\n",handle);
163 count++;
164 while(this) {
165 printf("%s\n",this->name);
166 count++;
167 this = this->next;
168 }
169 saw 1.1 return(count);
170 }
171 long thGetList(long handle, CLIENT *clnt)
172 /* Returns 0 for total success, -1 for total failure, a positive number
173 for the number of variables that didn't work */
174 {
175 thNameList *list;
176 thNameNode *next,*this;
177 int i;
178 RVALLIST *vals;
179 int nerrors;
180
181 list = (thNameList *) handle;
182 /* printf("list->nnames=%d\n",list->nnames);*/
183 if(!list->rpc_made) {
184 if(list->rpc.NAMELIST_len == 0) {
185 list->rpc.NAMELIST_len = list->nnames;
186 list->rpc.NAMELIST_val = (char **) malloc(list->rpc.NAMELIST_len
187 *sizeof(char *));
188 } else if (list->rpc.NAMELIST_len != list->nnames) {
189 list->rpc.NAMELIST_len = list->nnames;
190 saw 1.1 list->rpc.NAMELIST_val = (char **)
191 realloc(list->rpc.NAMELIST_val,list->rpc.NAMELIST_len*sizeof(char *));
192 }
193 this = list->namehead;
194 for(i=0;(i<list->nnames && this);i++){
195 list->rpc.NAMELIST_val[i] = this->name;
196 this = this->next;
197 }
198 }
199 nerrors = 0;
200 if(vals = davar_readmultiple_1(&(list->rpc),clnt)) {
201 this = list->namehead;
202 /* printf("list->rpc.NAMELIST_len=%d\n",list->rpc.NAMELIST_len);*/
203 for(i=0;(i<list->rpc.NAMELIST_len && this);i++){
204 /* printf("%s\n",this->name);*/
205 if(vals->RVALLIST_val[i].valtype != DAVARERROR_RPC){
206 if(daVarWriteVar(this->name,&(vals->RVALLIST_val[i])) != S_SUCCESS)
207 nerrors++;
208 } else {
209 nerrors++;
210 }
211 saw 1.1 this = this->next;
212 }
213 } else {
214 nerrors = -1;
215 }
216 return(nerrors);
217 }
218 #if 0
219 long thPutList(long handle, CLIENT *clnt)
220 /* Returns 0 for total success, -1 for total failure, a positive number
221 for the number of variables that didn't work */
222 {
223 thNameList *list;
224 thNameNode *next,*this;
225 int i;
226 WVALLIST vals;
227 int nerrors;
228
229 /* Create the write structure */
230 list = (thNameList *) handle;
231 /* printf("list->nnames=%d\n",list->nnames);*/
232 saw 1.1 if(!list->rpc_made) {
233 if(list->rpc.NAMELIST_len == 0) {
234 list->rpc.NAMELIST_len = list->nnames;
235 list->rpc.NAMELIST_val = (char **) malloc(list->rpc.NAMELIST_len
236 *sizeof(char *));
237 } else if (list->rpc.NAMELIST_len != list->nnames) {
238 list->rpc.NAMELIST_len = list->nnames;
239 list->rpc.NAMELIST_val = (char **)
240 realloc(list->rpc.NAMELIST_val,list->rpc.NAMELIST_len*sizeof(char *));
241 }
242 this = list->namehead;
243 for(i=0;(i<list->nnames && this);i++){
244 list->rpc.NAMELIST_val[i] = this->name;
245 this = this->next;
246 }
247 }
248 nerrors = 0;
249 if(vals = davar_readmultiple_1(&(list->rpc),clnt)) {
250 this = list->namehead;
251 /* printf("list->rpc.NAMELIST_len=%d\n",list->rpc.NAMELIST_len);*/
252 for(i=0;(i<list->rpc.NAMELIST_len && this);i++){
253 saw 1.1 /* printf("%s\n",this->name);*/
254 if(vals->RVALLIST_val[i].valtype != DAVARERROR_RPC){
255 if(daVarWriteVar(this->name,&(vals->RVALLIST_val[i])) != S_SUCCESS)
256 nerrors++;
257 } else {
258 nerrors++;
259 }
260 this = this->next;
261 }
262 } else {
263 nerrors = -1;
264 }
265 return(nerrors);
266 }
267 #endif
268 #if 0
269 int tsize=0;
270 struct timeval timeout;
271 long servone(int wait)
272 /* Need to move something that does this into CTP proper */
273 {
274 saw 1.1 fd_set readfdset;
275 extern int errno;
276
277 timeout.tv_sec = wait;
278 timeout.tv_usec = 1;
279
280 #ifdef hpux
281 if(!tsize) tsize = NFDBITS;
282 #else
283 if(!tsize) tsize = getdtablesize(); /* how many descriptors can we have */
284 #endif
285
286 readfdset = svc_fdset;
287 switch(select(tsize, &readfdset, (fd_set *) NULL, (fd_set *) NULL,
288 &timeout)) {
289 case -1:
290 if (errno == EBADF) break;
291 perror("select failed");
292 break;
293 case 0:
294 /* perform other functions here if select() timed-out */
295 saw 1.1 break;
296 default:
297 svc_getreqset(&readfdset);
298 }
299 }
300 #endif
301 long thGetList_test(long handle, CLIENT *clnt, char *test_condition,
302 int max_time_wait, int max_event_wait)
303 /* Returns 0 for total success, -1 for total failure, a positive number
304 for the number of variables that didn't work */
305 {
306 thNameList *list;
307 thNameNode *next,*this;
308 int i;
309 RVALLIST *vals;
310 int *status;
311 TESTNAMELIST *arg;
312 long servret;
313
314 /* Can return some kind of error if pending_arg is not zero */
315 list = (thNameList *) handle;
316 saw 1.1 /* printf("list->nnames=%d\n",list->nnames);*/
317 if(!list->rpc_made) {
318 if(list->rpc.NAMELIST_len == 0) {
319 list->rpc.NAMELIST_len = list->nnames;
320 list->rpc.NAMELIST_val = (char **) malloc(list->rpc.NAMELIST_len
321 *sizeof(char *));
322 } else if (list->rpc.NAMELIST_len != list->nnames) {
323 list->rpc.NAMELIST_len = list->nnames;
324 list->rpc.NAMELIST_val = (char **)
325 realloc(list->rpc.NAMELIST_val,list->rpc.NAMELIST_len*sizeof(char *));
326 }
327 this = list->namehead;
328 for(i=0;(i<list->nnames && this);i++){
329 list->rpc.NAMELIST_val[i] = this->name;
330 this = this->next;
331 }
332 }
333 arg = (TESTNAMELIST *) malloc(sizeof(TESTNAMELIST));
334 arg->test_condition = (char *) malloc(strlen(test_condition)+1);
335 strcpy(arg->test_condition,test_condition);
336 arg->max_time_wait = max_time_wait;
337 saw 1.1 arg->max_event_wait = max_event_wait;
338 arg->prog = DAVARSVR;
339 arg->vers = DAVARVERS+1;
340 arg->NAMELISTP = &list->rpc;
341 pending_arg = arg;
342 pending_flag = 1;
343
344 if(!(status = davar_readmultiple_test_1(arg,clnt)))
345 return(-1);
346
347 /* Now wait for the incoming network call */
348
349 servret = 1;
350 while(pending_flag && servret > 0) /* Wait for timeout, completion or failur*/
351 servret = daVarServOnce(arg->max_time_wait+10); /* Will wait double?? */
352 if(servret == 0) callback_result = -2; /* Timeout */
353 else if(servret == -1) callback_result = -3;
354
355 free(arg->test_condition);
356 free(arg);
357 pending_arg = 0;
358 saw 1.1
359 return(callback_result);
360 }
361 int *davar_readmultiple_test_cb_1(RVALLIST *vals, CLIENT *clnt)
362 {
363 static int result;
364
365 TESTNAMELIST *argp;
366 thNameNode *next,*this;
367 int i;
368
369 if(pending_arg) argp = pending_arg;
370 else {
371 pending_flag = 0;
372 return(&result); /* What error code ?? */
373 }
374
375 callback_result = 0;
376 if(argp->NAMELISTP->NAMELIST_len == vals->RVALLIST_len) {
377 for(i=0;(i<argp->NAMELISTP->NAMELIST_len);i++){
378 /* printf("%s\n",this->name);*/
379 saw 1.1 if(vals->RVALLIST_val[i].valtype != DAVARERROR_RPC){
380 if(daVarWriteVar(argp->NAMELISTP->NAMELIST_val[i]
381 ,&(vals->RVALLIST_val[i])) != S_SUCCESS)
382 callback_result++;
383 } else {
384 callback_result++;
385 }
386 }
387 } else if (vals->RVALLIST_len>0) {
388 printf("Lengths: %d %d",argp->NAMELISTP->NAMELIST_len,vals->RVALLIST_len);
389 callback_result = -1;
390 } else {
391 callback_result = -2; /* Server send timeout signal */
392 }
393 pending_flag = 0;
394 return(&result);
395 }
|