Subversion Repositories wimsdev

Rev

Rev 15779 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18. /* Computes class connection count (unit: student-minutes) */
  19.  
  20. #include "../Lib/libwims.h"
  21.  
  22. /* The maximal number of sessions within one day */
  23. #define MAX_SESSIONS (128*1024)
  24. /* The maximal number of classes within one day */
  25. #define MAX_CLASSES 8192
  26. /* At least these minutes will be counted for each session */
  27. #define MIN_CONNECT 1
  28. /* Add this number of minutes to each session */
  29. #define MIN_ADD 1
  30. /* Accounting discontinues after this number of idle minutes */
  31. #define MAX_LAPSE 15
  32.  
  33. struct {
  34.   char s[4], u[32], cl[20];
  35.   int start, end, cnt;
  36.  
  37. } ses[MAX_SESSIONS];
  38. int sescnt;
  39.  
  40. char *datestr;
  41.  
  42. struct cls {
  43.   char cl[20];
  44.   int cnt;
  45. } cls[MAX_CLASSES];
  46. int clscnt;
  47.  
  48. /* Read/write to a file with variable parms to print filename */
  49. /* same in Interfaces/common.c and wlogdaccessfile */
  50. static
  51. void accessfile(char *content, char *type, char *s,...)
  52. {
  53.   va_list vp;
  54.   char buf[MAX_LINELEN+1];
  55.   FILE *f;
  56.   int l;
  57.  
  58.   va_start(vp,s);
  59.   vsnprintf(buf,sizeof(buf),s,vp);
  60.   va_end(vp);
  61.   f=fopen(buf,type); if(f==NULL) {
  62.     if(*type=='r') content[0]=0;
  63.     return;
  64.   }
  65.   switch(*type) {
  66.     case 'a':
  67.     case 'w': {
  68.       l=strlen(content); fwrite(content,1,l,f); break;
  69.     }
  70.     case 'r': {
  71.       l=fread(content,1,MAX_LINELEN-1,f);
  72.       if(l>0 && l<MAX_LINELEN) content[l]=0;
  73.       else content[0]=0;
  74.       break;
  75.     }
  76.    default: {
  77.       content[0]=0; break;
  78.    }
  79.   }
  80.   fclose(f);
  81. }
  82. /* recursively generate a directory structure */
  83. void mkdirs2(char *s)
  84. {
  85.   struct stat st;
  86.   char *buf;
  87.   if(stat(s,&st)==-1) {
  88.   if(strrchr(s,'/')!=NULL) {
  89.     buf=xmalloc(strlen(s)+1);
  90.     ovlstrcpy(buf,s); *strrchr(buf,'/')=0;
  91.     mkdirs2(buf); free(buf);
  92.   }
  93.   mkdir(s,-1);
  94.   }
  95. }
  96.  
  97. /* line format is :
  98. YYYYMMDD.HH:MM:SS session IP cmd module (time) login,class
  99. time is displayed only for long request
  100. */
  101. static
  102. void oneline(char *p)
  103. {
  104.   char tbuf[8], sbuf[8], ubuf[32], cl[20];
  105.   char *p1  /*, *p2*/;
  106.   int i,t;
  107.   memmove(tbuf,p+9,6); tbuf[2]=tbuf[5]=0;
  108.   t=atoi(tbuf)*60+atoi(tbuf+3);
  109.   memmove(sbuf,p+18,4); sbuf[4]=0;
  110.   p1=strchr(p,','); if(p1==NULL) return;
  111.   if(!isdigit(*(p1+1))) return;
  112.   snprintf(cl,sizeof(cl),"%s",p1+1);
  113.   *p1=0; for(p1--;p1>p && !isspace(*(p1-1)); p1--);
  114.   snprintf(ubuf,sizeof(ubuf),"%s",p1);
  115.   for(i=0;i<sescnt;i++) {
  116.     if(memcmp(cl,ses[i].cl,20)==0 && memcmp(sbuf,ses[i].s,4)==0 &&
  117.         ses[i].end>=t-MAX_LAPSE) {
  118.       ses[i].end=t; return;
  119.     }
  120.   }
  121.   if(sescnt>=MAX_SESSIONS) return;
  122.   memmove(ses[sescnt].s,sbuf,4);
  123.   memmove(ses[sescnt].cl,cl,20);
  124.   ses[sescnt].start=ses[sescnt].end=t;
  125.   snprintf(ses[sescnt].u,sizeof(ses[sescnt].u),"%s",ubuf);
  126.   sescnt++;
  127. }
  128.  
  129. void onefile(char *fname)
  130. {
  131.   FILE *f;
  132.   long l;
  133.   char *fbuf, *p1, *p2, *p3;
  134.   l=filelength(fname); if(l<=0) return;
  135.   f=fopen(fname,"r"); if(f==NULL) return;
  136.   fbuf=xmalloc(l+16); (void)fread(fbuf,1,l,f); fclose(f); fbuf[l]=0;
  137.   for(p1=fbuf; *p1; p1=p2) {
  138.   p2=strchr(p1,'\n'); if(p2==NULL) p2=p1+strlen(p1); else *p2++=0;
  139.   p3=strchr(p1,','); if(p3==NULL) continue;
  140.   if(strncmp(p1,datestr,8)!=0) continue;
  141.   oneline(p1);
  142.   }
  143. }
  144.  
  145. void classaccount(void)
  146. {
  147.   int i,j;
  148.   clscnt=0;
  149.   for(i=0;i<sescnt;i++) {
  150.   ses[i].cnt=ses[i].end-ses[i].start+MIN_ADD;
  151.   if(ses[i].cnt<MIN_CONNECT) ses[i].cnt=MIN_CONNECT;
  152.   for(j=0;j<clscnt && ses[i].cl!=cls[j].cl;j++);
  153.   if(j<clscnt) cls[j].cnt+=ses[i].cnt;
  154.   else
  155.     if(clscnt<MAX_CLASSES) {
  156.       memmove(cls[clscnt].cl,ses[i].cl,20);
  157.       cls[clscnt].cnt=ses[i].cnt;
  158.       clscnt++;
  159.     }
  160.   }
  161. }
  162.  
  163. int clscmp(const void *c1, const void *c2)
  164. {
  165.   struct cls *cl1, *cl2;
  166.   cl1=(struct cls *) c1; cl2=(struct cls *) c2;
  167.   return cl1->cl-cl2->cl;
  168. }
  169.  
  170. void output(void)
  171. {
  172.   char *p, buf[1024], dbuf[1024];
  173.   int i,t;
  174.   p=getenv("ccsum_outdir"); if(p==NULL || *p==0) return;
  175.   for(i=0;i<sescnt;i++) {
  176.     snprintf(dbuf,sizeof(dbuf),"%s/%s",p,ses[i].cl);
  177.     mkdirs2(dbuf);
  178.     snprintf(buf,sizeof(buf),"%s.%02d:%02d %d\n",
  179.        datestr,ses[i].start/60,ses[i].start%60,ses[i].cnt);
  180.     accessfile(buf,"a","%s/%s",dbuf,ses[i].u);
  181.   }
  182.   snprintf(dbuf,sizeof(dbuf),"%s/bydate/%.4s",p,datestr);
  183.   mkdirs2(dbuf);
  184.   snprintf(dbuf+strlen(dbuf),sizeof(dbuf)-strlen(dbuf),"/%.2s",datestr+4);
  185.   t=0;
  186.   qsort(cls,clscnt,sizeof(cls[0]),clscmp);
  187.   for(i=0;i<clscnt;i++) {
  188.     snprintf(buf,sizeof(buf),"%s %d\n",datestr,cls[i].cnt);
  189.     accessfile(buf,"a","%s/%s/.total",p,cls[i].cl);
  190.     snprintf(buf,sizeof(buf),"%s %s %d\n",datestr+4,cls[i].cl,cls[i].cnt);
  191.     accessfile(buf,"a","%s",dbuf);
  192.     t+=cls[i].cnt;
  193.   }
  194.   snprintf(buf,sizeof(buf),"%s %d %d\n",datestr,t,(t+30)/60);
  195.   accessfile(buf,"a","%s/done",p);
  196. }
  197.  
  198. int main(int argc, char *argv[])
  199. {
  200.   sescnt=0;
  201.   if(argc<2) return 1;
  202.   datestr=getenv("ccsum_date");
  203.   if(datestr==NULL || strlen(datestr)!=8) return 2;
  204.   onefile(argv[1]);
  205.   classaccount();
  206.   output();
  207.   return 0;
  208. }
  209.  
  210.