diff options
author | Russ Cox <rsc@swtch.com> | 2008-08-03 07:42:27 -0700 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2008-08-03 07:42:27 -0700 |
commit | 18824b586835525594cde126fbc90b8281d5af8b (patch) | |
tree | e8b69c05eda4543b6d2f3d30777abe6109b48b7f /src/cmd/smugfs/icache.c | |
parent | 3d36f4437348227c5bad62587dc12b5fd4a3e95e (diff) | |
download | plan9port-18824b586835525594cde126fbc90b8281d5af8b.tar.gz plan9port-18824b586835525594cde126fbc90b8281d5af8b.tar.bz2 plan9port-18824b586835525594cde126fbc90b8281d5af8b.zip |
smugfs(4): new program
Diffstat (limited to 'src/cmd/smugfs/icache.c')
-rw-r--r-- | src/cmd/smugfs/icache.c | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/cmd/smugfs/icache.c b/src/cmd/smugfs/icache.c new file mode 100644 index 00000000..750f232c --- /dev/null +++ b/src/cmd/smugfs/icache.c @@ -0,0 +1,171 @@ +#include "a.h" + +// This code is almost certainly wrong. + +typedef struct Icache Icache; +struct Icache +{ + char *url; + HTTPHeader hdr; + char *tmpfile; + int fd; + Icache *next; + Icache *prev; + Icache *hash; +}; + +enum { + NHASH = 128, + MAXCACHE = 128, +}; +static struct { + Icache *hash[NHASH]; + Icache *head; + Icache *tail; + int n; +} icache; + +static Icache* +icachefind(char *url) +{ + int h; + Icache *ic; + + h = hash(url) % NHASH; + for(ic=icache.hash[h]; ic; ic=ic->hash){ + if(strcmp(ic->url, url) == 0){ + /* move to front */ + if(ic->prev) { + ic->prev->next = ic->next; + if(ic->next) + ic->next->prev = ic->prev; + else + icache.tail = ic->prev; + ic->prev = nil; + ic->next = icache.head; + icache.head->prev = ic; + icache.head = ic; + } + return ic; + } + } + return nil; +} + +static Icache* +icacheinsert(char *url, HTTPHeader *hdr, char *file, int fd) +{ + int h; + Icache *ic, **l; + + if(icache.n == MAXCACHE){ + ic = icache.tail; + icache.tail = ic->prev; + if(ic->prev) + ic->prev->next = nil; + else + icache.head = ic->prev; + h = hash(ic->url) % NHASH; + for(l=&icache.hash[h]; *l; l=&(*l)->hash){ + if(*l == ic){ + *l = ic->hash; + goto removed; + } + } + sysfatal("cannot find ic in cache"); + removed: + free(ic->url); + close(ic->fd); + remove(ic->file); + free(ic->file); + }else{ + ic = emalloc(sizeof *ic); + icache.n++; + } + + ic->url = estrdup(url); + ic->fd = dup(fd, -1); + ic->file = estrdup(file); + ic->hdr = *hdr; + h = hash(url) % NHASH; + ic->hash = icache.hash[h]; + icache.hash[h] = ic; + ic->prev = nil; + ic->next = icache.head; + if(ic->next) + ic->next->prev = ic; + else + icache.tail = ic; + return ic; +} + +void +icacheflush(char *substr) +{ + Icache **l, *ic; + + for(l=&icache.head; (ic=*l); ) { + if(substr == nil || strstr(ic->url, substr)) { + icache.n--; + *l = ic->next; + free(ic->url); + close(ic->fd); + remove(ic->file); + free(ic->file); + free(ic); + }else + l = &ic->next; + } + + if(icache.head) { + icache.head->prev = nil; + for(ic=icache.head; ic; ic=ic->next){ + if(ic->next) + ic->next->prev = ic; + else + icache.tail = ic; + } + }else + icache.tail = nil; +} + +int +urlfetch(char *url, HTTPHeader hdr) +{ + Icache *ic; + char buf[50], *host, *path, *p; + int fd, len; + + ic = icachefind(url); + if(ic != nil){ + *hdr = ic->hdr; + return dup(ic->fd, -1); + } + + if(memcmp(url, "http://", 7) != 0){ + werrstr("non-http url"); + return -1; + } + p = strchr(url+7, '/'); + if(p == nil) + p = url+strlen(url); + len = p - (url+7); + host = emalloc(len+1); + memmove(host, url+7, len); + host[len] = 0; + if(*p == 0) + p = "/"; + + strcpy(buf, "/var/tmp/smugfs.XXXXXX"); + fd = opentemp(buf, ORDWR|ORCLOSE); + if(fd < 0) + return -1; + if(httptofile(http, host, req, &hdr, fd) < 0){ + free(host); + return -1; + } + free(host); + icacheinsert(url, &hdr, buf, fd); + return fd; +} + |