made node links a single linked list instead of array

This will save some complicated memory allocations
This commit is contained in:
jmjatlanta 2016-12-12 16:58:27 -05:00
parent 4fe768c2c5
commit a36ba20557
5 changed files with 126 additions and 144 deletions

View file

@ -46,12 +46,12 @@ int main(int argc, char** argv)
struct Node * Mynode; struct Node * Mynode;
Mynode = N_Create_From_Link(mylink); Mynode = N_Create_From_Link(mylink);
mylink->name = "HAHA";//Testing for valid node creation 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 //N_Add_Link
Mynode = N_Add_Link(&Mynode, mylink2, sizeof(mylink2)); Mynode = N_Add_Link(&Mynode, mylink2, sizeof(mylink2));
mylink2->name = "HAHA";//Testing for valid node creation 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 //Node_Get_Link
struct Link * ResultLink = Node_Get_Link(Mynode, "Simo"); struct Link * ResultLink = Node_Get_Link(Mynode, "Simo");
@ -74,7 +74,7 @@ int main(int argc, char** argv)
//Node Copy //Node Copy
struct Node * Node2; struct Node * Node2;
Node2 = Node_Copy(Mynode); 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_Delete(Node2);
//Node_Set_Data //Node_Set_Data

View file

@ -17,6 +17,7 @@ struct NodeLink
{ {
char* name; char* name;
struct Cid * cid; struct Cid * cid;
struct NodeLink* next;
}; };
struct Node struct Node
@ -25,8 +26,7 @@ struct Node
size_t data_size; size_t data_size;
unsigned char* encoded; unsigned char* encoded;
struct Cid* cached; struct Cid* cached;
int link_amount; struct NodeLink* head_link;
struct NodeLink* links[];
}; };
/*==================================================================================== /*====================================================================================
@ -123,12 +123,6 @@ int ipfs_node_set_encoded(struct Node * N, unsigned char * Data);
*/ */
unsigned char * ipfs_node_get_data(struct Node * N); 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 /*ipfs_node_free
* Once you are finished using a node, always delete it using this. * Once you are finished using a node, always delete it using this.
* It will take care of the links inside it. * 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) * @param linksz: sizeof(your cid here)
* Returns your node with the newly added link * 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 /*ipfs_node_new_from_link
* Create a node from a link * Create a node from a link

View file

@ -30,6 +30,7 @@ int ipfs_node_link_new(char * name, unsigned char * ahash, struct NodeLink** nod
if (*node_link == NULL) if (*node_link == NULL)
return 0; return 0;
(*node_link)->name = name; (*node_link)->name = name;
(*node_link)->next = NULL;
int ver = 0; int ver = 0;
size_t lenhash = strlen((char*)ahash); size_t lenhash = strlen((char*)ahash);
if (ipfs_cid_new(ver, ahash, lenhash, CID_PROTOBUF, &(*node_link)->cid) == 0) { 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 = (struct NodeLink*)malloc(sizeof(struct NodeLink));
(*link)->cid = NULL; (*link)->cid = NULL;
(*link)->name = NULL; (*link)->name = NULL;
(*link)->next = NULL;
unsigned char* temp_buffer = NULL; unsigned char* temp_buffer = NULL;
size_t temp_size; 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); size += 11 + ipfs_cid_protobuf_encode_size(node->cached);
// links // links
size += 11; size += 11;
for(int i = 0; i < node->link_amount; i++) { struct NodeLink* current = node->head_link;
size += 11 + strlen(node->links[i]->name) + ipfs_cid_protobuf_encode_size(node->links[i]->cid); while(current != NULL) {
size += 11 + strlen(current->name) + ipfs_cid_protobuf_encode_size(current->cid);
current = current->next;
} }
return size; 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); 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; *bytes_written += bytes_used;
// links // links
for(int i = 0; i < node->link_amount; i++) { struct NodeLink* current = node->head_link;
while(current != NULL) {
// size + name + cid // 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]; 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); 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; *bytes_written += bytes_used;
current = current->next;
} }
return 1; return 1;
@ -243,9 +249,7 @@ int ipfs_node_protobuf_decode(unsigned char* buffer, size_t buffer_length, struc
goto exit; goto exit;
free(temp_buffer); free(temp_buffer);
temp_buffer = NULL; temp_buffer = NULL;
*node = ipfs_node_add_link(node, temp_link, sizeof(temp_link)); ipfs_node_add_link(*node, temp_link);
ipfs_node_link_free(temp_link);
temp_link = NULL;
break; break;
} }
} }
@ -256,8 +260,6 @@ exit:
if (retVal == 0) { if (retVal == 0) {
ipfs_node_free(*node); ipfs_node_free(*node);
} }
if (temp_link != NULL)
ipfs_node_link_free(temp_link);
if (temp_buffer != NULL) if (temp_buffer != NULL)
free(temp_buffer); free(temp_buffer);
@ -279,7 +281,7 @@ int ipfs_node_new(struct Node** node)
(*node)->cached = NULL; (*node)->cached = NULL;
(*node)->data = NULL; (*node)->data = NULL;
(*node)->encoded = NULL; (*node)->encoded = NULL;
(*node)->link_amount = 0; (*node)->head_link = NULL;
return 1; return 1;
} }
@ -349,25 +351,39 @@ unsigned char * ipfs_node_get_data(struct Node * N)
return DATA; return DATA;
} }
/*ipfs_node_copy: Returns a copy of the node you input struct NodeLink* ipfs_node_link_last(struct Node* node) {
* @param Node: The node you want to copy (struct CP_Node *) struct NodeLink* current = node->head_link;
* Returns a copy of the node you wanted to copy. while(current != NULL) {
*/ if (current->next == NULL)
struct Node * ipfs_node_copy(struct Node * CP_Node) break;
{ current = current->next;
struct Node * CN;
CN = (struct Node*) malloc(sizeof(struct Node) + sizeof(struct NodeLink) * 2);
if(CP_Node->link_amount != 0)
{
for(int i=0; i<CP_Node->link_amount; i++)
{
CN->links[i] = malloc(sizeof(struct NodeLink));
} }
} return current;
memcpy(CN, CP_Node, sizeof(struct Node));
memcpy(CN->links[0],CP_Node->links[0], sizeof(struct NodeLink));
return CN;
} }
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 /*ipfs_node_free
* Once you are finished using a node, always delete it using this. * Once you are finished using a node, always delete it using this.
* It will take care of the links inside it. * 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) void ipfs_node_free(struct Node * N)
{ {
if(N) if(N != NULL)
{ {
if(N->link_amount > 0) struct NodeLink* current = ipfs_node_link_last(N);
{ while (current != NULL) {
for(int i=0; i<N->link_amount; i++) struct NodeLink* toDelete = current;
{ current = current->next;
free(N->links[i]); ipfs_node_remove_link(N, toDelete);
}
} }
if(N->cached) if(N->cached)
{ {
@ -394,6 +409,7 @@ void ipfs_node_free(struct Node * N)
free(N); free(N);
} }
} }
/*ipfs_node_get_link_by_name /*ipfs_node_get_link_by_name
* Returns a copy of the link with given name * Returns a copy of the link with given name
* @param Name: (char * name) searches for link with this 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 * ipfs_node_get_link_by_name(struct Node * N, char * Name)
{ {
struct NodeLink * L; struct NodeLink* current = N->head_link;
for(int i=0;i<N->link_amount;i++) while(current != NULL && strcmp(Name, current->name) != 0) {
{ current = current->next;
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;
} }
} return current;
return NULL;
} }
/*ipfs_node_remove_link_by_name /*ipfs_node_remove_link_by_name
* Removes a link from node if found by name. * Removes a link from node if found by name.
* @param name: Name of link (char * 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) int ipfs_node_remove_link_by_name(char * Name, struct Node * mynode)
{ {
for(int i=0; i<mynode->link_amount; i++) struct NodeLink* current = mynode->head_link;
{ struct NodeLink* previous = NULL;
if(mynode->links[i]->name == Name) while( (current != NULL)
{ && (( Name == NULL && current->name != NULL )
for(int x=i;x<mynode->link_amount && x+1 != mynode->link_amount;i++) || ( Name != NULL && current->name == NULL )
{ || ( Name != NULL && current->name != NULL && strcmp(Name, current->name) != 0) ) ) {
memcpy(mynode->links[x],mynode->links[x+1],sizeof(struct NodeLink)); previous = current;
current = current->next;
} }
free(mynode->links[mynode->link_amount-1]); if (current != NULL) {
mynode->link_amount--; // 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 1;
} }
}
return 0; return 0;
} }
/* ipfs_node_add_link /* ipfs_node_add_link
* Adds a link to your nodse * Adds a link to your nodse
* @param mynode: &yournode * @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) * @param linksz: sizeof(your cid here)
* Returns your node with the newly added link * 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; if(Nl->head_link != NULL) {
Nl->link_amount++; // add to existing by finding last one
size_t calculatesize = 0; struct NodeLink* current_end = Nl->head_link;
if(Nl->link_amount != 0) while(current_end->next != NULL) {
{ current_end = current_end->next;
for(int i=0; i<Nl->link_amount-1;i++)
{
calculatesize = calculatesize + sizeof(Nl->links[i]);
} }
calculatesize = calculatesize + linksz; // now we have the last one, add to it
Nl = (struct Node *) realloc(Nl, sizeof(struct Node) + calculatesize); current_end->next = mylink;
} }
else else
{ {
Nl = (struct Node *) malloc(sizeof(struct Node) + linksz); Nl->head_link = mylink;
} }
Nl->links[Nl->link_amount-1] = malloc(sizeof(struct NodeLink)); return 1;
memcpy(Nl->links[Nl->link_amount-1],mylink,sizeof(struct NodeLink));
return Nl;
} }
/*ipfs_node_new_from_link /*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) 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) if (*node == NULL)
return 0; return 0;
(*node)->link_amount = 1; (*node)->head_link = NULL;
(*node)->links[0] = malloc(sizeof(struct NodeLink)); ipfs_node_add_link(*node, mylink);
if ((*node)->links[0] == NULL) {
free(*node);
return 0;
}
memcpy((*node)->links[0], mylink, sizeof(struct NodeLink));
(*node)->cached = NULL; (*node)->cached = NULL;
(*node)->data = NULL; (*node)->data = NULL;
(*node)->encoded = NULL; (*node)->encoded = NULL;

View file

@ -225,23 +225,20 @@ int test_merkledag_add_node_with_links() {
return 0; return 0;
} }
if (node2->link_amount != node1->link_amount) { struct NodeLink* node1_link = node1->head_link;
printf("Link amount %d does not match %d\n", node2->link_amount, node1->link_amount); 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_repo_fsrepo_free(fs_repo);
ipfs_node_free(node1); ipfs_node_free(node1);
ipfs_node_free(node2); ipfs_node_free(node2);
return 0; 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;
} }
node1_link = node1_link->next;
node2_link = node2_link->next;
} }
ipfs_node_free(node1); ipfs_node_free(node1);

View file

@ -3,39 +3,24 @@
int test_node() { int test_node() {
//Variables of link: //Variables of link:
char * name = "Alex"; char * name = "Alex";
unsigned char * ahash = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG"; unsigned char * ahash = (unsigned char*)"QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG";
struct NodeLink * mylink; struct NodeLink * mylink;
int retVal = ipfs_node_link_new(name,ahash, &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 //Link Two for testing purposes
char * name2 = "Simo"; char * name2 = "Simo";
unsigned char * ahash2 = "QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo"; unsigned char * ahash2 = (unsigned char*)"QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnSimo";
struct NodeLink * mylink2; struct NodeLink * mylink2;
retVal = ipfs_node_link_new(name2, ahash2, &mylink2); retVal = ipfs_node_link_new(name2, ahash2, &mylink2);
//Nodes //Nodes
struct Node * Mynode; struct Node * Mynode;
retVal = ipfs_node_new_from_link(mylink, &Mynode); retVal = ipfs_node_new_from_link(mylink, &Mynode);
mylink->name = "HAHA";//Testing for valid node creation //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); retVal = ipfs_node_add_link(Mynode, mylink2);
Mynode = ipfs_node_add_link(&Mynode, mylink2, sizeof(mylink2)); //mylink2->name = "HAHA";//Testing for valid node creation
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);
struct NodeLink * ResultLink = ipfs_node_get_link_by_name(Mynode, "Simo"); 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); 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); ipfs_node_free(Mynode);
return 1; return 1;
} }
@ -121,13 +106,13 @@ int test_node_encode_decode() {
if (ipfs_node_link_new((char*)"Link1", (unsigned char*)"QmLink1", &link1) == 0) if (ipfs_node_link_new((char*)"Link1", (unsigned char*)"QmLink1", &link1) == 0)
goto exit; goto exit;
if ( (control = ipfs_node_add_link(&control, link1, sizeof(link1))) == NULL) if ( ipfs_node_add_link(control, link1) == 0)
goto exit; goto exit;
// second link // second link
if (ipfs_node_link_new((char*)"Link2", (unsigned char*)"QmLink2", &link2) == 0) if (ipfs_node_link_new((char*)"Link2", (unsigned char*)"QmLink2", &link2) == 0)
goto exit; goto exit;
if ( (control = ipfs_node_add_link(&control, link2, sizeof(link2))) == NULL) if ( ipfs_node_add_link(control, link2) == 0)
goto exit; goto exit;
// encode // encode
@ -141,14 +126,16 @@ int test_node_encode_decode() {
goto exit; goto exit;
// compare results // compare results
if (control->link_amount != results->link_amount || control->link_amount != 2)
goto exit;
for(int i = 0; i < control->link_amount; i++) { struct NodeLink* control_link = control->head_link;
if (compare_link(control->links[i], results->links[i]) == 0) { struct NodeLink* results_link = results->head_link;
printf("Error was on link %d\n", i); while(control_link != NULL) {
if (compare_link(control_link, results_link) == 0) {
printf("Error was on link %s\n", control_link->name);
goto exit; goto exit;
} }
control_link = control_link->next;
results_link = results_link->next;
} }
if (control->data_size != results->data_size) if (control->data_size != results->data_size)
@ -165,10 +152,6 @@ exit:
ipfs_node_free(control); ipfs_node_free(control);
if (results != NULL) if (results != NULL)
ipfs_node_free(results); ipfs_node_free(results);
if (link1 != NULL)
ipfs_node_link_free(link1);
if (link2 != NULL)
ipfs_node_link_free(link2);
if (buffer != NULL) if (buffer != NULL)
free(buffer); free(buffer);