last fixes + removed debug messages
[physik/nlsop.git] / nlsop_server.c
1 /*
2  * nlsop server code
3  *
4  * author: frank zirkelbach (frank.zirkelbach@physik.uni-augsburg.de)
5  *
6  * this program tries helping to understand the amorphous depuration
7  * and recrystallization of SiCx while ion implantation at temperatures
8  * below 400 degree celsius.
9  * hopefully the program will simulate the stabilization of the
10  * selforganizing lamella structure in the observed behaviour.
11  *
12  * refs: 
13  *  - J. K. N. Lindner. Habil.Schrift, Universitaet Augsburg.
14  *  - Maik Haeberlen. Diplomarbeit, Universitaet Augsburg.
15  *
16  * Copyright (C) 2004 Frank Zirkelbach
17  *
18  * This program is free software; you can redistribute it and/or modify
19  * it under the terms of the GNU General Public License as published by
20  * the Free Software Foundation; either version 2 of the License, or
21  * (at your option) any later version.
22  *
23  * This program is distributed in the hope that it will be useful,
24  * but WITHOUT ANY WARRANTY; without even the implied warranty of
25  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  * GNU General Public License for more details.
27  *
28  * You should have received a copy of the GNU General Public License
29  * along with this program; if not, write to the Free Software
30  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
31  *
32  */
33
34 #define _GNU_SOURCE
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <fcntl.h>
41 #include <unistd.h>
42 #include <signal.h>
43
44 #include "nlsop.h"
45 #include "dfbapi.h"
46 #include "random.h"
47
48 #include "network.h"
49 #include "event.h"
50 #include "list.h"
51
52 #include "nlsop_general.h"
53
54 typedef struct s_priv {
55   t_event event;
56   t_net net;
57   t_list client;
58   t_list gui;
59   t_list job;
60 } t_priv;
61
62 /* global */
63 int alert;
64 int gi;
65 t_priv priv;
66
67 /*
68  * server specific stuff
69  */
70
71 int usage(char *prog)
72 {
73  puts("usage:");
74  printf("%s <listen port>\n",prog);
75  return 1;
76 }
77
78 int add_node(void) {
79
80   int channel;
81   unsigned char data;
82   t_client client;
83   int gui_chan;
84
85   channel=network_manage_incoming(&(priv.net));
86   if(channel==N_E_ACCEPT) {
87     printf("accept failed!\n");
88     return -1;
89   }
90   if(channel==N_E_MAXC) {
91     printf("maximum connections reached!\n");
92     return -1;
93   }
94   printf("connection from %s port %d (ch: %d)\n",
95          priv.net.connection[channel].ip,priv.net.connection[channel].port,
96          channel);
97
98   /* are you client or gui? */
99   network_receive_chan(&(priv.net),channel,&data,1);
100   if(data==NLSOP_GUI) {
101     gui_chan=channel;
102     list_add_element(&(priv.gui),&gui_chan,sizeof(int));
103     printf("node is a gui\n");
104   }
105   else if(data==NLSOP_CLIENT) {
106     client.status=IDLE;
107     client.channel=channel;
108     list_add_element(&(priv.client),&client,sizeof(t_client));
109     printf("node is a client\n");
110   }
111   else {
112     printf("not a client or gui - lets kick that ass out of here!\n");
113     network_close(&(priv.net),channel);
114     return -1;
115   }
116
117   /* if we have a new node - care for it! */
118   event_math(priv.net.connection[channel].fd,&(priv.event),READ,ADD);
119
120   printf("\n");
121
122   return 1;
123 }
124
125 int save_job(unsigned char dc) {
126
127   char filename[128];
128   int fd;
129   int ret;
130   d3_lattice d3l;
131   info info;
132   t_job *j;
133
134   j=(t_job *)priv.job.current->data;
135
136   printf("receiving data from client (#cells=%d)\n",j->size);
137
138   network_receive_chan(&(priv.net),gi,(unsigned char *)&d3l,
139                        sizeof(d3_lattice));
140   network_receive_chan(&(priv.net),gi,(unsigned char *)&info,sizeof(info));
141   network_receive_chan(&(priv.net),gi,j->ac,j->size*sizeof(unsigned char));
142   network_receive_chan(&(priv.net),gi,(unsigned char *)j->cc,
143                        j->size*sizeof(int));
144   network_receive_chan(&(priv.net),gi,(unsigned char *)&(j->step),sizeof(int));
145
146   if(dc!=DC_QUIT) {
147     snprintf(filename,128,"./data/nlsop_b%f_c%f_s%f_ds%d_dr%f_-_%d_of_%d.save",
148              j->info.b,j->info.c,j->info.s,
149              j->info.diff_rate,j->info.dr_ac,
150              j->step,j->info.steps);
151     if((fd=open(filename,O_WRONLY|O_CREAT))<0) {
152       printf("FATAL: unable to open file %s\n",filename);
153       return -1;
154     }
155
156     if(write(fd,&d3l,sizeof(d3_lattice))<sizeof(d3_lattice)) {
157       printf("FATAL: write of d3_lattice failed\n");
158       return -1;
159     }
160
161     if(write(fd,&info,sizeof(info))<sizeof(info)) {
162       printf("FATAL: write of info failed\n");
163       return -1;
164     }
165
166     ret=write(fd,j->ac,j->size*sizeof(unsigned char));
167     if(ret<j->size*sizeof(unsigned char)) {
168       printf("FATAL: write of a/c states failed\n");
169       return -1;
170     }
171    
172     ret=write(fd,j->cc,j->size*sizeof(int));
173     if(ret<j->size*sizeof(int)) {
174       printf("FATAL: write of c.-conc. failed\n");
175       return -1;
176     }
177
178     close(fd);
179     
180   }
181
182   return 1;
183 }
184
185 int add_job(void) {
186
187   t_job job;
188
189   job.channel=-1;
190   job.status=IN_QUEUE;
191   job.progress=0;
192
193   network_receive_chan(&(priv.net),gi,(unsigned char *)&(job.x),sizeof(int));
194   network_receive_chan(&(priv.net),gi,(unsigned char *)&(job.y),sizeof(int));
195   network_receive_chan(&(priv.net),gi,(unsigned char *)&(job.z),sizeof(int));
196   network_receive_chan(&(priv.net),gi,(unsigned char *)&(job.info),
197                        sizeof(info));
198
199   job.size=job.x*job.y*job.z;
200
201   job.ac=(unsigned char *)malloc(job.size*sizeof(unsigned char));
202   if(job.ac==NULL) {
203     printf("unable to malloc a/c memory\n");
204     return -1;
205   }
206
207   job.cc=(int *)malloc(job.size*sizeof(int));
208   if(job.cc==NULL) {
209     printf("unable to malloc cc memory\n");
210     return -1;
211   }
212
213   job.step=0;
214
215   list_add_element(&(priv.job),&job,sizeof(t_job));
216   
217   printf("job added: b=%f | c=%f | s=%f ...\n",
218          job.info.b,job.info.c,job.info.s);
219
220   return 1;
221 }
222
223 int send_status(void) {
224
225   unsigned char data;
226   int count;
227   int i;
228
229   data=GUI_INFO;
230
231   count=list_count(&(priv.job));
232
233   printf("sending job info\n");
234
235   network_send_chan(&(priv.net),gi,&data,sizeof(unsigned char));
236   network_send_chan(&(priv.net),gi,(unsigned char *)&count,sizeof(int));
237
238   list_reset(&(priv.job));
239   for(i=0;i<count;i++) {
240     network_send_chan(&(priv.net),gi,priv.job.current->data,sizeof(t_job));
241     list_next(&(priv.job));
242   }
243
244   return 1;
245 }
246
247 int handle_node(void) {
248
249   unsigned char data;
250   t_client *c;
251   t_job *j;
252
253   for(gi=0;gi<MAX_CONNECTIONS;gi++) {
254     if(FD_ISSET(priv.net.connection[gi].fd,&(priv.event.rfds))) {
255
256       alert=0;
257       alarm(1);
258       network_receive_chan(&(priv.net),gi,&data,1);
259       alarm(0);
260
261       if(alert==1) return -1;
262
263       if(list_search_data(&(priv.client),&gi,sizeof(int))==L_SUCCESS) {
264         /* it's a client */
265         list_search_data(&(priv.job),&gi,sizeof(int));
266         j=(t_job *)priv.job.current->data;
267         c=(t_client *)priv.client.current->data;
268
269         if(data==DC_END) {
270           save_job(DC_END);
271           /* reset client */
272           c->status=IDLE;
273           /* free job memory */
274           free(j->ac);
275           free(j->cc);
276           /* delete job entry */
277           list_del_current(&(priv.job));
278           printf("job ended, saved and removed from list.\n");
279         }
280
281         if(data==DC_OK) {
282           save_job(DC_OK);
283           /* inc progress state */
284           j->progress+=1;
285           printf("job at next level, saved.\n");
286         }
287
288         if(data==DC_QUIT) {
289           save_job(DC_QUIT);
290           /* network disconnect */
291           event_math(priv.net.connection[gi].fd,&(priv.event),READ,REMOVE);
292           network_close(&(priv.net),gi);
293           /* del from client list */
294           list_del_current(&(priv.client));
295           /* change job state */
296           j->status=IN_QUEUE;
297           printf("client terminating, job queued, client removed.\n");
298         }
299       }
300
301       else if(list_search_data(&(priv.gui),&gi,sizeof(int))==L_SUCCESS) {
302         /* its a gui */
303         if(data==GUI_ADDJOB) add_job();
304
305         else if(data==GUI_INFO) send_status();
306
307         else if(data==GUI_QUIT) {
308           printf("disconnecting gui on channel %d\n",gi);
309           event_math(priv.net.connection[gi].fd,&(priv.event),READ,REMOVE);
310           network_close(&(priv.net),gi);
311           list_del_current(&(priv.gui));
312         }
313
314         else {
315           printf("unknown gui command\n");
316           return -1;
317         }
318       }
319
320       else {
321         printf("this chan is not in client or gui list! i disconnect now!\n");
322         event_math(priv.net.connection[gi].fd,&(priv.event),READ,REMOVE);
323         network_close(&(priv.net),gi);
324       }
325     }
326   }
327
328   printf("\n");
329    
330   return 1;
331 }
332
333 int distribute_jobs(t_event *event,void *allineed) {
334
335   int count_j,count_c,min;
336   t_job *j;
337   t_client *c;
338   unsigned char data;
339   d3_lattice d3l;
340
341   list_reset(&(priv.job));
342   list_reset(&(priv.client));
343
344   count_j=0;
345   count_c=0;
346
347   if((priv.client.current==NULL)||(priv.job.current==NULL)) return 2;
348
349   j=(t_job *)priv.job.current->data;
350   c=(t_client *)priv.client.current->data;
351   if(j->status==IN_QUEUE) count_j++;
352   if(c->status==IDLE) count_c++;
353
354   while(list_next(&(priv.job))!=L_NO_NEXT_ELEMENT) {
355     j=(t_job *)priv.job.current->data;
356     if(j->status==IN_QUEUE) count_j++;
357   }
358   while(list_next(&(priv.client))!=L_NO_NEXT_ELEMENT) {
359     c=(t_client *)priv.client.current->data;
360     if(c->status==IDLE) count_c++;
361   }
362  
363   min=(count_c<count_j)?count_c:count_j;
364
365   if(min!=0) {
366     printf("d: distributing jobs ...\n");
367     printf("%d queued jobs, %d idle clients\n\n",count_j,count_c);
368   }
369
370   list_reset(&(priv.job));
371   list_reset(&(priv.client));
372
373   while(min) {
374     j=(t_job *)priv.job.current->data;
375     c=(t_client *)priv.client.current->data;
376     while(c->status!=IDLE) {
377       list_next(&(priv.client));
378       c=(t_client *)priv.client.current->data;
379     }
380     while(j->status!=IN_QUEUE) {
381       list_next(&(priv.job));
382       j=(t_job *)priv.job.current->data;
383     }
384
385     /* direct current job to current client */
386     if(j->step==0) data=NLSOP_NJOB;
387     else data=NLSOP_CJOB;
388
389     c->status=WORK;
390     j->channel=c->channel;
391     j->status=IN_WORK;
392
393     d3l.max_x=j->x;
394     d3l.max_y=j->y;
395     d3l.max_z=j->z;
396
397     network_send_chan(&(priv.net),c->channel,&data,sizeof(unsigned char));
398     network_send_chan(&(priv.net),c->channel,(unsigned char *)&d3l,
399                       sizeof(d3_lattice));
400     network_send_chan(&(priv.net),c->channel,(unsigned char *)&(j->info),
401                       sizeof(info));
402
403     if(data==NLSOP_CJOB) {
404       network_send_chan(&(priv.net),c->channel,j->ac,
405                         j->size*sizeof(unsigned char));
406       network_receive_chan(&(priv.net),c->channel,&data,sizeof(unsigned char));
407       network_send_chan(&(priv.net),c->channel,(unsigned char *)&(j->cc),
408                         j->size*sizeof(int));
409       network_receive_chan(&(priv.net),c->channel,&data,sizeof(unsigned char));
410       network_send_chan(&(priv.net),c->channel,(unsigned char *)&(j->step),
411                         sizeof(int));
412       network_receive_chan(&(priv.net),c->channel,&data,sizeof(unsigned char));
413     }
414
415     --min;
416     list_next(&(priv.client));
417     list_next(&(priv.job));
418   }
419
420   return 1;
421 }
422
423 int parse_incoming(t_event *event,void *allineed) {
424
425   /* decide what to do */
426   if(FD_ISSET(priv.net.l_fd,&(priv.event.rfds))) {
427     /* new node */
428     printf("new node ...\n");
429     add_node();
430   }
431   else {
432     /* client/gui interaction */
433     printf("node interaction ...\n");
434     handle_node();
435   }
436     
437   return 1;
438 }
439
440 void destroy_it(int signum) {
441
442   printf("connection to client (ch %d) fucked up!\n",gi);
443   event_math(priv.net.connection[gi].fd,&(priv.event),READ,REMOVE);
444   network_close(&(priv.net),gi);
445   if(list_search_data(&(priv.client),&gi,sizeof(int))==L_SUCCESS) {
446     list_del_current(&(priv.client));
447     printf("removed client from list\n");
448   }
449   if(list_search_data(&(priv.gui),&gi,sizeof(int))==L_SUCCESS) {
450     list_del_current(&(priv.gui));
451     printf("removed gui from list\n");
452   }
453
454   alert=1;
455   alarm(0);
456
457 }
458
459 /*
460  * main program
461  */
462
463 int main(int argc,char **argv)
464 {
465
466   int port;
467
468   /* default values */
469   port=1025;
470
471   /* parse argv */
472   if(argc==2) port=atoi(argv[1]);
473
474   /* event init */
475   event_init(&(priv.event),1);
476   /* 10 sec event timeout - distributing jobs */
477   event_set_timeout(&(priv.event),10,0);
478
479   /* list init */
480   list_init(&(priv.client),1);
481   list_init(&(priv.gui),1);
482   list_init(&(priv.job),1);
483
484   /* connect to server */
485   network_init(&(priv.net),1);
486   network_set_listen_port(&(priv.net),port);
487   if(network_listen(&(priv.net))!=N_SUCCESS) {
488     printf("unable to listen on port %d, aborting!\n",port);
489     return -1;
490   }
491
492   /* install sighandler */
493   signal(SIGALRM,destroy_it);
494
495   /* wait for events :) */
496   event_math(priv.net.l_fd,&(priv.event),READ,ADD);
497   printf("\nNLSOP_SERVER started!\n\n");
498   event_start(&(priv.event),NULL,parse_incoming,distribute_jobs);
499
500   return 1;
501 }
502