Skip to content

Commit 1f0a4ac

Browse files
committed
lru cache
1 parent 98a6786 commit 1f0a4ac

File tree

10 files changed

+341
-124
lines changed

10 files changed

+341
-124
lines changed

proxylab-handout/Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ all: proxy
1515
%.o: %.c
1616
$(CC) $(CFLAGS) -c $<
1717

18-
H_FILES = util.h dstring.h csapp.h
18+
H_FILES = util.h bytes.h csapp.h cache.h
1919

20-
OBJ_SRC = csapp.c dstring.c util.c
20+
OBJ_SRC = csapp.c bytes.c util.c cache.c
2121

2222
PROXY_SRC = $(OBJ_SRC) proxy.c
2323

2424
PROXY_OBJ = $(PROXY_SRC:%c=%o)
2525

2626

2727
proxy: $(PROXY_OBJ) $(H_FILES)
28-
$(CC) $(LDFLAGS) $(PROXY_OBJ) -o $@
28+
$(CC) $(CFLAGS) $(LDFLAGS) $(PROXY_OBJ) -o $@
2929

3030
TEST_SRC = $(OBJ_SRC) test.c
3131

3232
TEST_OBJ = $(TEST_SRC:%c=%o)
3333

3434
test: $(TEST_OBJ) $(H_FILES)
35-
$(CC) $(LDFLAGS) $(TEST_OBJ) -o $@
35+
$(CC) $(CFLAGS) $(LDFLAGS) $(TEST_OBJ) -o $@
3636

3737
# Creates a tarball in ../proxylab-handin.tar that you should then
3838
# hand in to Autolab. DO NOT MODIFY THIS!

proxylab-handout/bytes.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include "bytes.h"
2+
#include <string.h>
3+
4+
#define DEFAULT_LENGTH 1024
5+
6+
void bytes_malloc(Bytes *pstr)
7+
{
8+
pstr->size = DEFAULT_LENGTH;
9+
pstr->buf = (char *)malloc(pstr->size * sizeof(char));
10+
pstr->len = 0;
11+
}
12+
13+
void bytes_free(Bytes *pstr)
14+
{
15+
pstr->len = 0;
16+
pstr->size = 0;
17+
free(pstr->buf);
18+
}
19+
20+
/* ceil_divide: a divide by b, return ceil value
21+
* Assert a > b.
22+
*/
23+
inline static size_t ceil_divide(size_t a, size_t b)
24+
{
25+
size_t m = 2;
26+
for (m = 2; m * b < a; m+=1) {}
27+
return m;
28+
}
29+
30+
/* bytes_append : append cstr to the end of pstr.
31+
* Assert cstr and pstr is not overlapped.
32+
*
33+
* TODO: support overlapping
34+
*/
35+
void bytes_append(Bytes *pstr, const char *cstr)
36+
{
37+
size_t cstr_len = strlen(cstr);
38+
bytes_appendn(pstr, cstr, cstr_len);
39+
}
40+
41+
void bytes_appendn(Bytes *pstr, const char *buf, size_t buf_len)
42+
{
43+
if (pstr->len + buf_len + 1 <= pstr->size) {
44+
int i;
45+
for (i = 0; i < buf_len; i++) {
46+
pstr->buf[pstr->len+i] = buf[i];
47+
}
48+
pstr->len += buf_len;
49+
} else {
50+
size_t multipler = ceil_divide((buf_len + pstr->len + 1),
51+
pstr->size);
52+
size_t new_size = multipler * pstr->size;
53+
char *new_buf = (char *)malloc(new_size*sizeof(char));
54+
int i;
55+
for (i = 0; i < pstr->len; i++) {
56+
new_buf[i] = pstr->buf[i];
57+
}
58+
for (i = 0; i < buf_len; i++) {
59+
new_buf[pstr->len+i] = buf[i];
60+
}
61+
pstr->len += buf_len;
62+
pstr->size = new_size;
63+
pstr->buf = new_buf;
64+
}
65+
}
66+
67+
/* return bytes as a cstr */
68+
void bytes_cstr(Bytes str, char *cstr)
69+
{
70+
for (int i = 0; i < str.len; i++) {
71+
cstr[i] = str.buf[i];
72+
}
73+
cstr[str.len] = '\0';
74+
}

proxylab-handout/bytes.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#ifndef __DBYTES_H__
2+
#define __DBYTES_H__
3+
4+
#include <stdlib.h>
5+
6+
typedef struct Bytes {
7+
char *buf;
8+
size_t size; /* content size */
9+
size_t len; /* bytes length */
10+
} Bytes;
11+
12+
#define bytes_length(str) ((str).len)
13+
#define bytes_buf(str) ((str).buf)
14+
#define bytes_size(str) ((str).size)
15+
#define bytes_ref(str, i) (bytes_buf(str)[(i)])
16+
17+
void bytes_malloc(Bytes *pstr);
18+
19+
void bytes_free(Bytes *pstr);
20+
21+
void bytes_append(Bytes *pstr, const char *cstr);
22+
void bytes_appendn(Bytes *pstr, const char *buf, size_t buf_len);
23+
24+
void bytes_cstr(Bytes str, char *cstr);
25+
26+
#endif

proxylab-handout/cache.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#include "cache.h"
2+
3+
#define node_cache_size(pnode) (((pnode)->value_len)*sizeof(char))
4+
5+
static lru_cache_node_t *create_empty_node()
6+
{
7+
lru_cache_node_t *pnode = (lru_cache_node_t*)Malloc(sizeof(lru_cache_node_t));
8+
pnode->value_len = 0;
9+
pnode->key[0] = '\0';
10+
pnode->value = NULL;
11+
pnode->next = NULL;
12+
pnode->prev = NULL;
13+
return pnode;
14+
}
15+
16+
static void free_node(lru_cache_node_t *pnode)
17+
{
18+
free(pnode->value);
19+
free(pnode);
20+
}
21+
static lru_cache_node_t *create_node_from(
22+
const char *key,
23+
const char *value,
24+
size_t value_len)
25+
{
26+
lru_cache_node_t *pnode = create_empty_node();
27+
pnode->value = (char *)malloc(value_len*sizeof(char));
28+
pnode->value_len = value_len;
29+
strcpy(pnode->key, key);
30+
for (int i = 0; i < value_len; i++) {
31+
pnode->value[i] = value[i];
32+
}
33+
return pnode;
34+
}
35+
36+
void lru_cache_init(lru_cache_t *pcache, size_t max_cache_size)
37+
{
38+
pcache->max_cache_size = max_cache_size;
39+
pcache->sentinel = create_empty_node();
40+
pcache->sentinel->next = pcache->sentinel;
41+
pcache->sentinel->prev = pcache->sentinel;
42+
}
43+
44+
void lru_cache_free(lru_cache_t *pcache)
45+
{
46+
lru_cache_node_t *cur, *next = NULL;
47+
cur = pcache->sentinel->next;
48+
while (cur != pcache->sentinel) {
49+
next = cur->next;
50+
free_node(cur);
51+
cur = next;
52+
}
53+
free_node(pcache->sentinel);
54+
}
55+
56+
57+
static inline void lru_cache_insert_next(lru_cache_t *pcache,
58+
lru_cache_node_t *prev,
59+
lru_cache_node_t *pnode)
60+
{
61+
62+
pnode->next = prev->next;
63+
pnode->prev = prev;
64+
prev->next->prev = pnode;
65+
prev->next = pnode;
66+
pcache->cache_size += node_cache_size(pnode);
67+
}
68+
69+
static inline void lru_cache_remove(lru_cache_t *pcache,
70+
lru_cache_node_t *cur)
71+
{
72+
cur->prev->next = cur->next;
73+
cur->next->prev = cur->prev;
74+
pcache->cache_size -= node_cache_size(cur);
75+
}
76+
77+
/*
78+
* assert prev->next != NULL
79+
*/
80+
static void lru_cache_raise(lru_cache_t *pcache, lru_cache_node_t *cur)
81+
{
82+
// remove the node
83+
lru_cache_remove(pcache, cur);
84+
lru_cache_insert_next(pcache, pcache->sentinel, cur);
85+
}
86+
87+
lru_cache_node_t *lru_cache_find(lru_cache_t *pcache, const char *key)
88+
{
89+
for (lru_cache_node_t *cur = pcache->sentinel->next;
90+
cur != pcache->sentinel; cur = cur->next) {
91+
if (strcasecmp(cur->key, key) == 0) {
92+
lru_cache_raise(pcache, cur);
93+
return cur;
94+
}
95+
}
96+
return NULL;
97+
}
98+
99+
void lru_cache_insert(lru_cache_t *pcache,
100+
const char *key,
101+
const char *value,
102+
size_t value_len)
103+
{
104+
lru_cache_node_t *pnode = create_node_from(key, value, value_len);
105+
lru_cache_insert_next(pcache, pcache->sentinel, pnode);
106+
while (pcache->cache_size > pcache->max_cache_size) {
107+
lru_cache_remove(pcache, lru_cache_tail(pcache));
108+
}
109+
}

proxylab-handout/cache.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef __CACHE_H__
2+
#define __CACHE_H__
3+
4+
#include "csapp.h"
5+
6+
typedef struct lru_cache_node_t {
7+
char *value;
8+
size_t value_len;
9+
// for simplicity, assume key is a null terminated string
10+
char key[MAXLINE];
11+
struct lru_cache_node_t *next;
12+
struct lru_cache_node_t *prev;
13+
} lru_cache_node_t;
14+
15+
typedef struct lru_cache_t {
16+
size_t max_cache_size;
17+
lru_cache_node_t *sentinel;
18+
lru_cache_node_t *front; /* front points to most recently used */
19+
// lru_cache_node_t *tail; /* tail points to least recently used */
20+
size_t cache_size;
21+
} lru_cache_t;
22+
23+
void lru_cache_init(lru_cache_t *pcache, size_t max_cache_size);
24+
void lru_cache_free(lru_cache_t *pcache);
25+
26+
lru_cache_node_t *lru_cache_find(lru_cache_t *pcache, const char *key);
27+
28+
void lru_cache_insert(lru_cache_t *pcache, const char *key, const char *value, size_t value_len);
29+
30+
#define lru_cache_tail(pcache) ((pcache)->sentinel->prev)
31+
32+
#endif

proxylab-handout/dstring.c

Lines changed: 0 additions & 67 deletions
This file was deleted.

proxylab-handout/dstring.h

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)