#include "chunk_array.h" #include "stdbool.h" #include "stdlib.h" #include #include #define MAX_CHUNK_SIZE 11248640 #define N_BUFFERS 100 int min(int value1, int value2) { if (value1 < value2) return value1; return value2; } 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) { //printf("range: [%d; %d] pos: %d", init_pos, init_pos + chunk_array->chunk_size-1, pos); if (posinit_pos + chunk_array->chunk_size-1) { //printf(" FALSE\n"); return false; } //printf(" TRUE\n"); return true; } void chunk_array_free(chunk_array_t* chunk_array) { if (chunk_array->mmap_array) munmap(chunk_array->mmap_array, chunk_array->total_size * sizeof(double)); for (int i = 0; i < chunk_array->n_buffers; i++) { buffer_free(chunk_array->buffers[i]); } free(chunk_array->buffers); free(chunk_array); } void buffer_flush(chunk_array_t* chunk_array, buffer_t* buffer) { if (buffer->dirty && chunk_array->mmap_array) { int mod = get_mod(chunk_array, buffer->init_pos); memcpy(&chunk_array->mmap_array[buffer->init_pos], buffer->data, mod * sizeof(double)); buffer->dirty = false; } } void buffer_update(chunk_array_t* chunk_array, buffer_t* buffer, size_t pos) { //printf("[UPDATE BUFFER][%s] old init_pos %d pos %d\n",chunk_array->filename, buffer->init_pos, pos); //printf("miss pos: %d\n", pos); buffer_flush(chunk_array, buffer); if (chunk_array->mmap_array) { int new_init = pos/chunk_array->chunk_size; buffer->init_pos = new_init * chunk_array->chunk_size; int mod = get_mod(chunk_array, buffer->init_pos); memcpy(buffer->data, &chunk_array->mmap_array[buffer->init_pos], mod * sizeof(double)); } } buffer_t* buffer_create(int size, int init) { buffer_t * buffer = (buffer_t*)malloc(sizeof(buffer_t)); if (buffer == NULL) return NULL; buffer->data = malloc(size * sizeof(double)); if (buffer->data == NULL) { free(buffer); return NULL; } buffer->init_pos = init; 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)); if (chunk_array == NULL) { return NULL; } printf("totalsize %d\n", total_size); chunk_array->chunk_size = min(MAX_CHUNK_SIZE, total_size); chunk_array->buffers = malloc(sizeof(buffer_t) * N_BUFFERS); chunk_array->buffers[0] = buffer_create(chunk_array->chunk_size, 0); chunk_array->n_buffers = 1; chunk_array->last_updated = -1; for (int i = 1; i i*chunk_array->chunk_size) { chunk_array->n_buffers++; chunk_array->buffers[i] = buffer_create(chunk_array->chunk_size, i*chunk_array->chunk_size); } else { break; } } if (chunk_array->chunk_size*chunk_array->n_buffers < total_size) { chunk_array->mmap_array = mmap ( NULL, total_size*sizeof(double), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0 ); if (chunk_array->mmap_array == NULL) { return NULL; } } chunk_array->filename = filename; chunk_array->total_size = total_size; return chunk_array; } buffer_t* chunk_array_update(chunk_array_t* chunk_array, size_t pos) { ////printf("[%s] miss: %d\n",chunk_array->filename, pos); //buffer_t* buffer = chunk_array->buffers[0]; //int distance = abs(buffer->init_pos - pos); srand(time(NULL)); // Initialization, should only be called once. int random = rand()%chunk_array->n_buffers; while (random == chunk_array->last_updated) { //printf("ACA!\n"); random = rand()%chunk_array->n_buffers; } chunk_array->last_updated = random; /*for(int i=1; in_buffers; i++) { int new_distance = abs(chunk_array->buffers[i]->init_pos - pos); if (new_distance < distance) { distance = new_distance; buffer = chunk_array->buffers[i]; } }*/ buffer_t* buffer = chunk_array->buffers[random]; buffer_update(chunk_array, buffer, pos); return buffer; } bool chunk_array_get(chunk_array_t* chunk_array, size_t pos, double *valor) { // full memory if (chunk_array->total_size <= chunk_array->chunk_size) { *valor=chunk_array->buffers[0]->data[pos]; return true; } // mmap buffer_t* buffer = NULL; for (int i = 0; in_buffers; i++) { if (inside_buffer(chunk_array, chunk_array->buffers[i]->init_pos, pos)) { buffer = chunk_array->buffers[i]; break; } } if (!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) { // full memory if (chunk_array->total_size <= chunk_array->chunk_size) { chunk_array->buffers[0]->data[pos]=valor; chunk_array->buffers[0]->dirty = true; return true; } // mmap buffer_t* buffer = NULL; for (int i = 0; in_buffers; i++) { if (inside_buffer(chunk_array, chunk_array->buffers[i]->init_pos, pos)) { buffer = chunk_array->buffers[i]; break; } } if (!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; }