double_struct *merge_partitions(cog *c, long low, long high) { list *list = create_list(); int has_merge_work; gather_partitions(list, c); struct cog *right_replacement = NULL; struct cog *left_replacement = NULL; struct list *list_iter; struct iter_list *tail; struct stack_triple *stack = create_stack(); struct iter_list *head_list = malloc(sizeof(struct iter_list)); tail = head_list; list_iter = list; iterator merge_iter; cog *c1 = malloc(sizeof(struct cog)); while(list_has_next(list_iter)) { list_iter = get_cog_from_list(list_iter, c1); struct extracted_components *components = extract_partitions(c1, low, high); if(components->iter != NULL) { has_merge_work = 1; tail = iter_list_add(tail, components->iter); } if(components->rhs != NULL) { if(right_replacement == NULL) { right_replacement = components->rhs; } else { right_replacement = make_concat(right_replacement, components->rhs); } } if(components->lhs != NULL) { if(left_replacement == NULL) { left_replacement = components->lhs; } else { left_replacement = make_concat(left_replacement, components->lhs); } } free(components); } cleanup_list(list); free(c1); if(has_merge_work != 0) { double_struct *ret = create_double_struct(); merge_iter = iter_merge(head_list); record r = malloc(sizeof(struct record)); while(1) { int i; buffer out = buffer_alloc(MERGE_BLOCK_SIZE); record buf = out->data; for(i = 0; i < MERGE_BLOCK_SIZE && iter_has_next(merge_iter); i++) { iter_next(merge_iter, r); record_set(&buf[i], r->key, r->value); } if(i == 0) { break; } struct cog *buffer = make_sortedarray(0, i, out); fold_append(&stack, buffer, cog_min(buffer)); if(i < MERGE_BLOCK_SIZE) { break; } } cog *root = fold(&stack); if(root == NULL) { root = make_btree(left_replacement, right_replacement, high); } else { ret->iter = scan(root, low, high); if(left_replacement != NULL && cog_length(left_replacement) != 0) { root = make_btree(left_replacement, root, cog_min(root)); } if(right_replacement != NULL && cog_length(right_replacement) != 0) { root = make_btree(root, right_replacement, cog_min(right_replacement)); } } free(r); cleanup_stack(stack); iter_list_cleanup(head_list); iter_cleanup(merge_iter); ret->cog = root; return ret; } else { double_struct *ret; ret = amerge(list->cog, low, high); if(left_replacement != NULL) { ret->cog = make_concat(ret->cog, left_replacement); } if(right_replacement != NULL) { ret->cog = make_concat(ret->cog, right_replacement); } return ret; } }
int main(int argc, char *argv[]) { if(argc < 3) { printf("Insufficient number of arguments supplied\n"); exit(-1); } if(argc > 3) { printf("Too many arguments supplied\n"); exit(-1); } char index_file[DEF]; memset(index_file,0,sizeof(char)*DEF); if(argv[1]==NULL) { printf("Received a NULL index filename"); exit(-1); } //Index file strcpy(index_file,argv[1]); if(argv[2]==NULL) { printf("Received a NULL B Tree order"); exit(-1); } //B tree order btree_order=atoi(argv[2]); if(btree_order < 3) { printf("The order of the tree should be greater than or equal to 3\n"); exit(-1); } btree_node_ptr node_in_mem=NULL; btree_node_ptr aux_node_in_mem=NULL; //Get a new node which you can reuse node_in_mem = new_node_init(); //Get a new aux node which can we reused aux_node_in_mem = new_aux_node(); //debug bool //bool debug=true; if(debug) printf("Index filename received : %s\n",index_file); if(debug) printf("B Tree order : %d\n",btree_order); bool cmdIsValid=false; //File needs to be opened here //FILE *fin; fin = fopen (index_file, "r+b"); if(fin == NULL) { root_offset = -1; //Write -1 to the file fin = fopen (index_file, "w+b"); if(fin == NULL) { perror("Index file open error: "); exit(-1); } //else // fwrite(&root_offset, sizeof(long), 1, fin); } else fread(&root_offset, sizeof(long), 1, fin); //Open two aux FDs //file_open(index_file); char *cmd=(char *)malloc(sizeof(char)*CMD_LEN); char *temp_cmd=(char *)malloc(sizeof(char)*CMD_LEN); char *temp2_cmd=(char *)malloc(sizeof(char)*CMD_LEN); memset(cmd,0,sizeof(char)*CMD_LEN); memset(temp_cmd,0,sizeof(char)*CMD_LEN); memset(temp2_cmd,0,sizeof(char)*CMD_LEN); while(1) { cmdIsValid=false; int ret; size_t len = sizeof(char)*CMD_LEN; memset(cmd,0,sizeof(char)*CMD_LEN); memset(temp_cmd,0,sizeof(char)*CMD_LEN); memset(temp2_cmd,0,sizeof(char)*CMD_LEN); ret=getline(&cmd,&len,stdin); if(ret==-1) { perror("Command Read Error :"); exit(-1); } //Strip \n cmd[strlen(cmd)-1]='\0'; if(strlen(cmd)==0) continue; if(debug) printf("getline returns : %s\n",cmd); strcpy(temp_cmd,cmd); strcpy(temp2_cmd,cmd); char *tok=strtok(temp_cmd," "); if(strcmp(tok,"add")==0 || strcmp(tok,"find")==0 || strcmp(tok,"print")==0 || strcmp(tok,"end")==0) cmdIsValid=true; if(cmdIsValid) { if(strcmp(tok,"add")==0) { tok=strtok(NULL," "); if(tok==NULL) { printf("Key value not supplied to 'add' utility\n"); continue; } int key=atoi(tok); int found=0; found=find_key_in_btree(index_file, key); if(found) printf("Entry with key=%d already exists\n",key); else { //Add logic begins here size_of_tree++; if(root_offset==-1) { //The tree is empty. Construct the root; //Cleanup the node btree_node_ptr root = node_clean_up(node_in_mem); //btree_node_ptr root = new_node_init(); (root)->keys[0] = key; (root)->no_of_keys++; if(debug) printf("Root data : %d\t%d\n",(root)->keys[0],(root)->no_of_keys); //Write this node to the file //btree_node_ptr node= *root; //memcpy(node, *root, sizeof(btree_node)); write_node(root); root_offset = sizeof(long); } //Tree is not empty else { //Check if the root is not full //fseek(fin, sizeof(long), SEEK_SET); fseek(fin, root_offset, SEEK_SET); int keys_in_root=0; fread(&keys_in_root, sizeof(int), 1, fin); if(debug) printf("keys_in_root : %d\n",keys_in_root); { //printf("Root is Full \n"); //The recursive procedure goes here to split upto the root //Step 1 : Populate the parent pointers upto the leaf responsible for this insert //long parent_pointers[size_of_tree]; int i=0; /*for(i=0;i<size_of_tree;i++) { parent_pointers[i] = -1; if(debug) printf("parent pointer : %d\t%ld",i,parent_pointers[i]); }*/ //Essentially a find operation that pushes in the parent offsets in a stack cleanup_stack(); populate_parents( index_file, key); //print_stack(); //Step 2 : Get the leaf offset if(debug) printf("Leaf offset : %ld\n",leaf_offset); //Get the number of nodes in the leaf fseek(fin, 0, SEEK_SET); fseek(fin, leaf_offset, SEEK_CUR); int node_keys = 0; fread(&node_keys, sizeof(int), 1, fin); if(debug) printf("Keys in node : %d\n",node_keys); if(node_keys == btree_order - 1) add_key_to_tree(aux_node_in_mem, node_keys, leaf_offset, key); else insert_in_node(leaf_offset, node_keys, key); } } } } else if(strcmp(tok,"find")==0) { tok=strtok(NULL," "); if(tok==NULL) { printf("Key value not supplied to 'find' utility\n"); continue; } int key=atoi(tok); bool found=find_key_in_btree(index_file, key); if(found) printf("Entry with key=%d exists\n",key); else printf("Entry with key=%d does not exist\n",key); } else if(strcmp(tok,"print")==0) { print_tree(index_file); } else if(strcmp(tok,"end")==0) { //Write the updates root offset fseek(fin, 0, SEEK_SET); fwrite(&root_offset, sizeof(long), 1, fin); fclose(fin); break; } else printf("Invalid command received\n"); } else printf("Invalid command received\n"); } return 0; }