You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
simulacion-permeabilidad/fftma_module/gen/lib_src/chunk_array.c

193 lines
5.7 KiB
C

#include "chunk_array.h"
#include "stdbool.h"
#include "stdlib.h"
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define MAX_CHUNK_SIZE 268435456
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) {
if (pos<init_pos || pos>init_pos + chunk_array->chunk_size-1) {
return false;
}
return true;
}
void chunk_array_free(chunk_array_t* chunk_array) {
//fclose(chunk_array->fp);
munmap(chunk_array->mmap_array, chunk_array->total_size * sizeof(double));
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);
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) {
buffer_flush(chunk_array, buffer);
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);
//fseek(chunk_array->fp, buffer->init_pos * sizeof(double), SEEK_SET);
//fread(buffer->data, sizeof(double), chunk_array->chunk_size, chunk_array->fp);
memcpy(buffer->data, &chunk_array->mmap_array[buffer->init_pos], mod * sizeof(double));
}
buffer_t* buffer_create(int size) {
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 = 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));
if (chunk_array == NULL) {
return NULL;
}
int fd = open(filename, O_RDWR | O_CREAT, 0644);
if(fd < 0){
free(chunk_array);
return NULL;
}
chunk_array->mmap_array = mmap ( NULL, total_size * sizeof(double), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
if (chunk_array->mmap_array == NULL) {
free(chunk_array);
return NULL;
}
ftruncate(fd, total_size * sizeof(double));
close(fd);
chunk_array->chunk_size = min(MAX_CHUNK_SIZE, total_size);
chunk_array->buffer1 = buffer_create(chunk_array->chunk_size);
if (chunk_array->buffer1 == NULL) {
fclose(chunk_array->fp);
free(chunk_array);
return NULL;
}
chunk_array->buffer2 = buffer_create(chunk_array->chunk_size);
if (chunk_array->buffer2 == NULL) {
buffer_free(chunk_array->buffer1);
free(chunk_array);
return NULL;
}
memcpy(chunk_array->buffer1->data, chunk_array->mmap_array, chunk_array->chunk_size * sizeof(double));
chunk_array->buffer1->init_pos = 0;
if (total_size > chunk_array->chunk_size) {
int mod = get_mod(chunk_array, chunk_array->buffer1->init_pos + chunk_array->chunk_size);
memcpy(chunk_array->buffer2->data, &chunk_array->mmap_array[chunk_array->chunk_size], mod * sizeof(double));
chunk_array->buffer2->init_pos = chunk_array->chunk_size;
}
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) {
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;
}