status check_direct(int test[], char* hit_miss[] , int s ,int l, int test_num ){ int i, j ; int numlines ; unsigned int new_tag, index ; queue Q ; numlines= s / l ; line cache[MAXLINES] ; // initialize the cache and the queue // the queue will store the index of the cache line // which has its valid field changed from 0 to 1 init_cache ( cache, numlines ) ; init_queue ( &Q ) ; for ( i = 0 ; i < test_num; i++ ){ if( cache_full( cache, numlines ) == TRUE ) evict_cache( cache , &Q ) ; get_tag_index ( &new_tag, &index, test[i], l, numlines ) ; if( cache[index].valid == 1 && cache[index].tag == new_tag ) hit_miss[i] = "HIT" ; else{ hit_miss[i] = "MISS" ; cache[index].tag = new_tag ; if ( cache[index].valid == 0 ){ push_int( &Q, index ) ; } cache[index].valid = 1 ; } } return OK ; }
static struct cache * find_empty_cache() { struct list_elem * e; if(!list_empty(&cache_table)) { for( e = list_begin(&cache_table); e != list_end(&cache_table); e = list_next(e)) { struct cache * t = list_entry(e,struct cache,cache_elem); if(t->used == false) return t; } struct cache * t = evict_cache(); return t; } }
void create_cache(char *buf, char *uri) { struct cache *cache = (struct cache *)Malloc(sizeof(struct cache)); pthread_mutex_init(&cache->c_lock, NULL); cache->data = (char *)Malloc(strlen(buf)); cache->uri = (char *)Malloc(strlen(uri)); cache->valid = 1; strcpy(cache->data, buf); strcpy(cache->uri, uri); pthread_mutex_lock(&s_lock); total_cache_size += strlen(cache->data); pthread_mutex_unlock(&s_lock); while (total_cache_size > MAX_CACHE_SIZE) evict_cache(); while (!insert_cache(cache)); }
void delete_cache(void) { while (head.next != &tail) evict_cache(); }
/* * serve - handle one HTTP request/response transaction */ void serve(int to_client_fd) { char buf[MAXLINE], method[MAXLINE], uri[MAXLINE], version[MAXLINE]; char filename[MAXLINE], hostname[MAXLINE]; char port[10]; rio_t rio_to_client; rio_t rio_to_server; int to_server_fd; /* Read request line and headers */ Rio_readinitb(&rio_to_client, to_client_fd); Rio_readlineb(&rio_to_client, buf, MAXLINE); sscanf(buf, "%s %s %s", method, uri, version); /* if not GET method, ignore it */ if (strcasecmp(method, "GET")) { return; } /* Parse URI from GET request */ parse_uri(uri, hostname, port, filename); // strange display error in csapp page if (strcasecmp(hostname, "csapp.cs.cmu.edu") == 0) { return; } sprintf(buf, "%s %s %s\r\n", "GET", filename, "HTTP/1.0"); /* search content in cache list */ struct cache_block* ptr = search_cache(head, uri); /* cache found, directly send to client */ if (ptr) { // add the number of existing threads reading add_reading_cnt(ptr); // send cache to client Rio_writen(to_client_fd, ptr->file, ptr->size); // subtract the number of existing threads reading sub_reading_cnt(ptr); // update timestamp and reorder LRU list update_timestamp(head, ptr); return; } /* cache not found, connect with server */ to_server_fd = Open_clientfd(hostname, port); Rio_readinitb(&rio_to_server, to_server_fd); // send request line: GET HTTP/1.0 Rio_writen(to_server_fd, buf, strlen(buf)); // send host to server sprintf(buf, "Host: %s\r\n", hostname); Rio_writen(to_server_fd, buf, strlen(buf)); /* read http headers from client and write to server */ Rio_readlineb(&rio_to_client, buf, MAXLINE); while (strncmp(buf, "\r\n", MAXLINE) != 0) { if (strstr(buf, "User-Agent")) strncpy(buf, user_agent_hdr, MAXLINE); else if (strstr(buf, "Connection")) strncpy(buf, "Connection: close\r\n", MAXLINE); else if (strstr(buf, "Proxy-Connection")) strncpy(buf, "Proxy-Connection: close\r\n", MAXLINE); else if (strstr(buf, "Host")) { // ignore, because we already sent one Rio_readlineb(&rio_to_client, buf, MAXLINE); continue; } Rio_writen(to_server_fd, buf, strlen(buf)); Rio_readlineb(&rio_to_client, buf, MAXLINE); } /* terminates request headers */ Rio_writen(to_server_fd, "\r\n", 2); /* read http response from server and write to client */ memset(buf, 0, MAXLINE); Rio_readlineb(&rio_to_server, buf, MAXLINE); int content_len = 0; while (strncmp(buf, "\r\n", MAXLINE) != 0) { char* ptr = strstr(buf, "Content-length"); if (ptr) { content_len = atoi(ptr + 16); } //printf("write2: %s\n", uri); //printf("fd: %d\n", to_client_fd); //printf("%d: %s\n", strlen(buf), buf); Rio_writen(to_client_fd, buf, strlen(buf)); memset(buf, 0, MAXLINE); Rio_readlineb(&rio_to_server, buf, MAXLINE); } /* terminates response headers */ Rio_writen(to_client_fd, "\r\n", 2); int size = 0; int need_cache = 0; /* shall we cache it? */ if (content_len < MAX_OBJECT_SIZE) need_cache = 1; /* init a new cache block */ struct cache_block* blk = (struct cache_block*) malloc(sizeof(struct cache_block)); init_cache(blk); strncpy(blk->uri, uri, MAXLINE); if (content_len > 0) blk->file = (char*) malloc(sizeof(char) * content_len); else blk->file = (char*) malloc(sizeof(char) * MAX_OBJECT_SIZE); memset(buf, 0, MAXLINE); int total_size = 0; char* headptr = blk->file; /* read response contents and write to client */ while ((size = Rio_readnb(&rio_to_server, buf, MAXLINE)) > 0) { total_size += size; if (total_size > MAX_OBJECT_SIZE) need_cache = 0; if (need_cache) { memcpy(headptr, buf, size); headptr += size; } //printf("write3: %s\n", uri); Rio_writen(to_client_fd, buf, size); memset(buf, 0, MAXLINE); } /* add cache block */ if (need_cache) { blk->size = total_size; // resize block blk->file = (char*) realloc(blk->file, blk->size); // size overflow, need to evict using LRU if (blk->size + cache_size > MAX_CACHE_SIZE) evict_cache(head, blk->size); // add it add_cache(head, blk); } /* prevent memory leakage */ else { free_cache_node(blk); } Close(to_server_fd); return; }