Distributed File System written in C
at main 4.8 kB view raw
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}