#include "dnode.h" // Implement all of the functions for ListDNode and ListDNodeInfo ImplList(DNode) ImplList(DNodeInfo) Buffer DNodeInfo_serialize(DNodeInfo dinfo) { return concat(DNode_serialize(dinfo.dnode), concat(UUID_serialize(dinfo.cid), size_t_serialize(dinfo.seq))); } DNodeInfo DNodeInfo_deserialize(Buffer buf) { Buffer tmp = UUID_serialize((UUID){0}); free(tmp.buf); DNode dnode = DNode_deserialize((Buffer){ .buf = buf.buf, .len = tmp.len + sizeof(IPv4) + sizeof(Port) }); UUID cid = UUID_deserialize((Buffer){ .buf = buf.buf + tmp.len + sizeof(IPv4) + sizeof(Port), .len = tmp.len }); size_t seq = size_t_deserialize((Buffer){ .buf = buf.buf + tmp.len + sizeof(IPv4) + sizeof(Port) + tmp.len, .len = sizeof(size_t)}); return (DNodeInfo){ .dnode = dnode, .cid = cid, .seq = seq, }; } Buffer ListDNodeInfo_serialize(ListDNodeInfo list) { Buffer out = {0}; for (ListDNodeInfo lptr = list; lptr != NULL; lptr = lptr->rest) { DNodeInfo d = lptr->head; out = concat(out, DNodeInfo_serialize(d)); } return out; } ListDNodeInfo ListDNodeInfo_deserialize(Buffer buf) { ListDNodeInfo out = NULL; for (size_t len = 0; len < buf.len; len += sizeof(UUID) + sizeof(IPv4) + sizeof(Port) + sizeof(UUID) + sizeof(size_t)) { out = ListDNodeInfo_cons(DNodeInfo_deserialize((Buffer){ .len = 0, // INFO: this does not have to be set. .buf = buf.buf + len, }), out); } return out; } Buffer DNode_serialize(DNode dnode) { Buffer uuid_buf = UUID_serialize(dnode.nid); Buffer address_buf = IPv4_serialize(dnode.address); Buffer port_buf = Port_serialize(dnode.port); return concat(uuid_buf, concat(address_buf, port_buf)); } DNode DNode_deserialize(Buffer buf) { Buffer nid_buf = { .buf = buf.buf, .len = sizeof(UUID), }; UUID nid = UUID_deserialize(nid_buf); Buffer address_buf = { .buf = buf.buf + sizeof(UUID), .len = sizeof(IPv4), }; IPv4 address = IPv4_deserialize(address_buf); Buffer port_buf = { .buf = buf.buf + sizeof(UUID) + sizeof(IPv4), .len = sizeof(size_t), }; Port port = Port_deserialize(port_buf); return (DNode){ .nid = nid, .address = address, .port = port, }; } Buffer ListDNode_serialize(ListDNode list) { if (list != NULL) return concat(DNode_serialize(list->head), ListDNode_serialize(list->rest)); else return (Buffer){ .len = 0, .buf = NULL, }; } ListDNode ListDNode_deserialize(Buffer buf) { ListDNode out = NULL; DNode current = {0}; for (size_t len = 0; len < buf.len; len += sizeof(IPv4) + sizeof(UUID) + sizeof(Port)) { Buffer tmp = { .len = 0, // INFO: this does not have to be set. .buf = buf.buf + len, }; current = DNode_deserialize(tmp); out = ListDNode_cons(current, out); } return ListDNode_reverse(out); } void insert_into_dnode(IPv4 address, Port port) { ListDNode dnodes = DNode_get_db(); DNode dnode = { .nid = new_uuid(), .address = address, .port = port, }; bool unique = true; for (ListDNode dptr = dnodes; dptr != NULL; dptr = dptr->rest) { DNode d = dptr->head; if (address.ip == d.address.ip && port == d.port) unique = false; } if (unique) { log(INFO, "DB: Inserted DNode: "); print_dnode(dnode); printf("\n"); dnodes = ListDNode_cons(dnode, dnodes); } else { log(WARN, "DB: Repeated DNode: "); print_dnode(dnode); printf("\n"); } DNode_set_db(dnodes); ListDNode_deinit(dnodes); } ListDNode select_from_dnode(UUID* nid, IPv4* address, Port* port) { ListDNode out = NULL; ListDNode dnodes = DNode_get_db(); for (ListDNode dptr = dnodes; dptr != NULL; dptr = dptr->rest) { DNode dnode = dptr->head; if ((nid != NULL ? UUID_eq(*nid, dnode.nid) : true) && (address != NULL ? address->ip == dnode.address.ip : true) && (port != NULL ? *port == dnode.port : true)) out = ListDNode_cons(dnode, out); } ListDNode_deinit(dnodes); return out; } ListDNode DNode_get_db(void) { FILE* f = fopen(DNODE_TABLE, "r"); exists(f); Buffer buf = Buffer_read(f); exists(buf.buf); ListDNode dnodes = ListDNode_deserialize(buf); free(buf.buf); fclose(f); return dnodes; } void DNode_set_db(ListDNode dnodes) { FILE* f = fopen(DNODE_TABLE, "w"); exists(f); Buffer buf = ListDNode_serialize(dnodes); exists(buf.buf); Buffer_write(buf, f); free(buf.buf); fclose(f); } void print_dnode(DNode dnode) { printf("(nid: %s, address: %d, port: %d)", utoa(dnode.nid).uuid, dnode.address.ip, dnode.port); } ListDNodeInfo insert(ListDNodeInfo l, DNodeInfo a) { if (l == NULL) { return ListDNodeInfo_cons(a, NULL); } else { return l->head.seq > a.seq ? ListDNodeInfo_cons(a, l) : ListDNodeInfo_cons(l->head, insert(l->rest, a)); } } ListDNodeInfo sort(ListDNodeInfo l) { ListDNodeInfo acc = NULL; for (;l != NULL; l = l->rest) acc = insert(acc, l->head); return acc; }