hashfile/src/hash_file.c
HT_ErrorCode HT_CreateIndex(const char *fileName, int buckets) {
    int file_desc;
    CALL_BF(BF_CreateFile(fileName));
    CALL_BF(BF_OpenFile(fileName, &file_desc));
    
    BF_Block *block;
    BF_Block_Init (&block);

    char *data;
    CALL_BF(BF_AllocateBlock(file_desc, block));
    data = BF_Block_GetData(block);
    // Set an identifier('*') at the start to indicate that the file is a hashfile.
    // Also set the number of buckets.
    char h = '*';
    memcpy(data, &h, sizeof(char));
    memcpy(data+sizeof(char), &buckets, sizeof(int));
    BF_Block_SetDirty(block);
    CALL_BF(BF_UnpinBlock(block));
    
    int zero = 0;
    // Allocate as many blocks as the buckets, which will give us our starting map.
    // Save the number of records at the start of each block (zero at creation).
    // Also save a number which points to the next block, if this block gets filled.
    for (int i = 0; i < buckets; i++) {
        CALL_BF(BF_AllocateBlock(file_desc, block));
        data = BF_Block_GetData(block);
        memcpy(data, &zero, sizeof(int));
        memcpy(data+sizeof(int), &zero, sizeof(int));
        BF_Block_SetDirty(block);
        CALL_BF(BF_UnpinBlock(block));
    }
    BF_Block_Destroy(&block);
    int blocks_num;
    //CALL_BF(BF_GetBlockCounter(file_desc, &blocks_num));
    CALL_BF(BF_CloseFile(file_desc));
    
    return HT_OK;
}
/**
 * Our implementation:
 *  - Preallocate a number of 'buckets', for the initial hashing, which we will call our map.
 *  - Any new 'bucket' will go below the map.
 *  When a new record comes, we only have to find its hashing value, and add it to the corrensponding bucket.
 *  Conveniently the hashing value will be the same as the number of the bucket.
 *  If that bucket is full, a new block will be allocated at the end and its number(int) will be added to the previous one, creating something like a linking relation between the two.
 */
Our implementation:
- Preallocate a number of 'buckets', for the initial hashing, which we will call our map.
- Any new 'bucket' will go below the map.
When a new record comes, we only have to find its hashing value, and add it to the corrensponding bucket.
Conveniently the hashing value will be the same as the number of the bucket.
If that bucket is full, a new block will be allocated at the end and its number(int) will be added to the previous one, creating something like a linking relation between the two.
Our implementation : - Preallocate a number of ' buckets ' for the initial hashing which we will call our map . - Any new ' bucket ' will go below the map . When a new record comes we only have to find its hashing value and add it to the corrensponding bucket . Conveniently the hashing value will be the same as the number of the bucket . If that bucket is full a new block will be allocated at the end and its number ( int ) will be added to the previous one creating something like a linking relation between the two .
HT_ErrorCode HT_CreateIndex(const char *fileName, int buckets) {
    int file_desc;
    CALL_BF(BF_CreateFile(fileName));
    CALL_BF(BF_OpenFile(fileName, &file_desc));
    BF_Block *block;
    BF_Block_Init (&block);
    char *data;
    CALL_BF(BF_AllocateBlock(file_desc, block));
    data = BF_Block_GetData(block);
    char h = '*';
    memcpy(data, &h, sizeof(char));
    memcpy(data+sizeof(char), &buckets, sizeof(int));
    BF_Block_SetDirty(block);
    CALL_BF(BF_UnpinBlock(block));
    int zero = 0;
    for (int i = 0; i < buckets; i++) {
        CALL_BF(BF_AllocateBlock(file_desc, block));
        data = BF_Block_GetData(block);
        memcpy(data, &zero, sizeof(int));
        memcpy(data+sizeof(int), &zero, sizeof(int));
        BF_Block_SetDirty(block);
        CALL_BF(BF_UnpinBlock(block));
    }
    BF_Block_Destroy(&block);
    int blocks_num;
    CALL_BF(BF_CloseFile(file_desc));
    return HT_OK;
}
HT_ErrorCode HT_CreateIndex ( const char * fileName , int buckets ) { int file_desc ; CALL_BF ( BF_CreateFile ( fileName ) ) ; CALL_BF ( BF_OpenFile ( fileName , & file_desc ) ) ; BF_Block * block ; BF_Block_Init ( & block ) ; char * data ; CALL_BF ( BF_AllocateBlock ( file_desc , block ) ) ; data = BF_Block_GetData ( block ) ; char h = ' ' ; memcpy ( data , & h , sizeof ( char ) ) ; memcpy ( data + sizeof ( char ) , & buckets , sizeof ( int ) ) ; BF_Block_SetDirty ( block ) ; CALL_BF ( BF_UnpinBlock ( block ) ) ; int zero = 0 ; for ( int i = 0 ; i < buckets ; i ++ ) { CALL_BF ( BF_AllocateBlock ( file_desc , block ) ) ; data = BF_Block_GetData ( block ) ; memcpy ( data , & zero , sizeof ( int ) ) ; memcpy ( data + sizeof ( int ) , & zero , sizeof ( int ) ) ; BF_Block_SetDirty ( block ) ; CALL_BF ( BF_UnpinBlock ( block ) ) ; } BF_Block_Destroy ( & block ) ; int blocks_num ; CALL_BF ( BF_CloseFile ( file_desc ) ) ; return HT_OK ; }
Our implementation:
  - Preallocate a number of 'buckets', for the initial hashing, which we will call our map.
Our implementation : - Preallocate a number of ' buckets ' for the initial hashing which we will call our map .
// Set an identifier('*') at the start to indicate that the file is a hashfile. // Also set the number of buckets. // Allocate as many blocks as the buckets, which will give us our starting map. // Save the number of records at the start of each block (zero at creation). // Also save a number which points to the next block, if this block gets filled. //CALL_BF(BF_GetBlockCounter(file_desc, &blocks_num));