icache.c (2808B)
1 #include "a.h" 2 3 // This code is almost certainly wrong. 4 5 typedef struct Icache Icache; 6 struct Icache 7 { 8 char *url; 9 HTTPHeader hdr; 10 char *tmpfile; 11 int fd; 12 Icache *next; 13 Icache *prev; 14 Icache *hash; 15 }; 16 17 enum { 18 NHASH = 128, 19 MAXCACHE = 128, 20 }; 21 static struct { 22 Icache *hash[NHASH]; 23 Icache *head; 24 Icache *tail; 25 int n; 26 } icache; 27 28 static Icache* 29 icachefind(char *url) 30 { 31 int h; 32 Icache *ic; 33 34 h = hash(url) % NHASH; 35 for(ic=icache.hash[h]; ic; ic=ic->hash){ 36 if(strcmp(ic->url, url) == 0){ 37 /* move to front */ 38 if(ic->prev) { 39 ic->prev->next = ic->next; 40 if(ic->next) 41 ic->next->prev = ic->prev; 42 else 43 icache.tail = ic->prev; 44 ic->prev = nil; 45 ic->next = icache.head; 46 icache.head->prev = ic; 47 icache.head = ic; 48 } 49 return ic; 50 } 51 } 52 return nil; 53 } 54 55 static Icache* 56 icacheinsert(char *url, HTTPHeader *hdr, char *file, int fd) 57 { 58 int h; 59 Icache *ic, **l; 60 61 if(icache.n == MAXCACHE){ 62 ic = icache.tail; 63 icache.tail = ic->prev; 64 if(ic->prev) 65 ic->prev->next = nil; 66 else 67 icache.head = ic->prev; 68 h = hash(ic->url) % NHASH; 69 for(l=&icache.hash[h]; *l; l=&(*l)->hash){ 70 if(*l == ic){ 71 *l = ic->hash; 72 goto removed; 73 } 74 } 75 sysfatal("cannot find ic in cache"); 76 removed: 77 free(ic->url); 78 close(ic->fd); 79 remove(ic->file); 80 free(ic->file); 81 }else{ 82 ic = emalloc(sizeof *ic); 83 icache.n++; 84 } 85 86 ic->url = estrdup(url); 87 ic->fd = dup(fd, -1); 88 ic->file = estrdup(file); 89 ic->hdr = *hdr; 90 h = hash(url) % NHASH; 91 ic->hash = icache.hash[h]; 92 icache.hash[h] = ic; 93 ic->prev = nil; 94 ic->next = icache.head; 95 if(ic->next) 96 ic->next->prev = ic; 97 else 98 icache.tail = ic; 99 return ic; 100 } 101 102 void 103 icacheflush(char *substr) 104 { 105 Icache **l, *ic; 106 107 for(l=&icache.head; (ic=*l); ) { 108 if(substr == nil || strstr(ic->url, substr)) { 109 icache.n--; 110 *l = ic->next; 111 free(ic->url); 112 close(ic->fd); 113 remove(ic->file); 114 free(ic->file); 115 free(ic); 116 }else 117 l = &ic->next; 118 } 119 120 if(icache.head) { 121 icache.head->prev = nil; 122 for(ic=icache.head; ic; ic=ic->next){ 123 if(ic->next) 124 ic->next->prev = ic; 125 else 126 icache.tail = ic; 127 } 128 }else 129 icache.tail = nil; 130 } 131 132 int 133 urlfetch(char *url, HTTPHeader hdr) 134 { 135 Icache *ic; 136 char buf[50], *host, *path, *p; 137 int fd, len; 138 139 ic = icachefind(url); 140 if(ic != nil){ 141 *hdr = ic->hdr; 142 return dup(ic->fd, -1); 143 } 144 145 if(memcmp(url, "http://", 7) != 0){ 146 werrstr("non-http url"); 147 return -1; 148 } 149 p = strchr(url+7, '/'); 150 if(p == nil) 151 p = url+strlen(url); 152 len = p - (url+7); 153 host = emalloc(len+1); 154 memmove(host, url+7, len); 155 host[len] = 0; 156 if(*p == 0) 157 p = "/"; 158 159 strcpy(buf, "/var/tmp/smugfs.XXXXXX"); 160 fd = opentemp(buf, ORDWR|ORCLOSE); 161 if(fd < 0) 162 return -1; 163 if(httptofile(http, host, req, &hdr, fd) < 0){ 164 free(host); 165 return -1; 166 } 167 free(host); 168 icacheinsert(url, &hdr, buf, fd); 169 return fd; 170 }