Distributed File System written in C
1#include "dnode.h"
2
3// Implement all of the functions for ListDNode and ListDNodeInfo
4ImplList(DNode)
5ImplList(DNodeInfo)
6
7Buffer DNodeInfo_serialize(DNodeInfo dinfo) {
8 return concat(DNode_serialize(dinfo.dnode), concat(UUID_serialize(dinfo.cid), size_t_serialize(dinfo.seq)));
9}
10
11DNodeInfo DNodeInfo_deserialize(Buffer buf) {
12 Buffer tmp = UUID_serialize((UUID){0});
13 free(tmp.buf);
14 DNode dnode = DNode_deserialize((Buffer){ .buf = buf.buf, .len = tmp.len + sizeof(IPv4) + sizeof(Port) });
15 UUID cid = UUID_deserialize((Buffer){ .buf = buf.buf + tmp.len + sizeof(IPv4) + sizeof(Port), .len = tmp.len });
16 size_t seq = size_t_deserialize((Buffer){ .buf = buf.buf + tmp.len + sizeof(IPv4) + sizeof(Port) + tmp.len, .len = sizeof(size_t)});
17
18 return (DNodeInfo){
19 .dnode = dnode,
20 .cid = cid,
21 .seq = seq,
22 };
23}
24
25
26Buffer ListDNodeInfo_serialize(ListDNodeInfo list) {
27 Buffer out = {0};
28 for (ListDNodeInfo lptr = list; lptr != NULL; lptr = lptr->rest) {
29 DNodeInfo d = lptr->head;
30 out = concat(out, DNodeInfo_serialize(d));
31 }
32
33 return out;
34}
35
36ListDNodeInfo ListDNodeInfo_deserialize(Buffer buf) {
37 ListDNodeInfo out = NULL;
38 for (size_t len = 0; len < buf.len; len += sizeof(UUID) + sizeof(IPv4) + sizeof(Port) + sizeof(UUID) + sizeof(size_t)) {
39 out = ListDNodeInfo_cons(DNodeInfo_deserialize((Buffer){
40 .len = 0, // INFO: this does not have to be set.
41 .buf = buf.buf + len,
42 }), out);
43 }
44 return out;
45}
46
47
48Buffer DNode_serialize(DNode dnode) {
49 Buffer uuid_buf = UUID_serialize(dnode.nid);
50 Buffer address_buf = IPv4_serialize(dnode.address);
51 Buffer port_buf = Port_serialize(dnode.port);
52
53 return concat(uuid_buf, concat(address_buf, port_buf));
54}
55
56DNode DNode_deserialize(Buffer buf) {
57 Buffer nid_buf = {
58 .buf = buf.buf,
59 .len = sizeof(UUID),
60 };
61 UUID nid = UUID_deserialize(nid_buf);
62
63 Buffer address_buf = {
64 .buf = buf.buf + sizeof(UUID),
65 .len = sizeof(IPv4),
66 };
67 IPv4 address = IPv4_deserialize(address_buf);
68
69 Buffer port_buf = {
70 .buf = buf.buf + sizeof(UUID) + sizeof(IPv4),
71 .len = sizeof(size_t),
72 };
73 Port port = Port_deserialize(port_buf);
74
75 return (DNode){
76 .nid = nid,
77 .address = address,
78 .port = port,
79 };
80}
81
82Buffer ListDNode_serialize(ListDNode list) {
83 if (list != NULL) return concat(DNode_serialize(list->head), ListDNode_serialize(list->rest));
84 else return (Buffer){ .len = 0, .buf = NULL, };
85}
86
87ListDNode ListDNode_deserialize(Buffer buf) {
88 ListDNode out = NULL;
89 DNode current = {0};
90 for (size_t len = 0; len < buf.len; len += sizeof(IPv4) + sizeof(UUID) + sizeof(Port)) {
91 Buffer tmp = {
92 .len = 0, // INFO: this does not have to be set.
93 .buf = buf.buf + len,
94 };
95 current = DNode_deserialize(tmp);
96 out = ListDNode_cons(current, out);
97 }
98 return ListDNode_reverse(out);
99}
100
101void insert_into_dnode(IPv4 address, Port port) {
102 ListDNode dnodes = DNode_get_db();
103
104 DNode dnode = {
105 .nid = new_uuid(),
106 .address = address,
107 .port = port,
108 };
109
110
111 bool unique = true;
112 for (ListDNode dptr = dnodes; dptr != NULL; dptr = dptr->rest) {
113 DNode d = dptr->head;
114 if (address.ip == d.address.ip && port == d.port)
115 unique = false;
116 }
117
118 if (unique) {
119 log(INFO, "DB: Inserted DNode: ");
120 print_dnode(dnode);
121 printf("\n");
122 dnodes = ListDNode_cons(dnode, dnodes);
123 } else {
124 log(WARN, "DB: Repeated DNode: ");
125 print_dnode(dnode);
126 printf("\n");
127 }
128
129 DNode_set_db(dnodes);
130 ListDNode_deinit(dnodes);
131}
132
133ListDNode select_from_dnode(UUID* nid, IPv4* address, Port* port) {
134 ListDNode out = NULL;
135
136 ListDNode dnodes = DNode_get_db();
137 for (ListDNode dptr = dnodes; dptr != NULL; dptr = dptr->rest) {
138 DNode dnode = dptr->head;
139 if ((nid != NULL ? UUID_eq(*nid, dnode.nid) : true)
140 && (address != NULL ? address->ip == dnode.address.ip : true)
141 && (port != NULL ? *port == dnode.port : true))
142 out = ListDNode_cons(dnode, out);
143 }
144 ListDNode_deinit(dnodes);
145
146 return out;
147}
148
149ListDNode DNode_get_db(void) {
150 FILE* f = fopen(DNODE_TABLE, "r");
151 exists(f);
152
153 Buffer buf = Buffer_read(f);
154 exists(buf.buf);
155
156 ListDNode dnodes = ListDNode_deserialize(buf);
157
158 free(buf.buf);
159 fclose(f);
160 return dnodes;
161}
162
163void DNode_set_db(ListDNode dnodes) {
164 FILE* f = fopen(DNODE_TABLE, "w");
165 exists(f);
166
167 Buffer buf = ListDNode_serialize(dnodes);
168 exists(buf.buf);
169
170 Buffer_write(buf, f);
171
172 free(buf.buf);
173 fclose(f);
174}
175
176void print_dnode(DNode dnode) {
177 printf("(nid: %s, address: %d, port: %d)", utoa(dnode.nid).uuid, dnode.address.ip, dnode.port);
178}
179
180
181ListDNodeInfo insert(ListDNodeInfo l, DNodeInfo a) {
182 if (l == NULL) {
183 return ListDNodeInfo_cons(a, NULL);
184 } else {
185 return l->head.seq > a.seq ?
186 ListDNodeInfo_cons(a, l) :
187 ListDNodeInfo_cons(l->head, insert(l->rest, a));
188 }
189}
190
191ListDNodeInfo sort(ListDNodeInfo l) {
192 ListDNodeInfo acc = NULL;
193 for (;l != NULL; l = l->rest) acc = insert(acc, l->head);
194 return acc;
195}