Annotation of OpenXM_contrib2/asir2000/io/ox.c, Revision 1.3
1.3 ! noro 1: /* $OpenXM: OpenXM_contrib2/asir2000/io/ox.c,v 1.2 2000/01/26 02:05:34 noro Exp $ */
1.1 noro 2: #include "ca.h"
3: #include "parse.h"
1.3 ! noro 4: #include "signal.h"
1.1 noro 5: #include "wsio.h"
6: #include "ox.h"
7:
8: #define ISIZ sizeof(int)
9:
10: void ox_flush_stream(),ox_write_int(),ox_write_cmo();
11: void ox_read_int(),ox_read_cmo();
12: void mclist_to_mc();
13: void ox_read_local();
14:
15: extern Obj VOIDobj;
16:
17: extern int ox_need_conv;
18: extern int ox_usr1_sent, ox_int_received, critical_when_signal;
19: unsigned int ox_serial;
20: int ox_flushing;
21: int ox_batch;
22: int ox_check=1;
1.2 noro 23: int ox_exchange_mathcap=1;
1.1 noro 24: jmp_buf ox_env;
25:
26: MATHCAP my_mathcap;
27:
28: struct oxcap {
29: unsigned int ox;
30: int ncap;
31: int *cap;
32: };
33:
34: struct mathcap {
35: LIST mc;
36: unsigned int version;
37: char *servername;
38: int nsmcap;
39: unsigned int *smcap;
40: int noxcap;
41: struct oxcap *oxcap;
42: };
43:
44: struct oxcap *my_oxcap;
45:
46: static struct mathcap my_mc;
47: static struct mathcap *remote_mc;
48: static int remote_mc_len;
49:
50: void ox_resetenv(s)
51: char *s;
52: {
53: fprintf(stderr,"%s\n",s);
54: longjmp(ox_env,1);
55: }
56:
57: static int available_cmo[] = {
58: CMO_NULL, CMO_INT32, CMO_DATUM, CMO_STRING, CMO_MATHCAP,
59: CMO_ERROR, CMO_ERROR2, CMO_LIST, CMO_MONOMIAL32,
60: CMO_ZZ, CMO_QQ, CMO_ZERO,
61: CMO_DMS_GENERIC, CMO_DMS_OF_N_VARIABLES,
62: CMO_RING_BY_NAME, CMO_DISTRIBUTED_POLYNOMIAL,
63: CMO_RECURSIVE_POLYNOMIAL, CMO_UNIVARIATE_POLYNOMIAL,
64: CMO_INDETERMINATE,
65: 0
66: };
67:
68: static int available_sm[] = {
69: SM_dupErrors, SM_getsp, SM_popSerializedLocalObject,
70: SM_popCMO, SM_popString, SM_setName,
71: SM_evalName, SM_executeStringByLocalParser,
72: SM_executeStringByLocalParserInBatchMode,
73: SM_executeFunction, SM_shutdown, SM_pops,
74: SM_mathcap, SM_setMathcap, SM_nop,
75: SM_beginBlock, SM_endBlock,
76: 0
77: };
78:
79: /*
80: mathcap =
81: [
82: version list,
83: SMlist,
84: [
85: [OX tag,CMO tag list],
86: [OX tag,CMO tag list],
87: ...
88: ]
89: ]
90: */
91:
92: void create_my_mathcap(char *system)
93: {
94: NODE n,n0;
95: int i,k;
96: STRING str;
97: LIST sname,smlist,oxlist,cmolist,asirlist,oxtag,oxasir,r;
98: USINT tag,t,t1;
99:
100: if ( my_mathcap )
101: return;
102: /* version */
103: MKSTR(str,system);
104: MKUSINT(t,OX_VERSION);
105: n0 = mknode(2,t,str); MKLIST(sname,n0);
106:
107: /* cmo tag */
108: for ( n0 = 0, i = 0; k = available_sm[i]; i++ ) {
109: NEXTNODE(n0,n); MKUSINT(t,k); BDY(n) = (pointer)t;
110: }
111: NEXT(n) = 0; MKLIST(smlist,n0);
112:
113: /* creation of [OX_DATA,CMO list] */
114: /* ox tag */
115: MKUSINT(tag,OX_DATA);
116: /* cmo tag */
117: for ( n0 = 0, i = 0; k = available_cmo[i]; i++ ) {
118: NEXTNODE(n0,n); MKUSINT(t,k); BDY(n) = (pointer)t;
119: }
120: NEXT(n) = 0; MKLIST(cmolist,n0);
121: /* [ox tag, cmo list] */
122: n0 = mknode(2,tag,cmolist);
123: MKLIST(oxlist,n0);
124:
125: /* creation of [OX_LOCAL_OBJECT_ASIR,ASIR tag] */
126: /* ox tag */
127: MKUSINT(tag,OX_LOCAL_OBJECT_ASIR);
128: /* local tag */
129: MKUSINT(t,ASIR_VL);
130: MKUSINT(t1,ASIR_OBJ);
131: n0 = mknode(2,t,t1); MKLIST(cmolist,n0);
132: /* [ox tag, local list] */
133: n0 = mknode(2,tag,cmolist);
134: MKLIST(asirlist,n0);
135:
136: /* [oxlist,asirlist] */
137: n0 = mknode(2,oxlist,asirlist); MKLIST(oxasir,n0);
138:
139: /* [version,sm,oxasir] */
140: n0 = mknode(3,sname,smlist,oxasir); MKLIST(r,n0);
141:
142: MKMATHCAP(my_mathcap,r);
143: mclist_to_mc(r,&my_mc);
144: my_oxcap = my_mc.oxcap;
145: }
146:
147: void store_remote_mathcap(int s,MATHCAP mc)
148: {
149: if ( !remote_mc ) {
150: remote_mc_len = 16;
151: remote_mc = (struct mathcap *)
152: CALLOC(remote_mc_len,sizeof(struct mathcap));
153: }
154: if ( s >= remote_mc_len ) {
155: remote_mc_len *= 2;
156: remote_mc = (struct mathcap *)REALLOC(remote_mc,
157: remote_mc_len*sizeof(struct mathcap));
158: }
159: mclist_to_mc(BDY(mc),&remote_mc[s]);
160: }
161:
162: /*
163: mathcap =
164: [
165: version list,
166: SMlist,
167: [
168: [OX tag,CMO tag list],
169: [OX tag,CMO tag list],
170: ...
171: ]
172: ]
173:
174: ===>
175:
176: mathcap
177: | version | &servername | nsmcap | &smcap | noxcap | &oxcap |
178: smcap
179: | SM_xxx | SM_yyy | ... |
180: oxcap
181: | oxcap[0] | oxcap[1] | ... |
182: oxcap[i]
183: | ox | ncap | &cap |
184: cap
185: | CMO_xxx | CMO_yyy | ... |
186: */
187:
188: void mclist_to_mc(LIST mclist,struct mathcap *mc)
189: {
190: int id,l,i,j;
191: NODE n,t,oxcmo,ox,cap;
192: int *ptr;
193:
194: /*
195: [
196: [ version,servername ]
197: [sm1,sm2,...],
198: [
199: [o1,[n11,n12,...]],
200: [o2,[n21,n22,...]],
201: ...
202: ]
203: ]
204: */
205: n = BDY(mclist);
206: mc->mc = mclist;
207: mc->version = BDY((USINT)BDY(BDY((LIST)BDY(n))));
208: mc->servername = BDY((STRING)BDY(NEXT(BDY((LIST)BDY(n)))));
209:
210: /* smcap */
211: n = NEXT(n);
212: t = BDY((LIST)BDY(n));
213: mc->nsmcap = length(t);
214: mc->smcap = (int *)MALLOC_ATOMIC(mc->nsmcap*sizeof(int));
215: for ( j = 0, ptr = mc->smcap; j < mc->nsmcap; j++, t = NEXT(t) )
216: ptr[j] = BDY((USINT)BDY(t));
217:
218: n = NEXT(n);
219: n = BDY((LIST)BDY(n));
220: /* n -> BDY([[OX1,CMOlist1], [OX2,CMOlist2], ...]) */
221: mc->noxcap = length(n);
222: mc->oxcap = (struct oxcap *)MALLOC(mc->noxcap*sizeof(struct oxcap));
223: for ( j = 0; j < mc->noxcap; j++, n = NEXT(n) ) {
224: oxcmo = BDY((LIST)BDY(n));
225: /* oxcmo = BDY([OXj,CMOlistj]) */
226: mc->oxcap[j].ox = BDY((USINT)BDY(oxcmo));
227: cap = BDY((LIST)BDY(NEXT(oxcmo)));
228: /* cap ->BDY(CMOlistj) */
229: l = length(cap);
230: mc->oxcap[j].ncap = l;
231: mc->oxcap[j].cap = (unsigned int *)CALLOC(l+1,sizeof(unsigned int));
232: for ( t = cap, ptr = mc->oxcap[j].cap, i = 0; i < l; t = NEXT(t), i++ )
233: ptr[i] = BDY((USINT)BDY(t));
234: }
235: }
236:
237: int check_sm_by_mc(s,smtag)
238: int s;
239: unsigned int smtag;
240: {
241: struct mathcap *rmc;
242: int nsmcap,i;
243: unsigned int *smcap;
244:
245: /* XXX : return 1 if remote_mc is not available. */
246: if ( !remote_mc )
247: return 1;
248: rmc = &remote_mc[s];
249: nsmcap = rmc->nsmcap;
250: smcap = rmc->smcap;
251: if ( !smcap )
252: return 1;
253: for ( i = 0; i < nsmcap; i++ )
254: if ( smcap[i] == smtag )
255: break;
256: if ( i == nsmcap )
257: return 0;
258: else
259: return 1;
260: }
261:
262: int check_by_mc(s,oxtag,cmotag)
263: int s;
264: unsigned int oxtag,cmotag;
265: {
266: struct mathcap *rmc;
267: int noxcap,ncap,i,j;
268: struct oxcap *oxcap;
269: unsigned int *cap;
270:
271: /* XXX : return 1 if remote_mc is not available. */
272: if ( !remote_mc )
273: return 1;
274: rmc = &remote_mc[s];
275: noxcap = rmc->noxcap;
276: oxcap = rmc->oxcap;
277: if ( !oxcap )
278: return 1;
279: for ( i = 0; i < noxcap; i++ )
280: if ( oxcap[i].ox == oxtag )
281: break;
282: if ( i == noxcap )
283: return 0;
284: ncap = oxcap[i].ncap;
285: cap = oxcap[i].cap;
286: for ( j = 0; j < ncap; j++ )
287: if ( cap[j] == cmotag )
288: break;
289: if ( j == ncap )
290: return 0;
291: else
292: return 1;
293: }
294:
295: void begin_critical() {
296: critical_when_signal = 1;
297: }
298:
299: void end_critical() {
300: critical_when_signal = 0;
301: if ( ox_usr1_sent ) {
302: ox_usr1_sent = 0; ox_usr1_handler();
303: }
304: if ( ox_int_received ) {
305: ox_int_received = 0; int_handler(SIGINT);
306: }
307: }
308:
309: void ox_usr1_handler(sig)
310: int sig;
311: {
312: extern jmp_buf env;
313: unsigned int cmd;
314:
315: #if !defined(VISUAL)
316: signal(SIGUSR1,ox_usr1_handler);
317: #endif
318: if ( critical_when_signal ) {
319: fprintf(stderr,"usr1 : critical\n");
320: ox_usr1_sent = 1;
321: } else {
322: ox_flushing = 1;
323: ox_resetenv("usr1 : return to toplevel by SIGUSR1");
324: }
325: }
326:
327: void clear_readbuffer()
328: {
329: char c;
330: fd_set r,w,e;
331: struct timeval interval;
332: int n,sock;
333:
334: #if defined(linux)
335: iofp[0].in->_IO_read_ptr = iofp[0].in->_IO_read_end;
336: #elif defined(__FreeBSD__)
337: fpurge(iofp[0].in);
338: #endif
339: /*
340: sock = fileno(iofp[0].in);
341: interval.tv_sec = (int)0;
342: interval.tv_usec = (int)0;
343:
344: FD_ZERO(&r); FD_ZERO(&w); FD_ZERO(&e);
345: FD_SET(sock,&r);
346: while ( 1 ) {
347: n = select(FD_SETSIZE,&r,&w,&e,&interval);
348: if ( !n )
349: break;
350: read(sock,&c,1);
351: }
352: */
353: }
354:
355: #if MPI
356: int ox_data_is_available(int s)
357: {
358: return 1;
359: }
360:
361: void wait_for_data(int s)
362: {
363: return;
364: }
365: #else
366: int ox_data_is_available(int s)
367: {
368: return FP_DATA_IS_AVAILABLE(iofp[s].in);
369: }
370:
371: void wait_for_data(int s)
372: {
373: fd_set r;
374: int sock;
375:
376: if ( !FP_DATA_IS_AVAILABLE(iofp[s].in) ) {
377: #if defined(VISUAL)
378: sock = iofp[s].in->fildes;
379: FD_ZERO(&r);
380: FD_SET(sock,&r);
381: select(0,&r,NULL,NULL,NULL);
382: #else
383: sock = fileno(iofp[s].in);
384: FD_ZERO(&r);
385: FD_SET(sock,&r);
386: select(FD_SETSIZE,&r,NULL,NULL,NULL);
387: #endif
388: }
389: }
390: #endif
391:
392: void ox_send_data(int s,pointer p)
393: {
394: if ( ox_check && !ox_check_cmo(s,(Obj)p) )
395: error("ox_send_data : Mathcap violation");
396: begin_critical();
397: ox_write_int(s,OX_DATA);
398: ox_write_int(s,ox_serial++);
399: ox_write_cmo(s,p);
400: ox_flush_stream(s);
401: end_critical();
402: }
403:
404: void ox_send_cmd(int s,int id)
405: {
406: if ( ox_check && !check_sm_by_mc(s,id) )
407: error("ox_send_cmd : Mathcap violation");
408: begin_critical();
409: ox_write_int(s,OX_COMMAND);
410: ox_write_int(s,ox_serial++);
411: ox_write_int(s,id);
412: ox_flush_stream(s);
413: end_critical();
414: }
415:
416: void ox_send_sync(int s)
417: {
418: begin_critical();
419: ox_write_int(s,OX_SYNC_BALL);
420: ox_write_int(s,ox_serial++);
421: ox_flush_stream(s);
422: end_critical();
423: }
424:
425: void ox_send_local_data(int s,Obj p)
426: {
427: begin_critical();
428: ox_write_int(s,OX_LOCAL_OBJECT_ASIR);
429: ox_write_int(s,ox_serial++);
430: ox_write_int(s,ASIR_OBJ);
431: saveobj(iofp[s].out,p);
432: ox_flush_stream(s);
433: end_critical();
434: }
435:
436: void ox_send_local_ring(int s,VL vl)
437: {
438: begin_critical();
439: ox_write_int(s,OX_LOCAL_OBJECT_ASIR);
440: ox_write_int(s,ox_serial++);
441: ox_write_int(s,ASIR_VL);
442: savevl(iofp[s].out,vl);
443: ox_flush_stream(s);
444: end_critical();
445: }
446:
447: unsigned int ox_recv(int s, int *id, pointer *p)
448: {
449: unsigned int cmd,serial;
450: USINT ui;
451:
452: wait_for_data(s);
453: begin_critical();
454: ox_read_int(s,id);
455: ox_read_int(s,&serial);
456: switch ( *id ) {
457: case OX_COMMAND:
458: ox_read_int(s,&cmd);
459: MKUSINT(ui,cmd);
460: *p = (pointer)ui;
461: break;
462: case OX_DATA:
463: ox_read_cmo(s,p);
464: break;
465: case OX_LOCAL_OBJECT_ASIR:
466: ox_read_local(s,p);
467: break;
468: default:
469: *p = 0;
470: break;
471: }
472: end_critical();
473: return serial;
474: }
475:
476: void ox_get_result(s,rp)
477: int s;
478: Obj *rp;
479: {
480: int id;
481: Obj obj,r;
482: int level;
483:
484: level = 0;
485: r = 0;
486: do {
487: ox_recv(s,&id,(pointer *)&obj);
488: if ( id == OX_COMMAND ) {
489: switch ( ((USINT)obj)->body ) {
490: case SM_beginBlock:
491: level++;
492: break;
493: case SM_endBlock:
494: level--;
495: }
496: } else
497: r = obj;
498: } while ( level );
499: *rp = r;
500: }
501:
502: void ox_read_int(int s, int *n)
503: {
504: ox_need_conv = iofp[s].conv;
505: read_int(iofp[s].in,n);
506: }
507:
508: void ox_read_cmo(int s, Obj *rp)
509: {
510: ox_need_conv = iofp[s].conv;
511: read_cmo(iofp[s].in,rp);
512: }
513:
514: void ox_read_local(int s, Obj *rp)
515: {
516: int id;
517:
518: ox_need_conv = iofp[s].conv;
519: read_int(iofp[s].in,&id);
520: switch ( id ) {
521: case ASIR_VL:
522: loadvl(iofp[s].in);
523: *rp = VOIDobj;
524: break;
525: case ASIR_OBJ:
526: loadobj(iofp[s].in,rp);
527: break;
528: default:
529: error("ox_read_local : unsupported id");
530: break;
531: }
532: }
533:
534: void ox_write_int(int s, int n)
535: {
536: ox_need_conv = iofp[s].conv;
537: write_int(iofp[s].out,&n);
538: }
539:
540: void ox_write_cmo(int s, Obj obj)
541: {
542: ox_need_conv = iofp[s].conv;
543: write_cmo(iofp[s].out,obj);
544: }
545:
546: int ox_check_cmo(int s, Obj obj)
547: {
548: NODE m;
549:
550: if ( !obj )
551: return 1;
552: switch ( OID(obj) ) {
553: case O_MATHCAP: case O_STR: case O_ERR: case O_USINT: case O_VOID:
554: return 1;
555: case O_P:
556: if ( !check_by_mc(s,OX_DATA,CMO_RECURSIVE_POLYNOMIAL) )
557: return 0;
558: else
559: return ox_check_cmo_p(s,(P)obj);
560: case O_R:
561: if ( !check_by_mc(s,OX_DATA,CMO_RATIONAL) )
562: return 0;
563: else if ( !check_by_mc(s,OX_DATA,CMO_RECURSIVE_POLYNOMIAL) )
564: return 0;
565: else
566: return ox_check_cmo_p(s,NM((R)obj)) && ox_check_cmo_p(s,DN((R)obj));
567: case O_DP:
568: return ox_check_cmo_dp(s,(DP)obj);
569: case O_N:
570: if ( NID((Num)obj) == N_Q ) {
571: if ( INT((Q)obj) )
572: return check_by_mc(s,OX_DATA,CMO_ZZ);
573: else
574: return check_by_mc(s,OX_DATA,CMO_QQ);
575: } else
576: return 0;
577: case O_LIST:
578: for ( m = BDY((LIST)obj); m; m = NEXT(m) )
579: if ( !ox_check_cmo(s,(BDY(m))) )
580: return 0;
581: return 1;
582: default:
583: return 0;
584: }
585: }
586:
587: void ox_get_serverinfo(int s, LIST *rp)
588: {
589: if ( remote_mc )
590: *rp = remote_mc[s].mc;
591: else {
592: MKLIST(*rp,0);
593: }
594: }
595:
596: int ox_check_cmo_p(int s, P p)
597: {
598: DCP dc;
599:
600: if ( NUM(p) )
601: return ox_check_cmo(s,(Obj)p);
602: else {
603: for ( dc = DC(p); dc; dc = NEXT(dc) )
604: if ( !ox_check_cmo_p(s,COEF(dc)) )
605: return 0;
606: return 1;
607: }
608: }
609:
610: int ox_check_cmo_dp(int s, DP p)
611: {
612: MP m;
613:
614: for ( m = BDY(p); m; m = NEXT(m) )
615: if ( !ox_check_cmo(s,(Obj)m->c) )
616: return 0;
617: return 1;
618: }
619:
620: void ox_flush_stream(s)
621: int s;
622: {
623: if ( ox_batch )
624: return;
625: #if defined(VISUAL)
626: if ( _fileno(&iofp[s].out->fp) < 0 )
627: cflush(iofp[s].out);
628: else
629: #elif MPI
630: if ( (char)fileno(&iofp[s].out->fp) < 0 )
631: cflush(iofp[s].out);
632: else
633: #endif
634: fflush(iofp[s].out);
635: }
636:
637: void ox_flush_stream_force(s)
638: int s;
639: {
640: #if defined(VISUAL)
641: if ( _fileno(&iofp[s].out->fp) < 0 )
642: cflush(iofp[s].out);
643: else
644: #elif MPI
645: if ( (char)fileno(&iofp[s].out->fp) < 0 )
646: cflush(iofp[s].out);
647: else
648: #endif
649: fflush(iofp[s].out);
650: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>