Пример #1
0
/**
  * @author Mislav Čakarić
  * @brief Function that fetches nth main bucket
  * @param indexName name of index
  * @param n number of main bucket
  * @return address structure with data where the bucket is stored
 */
struct_add* Ak_get_nth_main_bucket_add(char *indexName, int n) {
    int i = 0, j = 0, k = 0, counter = 0, end = 0;
    AK_PRO;
    struct_add *add = (struct_add*) AK_malloc(sizeof (struct_add));
    add->addBlock = 301;
    add->indexTd = 2;
    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexName);
    while (addresses->address_from[i]) {
        for (j = addresses->address_from[i]; j < addresses->address_to[i]; j++) {
            AK_block *temp = (AK_block*) AK_read_block(j);
            for (k = 0; k < DATA_BLOCK_SIZE; k++) {
                if (temp->tuple_dict[k].type == FREE_INT)
                    break;
                if (temp->tuple_dict[k].type == MAIN_BUCKET) {
                    if (n == counter) {
                        add->addBlock = j;
                        add->indexTd = k;
                        end = 1;
                        break;
                    }
                    counter++;
                }
            }
            if (end) break;
        }
        i++;
    }
    AK_EPI;
    return add;
    AK_free(add);
}
Пример #2
0
/**
  * @author Mislav Čakarić
  * @brief Function that fetches the info for hash index
  * @param indexName name of index
  * @return info bucket with info data for hash index
 */
hash_info* AK_get_hash_info(char *indexName) {
    AK_PRO;
    table_addresses *hash_addresses = (table_addresses*) AK_get_index_addresses(indexName);
    int block_add = hash_addresses->address_from[ 0 ];
    hash_info *info = (hash_info*) AK_malloc(sizeof (hash_info));
    memset(info, 0, sizeof (hash_info));
    if (block_add == 0) {
        printf("Hash index does not exist!\n");
	AK_EPI;
        return info;
    }
    AK_block *block = (AK_block*) AK_read_block(block_add);
    memcpy(info, block->data, sizeof (hash_info));
    AK_EPI;
    return info;
}
Пример #3
0
/**
 * @author Matija Šestak, modified for indexes by Lovro Predovan
 * @brief Function that gets value in some row and column
 * @param row zero-based row index
 * @param column zero-based column index
 * @param *tblName table name
 * @return value in the list
 */
struct list_node *AK_get_index_tuple(int row, int column, char *indexTblName) {
    AK_PRO;

    int num_rows = AK_get_index_num_records(indexTblName);
    int num_attr = AK_num_index_attr(indexTblName);

    if (row >= num_rows || column >= num_attr){
        AK_EPI;
        return NULL;
    }

    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexTblName);

    struct list_node *row_root = (struct list_node *) AK_malloc(sizeof (struct list_node));
    Ak_Init_L3(&row_root);

    int i, j, k, counter;
    char data[ MAX_VARCHAR_LENGTH ];

    i = 0;
    counter = -1;
    while (addresses->address_from[ i ] != 0) {
        for (j = addresses->address_from[ i ]; j < addresses->address_to[ i ]; j++) {
            AK_mem_block *temp = (AK_mem_block*) AK_get_block(j);
            if (temp->block->last_tuple_dict_id == 0) break;
            for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) {
                if (temp->block->tuple_dict[k].size > 0)
                    counter++;
                if (counter == row) {
                    int type = temp->block->tuple_dict[ k + column ].type;
                    int size = temp->block->tuple_dict[ k + column ].size;
                    int address = temp->block->tuple_dict[ k + column ].address;
                    memcpy(data, &temp->block->data[address], size);
                    data[ size ] = '\0';
                    Ak_InsertAtEnd_L3(type, data, size, row_root);
                    AK_free(addresses);
                    AK_EPI;
                    return (struct list_node *) Ak_First_L2(row_root);
                }
            }
        }
        i++;
    }
    AK_free(addresses);
    AK_EPI;
    return NULL;
}
Пример #4
0
/**
 * @author Matija Šestak, modified for indexes by Lovro Predovan
 * @brief  Function that getts index table header
 * <ol>
 * <li>Read addresses of extents</li>
 * <li>If there is no extents in the table, return -1</li>
 * <li>else read the first block</li>
 * <li>allocate array</li>
 * <li>copy table header to the array</li>
 * </ol>
 * @param  *tblName table name
 * @result array of table header
 */
AK_header *AK_get_index_header(char *indexTblName) {
    AK_PRO;

    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexTblName);

    if (addresses->address_from[0] == 0){
        AK_EPI;
        return 0;
    }

    AK_mem_block *temp = (AK_mem_block*) AK_get_block(addresses->address_from[0]);
    int num_attr = AK_num_index_attr(indexTblName);
    AK_header *head = (AK_header*) AK_calloc(num_attr, sizeof (AK_header));
    memcpy(head, temp->block->header, num_attr * sizeof (AK_header));
    AK_EPI;
    return head;
}
Пример #5
0
/**
 * @author Lovro Predovan
 * @brief Function for getting number of elements in index table
 * @param index table name
 * @return No return value
 * */
int AK_num_index_attr(char *indexTblName) {

    int num_attr = 0;
    AK_PRO;
    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexTblName);

    if (addresses->address_from[0] == 0)
        num_attr = 0;
    else {
        AK_mem_block *temp_block = (AK_mem_block*) AK_get_block(addresses->address_from[0]);

        while (strcmp(temp_block->block->header[num_attr].att_name, "\0") != 0) {
            num_attr++;
        }
    }

    AK_free(addresses);
    AK_EPI;
    return num_attr;
}
Пример #6
0
/**
  * @author Mislav Čakarić
  * @brief Function that changes a info of hash index
  * @param indexName name of index
  * @param modulo value for modulo hash function
  * @param main_bucket_num number of main buckets
  * @param hash_bucket_num number of hash buckets
  * @return No return value
 */
void AK_change_hash_info(char *indexName, int modulo, int main_bucket_num, int hash_bucket_num) {
    AK_PRO;
    table_addresses *hash_addresses = (table_addresses*) AK_get_index_addresses(indexName);
    int block_add = hash_addresses->address_from[ 0 ];
    if (block_add == 0) {
        printf("Hash index does not exist!\n");
    }
    AK_block *block = (AK_block*) AK_read_block(block_add);
    hash_info *info = (hash_info*) AK_malloc(sizeof (hash_info));
    info->modulo = modulo;
    info->main_bucket_num = main_bucket_num;
    info->hash_bucket_num = hash_bucket_num;

    memcpy(block->data, info, sizeof (hash_info));
    block->tuple_dict[0].address = 0;
    block->tuple_dict[0].type = INFO_BUCKET;
    block->tuple_dict[0].size = sizeof (hash_info);
    AK_write_block(block);
    AK_EPI;
}
Пример #7
0
/**
  * @author Mislav Čakarić
  * @brief Function that inserts a bucket to block
  * @param indexName name of index
  * @param data content of bucket stored in char array
  * @param type type of bucket (MAIN_BUCKET or HASH_BUCKET)
  * @return address structure with data where the bucket is stored 
 */
struct_add* Ak_insert_bucket_to_block(char *indexName, char *data, int type) {
    int size, id;
    AK_PRO;
    struct_add *add = (struct_add*) AK_malloc(sizeof (struct_add));
    add->addBlock = 0;
    add->indexTd = 0;

    int adr_to_write = (int) AK_find_AK_free_space(AK_get_index_addresses(indexName));
    if (adr_to_write == -1)
        adr_to_write = (int) AK_init_new_extent(indexName, SEGMENT_TYPE_INDEX);
    if (adr_to_write == 0){
	AK_EPI;
        return add;
    }

    AK_block *block = (AK_block*) AK_read_block(adr_to_write);

    Ak_dbg_messg(HIGH, INDICES, "insert_bucket_to_block: Position to write (tuple_dict_index) %d\n", adr_to_write);

    switch (type) {
        case MAIN_BUCKET:
            size = sizeof (main_bucket);
            break;
        case HASH_BUCKET:
            size = sizeof (hash_bucket);
            break;
    }
    id = block->last_tuple_dict_id + 1;
    memcpy(&block->data[block->AK_free_space], data, size);
    block->tuple_dict[id].address = block->AK_free_space;
    block->AK_free_space += size;
    block->tuple_dict[id].type = type;
    block->tuple_dict[id].size = size;
    block->last_tuple_dict_id = id;
    AK_write_block(block);

    add->addBlock = adr_to_write;
    add->indexTd = id;
    AK_EPI;
    return add;
}
Пример #8
0
/**
 * @author Matija Šestak, modified for indexes by Lovro Predovan
 * @brief  Determine number of rows in the table
 * <ol>
 * <li>Read addresses of extents</li>
 * <li>If there is no extents in the table, return -1</li>
 * <li>For each extent from table</li>
 * <li>For each block in the extent</li>
 * <li>Get a block</li>
 * <li>Exit if there is no records in block</li>
 * <li>Count tuples in block</li>
 * <li>Return the number of tuples divided by number of attributes</li>
 * </ol>
 * @param *tableName table name
 * @return number of rows in the table
 */
int AK_get_index_num_records(char *indexTblName) {
    int num_rec = 0;
    int number_of_rows = 0;
    AK_PRO;

    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexTblName);

    if (addresses->address_from[0] == 0){
        AK_EPI;
        return 0;
    }
    int i = 0, j, k;
    AK_mem_block *temp = (AK_mem_block*) AK_get_block(addresses->address_from[0]);

    while (addresses->address_from[ i ] != 0) {

        for (j = addresses->address_from[ i ]; j < addresses->address_to[ i ]; j++) {
            temp = (AK_mem_block*) AK_get_block(j);

            if (temp->block->last_tuple_dict_id == 0)
                break;

            for (k = 0; k < DATA_BLOCK_SIZE; k++) {
                if (temp->block->tuple_dict[ k ].size > 0) {
                    num_rec++;
                }
            }
        }
        i++;
    }

    AK_free(addresses);
    int num_head = AK_num_index_attr(indexTblName);
    number_of_rows = (num_rec / num_head);

    AK_EPI;
    return number_of_rows;
}
Пример #9
0
/**
 * @author Matija Šestak, modified for indexes by Lovro Predovan
 * @brief  Function for printing index table
 * @param *tblName table name
 * @return No return value
 */
void AK_print_index_table(char *indexTblName) {
    AK_PRO;
    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexTblName);
    char *index_table = "AK_index";

    if ((addresses->address_from[0] == 0)  || (AK_index_table_exist(indexTblName) == 0)) {
        printf("Table %s does not exist!\n", indexTblName);
        AK_EPI;
    } else {

        AK_header *head = AK_get_index_header(indexTblName);

        int i, j, k, l;
        int num_attr = AK_num_index_attr(indexTblName);
        int num_rows = AK_get_index_num_records(indexTblName);
        int len[num_attr]; //max length for each attribute in row
        int length = 0; //length of spacer
        clock_t t;

        //printf("BROJ ATTR %i ; BROJ REDOVA %i U TABLICI %s",num_attr,num_rows,indexTblName);
        //store lengths of header attributes
        for (i = 0; i < num_attr; i++) {
            len[i] = strlen((head + i)->att_name);
        }


        //for each header attribute iterate through all table rows and check if
        //there is longer element than previously longest and store it in array
        for (i = 0; i < num_attr; i++) {
            for (j = 0; j < num_rows; j++) {
                struct list_node *el = AK_get_index_tuple(j, i, indexTblName);
                switch (el->type) {

                    case TYPE_INT:
                        length = AK_chars_num_from_number(*((int *) (el)->data), 10);
                        if (len[i] < length) {
                            len[i] = length;
                        }
                        break;
                    case TYPE_FLOAT:
                        length = AK_chars_num_from_number(*((float *) (el)->data), 10);
                        if (len[i] < length) {
                            len[i] = length;
                        }
                        break;
                    case TYPE_VARCHAR:
                    default:
                        if (len[i] < el->size) {
                            len[i] = el->size;
                        }
                        break;
                }
            }
        }
        //num_attr is number of char | + space in printf
        //set offset to change the box size

        length = 0;
        for (i = 0; i < num_attr; length += len[i++]);
        length += num_attr * TBL_BOX_OFFSET + 2 * num_attr + 1;

        //start measuring time
        t = clock();

        if (num_attr <= 0 || num_rows <= 0) {
            printf("Table is empty.\n");
            AK_EPI;
        } else {

            AK_print_row_spacer(len, length);
            printf("\n|");

            //HEADER
            for (i = 0; i < num_attr; i++) {
                //PRINTING HEADER ELEMENTS CENTERED
                k = (len[i] - (int) strlen((head + i)->att_name) + TBL_BOX_OFFSET + 1);
                if (k % 2 == 0) {
                    k /= 2;
                    printf("%-*s%-*s|", k, " ", k + (int) strlen((head + i)->att_name), (head + i)->att_name);
                } else {
                    k /= 2;
                    printf("%-*s%-*s|", k, " ", k + (int) strlen((head + i)->att_name) + 1, (head + i)->att_name);
                }
            }
            printf("\n");
            AK_print_row_spacer(len, length);
            //END HEADER

            struct list_node *row_root = (struct list_node *) AK_malloc(sizeof (struct list_node));
            Ak_Init_L3(&row_root);
            int type, size, address,last_addres_value;
            i = 0;

            if(addresses->address_to[i] != 0){
                last_addres_value = addresses->address_to[i];
            }


            while (addresses->address_from[i] != 0) {

                for (j = addresses->address_from[i]; j < addresses->address_to[i]; j++) {
                    AK_mem_block *temp = (AK_mem_block*) AK_get_block(j);

                    //THIS IS KINDA HACK, THIS PROBABLY SHOULD BE CHANGED SO MAIN INDEX TABLE ARE NOT INCLUDED
                    if ((temp->block->last_tuple_dict_id == 0) && (last_addres_value == addresses->address_to[i])){
                        printf("\nIndex: %s\n", indexTblName);


                        //PRINTING OUT TIME STATS
                        t = clock() - t;
                        if ((((double) t) / CLOCKS_PER_SEC) < 0.1) {
                            printf("%i rows found, duration: %f μs\n", num_rows, ((double) t) / CLOCKS_PER_SEC * 1000);
                        } else {
                            printf("%i rows found, duration: %f s\n", num_rows, ((double) t) / CLOCKS_PER_SEC);
                        }

                        AK_free(row_root);
                        AK_free(addresses);
                        AK_EPI;
                        //break;
                        return 1;
                    }

                    //PRINTING VALUES IN INDEX TABLE
                    for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) {
                        if (temp->block->tuple_dict[k].size > 0) {
                            for (l = 0; l < num_attr; l++) {

                                type = temp->block->tuple_dict[k + l].type;
                                size = temp->block->tuple_dict[k + l].size;
                                address = temp->block->tuple_dict[k + l].address;

                                Ak_InsertAtEnd_L3(type, &temp->block->data[address], size, row_root);
                            }

                            AK_print_row(len, row_root);
                            AK_print_row_spacer(len, length);
                            Ak_DeleteAll_L3(&row_root);
                        }
                    }
                }
                i++;
            }

        AK_free(row_root);
        }
    }

    AK_free(addresses);
    AK_EPI;
}
Пример #10
0
/**
  *  @author Mislav Čakarić
  *  @brief Function that inserts a record in hash bucket
  *  @param indexName name of index
  *  @param hashValue hash value of record that is being inserted
  *  @param add address structure with data where the hash bucket is stored
  *  @return No return value
 */
void AK_insert_in_hash_index(char *indexName, int hashValue, struct_add *add) {
    int i, address, size, hash_AK_free_space = 0;
    AK_PRO;
    struct_add *main_add = (struct_add*) AK_malloc(sizeof (struct_add));
    struct_add *hash_add = (struct_add*) AK_malloc(sizeof (struct_add));
    main_bucket *temp_main_bucket = (main_bucket*) AK_malloc(sizeof (main_bucket));
    hash_bucket *temp_hash_bucket = (hash_bucket*) AK_malloc(sizeof (hash_bucket));

    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexName);
    if (addresses->address_from[0] == 0)
        printf("Hash index does not exist!\n");
    else {
        char data[255];
        memset(data, 0, 255);
        hash_info *info = (hash_info*) AK_malloc(sizeof (hash_info));
        info = AK_get_hash_info(indexName);
        if (info->main_bucket_num == 0) {
            for (i = 0; i < MAIN_BUCKET_SIZE; i++) {
                temp_main_bucket->element[i].value = i;
                memset(&temp_main_bucket->element[i].add, 0, sizeof (struct_add));
            }
            memcpy(&data, temp_main_bucket, sizeof (main_bucket));
            main_add = Ak_insert_bucket_to_block(indexName, data, MAIN_BUCKET);

            temp_hash_bucket->bucket_level = MAIN_BUCKET_SIZE;
            for (i = 0; i < HASH_BUCKET_SIZE; i++) {
                temp_hash_bucket->element[i].value = -1;
            }
            memcpy(&data, temp_hash_bucket, sizeof (hash_bucket));
            for (i = 0; i < MAIN_BUCKET_SIZE; i++) {
                hash_add = Ak_insert_bucket_to_block(indexName, data, HASH_BUCKET);

                memcpy(&temp_main_bucket->element[i].add, hash_add, sizeof (struct_add));
            }
            memcpy(&data, temp_main_bucket, sizeof (main_bucket));
            Ak_update_bucket_in_block(main_add, data);
            AK_change_hash_info(indexName, MAIN_BUCKET_SIZE, 1, MAIN_BUCKET_SIZE);
        }
        int hash_bucket_id = hashValue % info->modulo;
        int main_bucket_id = (int) (hash_bucket_id / MAIN_BUCKET_SIZE);

        main_add = Ak_get_nth_main_bucket_add(indexName, main_bucket_id);

        AK_block *temp_block = (AK_block*) AK_read_block(main_add->addBlock);
        address = temp_block->tuple_dict[main_add->indexTd].address;
        size = temp_block->tuple_dict[main_add->indexTd].size;
        memcpy(temp_main_bucket, &temp_block->data[address], size);

        memcpy(hash_add, &temp_main_bucket->element[hash_bucket_id % MAIN_BUCKET_SIZE].add, sizeof (struct_add));


        temp_block = (AK_block*) AK_read_block(hash_add->addBlock);
        address = temp_block->tuple_dict[hash_add->indexTd].address;
        size = temp_block->tuple_dict[hash_add->indexTd].size;
        memcpy(temp_hash_bucket, &temp_block->data[address], size);
        for (i = 0; i < HASH_BUCKET_SIZE; i++) {
            if (temp_hash_bucket->element[i].value == -1) {
                hash_AK_free_space = 1;
                temp_hash_bucket->element[i].value = hashValue;
                memcpy(&temp_hash_bucket->element[i].add, add, sizeof (struct_add));
                memcpy(&data, temp_hash_bucket, sizeof (hash_bucket));
                Ak_update_bucket_in_block(hash_add, data);
                break;
            }
        }
        if (hash_AK_free_space == 0) {

            if (temp_hash_bucket->bucket_level == info->modulo) {
                //adding new main buckets
                for (i = 0; i < info->main_bucket_num; i++) {
                    main_add = Ak_get_nth_main_bucket_add(indexName, i);
                    AK_block *temp_block = (AK_block*) AK_read_block(main_add->addBlock);
                    address = temp_block->tuple_dict[main_add->indexTd].address;
                    size = temp_block->tuple_dict[main_add->indexTd].size;
                    memcpy(data, &temp_block->data[address], size);
                    Ak_insert_bucket_to_block(indexName, data, MAIN_BUCKET);
                }
                AK_change_hash_info(indexName, info->modulo * 2, info->main_bucket_num * 2, info->hash_bucket_num);
                info = AK_get_hash_info(indexName);
            }
            int hash_bucket_id2 = (hash_bucket_id + info->modulo / 2) % info->modulo;
            int main_bucket_id2 = (int) (hash_bucket_id2 / MAIN_BUCKET_SIZE);

            //swapping hash bucket id's
            if (hash_bucket_id2 < hash_bucket_id) {
                int temp = hash_bucket_id;
                hash_bucket_id = hash_bucket_id2;
                hash_bucket_id2 = temp;
                temp = main_bucket_id;
                main_bucket_id = main_bucket_id2;
                main_bucket_id2 = temp;
            }

            hash_bucket *temp_hash_bucket2 = (hash_bucket*) AK_malloc(sizeof (hash_bucket));
            temp_hash_bucket2->bucket_level = temp_hash_bucket->bucket_level * 2;
            for (i = 0; i < HASH_BUCKET_SIZE; i++) {
                temp_hash_bucket2->element[i].value = -1;
                memset(&temp_hash_bucket2->element[i].add, 0, sizeof (struct_add));
            }
            memcpy(data, temp_hash_bucket2, sizeof (hash_bucket));
            Ak_update_bucket_in_block(hash_add, data);

            main_add = Ak_get_nth_main_bucket_add(indexName, main_bucket_id2);
            temp_block = (AK_block*) AK_read_block(main_add->addBlock);
            address = temp_block->tuple_dict[main_add->indexTd].address;
            size = temp_block->tuple_dict[main_add->indexTd].size;
            memcpy(temp_main_bucket, &temp_block->data[address], size);

            hash_add = Ak_insert_bucket_to_block(indexName, data, HASH_BUCKET);
            memcpy(&temp_main_bucket->element[hash_bucket_id2 % MAIN_BUCKET_SIZE].add, hash_add, sizeof (struct_add));
            memcpy(data, temp_main_bucket, sizeof (main_bucket));
            Ak_update_bucket_in_block(main_add, data);

            AK_change_hash_info(indexName, info->modulo, info->main_bucket_num, info->hash_bucket_num + 1);
            for (i = 0; i < HASH_BUCKET_SIZE; i++) {
                int value = temp_hash_bucket->element[i].value;
                memcpy(main_add, &temp_hash_bucket->element[i].add, sizeof (struct_add));
                AK_insert_in_hash_index(indexName, value, main_add);
            }
            AK_insert_in_hash_index(indexName, hashValue, add);
        }
    }
    AK_EPI;
}
Пример #11
0
/**
  * @author Mislav Čakarić
  * @brief Function that fetches or deletes a record from hash index
  * @param indexName name of index
  * @param values list of values (one row) to search in hash index
  * @param delete if delete is 0 then record is only read otherwise it's deleted from hash index
  * @return address structure with data where the record is in table
 
 */
//Error: expected a ')'
struct_add *AK_find_delete_in_hash_index(char *indexName, struct list_node *values, int delete) {
    AK_PRO;
    struct_add *add = (struct_add*) AK_malloc(sizeof (struct_add));
    memset(add, 0, sizeof (struct_add));
    table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexName);
    if (addresses->address_from[0] == 0) {
        printf("Hash index does not exist!\n");
        AK_EPI;
        return add;
    } else {
        int hashValue = 0, address, size, i, j, k, found, match;
        struct list_node *temp_elem;
        temp_elem = Ak_First_L2(values);
        while (temp_elem) {
            hashValue += AK_elem_hash_value(temp_elem);
            temp_elem = Ak_Next_L2(temp_elem);
        }
        struct_add *main_add = (struct_add*) AK_malloc(sizeof (struct_add));
        struct_add *hash_add = (struct_add*) AK_malloc(sizeof (struct_add));
        main_bucket *temp_main_bucket = (main_bucket*) AK_malloc(sizeof (main_bucket));