Skip to content

Commit 06790c3

Browse files
author
Tanner
committed
Merge branch 'dev'
2 parents ce7e33d + fdfc819 commit 06790c3

9 files changed

+556
-92
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ cache
55
tiny/*
66
.proxy/*
77
.noproxy/*
8-
.vscode/*
8+
.vscode/*
9+
requests.txt
10+
requests.log

Makefile

+5-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ csapp.o: csapp.c csapp.h
1616
proxy.o: proxy.c csapp.h
1717
$(CC) $(CFLAGS) -c proxy.c
1818

19-
proxy: proxy.o csapp.o
19+
cache.o: cache.c cache.h
20+
$(CC) $(CFLAGS) -c cache.c
21+
22+
proxy: proxy.o csapp.o cache.o
2023
$(CC) $(CFLAGS) proxy.o csapp.o -o proxy $(LDFLAGS)
24+
2125

2226
# Creates a tarball in ../proxylab-handin.tar that you can then
2327
# hand in. DO NOT MODIFY THIS!

cache.c

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#include "cache.h"
2+
3+
cacheList* initCache() {
4+
cacheList* list = Malloc(sizeof(*list));
5+
list->head = list->tail = NULL;
6+
list->lock = Malloc(sizeof(*(list->lock)));
7+
pthread_rwlock_init((list->lock), NULL);
8+
list->bytesLeft = MAX_CACHE_SIZE;
9+
10+
return list;
11+
}
12+
13+
void deleteCache(cacheList* list) {
14+
if (list) {
15+
cacheNode* tmpHead = list->head;
16+
while (tmpHead) {
17+
cacheNode* tmp = tmpHead;
18+
tmpHead = tmp->next;
19+
deleteNode(tmp);
20+
}
21+
pthread_rwlock_destroy(list->lock);
22+
free(list->lock);
23+
free(list);
24+
}
25+
26+
}
27+
28+
void initNode(cacheNode* node) {
29+
if (node) {
30+
node->next = NULL;
31+
node->prev = NULL;
32+
node->length = 0;
33+
}
34+
}
35+
36+
void setNode(cacheNode* node, char* key, unsigned int length) {
37+
if (node) {
38+
node->key = Malloc(sizeof(char) * length);
39+
memcpy(node->key, key, length);
40+
node->length = length;
41+
}
42+
}
43+
44+
int addNode(cacheNode* node, cacheList* list) {
45+
if (list) {
46+
pthread_rwlock_wrlock(list->lock);
47+
// Make sure there is room for the next object, if not then forget don't add it
48+
if (node != NULL && (node->length < list->bytesLeft)) {
49+
50+
if (!list->tail) {
51+
list->head = list->tail = node;
52+
}
53+
else {
54+
list->tail->next = node;
55+
node->prev = list->tail;
56+
list->tail = node;
57+
}
58+
59+
list->bytesLeft -= node->length;
60+
}
61+
else {
62+
pthread_rwlock_unlock(list->lock);
63+
return -1;
64+
}
65+
pthread_rwlock_unlock(list->lock);
66+
}
67+
return 0;
68+
}
69+
70+
void deleteNode(cacheNode* node) {
71+
if (node) {
72+
// Free the arrays inside the node first then free the node up
73+
if (node->key) {
74+
free(node->key);
75+
}
76+
if (node->value) {
77+
free(node->value);
78+
}
79+
free(node);
80+
}
81+
}
82+
83+
cacheNode* findNode(cacheList* list, char* key) {
84+
if (list) {
85+
cacheNode* tmp = list->head;
86+
while (tmp) {
87+
if (strcmp(tmp->key, key) == 0) {
88+
return tmp;
89+
}
90+
91+
tmp = tmp->next;
92+
}
93+
}
94+
return NULL;
95+
}
96+
97+
int readNodeContent(cacheList* list, char* key, char* value, unsigned int *len) {
98+
if (!list) {
99+
return -1;
100+
}
101+
102+
pthread_rwlock_rdlock(list->lock);
103+
104+
cacheNode* tmp = findNode(list, key);
105+
106+
if (!tmp) {
107+
pthread_rwlock_unlock(list->lock);
108+
return -1;
109+
}
110+
111+
*len = tmp->length;
112+
memcpy(value, tmp->value, *len);
113+
pthread_rwlock_unlock(list->lock);
114+
115+
return 0;
116+
117+
}
118+
119+
int insertNodeContent(cacheList* list, char* key, char* value, unsigned int len) {
120+
if (!list) {
121+
return -1;
122+
}
123+
124+
cacheNode* tmp = Malloc(sizeof(*tmp));
125+
initNode(tmp);
126+
setNode(tmp, key, len);
127+
128+
if (!tmp) {
129+
return -1;
130+
}
131+
132+
tmp->value = Malloc(sizeof(char) * len);
133+
memcpy(tmp->value, value, len);
134+
if (addNode(tmp, list) == -1) {
135+
deleteNode(tmp);
136+
return -2;
137+
}
138+
139+
return 0;
140+
}

cache.h

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#ifndef __CACHE_H__
2+
#define __CACHE_H__
3+
4+
#include "csapp.h"
5+
#include <pthread.h>
6+
7+
#define MAX_CACHE_SIZE 1049000
8+
#define MAX_OBJECT_SIZE 102400
9+
10+
/*
11+
* A cacheNode is a response (value) from a web server
12+
* that is connected with a particular request (key)
13+
*/
14+
typedef struct cacheNode {
15+
char* key;
16+
char* value;
17+
struct cacheNode* prev;
18+
struct cacheNode* next;
19+
unsigned int length;
20+
} cacheNode;
21+
22+
/*
23+
* A cache is a linked list of cacheNodes
24+
*/
25+
typedef struct cacheList {
26+
cacheNode* head;
27+
cacheNode* tail;
28+
pthread_rwlock_t* lock;
29+
unsigned int bytesLeft;
30+
} cacheList;
31+
32+
cacheList* initCache();
33+
void deleteCache(cacheList* list);
34+
void initNode(cacheNode* node);
35+
void setNode(cacheNode* node, char* index, unsigned int length);
36+
int addNode(cacheNode* node, cacheList* list);
37+
void deleteNode(cacheNode* node);
38+
cacheNode* findNode(cacheList* list, char* index);
39+
40+
int readNodeContent(cacheList* list, char* index, char* content, unsigned int *len);
41+
int insertNodeContent(cacheList* list, char* index, char* content, unsigned int len);
42+
43+
44+
#endif

driver.sh

+38-12
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
# - Check maximum cache object size
1717

1818

19-
if [ -z "$6" ]; then
20-
echo "Usage: $0 <mode> <basic_pts> <concurrency_pts> <log_pts> <cleanup_pts> <cache_pts>"
19+
if [ -z "$7" ]; then
20+
echo "Usage: $0 <mode> <basic_pts> <concurrency_pts> <log_pts> <mem_mgmt_pts> <cleanup_pts> <cache_pts>"
2121
exit
2222
fi
2323

@@ -26,13 +26,14 @@ MODE=$1
2626
MAX_BASIC=$2
2727
MAX_CONCURRENCY=$3
2828
MAX_LOG=$4
29-
MAX_CLEANUP=$5
30-
MAX_CACHE=$6
29+
MAX_MEM_MGMT=$5
30+
MAX_CLEANUP=$6
31+
MAX_CACHE=$7
3132

3233
if [ $MODE != "multiprocess" -a $MODE != "processpool" -a \
3334
$MODE != "multithread" -a $MODE != "threadpool" -a \
3435
$MODE != "epoll" ]; then
35-
echo "Usage: $0 <mode> <basic_pts> <concurrency_pts> <log_pts> <cleanup_pts> <cache_pts>"
36+
echo "Usage: $0 <mode> <basic_pts> <concurrency_pts> <log_pts> <mem_mgmt_pts> <cleanup_pts> <cache_pts>"
3637
echo "mode should be one of: multiprocess, processpool, multithread, threadpool, epoll"
3738
exit
3839
fi
@@ -91,7 +92,7 @@ function download_proxy {
9192
cd $1
9293
curl --max-time ${TIMEOUT} --silent --proxy $4 --output $2 $3
9394
(( $? == 28 )) && echo "Error: Fetch timed out after ${TIMEOUT} seconds"
94-
cd $HOME_DIR
95+
cd "$HOME_DIR"
9596
}
9697

9798
#
@@ -100,9 +101,9 @@ function download_proxy {
100101
#
101102
function download_proxy_slow {
102103
cd $1
103-
$HOME_DIR/slow-client.py $4 $3 1 ${TIMEOUT} $2
104+
"$HOME_DIR"/slow-client.py $4 $3 1 ${TIMEOUT} $2
104105
(( $? == 1 )) && echo "Error: Fetch timed out after ${TIMEOUT} seconds"
105-
cd $HOME_DIR
106+
cd "$HOME_DIR"
106107
}
107108

108109
#
@@ -113,7 +114,7 @@ function download_noproxy {
113114
cd $1
114115
curl --max-time ${TIMEOUT} --silent --output $2 $3
115116
(( $? == 28 )) && echo "Error: Fetch timed out after ${TIMEOUT} seconds"
116-
cd $HOME_DIR
117+
cd "$HOME_DIR"
117118
}
118119

119120
#
@@ -239,6 +240,26 @@ then
239240
exit
240241
fi
241242

243+
# Make sure we have an existing executable slow-client.py file
244+
if [ ! -x ./slow-client.py ]
245+
then
246+
echo "Error: ./slow-client.py not found or not an executable file."
247+
exit
248+
fi
249+
250+
# At the moment, slow-client.py requires python2
251+
if ! python -V 2>&1 | grep -q "^Python 2"
252+
then
253+
echo "Error: ./slow-client.py requires python version 2."
254+
exit
255+
fi
256+
257+
# Check for valgrind
258+
if ! valgrind -h > /dev/null
259+
then
260+
exit
261+
fi
262+
242263
# Create the test directories if needed
243264
if [ ! -d ${PROXY_DIR} ]
244265
then
@@ -284,6 +305,9 @@ proxy_pid=$!
284305
# Wait for the proxy to start in earnest
285306
wait_for_port_use "${proxy_port}"
286307

308+
# Wait for threads to be initialized
309+
sleep 3
310+
287311
num_threads_pre=`ps --no-headers -Lo lwp --pid $proxy_pid | sort -u | wc -l`
288312
num_processes_pre=`ps --no-headers -o pid --pid $proxy_pid --ppid $proxy_pid | sort -u | wc -l`
289313

@@ -376,8 +400,9 @@ echo "logScore: $logScore/${MAX_LOG}"
376400
#
377401

378402
echo ""
379-
echo "*** Cleanup ***"
403+
echo "*** Memory management and Cleanup ***"
380404

405+
memmgmtScore=${MAX_MEM_MGMT}
381406
cleanupScore=${MAX_CLEANUP}
382407
def_lost=`grep 'definitely lost:' $VALGRIND_LOG | awk '{ print $4 }'`
383408
indir_lost=`grep 'indirectly lost:' $VALGRIND_LOG | awk '{ print $4 }'`
@@ -390,14 +415,15 @@ if [ \( -n "$def_lost" -a "$def_lost" != "0" \) -o \
390415
\( -n "$indir_lost" -a "$indir_lost" != "0" \) -o \
391416
\( -n "$poss_lost" -a "$poss_lost" != "0" \) ]; then
392417
echo " Bytes lost, either definitely, indirectly, or possibly"
393-
cleanupScore=`expr ${cleanupScore} - "(" ${MAX_CLEANUP} / 2 ")"`
418+
memmgmtScore=`expr ${memmgmtScore} - ${MAX_MEM_MGMT}`
394419
fi
395420

396421
if [ -n "$still_reach" -a "$still_reach" != "0" ]; then
397422
echo " Bytes still reachable"
398-
cleanupScore=`expr ${cleanupScore} - "(" ${MAX_CLEANUP} / 2 ")"`
423+
cleanupScore=`expr ${cleanupScore} - ${MAX_CLEANUP}`
399424
fi
400425

426+
echo "memmgmtScore: $memmgmtScore/${MAX_MEM_MGMT}"
401427
echo "cleanupScore: $cleanupScore/${MAX_CLEANUP}"
402428

403429
######

0 commit comments

Comments
 (0)