|
|
|
@ -1,36 +1,79 @@
|
|
|
|
|
#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 (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);
|
|
|
|
|
free(chunk_array->data);
|
|
|
|
|
buffer_free(chunk_array->buffer1);
|
|
|
|
|
buffer_free(chunk_array->buffer2);
|
|
|
|
|
free(chunk_array);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void chunk_array_flush(chunk_array_t* chunk_array) {
|
|
|
|
|
size_t mod;
|
|
|
|
|
if (chunk_array->total_size - chunk_array->init_pos > chunk_array->chunk_size ) {
|
|
|
|
|
mod = chunk_array->chunk_size;
|
|
|
|
|
} else {
|
|
|
|
|
mod = chunk_array->total_size - chunk_array->init_pos;
|
|
|
|
|
buffer_flush(chunk_array, chunk_array->buffer1);
|
|
|
|
|
buffer_flush(chunk_array, chunk_array->buffer2);
|
|
|
|
|
}
|
|
|
|
|
fseek(chunk_array->fp, chunk_array->init_pos * sizeof(double), SEEK_SET);
|
|
|
|
|
fwrite(chunk_array->data, sizeof(double), mod, chunk_array->fp);
|
|
|
|
|
|
|
|
|
|
void buffer_flush(chunk_array_t* chunk_array, buffer_t* buffer) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool chunk_array_update(chunk_array_t* chunk_array, size_t pos) {
|
|
|
|
|
chunk_array_flush(chunk_array);
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
chunk_array->init_pos = new_init * 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;
|
|
|
|
|
|
|
|
|
|
fseek(chunk_array->fp, chunk_array->init_pos * sizeof(double), SEEK_SET);
|
|
|
|
|
fread(chunk_array->data, sizeof(double), chunk_array->chunk_size, chunk_array->fp);
|
|
|
|
|
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) {
|
|
|
|
@ -41,50 +84,78 @@ chunk_array_t* chunk_array_create(char* filename, size_t total_size) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chunk_array->data = malloc(MAX_CHUNK_SIZE * sizeof(double));
|
|
|
|
|
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 (MAX_CHUNK_SIZE > 0 && chunk_array->data == NULL) {
|
|
|
|
|
if (chunk_array->buffer2 == NULL) {
|
|
|
|
|
fclose(chunk_array->fp);
|
|
|
|
|
buffer_free(chunk_array->buffer1);
|
|
|
|
|
free(chunk_array);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fread(chunk_array->data, sizeof(double), MAX_CHUNK_SIZE, chunk_array->fp);
|
|
|
|
|
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->init_pos = 0;
|
|
|
|
|
chunk_array->chunk_size = MAX_CHUNK_SIZE;
|
|
|
|
|
chunk_array->total_size = total_size;
|
|
|
|
|
return chunk_array;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool chunk_array_get(chunk_array_t* chunk_array, size_t pos, double *valor) {
|
|
|
|
|
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 (pos<chunk_array->init_pos || pos>chunk_array->init_pos + chunk_array->chunk_size-1) {
|
|
|
|
|
chunk_array_update(chunk_array, pos);
|
|
|
|
|
if (distance_to_1 < distance_to_2) {
|
|
|
|
|
buffer_update(chunk_array, chunk_array->buffer1, pos);
|
|
|
|
|
return chunk_array->buffer1;
|
|
|
|
|
}
|
|
|
|
|
size_t mod;
|
|
|
|
|
if (chunk_array->total_size - chunk_array->init_pos > chunk_array->chunk_size ) {
|
|
|
|
|
mod = chunk_array->chunk_size;
|
|
|
|
|
} else {
|
|
|
|
|
mod = chunk_array->total_size - chunk_array->init_pos;
|
|
|
|
|
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%mod;
|
|
|
|
|
*valor=chunk_array->data[real_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) {
|
|
|
|
|
if (pos<chunk_array->init_pos || pos>chunk_array->init_pos + chunk_array->chunk_size-1) {
|
|
|
|
|
chunk_array_update(chunk_array,pos);
|
|
|
|
|
buffer_t* buffer;
|
|
|
|
|
if (inside_buffer(chunk_array, chunk_array->buffer1->init_pos, pos)) {
|
|
|
|
|
buffer = chunk_array->buffer1;
|
|
|
|
|
}
|
|
|
|
|
size_t mod;
|
|
|
|
|
if (chunk_array->total_size - chunk_array->init_pos > chunk_array->chunk_size ) {
|
|
|
|
|
mod = chunk_array->chunk_size;
|
|
|
|
|
} else {
|
|
|
|
|
mod = chunk_array->total_size - chunk_array->init_pos;
|
|
|
|
|
else if (inside_buffer(chunk_array, chunk_array->buffer2->init_pos, pos)) {
|
|
|
|
|
buffer = chunk_array->buffer2;
|
|
|
|
|
}
|
|
|
|
|
chunk_array->data[pos%mod]=valor;
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
return true;
|
|
|
|
|
}
|