Untitled

 avatar
unknown
plain_text
5 months ago
5.0 kB
10
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GET_BLOCK_INFO(block) (HP_block_info *) ((block) + (BF_BLOCK_SIZE - sizeof(HP_block_info)))


#include "bf.h"
#include "hp_file.h"
#include "record.h"

#define CALL_BF(call)       \
{                           \
  BF_ErrorCode code = call; \
  if (code != BF_OK) {         \
    BF_PrintError(code);    \
    return HP_ERROR;        \
  }                         \
}

int HP_CreateFile(char *fileName) {
    int fd1;
    void *data = NULL;

    CALL_BF(BF_CreateFile(fileName))
    CALL_BF(BF_OpenFile(fileName, &fd1));

    BF_Block *block;
    BF_Block_Init(&block);
    CALL_BF(BF_AllocateBlock(fd1, block));

    data = BF_Block_GetData(block);
    HP_block_info* hpBlockInfo = GET_BLOCK_INFO(data);
    hpBlockInfo->num_records = 0;
    hpBlockInfo->next_block = -1;

    HP_info* info = data;
    info->last_free_block_id = 0; //initializing value, no blocks inserted
    info->block_record_capacity = (BF_BLOCK_SIZE - sizeof(HP_block_info)) / sizeof(Record);
    info->first_block_record_capacity = (BF_BLOCK_SIZE - sizeof(HP_block_info) - sizeof(HP_info)) / sizeof(Record);

    BF_Block_SetDirty(block);
    CALL_BF(BF_UnpinBlock(block));
    CALL_BF(BF_CloseFile(fd1));
    return 0;
}


HP_info* HP_OpenFile(char *fileName, int *file_desc){
    HP_info* hpInfo;
    BF_Block *block;
    BF_Block_Init(&block);

    BF_OpenFile(fileName, file_desc);
    BF_GetBlock(*file_desc, 0, block);

    void *data = BF_Block_GetData(block);
    hpInfo = (HP_info *) malloc(sizeof(HP_info));
    memcpy(hpInfo, data, sizeof(HP_info));

    return hpInfo;
}

int HP_CloseFile(int file_desc, HP_info* hp_info) {
    free(hp_info);
    CALL_BF(BF_CloseFile(file_desc));
    return 0;
}

static int allocate_new_block(int file_desc, HP_info *hp_info, BF_Block *old_block, BF_Block** ret_block) {
    BF_Block* new_block;
    BF_Block_Init(&new_block);

    CALL_BF(BF_AllocateBlock(file_desc, new_block));
    int blocks_num;
    CALL_BF(BF_GetBlockCounter(file_desc, &blocks_num));
    hp_info->last_free_block_id = blocks_num - 1;
    void* old_block_data = BF_Block_GetData(old_block);
    HP_block_info *old_block_info = GET_BLOCK_INFO(old_block_data);
    old_block_info->next_block = blocks_num -1;

    BF_Block_SetDirty(old_block);
    CALL_BF(BF_UnpinBlock(old_block));

    void* new_block_data = BF_Block_GetData(new_block);
    HP_block_info* new_block_info = GET_BLOCK_INFO(new_block_data);
    new_block_info->num_records = 0;
    new_block_info->next_block= -1;



    *ret_block = new_block;
    return 0;
}

static int insert_record_to_block(BF_Block *block, Record record, uint32_t offset) {
    void* block_data = BF_Block_GetData(block);

    HP_block_info *block_info = GET_BLOCK_INFO(block_data);

    void *record_data = block_data + offset + block_info->num_records * sizeof(Record);

    memcpy(record_data, &record, sizeof(Record));
    block_info->num_records += 1;
    BF_Block_SetDirty(block);
    CALL_BF(BF_UnpinBlock(block));

    return 0;
}

int HP_InsertEntry(int file_desc, HP_info* hp_info, Record record) {
    BF_Block* block;
    BF_Block_Init(&block);

    if (hp_info == NULL) {
        fprintf(stderr, "info was not found\n");
        return -1;
    }

    CALL_BF(BF_GetBlock(file_desc, hp_info->last_free_block_id, block));
    void* block_data = BF_Block_GetData(block);
    HP_block_info *block_info = GET_BLOCK_INFO(block_data);

    uint32_t record_capacity, offset;
    if (hp_info->last_free_block_id == 0) {
        record_capacity = hp_info->first_block_record_capacity;

        // HP_info is stored in the beginning of the first block so we have to account for it.
        offset = sizeof(HP_info);
    } else {
        record_capacity = hp_info->block_record_capacity;

        offset = 0;
    }

    if (block_info->num_records < record_capacity) {

        insert_record_to_block(block, record, offset);
    } else {
        BF_Block* new_block;
        int err = allocate_new_block(file_desc, hp_info, block, &new_block);

        if (err != 0) {
            return err;
        }
        err = insert_record_to_block(new_block, record, 0);
        if (err != 0) {
            return err;
        }
    }

    return hp_info->last_free_block_id;
}

int HP_GetAllEntries(int file_desc, HP_info* hp_info, int value) {
    BF_Block *block;
    BF_Block_Init(&block);
    for (int i = 0; i != -1 ;) {
        CALL_BF(BF_GetBlock(file_desc, i, block));
        void *data = BF_Block_GetData(block);

        HP_block_info* block_info = GET_BLOCK_INFO(data);
        if (i == 0) data += sizeof(HP_info);

       for (int j = 0; j < block_info->num_records; j++) {
         Record record;
            memcpy(&record, data + j * sizeof(Record), sizeof(Record));
            if (record.id == value)
                printRecord(record);
       }
        i = block_info->next_block;
        CALL_BF(BF_UnpinBlock(block));
    }

    return 0;
}
Editor is loading...
Leave a Comment