Back to index

wims  3.65+svn20090927
cache.c
Go to the documentation of this file.
00001 /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
00002  *
00003  *  This program is free software; you can redistribute it and/or modify
00004  *  it under the terms of the GNU General Public License as published by
00005  *  the Free Software Foundation; either version 2 of the License, or
00006  *  (at your option) any later version.
00007  *
00008  *  This program is distributed in the hope that it will be useful,
00009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *  GNU General Public License for more details.
00012  *
00013  *  You should have received a copy of the GNU General Public License
00014  *  along with this program; if not, write to the Free Software
00015  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00016  */
00017 
00018               /* Caches and its management */
00019 
00020        /* General information of an exercise. Size: 10 bytes. */
00021 typedef struct exodata {
00022     unsigned short int num;
00023     float weight, require;
00024 } exodata;
00025 
00026 struct classdata {
00027     char name[MAX_CLASSLEN+1];
00028     time_t start, last, modif;
00029     int exocnt, examcnt, examstart, access;
00030     struct exodata exos[MAX_CLASSEXOS];
00031     char ctbuf[CTBUFLEN];
00032     short int ctptr[MAX_EXOS];
00033 } classdata[MAX_CLASSCACHE];
00034 
00035 struct classcache {
00036     struct classdata *ptr;
00037 } classcache[MAX_CLASSCACHE];
00038 int classcaches;
00039 
00040 struct sheetdata {
00041     char buffer[SHEETBUFLEN];
00042     int name,header,status,exocnt,exo[MAX_EXOS];
00043     time_t start, last;
00044     int access;
00045 } sheetdata[MAX_SHEETCACHE];
00046 
00047 struct sheetcache {
00048     struct sheetdata *ptr;
00049 } sheetcache[MAX_SHEETCACHE];
00050 int sheetcaches;
00051 
00052        /* searches a list. Returns index if found, -1 if nomatch. 
00053         * Uses binary search, list must be sorted. */
00054 int search_data(void *list, int items, size_t item_size, unsigned short int t)
00055 {
00056     int i1,i2,j,k;
00057     unsigned short int *p;
00058     
00059     if(items<=0) return -1;
00060     j=0; p=list; k=*p-t;
00061     if(k==0) return k; if(k>0) return -1;
00062     p=list+(items-1)*item_size; 
00063     k=*p-t; if(k==0) return items-1; if(k<0) return ~items;
00064     for(i1=0,i2=items-1;i2>i1+1;) {
00065        j=(i2+i1)/2;
00066        p=list+(j*item_size);
00067        k=*p-t;
00068        if(k==0) return j;
00069        if(k>0) {i2=j; continue;}
00070        if(k<0) {i1=j; continue;}   
00071     }
00072     return ~i2;
00073 }
00074 
00075        /* remove old cache items */
00076 void cleancache(void)
00077 {
00078     int i;
00079     time_t now;
00080     struct classdata *cd;
00081     struct sheetdata *sd;
00082     now=time(NULL);
00083     for(i=0;i<classcaches;i++) {
00084        cd=classcache[i].ptr;
00085        if(now<cd->start+CLASSCACHE_DELAY) continue;
00086        cd->access=0;
00087        memmove(classcache+i,classcache+i+1,(classcaches-i-1)*sizeof(classcache[0]));
00088        classcaches--;
00089     }
00090     for(i=0;i<sheetcaches;i++) {
00091        sd=sheetcache[i].ptr;
00092        if(now<sd->start+SHEETCACHE_DELAY) continue;
00093        sd->access=0;
00094        memmove(sheetcache+i,sheetcache+i+1,(sheetcaches-i-1)*sizeof(sheetcache[0]));
00095        sheetcaches--;
00096     }
00097 }
00098 
00099        /* Locate the cache number of a class */
00100 struct classdata *getclasscache(char *cl)
00101 {
00102     int i,j,k,l,m,n, oldest;
00103     struct stat st;
00104     struct classdata *cd;
00105     char buf[MAX_LINELEN+1], buf2[MAX_LINELEN+1];
00106     char *p1, *p2, *q1, *q2;
00107     time_t tt;
00108     tt=0, oldest=0;
00109     for(i=0;i<classcaches;i++) {
00110        cd=classcache[i].ptr;
00111        if(tt>cd->start) {tt=cd->start; oldest=i;}
00112        if(strcmp(cd->name,cl)==0) {
00113            cd->access++;
00114            return cd;
00115        }
00116     }
00117     if(classcaches>=MAX_CLASSCACHE) {
00118        i=oldest;cd=classcache[i].ptr;
00119        cd->access=0;
00120        memmove(classcache+i,classcache+i+1,(classcaches-i-1)*sizeof(classcache[0]));
00121        classcaches--;
00122     }
00123     for(i=0;i<MAX_CLASSCACHE && classdata[i].access>0; i++);
00124     if(i>classcaches) return NULL;
00125     cd=classdata+i; cd->access=1;
00126     classcache[classcaches++].ptr=cd;
00127     snprintf(cd->name,sizeof(cd->name),"%s",cl);
00128     cd->start=time(NULL); cd->exocnt=0;
00129        /* Now get the exo data */
00130     accessfile(buf,"r","sheets/.require");
00131     for(i=k=0,p1=buf; *p1; i++,p1=p2) {
00132        p2=strchr(p1,'\n'); if(p2) *p2++=0; else p2=p1+strlen(p1);
00133        for(j=0,q1=find_word_start(p1); *q1 && k<MAX_CLASSEXOS; j++,q1=find_word_start(q2)) {
00134            q2=find_word_end(q1); if(*q2) *q2++=0;
00135            cd->exos[k].num=(i<<8)+j;cd->exos[k].require=atof(q1);
00136            cd->exos[k].weight=0;
00137            k++;          
00138        }
00139        
00140     }
00141     if(k>=MAX_CLASSEXOS) return NULL;
00142     cd->exocnt=k; cd->examstart=k; cd->modif=0;
00143     accessfile(buf,"r","sheets/.weight");
00144     for(i=k=0,p1=buf; *p1; i++,p1=p2) {
00145        p2=strchr(p1,'\n'); if(p2) *p2++=0; else p2=p1+strlen(p1);
00146        for(j=0,q1=find_word_start(p1); *q1 && k<MAX_CLASSEXOS; j++,q1=find_word_start(q2)) {
00147            q2=find_word_end(q1); if(*q2) *q2++=0;
00148            if(cd->exos[k].num==(i<<8)+j) {
00149               cd->exos[k].weight=atof(q1);
00150               k++;
00151            }
00152            else while(k<cd->exocnt && cd->exos[k].num<(i<<8)+j) k++;
00153        }
00154     }
00155     if(stat("exams/.exams",&st)==0) cd->modif=st.st_mtime; else return cd;
00156     accessfile(buf,"r","exams/.exams");
00157     if(buf[0]==0) return cd;
00158     if(buf[0]==':') p1=buf-1; else p1=strstr(buf,"\n:");
00159     for(n=m=0,k=cd->exocnt; p1 && k<MAX_CLASSEXOS && m<MAX_EXOS; p1=p2,m++) {
00160        p1+=2;
00161        p2=strstr(p1,"\n:"); if(p2) *p2=0;
00162        if(*find_word_start(p1)<'1') continue;    /* status */
00163        fnd_line(p1,3,buf2); if(buf2[0]==0) continue;
00164        q1=find_word_start(buf2); q2=find_word_end(q1);
00165        if(*q2) *q2++=0;
00166        q2=find_word_start(q2); *find_word_end(q2)=0;
00167        i=atoi(q1); j=atoi(q2); if(i<=0 || j<=0) continue;
00168        cd->exos[k].num=0xFF00+m;
00169        cd->exos[k].weight=i; cd->exos[k].require=j;     /* weight: duration. require: retries */
00170        fnd_line(p1,6,buf2); q1=find_word_start(buf2);
00171        singlespace(q1); strip_trailing_spaces(q1);
00172        cd->ctptr[k-cd->exocnt]=n; cd->ctbuf[n]=0;
00173        if(n+strlen(q1)>CTBUFLEN-MAX_EXOS-16) *q1=0;     /* silent truncation */
00174        l=strlen(q1)+1; memmove(cd->ctbuf+n,q1,l); n+=l;
00175        k++;
00176     }
00177     cd->examcnt=k-cd->exocnt; cd->exocnt=k;
00178     return cd;
00179 }
00180 
00181        /* prepare cache for a sheet */
00182 struct sheetata *getsheetcache(char *cl, char *sh)
00183 {
00184     
00185     
00186     
00187     return NULL;
00188 }
00189