some more printfs to server + deleted debug printf in gui
[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 /* globals */
55 int *gi;
56 t_net *gnet;
57 t_event *gevent;
58 t_list *gc_list;
59 t_list *gg_list;
60 int alert;
61
62 /*
63  * server specific stuff
64  */
65
66 int usage(char *prog)
67 {
68  puts("usage:");
69  printf("%s <listen port>\n",prog);
70  return 1;
71 }
72
73 int add_node(t_net *net,t_event *event,t_list *c_list,t_list *g_list) {
74
75   int channel;
76   unsigned char data;
77   t_client client;
78   int gui_chan;
79
80   channel=network_manage_incoming(net);
81   if(channel==N_E_ACCEPT) {
82     printf("accept failed!\n");
83     return -1;
84   }
85   if(channel==N_E_MAXC) {
86     printf("maximum connections reached!\n");
87     return -1;
88   }
89   printf("connection from %s port %d (ch: %d)\n",net->connection[channel].ip,
90                                                  net->connection[channel].port,
91                                                  channel);
92
93   /* are you client or gui? */
94   network_receive_chan(net,channel,&data,1);
95   if(data==NLSOP_GUI) {
96     gui_chan=channel;
97     list_add_element(g_list,&gui_chan,sizeof(int));
98     printf("node is a gui\n");
99   }
100   else if(data==NLSOP_CLIENT) {
101     client.status=IDLE;
102     client.channel=channel;
103     list_add_element(c_list,&client,sizeof(t_client));
104     printf("node is a client\n");
105   }
106   else {
107     printf("not a client or gui - lets kick that ass out of here!\n");
108     network_close(net,channel);
109     return -1;
110   }
111
112   /* if we have a new node - care for it! */
113   event_math(net->connection[channel].fd,event,READ,ADD);
114
115   printf("\n");
116
117   return 1;
118 }
119
120 int save_job(t_net *net,int channel,t_job *job,unsigned char dc) {
121
122   char filename[128];
123   int fd;
124   int ret;
125   d3_lattice d3l;
126   info info;
127
128   ret=network_receive_chan(net,channel,job->ac,job->size*sizeof(unsigned char));
129   if(ret==N_ERROR) printf("FATAL: getting ac status failed\n");
130   ret=network_receive_chan(net,channel,(unsigned char *)job->cc,
131                            job->size*sizeof(int));
132   if(ret==N_ERROR) printf("FATAL: getting cc failed\n");
133   ret=network_receive_chan(net,channel,(unsigned char *)&(job->step),
134                            sizeof(int));
135   if(ret==N_ERROR) printf("FATAL: getting step number failed\n");
136
137   if(dc!=DC_QUIT) {
138     snprintf(filename,128,"./data/nlsop_b%f_c%f_s%f_ds%d_dr%f_-_%d_of_%d.save",
139              job->info.b,job->info.c,job->info.s,
140              job->info.diff_rate,job->info.dr_ac,
141              job->step,job->info.steps);
142     if((fd=open(filename,O_WRONLY|O_CREAT))<0) {
143       printf("FATAL: unable to open file %s\n",filename);
144       return -1;
145     }
146
147     memset(&d3l,0,sizeof(d3_lattice));
148     d3l.max_x=job->x;
149     d3l.max_y=job->y;
150     d3l.max_z=job->z;
151     if(write(fd,&d3l,sizeof(d3_lattice))<sizeof(d3_lattice)) {
152       printf("FATAL: write of d3_lattice failed\n");
153       return -1;
154     }
155
156     if(write(fd,&(job->info),sizeof(info))<sizeof(info)) {
157       printf("FATAL: write of info failed\n");
158       return -1;
159     }
160
161     ret=write(fd,job->ac,job->size*sizeof(unsigned char));
162     if(ret<job->size*sizeof(unsigned char)) {
163       printf("FATAL: write of a/c states failed\n");
164       return -1;
165     }
166    
167     ret=write(fd,job->cc,job->size*sizeof(int));
168     if(ret<job->size*sizeof(int)) {
169       printf("FATAL: write of c.-conc. failed\n");
170       return -1;
171     }
172
173     close(fd);
174     
175   }
176
177   return 1;
178 }
179
180 int add_job(t_net *net,int chan,t_list *jl) {
181
182   t_job job;
183
184   job.channel=-1;
185   job.status=IN_QUEUE;
186   job.progress=0;
187
188   network_receive_chan(net,chan,(unsigned char *)&(job.x),sizeof(int));
189   network_receive_chan(net,chan,(unsigned char *)&(job.y),sizeof(int));
190   network_receive_chan(net,chan,(unsigned char *)&(job.z),sizeof(int));
191   network_receive_chan(net,chan,(unsigned char *)&(job.info),sizeof(info));
192
193   job.size=job.x*job.y*job.z;
194
195   job.ac=(unsigned char *)malloc(job.size*sizeof(unsigned char));
196   if(job.ac==NULL) {
197     printf("unable to malloc a/c memory\n");
198     return -1;
199   }
200
201   job.cc=(int *)malloc(job.size*sizeof(int));
202   if(job.cc==NULL) {
203     printf("unable to malloc cc memory\n");
204     return -1;
205   }
206
207   job.step=0;
208
209   list_add_element(jl,&job,sizeof(t_job));
210
211   return 1;
212 }
213
214 int send_status(t_net *net,int chan,t_list *jl) {
215
216   unsigned char data;
217   int count;
218   int i;
219
220   data=GUI_INFO;
221   count=list_count(jl);
222
223   network_send_chan(net,chan,&data,sizeof(unsigned char));
224   network_send_chan(net,chan,(unsigned char *)&count,sizeof(int));
225
226   list_reset(jl);
227   for(i=0;i<count;i++) {
228     network_send_chan(net,chan,jl->current->data,sizeof(t_job));
229     list_next(jl);
230   }
231
232   return 1;
233 }
234
235 int handle_node(t_net *net,t_event *event,
236                 t_list *c_list,t_list *g_list,t_list *job) {
237
238   int i;
239   unsigned char data;
240   t_client *c;
241   t_job *j;
242
243   gi=&i;
244
245   for(i=0;i<MAX_CONNECTIONS;i++) {
246     if(FD_ISSET(net->connection[i].fd,&(event->rfds))) {
247
248       alert=0;
249       alarm(1);
250       network_receive_chan(net,i,&data,1);
251       alarm(0);
252
253       if(alert==1) return -1;
254
255       if(list_search_data(c_list,&i,sizeof(int))==L_SUCCESS) {
256         /* it's a client */
257         list_search_data(job,&i,sizeof(int));
258         j=(t_job *)job->current->data;
259         c=(t_client *)c_list->current-data;
260
261         if(data==DC_END) {
262           save_job(net,i,j,DC_END);
263           /* reset client */
264           c->status=IDLE;
265           /* delete job entry */
266           list_del_current(job);
267           printf("job ended, saved and removed from list.\n");
268         }
269
270         if(data==DC_OK) {
271           save_job(net,i,j,DC_OK);
272           /* inc progress state */
273           j->progress+=1;
274           printf("job at next level, saved.\n");
275         }
276
277         if(data==DC_QUIT) {
278           save_job(net,i,j,DC_QUIT);
279           /* network disconnect */
280           event_math(net->connection[i].fd,event,READ,REMOVE);
281           network_close(net,i);
282           /* del from client list */
283           list_del_current(c_list);
284           /* change job state */
285           j->status=IN_QUEUE;
286           printf("client terminating, job queued, client removed.\n");
287         }
288       }
289
290       else if(list_search_data(g_list,&i,sizeof(int))==L_SUCCESS) {
291         /* its a gui */
292         if(data==GUI_ADDJOB) add_job(net,i,job);
293
294         else if(data==GUI_INFO) send_status(net,i,job);
295
296         else if(data==GUI_QUIT) {
297           printf("disconnecting gui on channel %d\n",i);
298           event_math(net->connection[i].fd,event,READ,REMOVE);
299           network_close(net,i);
300           list_del_current(g_list);
301         }
302
303         else {
304           printf("unknown gui command\n");
305           return -1;
306         }
307       }
308
309       else {
310         printf("this chan is not in client or gui list! i disconnect now!\n");
311         event_math(net->connection[i].fd,event,READ,REMOVE);
312         network_close(net,i);
313       }
314     }
315   }
316
317   printf("\n");
318    
319   return 1;
320 }
321
322 int distribute_jobs(t_event *event,void *allineed) {
323
324   t_net *net;
325   t_list *c_list,*g_list,*job;
326   int count_j,count_c;
327   t_job *j;
328   t_client *c;
329   unsigned char data;
330   d3_lattice d3l;
331   unsigned int addr[4];
332
333   memcpy(addr,allineed,4*sizeof(unsigned int));
334
335   net=(t_net *)addr[0];
336   c_list=(t_list *)addr[1];
337   g_list=(t_list *)addr[2];
338   job=(t_list *)addr[3];
339
340   count_j=list_count(job);
341   count_c=list_count(c_list);
342
343   list_reset(job);
344   list_reset(c_list);
345   while((count_c!=0)&&(count_j!=0)) {
346     j=(t_job *)job->current->data;
347     c=(t_client *)c_list->current->data;
348     while(c->status!=IDLE) {
349       list_next(c_list);
350       c=(t_client *)c_list->current->data;
351     }
352     while(j->status!=IN_QUEUE) {
353       list_next(job);
354       j=(t_job *)job->current->data;
355     }
356
357     /* direct current job to current client */
358     if(j->step==0) data=NLSOP_NJOB;
359     else data=NLSOP_CJOB;
360
361     c->status=WORK;
362     j->channel=c->channel;
363     j->status=IN_WORK;
364
365     d3l.max_x=j->x;
366     d3l.max_y=j->y;
367     d3l.max_z=j->z;
368
369     network_send_chan(net,c->channel,&data,sizeof(unsigned char));
370     network_send_chan(net,c->channel,(unsigned char *)&d3l,sizeof(d3_lattice));
371     network_send_chan(net,c->channel,(unsigned char *)&(j->info),sizeof(info));
372
373     if(data==NLSOP_CJOB) {
374       network_send_chan(net,c->channel,j->ac,j->size*sizeof(unsigned char));
375       network_send_chan(net,c->channel,(unsigned char *)&(j->cc),
376                         j->size*sizeof(int));
377     }
378
379     --count_c;
380     --count_j;
381     list_next(c_list);
382     list_next(job);
383   }
384
385   return 1;
386 }
387
388 int parse_incoming(t_event *event,void *allineed) {
389
390   t_net *net;
391   t_list *c_list,*g_list,*job;
392   unsigned int addr[4];
393
394   memcpy(addr,allineed,4*sizeof(unsigned int));
395
396   net=(t_net *)addr[0];
397   c_list=(t_list *)addr[1];
398   g_list=(t_list *)addr[2];
399   job=(t_list *)addr[3];
400
401   /* decide what to do */
402   if(FD_ISSET(net->l_fd,&(event->rfds))) {
403     /* new node */
404     printf("new node ...\n");
405     add_node(net,event,c_list,g_list);
406   }
407   else {
408     /* client/gui interaction */
409     printf("node interaction ...\n");
410     handle_node(net,event,c_list,g_list,job);
411   }
412     
413   return 1;
414 }
415
416 void destroy_it(int signum) {
417
418   printf("connection to client (ch %d) fucked up!\n",*gi);
419   event_math(gnet->connection[*gi].fd,gevent,READ,REMOVE);
420   network_close(gnet,*gi);
421   if(list_search_data(gc_list,gi,sizeof(int))==L_SUCCESS) {
422     list_del_current(gc_list);
423     printf("removed client from list\n");
424   }
425   if(list_search_data(gg_list,gi,sizeof(int))==L_SUCCESS) {
426     list_del_current(gg_list);
427     printf("removed gui from list\n");
428   }
429
430   alert=1;
431   alarm(0);
432
433 }
434
435 /*
436  * main program
437  */
438
439 int main(int argc,char **argv)
440 {
441
442   int port;
443   t_net net;
444   t_event event;
445   t_list c_list;
446   t_list g_list;
447   t_list job;
448   void *allyouneed;
449   unsigned int addr[4];
450
451   gnet=&net;
452   gevent=&event;
453   gc_list=&c_list;
454   gg_list=&g_list;
455
456   /* tzzz ... */
457   allyouneed=(void *)addr;
458   addr[0]=(unsigned int)&net;
459   addr[1]=(unsigned int)&c_list;
460   addr[2]=(unsigned int)&g_list;
461   addr[3]=(unsigned int)&job;
462   
463   /* default values */
464   port=1025;
465
466   /* parse argv */
467   if(argc==2) port=atoi(argv[1]);
468
469   /* event init */
470   event_init(&event,1);
471   /* 10 sec event timeout - distributing jobs */
472   event_set_timeout(&event,10,0);
473
474   /* list init */
475   list_init(&c_list,1);
476   list_init(&g_list,1);
477   list_init(&job,1);
478
479   /* connect to server */
480   network_init(&net,1);
481   network_set_listen_port(&net,port);
482   if(network_listen(&net)!=N_SUCCESS) {
483     printf("unable to listen on port %d, aborting!\n",port);
484     return -1;
485   }
486
487   /* install sighandler */
488   signal(SIGALRM,destroy_it);
489
490   /* wait for events :) */
491   event_math(net.l_fd,&event,READ,ADD);
492   printf("\nNLSOP_SERVER started!\n\n");
493   event_start(&event,allyouneed,parse_incoming,distribute_jobs);
494
495   return 1;
496 }
497