From a36ba20557573af5d7c3a324ceb2044ca894f443 Mon Sep 17 00:00:00 2001 From: jmjatlanta Date: Mon, 12 Dec 2016 16:58:27 -0500 Subject: [PATCH] made node links a single linked list instead of array This will save some complicated memory allocations --- include/ipfs/node/Example for this.c | 6 +- include/ipfs/node/node.h | 12 +- node/node.c | 174 ++++++++++++++------------- test/merkledag/test_merkledag.h | 29 ++--- test/node/test_node.h | 49 +++----- 5 files changed, 126 insertions(+), 144 deletions(-) diff --git a/include/ipfs/node/Example for this.c b/include/ipfs/node/Example for this.c index 1cf7d4a..1ec8f98 100644 --- a/include/ipfs/node/Example for this.c +++ b/include/ipfs/node/Example for this.c @@ -46,12 +46,12 @@ int main(int argc, char** argv) struct Node * Mynode; Mynode = N_Create_From_Link(mylink); mylink->name = "HAHA";//Testing for valid node creation - printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->links[0]->name, Mynode->links[0]->Lcid->hash); + printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->head_link[0]->name, Mynode->head_link[0]->Lcid->hash); //N_Add_Link Mynode = N_Add_Link(&Mynode, mylink2, sizeof(mylink2)); mylink2->name = "HAHA";//Testing for valid node creation - printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->links[1]->name,Mynode->links[1]->Lcid->hash); + printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->head_link[1]->name,Mynode->head_link[1]->Lcid->hash); //Node_Get_Link struct Link * ResultLink = Node_Get_Link(Mynode, "Simo"); @@ -74,7 +74,7 @@ int main(int argc, char** argv) //Node Copy struct Node * Node2; Node2 = Node_Copy(Mynode); - printf("NODE COPY TEST: [0]: %s\n", Node2->links[0]->Lcid->hash); + printf("NODE COPY TEST: [0]: %s\n", Node2->head_link[0]->Lcid->hash); Node_Delete(Node2); //Node_Set_Data diff --git a/include/ipfs/node/node.h b/include/ipfs/node/node.h index c8272f1..56990fe 100644 --- a/include/ipfs/node/node.h +++ b/include/ipfs/node/node.h @@ -17,6 +17,7 @@ struct NodeLink { char* name; struct Cid * cid; + struct NodeLink* next; }; struct Node @@ -25,8 +26,7 @@ struct Node size_t data_size; unsigned char* encoded; struct Cid* cached; - int link_amount; - struct NodeLink* links[]; + struct NodeLink* head_link; }; /*==================================================================================== @@ -123,12 +123,6 @@ int ipfs_node_set_encoded(struct Node * N, unsigned char * Data); */ unsigned char * ipfs_node_get_data(struct Node * N); -/*ipfs_node_copy: Returns a copy of the node you input - * @param Node: The node you want to copy (struct CP_Node *) - * Returns a copy of the node you wanted to copy. - */ -struct Node * ipfs_node_copy(struct Node * CP_Node); - /*ipfs_node_free * Once you are finished using a node, always delete it using this. * It will take care of the links inside it. @@ -157,7 +151,7 @@ int ipfs_node_remove_link_by_name(char * Name, struct Node * mynode); * @param linksz: sizeof(your cid here) * Returns your node with the newly added link */ -struct Node * ipfs_node_add_link(struct Node ** mynode, struct NodeLink * mylink, size_t linksz); +int ipfs_node_add_link(struct Node * mynode, struct NodeLink * mylink); /*ipfs_node_new_from_link * Create a node from a link diff --git a/node/node.c b/node/node.c index 8b339eb..8d037f2 100644 --- a/node/node.c +++ b/node/node.c @@ -30,6 +30,7 @@ int ipfs_node_link_new(char * name, unsigned char * ahash, struct NodeLink** nod if (*node_link == NULL) return 0; (*node_link)->name = name; + (*node_link)->next = NULL; int ver = 0; size_t lenhash = strlen((char*)ahash); if (ipfs_cid_new(ver, ahash, lenhash, CID_PROTOBUF, &(*node_link)->cid) == 0) { @@ -81,6 +82,7 @@ int ipfs_node_link_protobuf_decode(unsigned char* buffer, size_t buffer_length, *link = (struct NodeLink*)malloc(sizeof(struct NodeLink)); (*link)->cid = NULL; (*link)->name = NULL; + (*link)->next = NULL; unsigned char* temp_buffer = NULL; size_t temp_size; @@ -139,8 +141,10 @@ size_t ipfs_node_protobuf_encode_size(struct Node* node) { size += 11 + ipfs_cid_protobuf_encode_size(node->cached); // links size += 11; - for(int i = 0; i < node->link_amount; i++) { - size += 11 + strlen(node->links[i]->name) + ipfs_cid_protobuf_encode_size(node->links[i]->cid); + struct NodeLink* current = node->head_link; + while(current != NULL) { + size += 11 + strlen(current->name) + ipfs_cid_protobuf_encode_size(current->cid); + current = current->next; } return size; } @@ -172,13 +176,15 @@ int ipfs_node_protobuf_encode(struct Node* node, unsigned char* buffer, size_t m retVal = protobuf_encode_length_delimited(3, ipfs_node_message_fields[2], cid, cid_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used); *bytes_written += bytes_used; // links - for(int i = 0; i < node->link_amount; i++) { + struct NodeLink* current = node->head_link; + while(current != NULL) { // size + name + cid - size_t link_buffer_size = 11 + ipfs_node_link_protobuf_encode_size(node->links[i]); + size_t link_buffer_size = 11 + ipfs_node_link_protobuf_encode_size(current); unsigned char link_buffer[link_buffer_size]; - retVal = ipfs_node_link_protobuf_encode(node->links[i], link_buffer, link_buffer_size, &link_buffer_size); + retVal = ipfs_node_link_protobuf_encode(current, link_buffer, link_buffer_size, &link_buffer_size); protobuf_encode_length_delimited(4, ipfs_node_message_fields[3], link_buffer, link_buffer_size, &buffer[*bytes_written], max_buffer_length - *bytes_written, &bytes_used); *bytes_written += bytes_used; + current = current->next; } return 1; @@ -243,9 +249,7 @@ int ipfs_node_protobuf_decode(unsigned char* buffer, size_t buffer_length, struc goto exit; free(temp_buffer); temp_buffer = NULL; - *node = ipfs_node_add_link(node, temp_link, sizeof(temp_link)); - ipfs_node_link_free(temp_link); - temp_link = NULL; + ipfs_node_add_link(*node, temp_link); break; } } @@ -256,8 +260,6 @@ exit: if (retVal == 0) { ipfs_node_free(*node); } - if (temp_link != NULL) - ipfs_node_link_free(temp_link); if (temp_buffer != NULL) free(temp_buffer); @@ -279,7 +281,7 @@ int ipfs_node_new(struct Node** node) (*node)->cached = NULL; (*node)->data = NULL; (*node)->encoded = NULL; - (*node)->link_amount = 0; + (*node)->head_link = NULL; return 1; } @@ -349,25 +351,39 @@ unsigned char * ipfs_node_get_data(struct Node * N) return DATA; } -/*ipfs_node_copy: Returns a copy of the node you input - * @param Node: The node you want to copy (struct CP_Node *) - * Returns a copy of the node you wanted to copy. - */ -struct Node * ipfs_node_copy(struct Node * CP_Node) -{ - struct Node * CN; - CN = (struct Node*) malloc(sizeof(struct Node) + sizeof(struct NodeLink) * 2); - if(CP_Node->link_amount != 0) - { - for(int i=0; ilink_amount; i++) - { - CN->links[i] = malloc(sizeof(struct NodeLink)); - } +struct NodeLink* ipfs_node_link_last(struct Node* node) { + struct NodeLink* current = node->head_link; + while(current != NULL) { + if (current->next == NULL) + break; + current = current->next; } - memcpy(CN, CP_Node, sizeof(struct Node)); - memcpy(CN->links[0],CP_Node->links[0], sizeof(struct NodeLink)); - return CN; + return current; } + +int ipfs_node_remove_link(struct Node* node, struct NodeLink* toRemove) { + struct NodeLink* current = node->head_link; + struct NodeLink* previous = NULL; + while(current != NULL && current != toRemove) { + previous = current; + current = current->next; + } + if (current != NULL) { + if (previous == NULL) { + // we're trying to delete the head + previous = current->next; + ipfs_node_link_free(current); + node->head_link = previous; + } else { + // we're in the middle or end + previous = current->next; + ipfs_node_link_free(current); + } + return 1; + } + return 0; +} + /*ipfs_node_free * Once you are finished using a node, always delete it using this. * It will take care of the links inside it. @@ -375,14 +391,13 @@ struct Node * ipfs_node_copy(struct Node * CP_Node) */ void ipfs_node_free(struct Node * N) { - if(N) + if(N != NULL) { - if(N->link_amount > 0) - { - for(int i=0; ilink_amount; i++) - { - free(N->links[i]); - } + struct NodeLink* current = ipfs_node_link_last(N); + while (current != NULL) { + struct NodeLink* toDelete = current; + current = current->next; + ipfs_node_remove_link(N, toDelete); } if(N->cached) { @@ -394,6 +409,7 @@ void ipfs_node_free(struct Node * N) free(N); } } + /*ipfs_node_get_link_by_name * Returns a copy of the link with given name * @param Name: (char * name) searches for link with this name @@ -401,22 +417,13 @@ void ipfs_node_free(struct Node * N) */ struct NodeLink * ipfs_node_get_link_by_name(struct Node * N, char * Name) { - struct NodeLink * L; - for(int i=0;ilink_amount;i++) - { - if(strcmp(N->links[i]->name,Name) == 0) - { - L = (struct NodeLink *)malloc(sizeof(struct NodeLink)); - memcpy(L,N->links[i],sizeof(struct NodeLink)); - int ver = L->cid->version; - unsigned char * ahash = L->cid->hash; - size_t lenhash = L->cid->hash_length; - ipfs_cid_new(ver, ahash, lenhash, CID_PROTOBUF, &L->cid); - return L; - } + struct NodeLink* current = N->head_link; + while(current != NULL && strcmp(Name, current->name) != 0) { + current = current->next; } - return NULL; + return current; } + /*ipfs_node_remove_link_by_name * Removes a link from node if found by name. * @param name: Name of link (char * name) @@ -424,21 +431,32 @@ struct NodeLink * ipfs_node_get_link_by_name(struct Node * N, char * Name) */ int ipfs_node_remove_link_by_name(char * Name, struct Node * mynode) { - for(int i=0; ilink_amount; i++) - { - if(mynode->links[i]->name == Name) - { - for(int x=i;xlink_amount && x+1 != mynode->link_amount;i++) - { - memcpy(mynode->links[x],mynode->links[x+1],sizeof(struct NodeLink)); - } - free(mynode->links[mynode->link_amount-1]); - mynode->link_amount--; - return 1; + struct NodeLink* current = mynode->head_link; + struct NodeLink* previous = NULL; + while( (current != NULL) + && (( Name == NULL && current->name != NULL ) + || ( Name != NULL && current->name == NULL ) + || ( Name != NULL && current->name != NULL && strcmp(Name, current->name) != 0) ) ) { + previous = current; + current = current->next; + } + if (current != NULL) { + // we found it + if (previous == NULL) { + // we're first, use the next one (if there is one) + if (current->next != NULL) + mynode->head_link = current->next; + } else { + // we're somewhere in the middle, remove me from the list + previous->next = current->next; + ipfs_node_link_free(current); } + + return 1; } return 0; } + /* ipfs_node_add_link * Adds a link to your nodse * @param mynode: &yournode @@ -446,27 +464,22 @@ int ipfs_node_remove_link_by_name(char * Name, struct Node * mynode) * @param linksz: sizeof(your cid here) * Returns your node with the newly added link */ -struct Node * ipfs_node_add_link(struct Node ** mynode, struct NodeLink * mylink, size_t linksz) +int ipfs_node_add_link(struct Node* Nl, struct NodeLink * mylink) { - struct Node * Nl = *mynode; - Nl->link_amount++; - size_t calculatesize = 0; - if(Nl->link_amount != 0) - { - for(int i=0; ilink_amount-1;i++) - { - calculatesize = calculatesize + sizeof(Nl->links[i]); + if(Nl->head_link != NULL) { + // add to existing by finding last one + struct NodeLink* current_end = Nl->head_link; + while(current_end->next != NULL) { + current_end = current_end->next; } - calculatesize = calculatesize + linksz; - Nl = (struct Node *) realloc(Nl, sizeof(struct Node) + calculatesize); + // now we have the last one, add to it + current_end->next = mylink; } else { - Nl = (struct Node *) malloc(sizeof(struct Node) + linksz); + Nl->head_link = mylink; } - Nl->links[Nl->link_amount-1] = malloc(sizeof(struct NodeLink)); - memcpy(Nl->links[Nl->link_amount-1],mylink,sizeof(struct NodeLink)); - return Nl; + return 1; } /*ipfs_node_new_from_link @@ -477,16 +490,11 @@ struct Node * ipfs_node_add_link(struct Node ** mynode, struct NodeLink * mylink */ int ipfs_node_new_from_link(struct NodeLink * mylink, struct Node** node) { - *node = (struct Node *) malloc(sizeof(struct Node) + sizeof(struct NodeLink)); + *node = (struct Node *) malloc(sizeof(struct Node)); if (*node == NULL) return 0; - (*node)->link_amount = 1; - (*node)->links[0] = malloc(sizeof(struct NodeLink)); - if ((*node)->links[0] == NULL) { - free(*node); - return 0; - } - memcpy((*node)->links[0], mylink, sizeof(struct NodeLink)); + (*node)->head_link = NULL; + ipfs_node_add_link(*node, mylink); (*node)->cached = NULL; (*node)->data = NULL; (*node)->encoded = NULL; diff --git a/test/merkledag/test_merkledag.h b/test/merkledag/test_merkledag.h index c6477f7..632be2e 100644 --- a/test/merkledag/test_merkledag.h +++ b/test/merkledag/test_merkledag.h @@ -225,23 +225,20 @@ int test_merkledag_add_node_with_links() { return 0; } - if (node2->link_amount != node1->link_amount) { - printf("Link amount %d does not match %d\n", node2->link_amount, node1->link_amount); - ipfs_repo_fsrepo_free(fs_repo); - ipfs_node_free(node1); - ipfs_node_free(node2); - return 0; - } - - // make sure hashes match - for(int i = 0; i < node1->links[0]->cid->hash_length; i++) { - if(node1->links[0]->cid->hash[i] != node2->links[0]->cid->hash[i]) { - printf("Hashes do not match\n"); - ipfs_repo_fsrepo_free(fs_repo); - ipfs_node_free(node1); - ipfs_node_free(node2); - return 0; + struct NodeLink* node1_link = node1->head_link; + struct NodeLink* node2_link = node2->head_link; + while(node1_link != NULL) { + for(int i = 0; i < node1_link->cid->hash_length; i++) { + if(node1_link->cid->hash[i] != node2_link->cid->hash[i]) { + printf("Hashes do not match for node %s\n", node1_link->name); + ipfs_repo_fsrepo_free(fs_repo); + ipfs_node_free(node1); + ipfs_node_free(node2); + return 0; + } } + node1_link = node1_link->next; + node2_link = node2_link->next; } ipfs_node_free(node1); diff --git a/test/node/test_node.h b/test/node/test_node.h index e854f3b..ca0720f 100644 --- a/test/node/test_node.h +++ b/test/node/test_node.h @@ -3,39 +3,24 @@ int test_node() { //Variables of link: char * name = "Alex"; - unsigned char * ahash = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"; + unsigned char * ahash = (unsigned char*)"QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"; struct NodeLink * mylink; int retVal = ipfs_node_link_new(name,ahash, &mylink); - printf("===================================\n" \ - "Node Link:\n" \ - " -Name: %s\n" \ - "\n Cid Details:\n\n" \ - " -Version: %d\n" \ - " -Codec: %c\n" \ - " -Hash: %s\n" \ - " -Hash Length: %lu\n" \ - "====================================\n" \ - , mylink->name, mylink->cid->version,mylink->cid->codec,mylink->cid->hash,mylink->cid->hash_length); + //Link Two for testing purposes char * name2 = "Simo"; - unsigned char * ahash2 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo"; + unsigned char * ahash2 = (unsigned char*)"QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo"; struct NodeLink * mylink2; retVal = ipfs_node_link_new(name2, ahash2, &mylink2); + //Nodes struct Node * Mynode; retVal = ipfs_node_new_from_link(mylink, &Mynode); - mylink->name = "HAHA";//Testing for valid node creation - printf("Node Link[0] Name: %s\nHash: %s\n",Mynode->links[0]->name, Mynode->links[0]->cid->hash); - Mynode = ipfs_node_add_link(&Mynode, mylink2, sizeof(mylink2)); - mylink2->name = "HAHA";//Testing for valid node creation - printf("Node Link[1] Name: %s\nHash: %s\n",Mynode->links[1]->name,Mynode->links[1]->cid->hash); + //mylink->name = "HAHA";//Testing for valid node creation + retVal = ipfs_node_add_link(Mynode, mylink2); + //mylink2->name = "HAHA";//Testing for valid node creation struct NodeLink * ResultLink = ipfs_node_get_link_by_name(Mynode, "Simo"); - printf("\nResultLink: \nName: %s\nHash: %s\n", ResultLink->name, ResultLink->cid->hash); ipfs_node_remove_link_by_name("Simo", Mynode); - printf("Outlinkamt: %d\n", Mynode->link_amount); - ipfs_node_link_free(mylink); - ipfs_node_link_free(mylink2); - ipfs_node_link_free(ResultLink); ipfs_node_free(Mynode); return 1; } @@ -121,13 +106,13 @@ int test_node_encode_decode() { if (ipfs_node_link_new((char*)"Link1", (unsigned char*)"QmLink1", &link1) == 0) goto exit; - if ( (control = ipfs_node_add_link(&control, link1, sizeof(link1))) == NULL) + if ( ipfs_node_add_link(control, link1) == 0) goto exit; // second link if (ipfs_node_link_new((char*)"Link2", (unsigned char*)"QmLink2", &link2) == 0) goto exit; - if ( (control = ipfs_node_add_link(&control, link2, sizeof(link2))) == NULL) + if ( ipfs_node_add_link(control, link2) == 0) goto exit; // encode @@ -141,14 +126,16 @@ int test_node_encode_decode() { goto exit; // compare results - if (control->link_amount != results->link_amount || control->link_amount != 2) - goto exit; - for(int i = 0; i < control->link_amount; i++) { - if (compare_link(control->links[i], results->links[i]) == 0) { - printf("Error was on link %d\n", i); + struct NodeLink* control_link = control->head_link; + struct NodeLink* results_link = results->head_link; + while(control_link != NULL) { + if (compare_link(control_link, results_link) == 0) { + printf("Error was on link %s\n", control_link->name); goto exit; } + control_link = control_link->next; + results_link = results_link->next; } if (control->data_size != results->data_size) @@ -165,10 +152,6 @@ exit: ipfs_node_free(control); if (results != NULL) ipfs_node_free(results); - if (link1 != NULL) - ipfs_node_link_free(link1); - if (link2 != NULL) - ipfs_node_link_free(link2); if (buffer != NULL) free(buffer);