Skip to content

Carlos lantigua #320

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Binary file added example/sprintf_example
Binary file not shown.
35 changes: 35 additions & 0 deletions example/sprintf_example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <stdio.h>
#include <string.h>

/*
HTTP/1.1 200 OK\n
Date: .... <--- would be here but not in this example
Content-Type: text/html\n
Content-Length: %d\n
Connection: close\n
\n <--- needs to be a new line that separates header from body
<Body goes here>
*/

// Example of how to build a response
int main(void)
{
// buffer to hold the res data
char response[500000];

char *body = "<h1>Hello, world!</h1>";
int length = strlen(body);

// Let's build the actual response now
sprintf(response,
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Content-Length: %d\n"
"Connection: close\n"
"\n"
"%s",
length, body);

printf("%s", response);
return 0;
}
Binary file added example/sscanf_example
Binary file not shown.
27 changes: 27 additions & 0 deletions example/sscanf_example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <stdio.h>

/*
given this request, how do we parse (extract important parts of it) it?
GET /foobar HTTP/1.1
Host: www.example.com
Connection: close

*/

int main(void)
{
char *s = "GET /foobar HTTP/1.1\nHost: www.example.com\nConnection: close\n";

// buffer to hold the method
char method[200];
// buffer to hold the path
char path[8192];

// take some string, supply a format specifier
// %s %s pulls out the first two strings which will be the GET and path
sscanf(s, "%s %s", method, path);

printf("method: %s\n", method);
printf("path: %s\n", path);
return 0;
}
114 changes: 87 additions & 27 deletions src/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,42 @@
#include <string.h>
#include "hashtable.h"
#include "cache.h"

// day 2 stuff
/**
* Allocate a cache entry
*/
struct cache_entry *alloc_entry(char *path, char *content_type, void *content, int content_length)
{
///////////////////
// IMPLEMENT ME! //
///////////////////
// free spaces for cache entry
struct cache_entry *new_entry = malloc(sizeof(struct cache_entry));

// deep copy path
new_entry->path = malloc(strlen(path) + 1);
strcpy(new_entry->path, path);
// deep copy content type
new_entry->content_type = malloc(strlen(content_type) + 1);
strcpy(new_entry->content_type, content_type);
// deep copy content length
new_entry->content_length = malloc(strlen(content_length) + 1);
memcpy(new_entry->content_length, content, content_length);

new_entry->content_length = content_length;
new_entry->prev = new_entry->next = NULL;

return new_entry;
}

/**
* Deallocate a cache entry
*/
void free_entry(struct cache_entry *entry)
{
///////////////////
// IMPLEMENT ME! //
///////////////////
// free entry struct properties
free(entry->content);
free(entry->content_length);
free(entry->content_type);
// free the struct itself
free(entry);
}

/**
Expand All @@ -30,10 +47,13 @@ void free_entry(struct cache_entry *entry)
void dllist_insert_head(struct cache *cache, struct cache_entry *ce)
{
// Insert at the head of the list
if (cache->head == NULL) {
if (cache->head == NULL)
{
cache->head = cache->tail = ce;
ce->prev = ce->next = NULL;
} else {
}
else
{
cache->head->prev = ce;
ce->next = cache->head;
ce->prev = NULL;
Expand All @@ -46,13 +66,16 @@ void dllist_insert_head(struct cache *cache, struct cache_entry *ce)
*/
void dllist_move_to_head(struct cache *cache, struct cache_entry *ce)
{
if (ce != cache->head) {
if (ce == cache->tail) {
if (ce != cache->head)
{
if (ce == cache->tail)
{
// We're the tail
cache->tail = ce->prev;
cache->tail->next = NULL;

} else {
}
else
{
// We're neither the head nor the tail
ce->prev->next = ce->next;
ce->next->prev = ce->prev;
Expand All @@ -65,10 +88,9 @@ void dllist_move_to_head(struct cache *cache, struct cache_entry *ce)
}
}


/**
* Removes the tail from the list and returns it
*
*
* NOTE: does not deallocate the tail
*/
struct cache_entry *dllist_remove_tail(struct cache *cache)
Expand All @@ -85,15 +107,21 @@ struct cache_entry *dllist_remove_tail(struct cache *cache)

/**
* Create a new cache
*
*
* max_size: maximum number of entries in the cache
* hashsize: hashtable size (0 for default)
*/
struct cache *cache_create(int max_size, int hashsize)
{
///////////////////
// IMPLEMENT ME! //
///////////////////
struct cache *new_cache = malloc(sizeof(struct cache));
struct hashtable *hash_table = hashtable_create(hashsize, NULL);

new_cache->head = new_cache->tail = NULL;
new_cache->cur_size = 0;
new_cache->max_size = max_size;
new_cache->index = hash_table;

return new_cache;
}

void cache_free(struct cache *cache)
Expand All @@ -102,7 +130,8 @@ void cache_free(struct cache *cache)

hashtable_destroy(cache->index);

while (cur_entry != NULL) {
while (cur_entry != NULL)
{
struct cache_entry *next_entry = cur_entry->next;

free_entry(cur_entry);
Expand All @@ -117,22 +146,53 @@ void cache_free(struct cache *cache)
* Store an entry in the cache
*
* This will also remove the least-recently-used items as necessary.
*
*
* NOTE: doesn't check for duplicate cache entries
*/
void cache_put(struct cache *cache, char *path, char *content_type, void *content, int content_length)
{
///////////////////
// IMPLEMENT ME! //
///////////////////
// Allocate a new cache entry
struct cache_entry *new_entry = alloc_entry(path, content_type, content, content_length);

// Insert the entry at the head of the dll
dllist_insert_head(cache, new_entry);

// Store the entry into the hashtable
hashtable_put(cache->index, path, new_entry);

// Increment the current size of the cache
cache->cur_size += 1;

// If the cache size is greater than max size
if (cache->cur_size > cache->max_size)
{
// Remove the entry from dll tail
struct cache_entry *old_entry = dllist_remove_tail(cache);
// remove the entry from hash
hashtable_delete(cache->index, old_entry->path);
// Free the cache entry
free_entry(old_entry);
// bring down current size to be no bigger than max size
if (cache->cur_size > cache->max_size)
{
cache->cur_size -= 1;
}
}
}

/**
* Retrieve an entry from the cache
*/
struct cache_entry *cache_get(struct cache *cache, char *path)
{
///////////////////
// IMPLEMENT ME! //
///////////////////
// if entry at index is NULL
if (hashtable_get(cache->index, path) == NULL)
{
return NULL;
}
else
{ // Move entry to head of the dll
dllist_move_to_head(cache, hashtable_get(cache->index, path));
return cache->head;
}
}
12 changes: 7 additions & 5 deletions src/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
#define _WEBCACHE_H_

// Individual hash table entry
struct cache_entry {
char *path; // Endpoint path--key to the cache
struct cache_entry
{ // each entry is a node
char *path; // Endpoint path--key to the cache
char *content_type;
int content_length;
void *content;
Expand All @@ -12,11 +13,12 @@ struct cache_entry {
};

// A cache
struct cache {
struct cache
{
struct hashtable *index;
struct cache_entry *head, *tail; // Doubly-linked list
int max_size; // Maxiumum number of entries
int cur_size; // Current number of entries
int max_size; // Maxiumum number of entries
int cur_size; // Current number of entries
};

extern struct cache_entry *alloc_entry(char *path, char *content_type, void *content, int content_length);
Expand Down
Loading