diff options
Diffstat (limited to 'appl/svc/httpd/cache.b')
| -rw-r--r-- | appl/svc/httpd/cache.b | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/appl/svc/httpd/cache.b b/appl/svc/httpd/cache.b new file mode 100644 index 00000000..3d4549e4 --- /dev/null +++ b/appl/svc/httpd/cache.b @@ -0,0 +1,188 @@ +implement Cache; + +include "sys.m"; + sys : Sys; + +include "bufio.m"; + bufio : Bufio; +Iobuf : import bufio; + +include "lock.m"; + locks: Lock; + Semaphore: import locks; + +dbg_log : ref Sys->FD; + +include "cache.m"; + +HASHSIZE : con 1019; + +lru ,cache_size : int; # lru link, and maximum size of cache. +cur_size, cur_tag : int; # current size of cache and current number. + +lock: ref Semaphore; + +Cache_link : adt{ + name : string; # name of file + contents : array of byte; # contents + length : int; # length of file + qid:Sys->Qid; + tag : int; +}; + +tab := array[HASHSIZE] of list of Cache_link; + +hashasu(key : string,n : int): int +{ + i, h : int; + h=0; + i=0; + while(i<len key){ + h = 10*h + key[i]; + h = h%n; + i++; + } + return h%n; +} + + +insert(name: string, ctents: array of byte , length : int, qid:Sys->Qid) : int +{ + tmp : Cache_link; + hash : int; + lock.obtain(); + hash = hashasu(name,HASHSIZE); + if (dbg_log!=nil){ + sys->fprint(dbg_log,"current size is %d, adding %s\n", cur_size,name); + } + while (cur_size+length > cache_size) + throw_out(); + tmp.name =name; + tmp.contents = ctents; + tmp.length = length; + tmp.qid = qid; + tmp.tag = cur_tag; + cur_size+=length; + cur_tag++; + if (cur_tag<0) cur_tag=0; + tab[hash]= tmp :: tab[hash]; + lock.release(); + return 1; +} + +find(name : string, qid:Sys->Qid) : (int, array of byte) +{ + hash,flag,stale : int; + nlist : list of Cache_link; + retval : array of byte; + flag=0; + nlist=nil; + retval=nil; + stale=0; + lock.obtain(); + hash = hashasu(name,HASHSIZE); + tmp:=tab[hash]; + for(;tmp!=nil;tmp = tl tmp){ + link:=hd tmp; + if (link.name==name){ + if(link.qid.path==qid.path && link.qid.vers==qid.vers){ + link.tag=cur_tag; + cur_tag++; + flag = 1; + retval = (hd tmp).contents; + } else { # cache is stale + lru--; if(lru<0) lru = 0; + link.tag = lru; + stale = 1; + } + } + nlist = link :: nlist; + } + tab[hash]=nlist; + if (flag && (dbg_log!=nil)) + sys->fprint(dbg_log,"Found %s in cache, cur_tag is %d\n",name,cur_tag); + if (stale){ + if (dbg_log!=nil) + sys->fprint(dbg_log,"Stale %s in cache\n",name); + throw_out(); + } + lock.release(); + return (flag,retval); +} + +throw_out() +{ + nlist : list of Cache_link; + for(i:=0;i<HASHSIZE;i++){ + tmp:=tab[i]; + for(;tmp!=nil;tmp = tl tmp) + if ((hd tmp).tag==lru) + break; + if (tmp!=nil) + break; + } + if (i==HASHSIZE && (dbg_log!=nil)) + sys->fprint(dbg_log,"LRU not found!!!\n"); + # now, the lru is in tab[i]... + nlist=nil; + for(;tab[i]!=nil;tab[i]=tl tab[i]){ + if ((hd tab[i]).tag==lru){ + if (dbg_log!=nil) + sys->fprint(dbg_log,"Throwing out %s\n",(hd tab[i]).name); + cur_size-=(hd tab[i]).length; + tab[i] = tl tab[i]; + } + if (tab[i]!=nil) + nlist = (hd tab[i]) :: nlist; + if (tab[i]==nil) break; + } + lru=find_lru(); + if (dbg_log!=nil) + sys->fprint(dbg_log,"New lru is %d",lru); + tab[i] = nlist; +} + +find_lru() : int +{ + min := cur_tag; + for(i:=0;i<HASHSIZE;i++){ + tmp:=tab[i]; + for(;tmp!=nil;tmp = tl tmp) + if ((hd tmp).tag<min) + min=(hd tmp).tag; + } + return min; +} + +cache_init(log : ref Sys->FD, csize : int) +{ + n : int; + for(n=0;n<HASHSIZE;n++) + tab[n]= nil; + lru=0; + cur_size=0; + cache_size = csize*1024; + sys = load Sys Sys->PATH; + locks = load Lock Lock->PATH; + locks->init(); + lock = Semaphore.new(); + dbg_log = log; + if (dbg_log!=nil) + sys->fprint(dbg_log,"Cache initialised, max size is %d K\n",cache_size); +} + +dump() : list of (string,int,int) +{ + retval: list of (string,int,int); + lock.obtain(); + for(i:=0;i<HASHSIZE;i++){ + tmp:=tab[i]; + while(tmp!=nil){ + retval = ((hd tmp).name, (hd tmp).length, + (hd tmp).tag) :: retval; + tmp = tl tmp; + } + } + lock.release(); + return retval; +} |
