-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathapp_driver.c
322 lines (262 loc) · 7.52 KB
/
app_driver.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
#include <stdlib.h>
#include <stdio.h>
#include "chord_types.h"
#include "ring.h"
#include "util.h"
/**
* @TODO:
* check all functions are called
* check memory leaks
* * "accept list of peers and build a chord ring for these peers"
* * "print chord topology figure showing node ID locations (see L5 S10)"
* * "print the content of any node in the ring"
* - "insert and retrieve documents into/from the network:"
* - "a list of documents will be given to the program, and the program should be able
* to allocate these documents to nodes using chord strategies."
* * "Design your own hash functions. You may use file names as the input for hashing."
* - "accept a text query in terms of file name and reply with:"
* - "Print all nodes containing answer and the adopted route for transferring the data" or
* - "Print a message indicating a query answer is not found"
*
* - "You need to demonstrate both code and simulation results. Your report should have enough
* sample simulation results to demonstrate that you have met all required specifications and features."
*
* Part III: Reliability
* - "your program should allow a random number of nodes in joining in, departing, failure etc"
*/
char* random_string(int length);
void do_main_menu();
void do_node_add();
void do_node_print();
void do_node_leave();
void do_node_fail();
Node *do_node_get();
void do_document_add();
void do_document_query();
void do_ring_print();
void do_stabilise_node();
void do_fix_fingers();
void do_node_add_random(int num);
int main(int argc, char *argv[]) {
do_main_menu();
FooWidget *fw;
return EXIT_SUCCESS;
}
void do_node_add_random(int num) {
char *node_id;
int i;
Node *new_node;
Ring *ring = ring_get();
for (i = 0; i < num; i++) {
node_id = random_string(NODE_ID_LENGTH);
/*node_id = random_string(3);*/
new_node = node_init(node_id);
printf("%s\n", node_id);
if (ring_size() == 1) {
/* first node added. create the ring */
node_create(new_node);
}
else {
node_join(ring->nodes[0], new_node);
node_stabilise(new_node);
node_fix_fingers(new_node);
/* update chord ring if necessary */
if (new_node->key < ring->first_node->key) {
ring->first_node = new_node;
}
if (new_node->key > ring->last_node->key) {
ring->last_node = new_node;
}
ring_stabilise_all();
}
}
}
void do_main_menu() {
char *prompt = "> ";
int exit = FALSE;
int option;
while (!exit) {
printf("\nMain Menu:\n");
printf("1) Add node\n");
printf("2) Add document\n");
printf("3) Query document\n");
printf("4) Print ring\n");
printf("5) Print node\n");
printf("6) Node leave\n");
printf("7) Node fail\n");
printf("8) Stabilise node\n");
printf("9) Fix fingers\n");
printf("10) Stabilise and fix fingers on all nodes\n");
printf("11) Print all nodes\n");
printf("12) Add %d random nodes\n", NUM_RANDOM_NODES);
printf("13) Exit\n\n");
getInteger(&option, MAX_OPTION_INPUT_LENGTH, prompt, OPTION_MIN, OPTION_MAX);
switch (option) {
case 1:
do_node_add();
break;
case 2:
do_document_add();
break;
case 3:
do_document_query();
break;
case 4:
do_ring_print();
break;
case 5:
do_node_print();
break;
case 6:
do_node_leave();
break;
case 7:
do_node_fail();
break;
case 8:
do_stabilise_node();
break;
case 9:
do_fix_fingers();
break;
case 10:
ring_stabilise_all();
break;
case 11:
ring_print_all(FALSE, TRUE);
break;
case 12:
do_node_add_random(NUM_RANDOM_NODES);
break;
case 13:
exit = TRUE;
}
option = 0;
}
}
void do_stabilise_node() {
Node *node = do_node_get("Select node: ");
if (node != NULL) {
node_stabilise(node);
printf("\nNode %s stabilised.\n", node->id);
}
}
void do_fix_fingers() {
Node *node = do_node_get("Select node: ");
if (node != NULL) {
node_fix_fingers(node);
printf("\nNode %s finger tables fixed.\n", node->id);
}
}
Node *do_node_get(char* prompt) {
Node *node = NULL;
int node_idx = -100;
int node_idx_max = ring_size();
if (node_idx_max != 0) {
do {
ring_print(TRUE, FALSE);
getInteger(&node_idx, MAX_NODE_IDX, prompt, NODE_IDX_MIN, node_idx_max);
if (node_idx == RETURN_TO_MENU) {
break;
}
node = ring_get_node(node_idx);
} while (node == NULL);
}
else {
D1("Ring is empty");
}
return node;
}
void do_node_add() {
char *prompt = "Enter node ID in hex, max 10 chars: ";
char *new_node_id;
Node *new_node = NULL, *existing_node = NULL;
Ring *ring = ring_get();
if ((new_node_id = malloc(sizeof(char) * NODE_ID_LENGTH)) == NULL) {
BAIL("Failed to create node ID string");
}
getString(new_node_id, NODE_ID_LENGTH, prompt);
new_node = node_init(new_node_id);
if (ring_size() == 1) {
/* first node added. create the ring */
node_create(new_node);
}
else {
/* get node to join */
existing_node = do_node_get("Select node to join to: ");
if (existing_node == NULL) {
D1("Could not get node");
}
else {
D2("Joining to node", existing_node->id);
node_join(existing_node, new_node);
node_stabilise(new_node);
node_fix_fingers(new_node);
/* update chord ring if necessary */
if (new_node->key < ring->first_node->key) {
ring->first_node = new_node;
}
if (new_node->key > ring->last_node->key) {
ring->last_node = new_node;
}
ring_stabilise_all();
}
}
}
void do_node_print() {
Node *node = do_node_get("Select node: ");
printf("\n");
printf("%-4s %-11s %-5s %-5s %-7s\n", "Key", "ID", "Pred", "Succ", "# Docs");
printf("---- ----------- ----- ----- -------\n");
node_print(node);
printf("---- ----------- ----- ----- -------\n");
node_print_finger_table(node);
node_print_documents(node);
}
void do_node_leave() {
}
void do_node_fail() {
}
void do_document_add() {
Node *node;
char *prompt = "Enter document name: ";
char doc_filename[FILENAME_MAX_LENGTH];
Document *doc;
char doc_data[TEMP_STRING_LENGTH];
node = do_node_get("Select node context: ");
getString(doc_filename, FILENAME_MAX_LENGTH, prompt);
prompt = "Enter document data: ";
getString(doc_data, FILENAME_MAX_LENGTH, prompt);
if ((doc = malloc(sizeof(Document))) == NULL) {
BAIL("Failed to allocate memory for Document");
}
strcpy(doc->filename, doc_filename);
strcpy(doc->data, doc_data);
doc->key = chord_hash(doc_filename);
node_document_add(node, doc);
}
void do_document_query() {
Node *ctx_node;
char *prompt = "Enter document filename: ";
char doc_filename[FILENAME_MAX_LENGTH];
ctx_node = do_node_get("Select node to perform search from: ");
getString(doc_filename, FILENAME_MAX_LENGTH, prompt);
node_document_query(ctx_node, doc_filename);
}
void do_ring_print() {
ring_print(FALSE, FALSE);
}
char* random_string(int length) {
char *random;
int i, c;
char *chars = "abcdef0123456789";
/* allocate mem for random string */
if ((random = malloc(sizeof(char) * length)) == NULL) {
BAIL("Failed to allocate memory for random string");
}
for (i = 0; i < length; i++) {
c = (int) (rand() % strlen(chars));
random[i] = chars[c];
}
return random;
}