#include "chunk_array.h" #include "stdbool.h" #include "stdlib.h" #define MAX_CHUNK_SIZE 2048*2048 int get_mod(chunk_array_t* chunk_array,int init_pos) { int mod; if (chunk_array->total_size - init_pos > chunk_array->chunk_size ) { mod = chunk_array->chunk_size; } else { mod = chunk_array->total_size - init_pos; } return mod; } bool inside_buffer(chunk_array_t* chunk_array,int init_pos, size_t pos) { if (posinit_pos + chunk_array->chunk_size-1) { return false; } return true; } void chunk_array_free(chunk_array_t* chunk_array) { fclose(chunk_array->fp); buffer_free(chunk_array->buffer1); buffer_free(chunk_array->buffer2); free(chunk_array); } void chunk_array_flush(chunk_array_t* chunk_array) { buffer_flush(chunk_array, chunk_array->buffer1); buffer_flush(chunk_array, chunk_array->buffer2); } void buffer_flush(chunk_array_t* chunk_array, buffer_t* buffer) { if (buffer->dirty) { int mod = get_mod(chunk_array, buffer->init_pos); fseek(chunk_array->fp, buffer->init_pos * sizeof(double), SEEK_SET); fwrite(buffer->data, sizeof(double), mod, chunk_array->fp); buffer->dirty = false; } } void buffer_update(chunk_array_t* chunk_array, buffer_t* buffer, size_t pos) { buffer_flush(chunk_array, buffer); int new_init = pos/chunk_array->chunk_size; buffer->init_pos = new_init * chunk_array->chunk_size; fseek(chunk_array->fp, buffer->init_pos * sizeof(double), SEEK_SET); fread(buffer->data, sizeof(double), chunk_array->chunk_size, chunk_array->fp); } buffer_t* buffer_create() { buffer_t * buffer = (buffer_t*)malloc(sizeof(buffer_t)); if (buffer == NULL) return NULL; buffer->data = malloc(MAX_CHUNK_SIZE * sizeof(double)); if (buffer->data == NULL) { free(buffer); return NULL; } buffer->init_pos = 0; buffer->dirty = false; return buffer; } void buffer_free(buffer_t* buffer) { free(buffer->data); free(buffer); } chunk_array_t* chunk_array_create(char* filename, size_t total_size) { chunk_array_t* chunk_array = (chunk_array_t*)malloc(sizeof(chunk_array_t)); chunk_array->fp = fopen(filename, "r+"); if (chunk_array == NULL || chunk_array->fp == NULL) { chunk_array->fp = fopen(filename, "w+"); if (chunk_array->fp == NULL) { return NULL; } } chunk_array->buffer1 = buffer_create(); if (chunk_array->buffer1 == NULL) { fclose(chunk_array->fp); free(chunk_array); return NULL; } chunk_array->buffer2 = buffer_create(); if (chunk_array->buffer2 == NULL) { fclose(chunk_array->fp); buffer_free(chunk_array->buffer1); free(chunk_array); return NULL; } fread(chunk_array->buffer1->data, sizeof(double), MAX_CHUNK_SIZE, chunk_array->fp); chunk_array->buffer1->init_pos = 0; fread(chunk_array->buffer2->data, sizeof(double), MAX_CHUNK_SIZE, chunk_array->fp); chunk_array->buffer2->init_pos = MAX_CHUNK_SIZE; chunk_array->filename = filename; chunk_array->chunk_size = MAX_CHUNK_SIZE; chunk_array->total_size = total_size; return chunk_array; } buffer_t* chunk_array_update(chunk_array_t* chunk_array, size_t pos) { int distance_to_1 = abs(chunk_array->buffer1->init_pos - pos); int distance_to_2 = abs(chunk_array->buffer2->init_pos - pos); if (distance_to_1 < distance_to_2) { buffer_update(chunk_array, chunk_array->buffer1, pos); return chunk_array->buffer1; } buffer_update(chunk_array, chunk_array->buffer2, pos); return chunk_array->buffer2; } bool chunk_array_get(chunk_array_t* chunk_array, size_t pos, double *valor) { buffer_t* buffer; if (inside_buffer(chunk_array, chunk_array->buffer1->init_pos, pos)) { buffer = chunk_array->buffer1; } else if (inside_buffer(chunk_array, chunk_array->buffer2->init_pos, pos)) { buffer = chunk_array->buffer2; } else { // need to update one buffer buffer = chunk_array_update(chunk_array, pos); } int real_pos = pos%get_mod(chunk_array, buffer->init_pos); *valor=buffer->data[real_pos]; return true; } bool chunk_array_save(chunk_array_t* chunk_array, size_t pos, double valor) { buffer_t* buffer; if (inside_buffer(chunk_array, chunk_array->buffer1->init_pos, pos)) { buffer = chunk_array->buffer1; } else if (inside_buffer(chunk_array, chunk_array->buffer2->init_pos, pos)) { buffer = chunk_array->buffer2; } else { // need to update one buffer buffer = chunk_array_update(chunk_array, pos); } int real_pos = pos%get_mod(chunk_array, buffer->init_pos); buffer->data[real_pos]=valor; buffer->dirty = true; return true; }