Initial version of donated sources by Avertec, 3.4p5.
[tas-yagle.git] / distrib / sources / api / mbk / mbk_API.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <unistd.h>
5 #include <string.h>
6 #include <alloca.h>
7 #include <time.h>
8 #include <errno.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11
12 #include MUT_H
13 #include MLO_H
14 #include RCN_H
15 #include MLU_H
16 #include AVT_H
17 #include API_H
18 #define AVTWIG_AVOID_CONFLICT
19 #define API_USE_REAL_TYPES
20 #include "mbk_API.h"
21
22 #ifdef Solaris
23 extern char *ctime_r(const time_t *clock, char *buf, int buflen);
24 #endif
25
26 /*----------------------------------------------------------------------------*/
27 /* */
28 /* function DriveNetlist (API purpose) */
29 /* */
30 /*----------------------------------------------------------------------------*/
31
32 //_____________________________________________________
33 // Interface for qsort
34 //_____________________________________________________
35
36 static int vcomp (const void *p1, const void *p2)
37 {
38 int index1, index2;
39
40 index1 = *(long*)p1;
41 index2 = *(long*)p2;
42
43 if (index1 > index2) return 1;
44 if (index1 < index2) return -1;
45 return 0;
46 }
47
48 /*----------------------------------------------------------------------------*/
49
50 void mbk_Sort (int *index_array, void **value_array, int nbelem)
51 {
52 int i;
53 long *sort_array = (long*)malloc (nbelem * 2 * sizeof (long));
54
55 for (i = 0; i < nbelem; i++) {
56 sort_array[2 * i] = (long)index_array[i];
57 sort_array[2 * i + 1] = (long)value_array[i];
58 }
59
60 qsort (sort_array, nbelem, sizeof (long) * 2, vcomp);
61
62 for (i = 0; i < nbelem; i++) {
63 index_array[i] = (int)sort_array[2 * i];
64 value_array[i] = (void*)sort_array[2 * i + 1];
65 }
66
67 free (sort_array);
68 }
69
70 /*----------------------------------------------------------------------------*/
71
72 void mbk_FreeList(chain_list *lst)
73 {
74 freechain(lst);
75 }
76
77 /*----------------------------------------------------------------------------*/
78
79 int mbk_EndofList(chain_list *lst)
80 {
81 return lst==NULL;
82 }
83
84 /*----------------------------------------------------------------------------*/
85
86 chain_list *mbk_AddListItem (chain_list *lst, void *item)
87 {
88 return addchain ((chain_list*)lst, item);
89 }
90 /*----------------------------------------------------------------------------*/
91
92 chain_list *mbk_AppendList(chain_list *lst1, chain_list *lst2)
93 {
94 return append (lst1, lst2);
95 }
96
97 /*----------------------------------------------------------------------------*/
98
99 void *mbk_GetListItem(chain_list *lst)
100 {
101 return lst->DATA;
102 }
103
104 /*----------------------------------------------------------------------------*/
105
106 chain_list *mbk_GetListNext(chain_list *lst)
107 {
108 return lst->NEXT;
109 }
110
111 /*----------------------------------------------------------------------------*/
112 /* */
113 /* Hash Table API */
114 /* */
115 /*----------------------------------------------------------------------------*/
116
117 ht *mbk_NewHashTable (int size)
118 {
119 return addht (size);
120 }
121
122 /*----------------------------------------------------------------------------*/
123
124 long mbk_AddHashItem (ht *htable, void *key, long value)
125 {
126 return addhtitem ((ht*)htable, key, (long)value);
127 }
128
129 void mbk_AddStringHashItem (ht *htable, char *key, char *value)
130 {
131 addhtitem ((ht*)htable, sensitive_namealloc(key), (long)strdup(value));
132 }
133
134 /*----------------------------------------------------------------------------*/
135
136 long mbk_DelHashItem (ht *htable, void *key)
137 {
138 return delhtitem ((ht*)htable, key);
139 }
140
141 /*----------------------------------------------------------------------------*/
142
143 long mbk_GetHashItem (ht *htable, void *key)
144 {
145 return gethtitem (htable, key);
146 }
147
148 char *mbk_GetStringHashItem (ht *htable, char *key)
149 {
150 long res;
151 res=gethtitem (htable, sensitive_namealloc(key));
152 if (res!=EMPTYHT) return (char *)res;
153 return "?";
154 }
155
156 /*----------------------------------------------------------------------------*/
157
158 void mbk_FreeHashTable (ht *htable)
159 {
160 delht ((ht*)htable);
161 }
162 void mbk_FreeStringHashTable (ht *htable)
163 {
164 chain_list *cl;
165 cl=GetAllHTElems(htable);
166 while (cl!=NULL)
167 {
168 free(cl->DATA);
169 cl=delchain(cl,cl);
170 }
171 delht ((ht*)htable);
172 }
173 chain_list *mbk_GetStringHashTableKeys (ht *htable)
174 {
175 return GetAllHTKeys(htable);
176 }
177
178 /*----------------------------------------------------------------------------*/
179
180 int mbk_IsEmptyHashItem (long value)
181 {
182 return value == EMPTYHT;
183 }
184
185 /*----------------------------------------------------------------------------*/
186
187 lofig_list *mbk_GetNetlist (char *figname)
188 {
189 static int env = 0;
190 if (!env) {
191 avtenv ();
192 mbkenv ();
193 env = 1;
194 }
195 return getlofig (figname, 'A');
196 }
197
198 FILE *myfopen(char *name, const char *mode)
199 {
200 FILE *f;
201 if ((f=mbksysfopen(name,(char*)mode,0))==NULL)
202 {
203 if (strchr(mode,'r')!=NULL)
204 avt_errmsg(AVT_ERRMSG, "045", AVT_ERROR, name);
205 else
206 avt_errmsg(AVT_ERRMSG, "046", AVT_ERROR, name);
207 }
208 return f;
209 }
210
211 int myfputs (const char *s, FILE *stream)
212 {
213 if (stream!=NULL)
214 return fputs (s, stream);
215 return 1;
216 }
217
218 int myfclose(FILE *f)
219 {
220 if (f!=NULL)
221 return fclose (f);
222 return 0;
223 }
224
225 void myfflush(FILE *f)
226 {
227 if (f!=NULL)
228 return fflush (f);
229 }
230
231 /*----------------------------------------------------------------------------*/
232
233 int decodejob( char *numrun, int *jobs, int *parajobs )
234 {
235 int n ;
236 char *pt ;
237
238 *jobs = -1 ;
239 *parajobs = -1 ;
240
241 n = strtol( numrun, &pt, 10 );
242 if( *pt == '\0' ) {
243 *jobs = n ;
244 *parajobs = 1 ;
245 }
246 else {
247 if( *pt == ':' ) {
248 *jobs = n ;
249 n = strtol( pt+1, &pt, 10 );
250 if( *pt == '\0' ) {
251 *parajobs = n ;
252 }
253 }
254 }
255
256 if( *parajobs <= 0 || *jobs <= 0 ) {
257 avt_errmsg(AVT_ERRMSG, "050", AVT_ERROR, numrun);
258 return 0 ;
259 }
260
261 return 1 ;
262 }
263
264 #define STAT_EXEC_FREE 1
265 #define STAT_EXEC_WAIT 2
266 #define STAT_EXEC_RUN 3
267
268 typedef struct {
269 int id ;
270 int state ;
271 char *buffer ;
272 int size;
273 FILE *myfile;
274 } execslot ;
275
276
277 void runjob( char *script, char **argv )
278 {
279 int pid ;
280
281 pid = vfork() ;
282 if( pid < 0 ) {
283 perror( "vfork() " );
284 avt_errmsg(AVT_ERRMSG, "056", AVT_FATAL );
285 }
286 else {
287 if( pid ) {
288 mbksetautoackchld( pid );
289 }
290 else {
291 execvp( script, argv );
292 perror( "execvp() " );
293 avt_errmsg(AVT_ERRMSG, "056", AVT_FATAL );
294 }
295 }
296 }
297
298 FILE* openstatdatafile( char *resfile, int incremental )
299 {
300 FILE *file ;
301 char *point ;
302 char *lastpoint ;
303 char *name ;
304 char *ext ;
305 char *testfile ;
306 int n ;
307
308 if (incremental==1)
309 return mbkfopen( resfile, NULL, "al" );
310 else if (incremental==-1)
311 return mbkfopen( resfile, NULL, "wl" );
312
313 file = mbkfopen( resfile, NULL, "rl" );
314 if( file )
315 fclose( file );
316
317 if( file ) {
318
319 n = strlen( resfile );
320 name = alloca( sizeof(char)*(n+1) );
321 ext = alloca( sizeof(char)*(n+1) );
322 testfile = alloca( sizeof(char)*(n+10) );
323
324 lastpoint = NULL ;
325 point = resfile ;
326
327 while( ( point = strchr( point, '.' ) ) ) {
328 lastpoint = point ;
329 point = point + 1 ;
330 }
331
332 if( lastpoint ) {
333 strncpy( name, resfile, lastpoint-resfile );
334 name[lastpoint-resfile]='\0';
335 strcpy( ext, lastpoint+1 );
336 }
337 else {
338 strcpy( name, resfile );
339 ext = NULL ;
340 }
341
342 n=0 ;
343
344 do {
345
346 n++ ;
347
348 if( ext )
349 sprintf( testfile, "%s_%03d.%s", name, n, ext );
350 else
351 sprintf( testfile, "%s_%03d", name, n );
352
353 file = mbkfopen( testfile, NULL, "rl" );
354 if( file )
355 fclose( file );
356 }
357 while( file );
358 file = mbkfopen( testfile, NULL, "wl" );
359 avt_errmsg( AVT_ERRMSG, "057", AVT_WARNING, resfile, testfile );
360 }
361 else {
362 file = mbkfopen( resfile, NULL, "wl" );
363 }
364
365 return file ;
366 }
367
368 static void filltime(char *buf)
369 {
370 time_t clock;
371
372 strcpy(buf,"");
373 time(&clock);
374
375 #ifdef Solaris
376 ctime_r(&clock,buf,52);
377 #else
378 ctime_r(&clock,buf);
379 #endif
380 if (strlen(buf)>0)
381 buf[strlen(buf)-1] = '\0';
382 }
383
384
385 int handle_slave_data(FILE *file, mbk_comdata *comdata, execslot *es, chain_list **mutex, char *resdir)
386 {
387 char *res=NULL, *data=NULL;
388 int ok=0;
389 unsigned int i, lg;
390 const char *cmd[]=
391 {
392 "info:",
393 "ask:pwd",
394 "ask:getsetflag:",
395 "ask:unsetflag:",
396 "ask:createfile:",
397 "ask:closefile",
398 "ask:writefile:",
399 "ask:writefile32:",
400 "ask:resdir",
401 };
402
403 for (i=0; i<sizeof(cmd)/sizeof(*cmd); i++)
404 {
405 if (strncmp(es->buffer,cmd[i], strlen(cmd[i]))==0)
406 {
407 data=&es->buffer[strlen(cmd[i])];
408 break;
409 }
410 }
411
412 if (data!=NULL)
413 {
414 switch(i)
415 {
416 case 0: // info:
417 avt_log(-1, 0, " Job %d: %s\n",es->id, data);
418 break;
419 case 1: // ask:pwd
420 res=mbkalloc(1024);
421 getcwd(res, 1024);
422 break;
423 case 2: // ask:getsetflag:
424 data=sensitive_namealloc(data);
425 if (getchain(*mutex, data)==NULL)
426 *mutex=addchain(*mutex, data), ok=1;
427 res=mbkstrdup(ok?"ok":"ko");
428 break;
429 case 3: // ask:unsetflag:
430 data=sensitive_namealloc(data);
431 if (getchain(*mutex, data)!=NULL)
432 *mutex=delchaindata(*mutex, data), ok=1;
433 res=mbkstrdup(ok?"ok":"ko");
434 break;
435 case 4: // ask:createfile:
436 es->myfile=mbkfopen(data, NULL, "w");
437 res=mbkstrdup(es->myfile!=NULL?"ok":"ko");
438 break;
439 case 5: // ask:closefile:
440 if (es->myfile!=NULL)
441 ok=(fclose(es->myfile)==0);
442 else
443 ok=0;
444 res=mbkstrdup(ok?"ok":"ko");
445 break;
446 case 6: // ask:writefile:
447 // ok=(fputs(data, es->myfile)>=0);
448 lg=es->size-(data-es->buffer)-1; // -1 pour le 0 final
449 // printf("%d %d %d %d\n",strlen(data), lg, es->size, data-es->buffer);
450 if (es->myfile!=NULL)
451 ok=(fwrite(data, sizeof(char), lg, es->myfile)==lg);
452 else
453 ok=0;
454 res=mbkstrdup(ok?"ok":"ko");
455 break;
456 case 7: // ask:writefile32:
457 lg=es->size-(data-es->buffer);
458 // printf("%d %d %d %d\n",strlen(data), lg, es->size, data-es->buffer);
459 if ((lg % sizeof(int))!=0)
460 avt_errmsg( AVT_ERRMSG, "061", AVT_FATAL);
461 lg/=4;
462 if (es->myfile!=NULL)
463 ok=(fwrite(data, sizeof(int), lg, es->myfile)==lg);
464 else
465 ok=0;
466 res=mbkstrdup(ok?"ok":"ko");
467 break;
468 case 8: // ask:resdir
469 if (resdir)
470 res=strdup(resdir);
471 else
472 res=strdup("NULL");
473 break;
474 default:
475 avt_errmsg( AVT_ERRMSG, "059", AVT_FATAL, data, es->id );
476 }
477 // printf("%s\n",es->buffer);
478 if (res!=NULL)
479 {
480 mbk_commputdata( comdata, es->id, res, strlen(res)+1);
481 mbkfree(res);
482 }
483 }
484 else
485 {
486 fprintf( file, "-- begin %d --\n", es->id );
487 fprintf( file, "%s\n", es->buffer );
488 fprintf( file, "-- end %d --\n", es->id );
489 fflush( file );
490 }
491 return 0;
492 }
493
494 void runStatHiTas_sub( char *numrun, char *script, char *tool, char *resfile, int incremental, char *resdir)
495 {
496 int jobs ;
497 int parajobs ;
498 execslot *execs ;
499 char *argv[6] ;
500 char bufid[10] ;
501 char bufsubid[10] ;
502 int i ;
503 int id ;
504 int done ;
505 int launch ;
506 FILE *file ;
507 char hostname[256] ;
508 char connection[1024] ;
509 mbk_comdata *comdata ;
510 int type ;
511 char buf[256];
512 chain_list *mutex=NULL;
513
514 if( ! decodejob( numrun, &jobs, &parajobs ) )
515 return ;
516
517 file = openstatdatafile( resfile, incremental);
518
519 // printf( "running %d jobs, %d simultaneous jobs\n", jobs, parajobs );
520 avt_log(-1, 0, "Running %d jobs, %d simultaneous jobs\n", jobs, parajobs );
521
522
523 if (resdir!=NULL && strcmp(resdir,"NULL")!=0)
524 {
525 int res;
526 res=mkdir(resdir, 0777);
527 if (res!=0 && errno!=EEXIST)
528 avt_errmsg( AVT_ERRMSG, "062", AVT_FATAL, resdir);
529 }
530
531 comdata = mbk_activatecommaster( parajobs );
532 if( !comdata )
533 exit(0);
534
535 execs = alloca( sizeof( execslot ) * parajobs );
536 for( i=0 ; i<parajobs ; i++ ) {
537 execs[i].state = STAT_EXEC_FREE ;
538 }
539
540 gethostname( hostname, 256 );
541
542 argv[0] = script ;
543 argv[1] = tool ;
544 argv[2] = bufid ;
545 argv[3] = bufsubid ;
546 argv[4] = connection ;
547 argv[5] = NULL ;
548
549 done = 0 ;
550 launch = 0 ;
551
552 while( done < jobs ) {
553
554 for( i=0 ; i < parajobs ; i++ ) {
555
556 if( launch < jobs ) {
557 if( execs[i].state == STAT_EXEC_FREE ) {
558
559 launch++ ;
560 execs[i].id = launch ;
561 execs[i].state = STAT_EXEC_WAIT ;
562 sprintf( bufid, "%d", launch );
563 sprintf( bufsubid, "%d", i+1 );
564 sprintf( connection, "%s:%d:%d", hostname, comdata->port, launch );
565
566 // printf( "starting job %d : %d\n", launch, i+1 );
567 avt_log(-1, 0, "Starting job %d : %d\n", launch, i+1 );
568 runjob( script, argv );
569
570 }
571 }
572 }
573
574 if( done < jobs ) {
575 id = mbk_comwaiteventfromnet( comdata );
576
577 if( id >= 0 ) {
578
579 avt_log( LOGMBKCOM, 1, "an event is available for %d\n", id );
580
581 for( i=0 ; i<parajobs ; i++ ) {
582 if( execs[i].state == STAT_EXEC_RUN ||
583 execs[i].state == STAT_EXEC_WAIT ) {
584 if( execs[i].id == id )
585 break ;
586 }
587 }
588
589 if( i >= parajobs )
590 avt_errmsg( AVT_ERRMSG, "051", AVT_FATAL, id );
591
592 type = mbk_commgetdata( comdata, execs[i].id, &(execs[i].buffer), &execs[i].size );
593
594 if( type == MBK_COM_BEGIN ) {
595 if( execs[i].state != STAT_EXEC_WAIT )
596 avt_errmsg( AVT_ERRMSG, "052", AVT_FATAL, execs[i].id );
597 execs[i].state = STAT_EXEC_RUN ;
598 filltime(buf);
599 avt_log(-1, 0, " Job %d started [%s]\n", execs[i].id, buf ) ;
600 }
601
602 if( type == MBK_COM_DATA ) {
603 avt_log( LOGMBKCOM, 1, "data received from job %d\n", execs[i].id );
604 if( execs[i].state != STAT_EXEC_RUN )
605 avt_errmsg( AVT_ERRMSG, "053", AVT_FATAL, execs[i].id );
606
607 handle_slave_data(file, comdata, &execs[i], &mutex, resdir);
608
609 mbkfree( execs[i].buffer );
610 execs[i].buffer = NULL ;
611 }
612
613 if( type == MBK_COM_END ) {
614 if( execs[i].state != STAT_EXEC_RUN )
615 avt_errmsg( AVT_ERRMSG, "054", AVT_FATAL, execs[i].id );
616 // printf( " job %d completed\n", execs[i].id );
617 filltime(buf);
618 avt_log(-1, 0, " Job %d completed [%s]\n", execs[i].id, buf ) ;
619 execs[i].state = STAT_EXEC_FREE ;
620 done++ ;
621 }
622
623 if( type == MBK_COM_ABORT ) {
624 filltime(buf);
625 if( V_BOOL_TAB[ __TAS_STAT_HITAS_BREAK_ON_ERROR ].VALUE )
626 avt_errmsg( AVT_ERRMSG, "055", AVT_FATAL, execs[i].id, buf );
627 else
628 avt_errmsg( AVT_ERRMSG, "055", AVT_WARNING, execs[i].id, buf );
629 execs[i].state = STAT_EXEC_FREE ;
630 done++ ;
631 }
632 }
633 }
634 }
635
636 fclose( file );
637 mbk_terminatecommaster( comdata );
638 }
639
640 void avt_McInfo( char *msg )
641 {
642 if (MBK_SOCK!=-1)
643 {
644 char buf[2048];
645 sprintf(buf,"info:%s", msg);
646 mbk_sendmsg( MBK_COM_DATA, buf, strlen( buf )+1 );
647 }
648 }
649
650 void avt_McPostData( char *msg )
651 {
652 if (MBK_SOCK!=-1)
653 {
654 mbk_sendmsg( MBK_COM_DATA, msg, strlen( msg )+1 );
655 mbk_sendmsg( MBK_COM_END, NULL, 0 );
656 }
657 }
658
659 char *avt_McAsk( char *msg )
660 {
661 if (MBK_SOCK!=-1)
662 {
663 char buf[2048], *res;
664 sprintf(buf,"ask:%s", msg);
665 res=mbk_commtalk(buf, -1);
666 return res;
667 }
668 return NULL;
669 }
670
671 int avt_McIsSlave()
672 {
673 return MBK_SOCK!=-1;
674 }
675
676
677 quicklist *mbk_QuickListCreate()
678 {
679 quicklist *ql=mbkalloc(sizeof(quicklist));
680 ql->head=ql->end=NULL;
681 ql->nb=0;
682 return ql;
683 }
684
685 void mbk_QuickListAppend(quicklist *ql, char *item)
686 {
687 if (ql->end==NULL)
688 ql->end=ql->head=addchain(ql->head, strdup(item));
689 else
690 {
691 ql->end->NEXT=addchain(NULL, strdup(item));
692 ql->end=ql->end->NEXT;
693 }
694 ql->nb++;
695 }
696
697 StringList *mbk_QuickListToTCL(quicklist *ql)
698 {
699 chain_list *temp=ql->head;
700 mbkfree(ql);
701 return temp;
702 }
703
704 int mbk_QuickListLength(quicklist *ql)
705 {
706 return ql->nb;
707 }
708
709 void mbk_QuickListAppendDouble(quicklist *ql, double value)
710 {
711 chain_list *new;
712 if (ql->end==NULL)
713 new=ql->end=ql->head=addchain(ql->head, NULL);
714 else
715 {
716 new=ql->end->NEXT=addchain(NULL, NULL);
717 ql->end=ql->end->NEXT;
718 }
719 *(float *)&new->DATA=value;
720 ql->nb++;
721 }
722
723 static int cmpfloat(const void *a0, const void *b0)
724 {
725 float *a=(float *)a0, *b=(float *)b0;
726 if (*a<*b) return -1;
727 if (*a>*b) return 1;
728 return 0;
729 }
730
731 chain_list *mbk_QuickListComputeMeanVarMedian(quicklist *ql)
732 {
733 double mean=0, var=0, median=0, val;
734 float *tab;
735 chain_list *cl;
736 int i;
737
738 if (ql->nb>0)
739 {
740 for (cl=ql->head; cl!=NULL; cl=cl->NEXT)
741 mean=mean+*(float *)&cl->DATA;
742 mean/=ql->nb;
743 for (cl=ql->head; cl!=NULL; cl=cl->NEXT)
744 {
745 val=*(float *)&cl->DATA;
746 var=var+(val-mean)*(val-mean);
747 }
748 var=var/ql->nb;
749 tab=(float *)mbkalloc(sizeof(float)*ql->nb);
750 for (cl=ql->head, i=0; cl!=NULL; cl=cl->NEXT, i++)
751 tab[i]=*(float *)&cl->DATA;
752
753 qsort(tab, ql->nb, sizeof(float), cmpfloat);
754
755 median=tab[ql->nb/2];
756 mbkfree(tab);
757 }
758 cl=addchain(NULL, NULL);
759 *(float *)&cl->DATA=median;
760 cl=addchain(cl, NULL);
761 *(float *)&cl->DATA=var;
762 cl=addchain(cl, NULL);
763 *(float *)&cl->DATA=mean;
764 return cl;
765 }
766
767 void mbk_QuickListDoubleFree(quicklist *ql)
768 {
769 freechain(ql->head);
770 mbkfree(ql);
771 }
772