URI:
       ticache.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       ticache.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 }