Commit c739e843 authored by Loic Hausammann's avatar Loic Hausammann
Browse files

Improve the time array

parent e1367e66
......@@ -48,11 +48,11 @@ SUBDIRS = tests
# List required headers
include_HEADERS = logger_header.h logger_loader_io.h logger_particle.h logger_time.h logger_tools.h logger_reader.h \
logger_index.h logger_logfile.h
logger_logfile.h
# Common source files
AM_SOURCES = logger_header.c logger_loader_io.c logger_particle.c logger_time.c logger_tools.c logger_reader.c \
logger_index.c logger_logfile.c
logger_logfile.c
if HAVEPYTHON
AM_SOURCES += logger_python_wrapper.c
endif
......
......@@ -59,7 +59,8 @@ void *logger_loader_io_mmap_file(char *filename, size_t *file_size,
else
fd = open(filename, O_RDWR);
if (fd == -1) error("Unable to open file %s (%s).", filename, strerror(errno));
if (fd == -1)
error("Unable to open file %s (%s).", filename, strerror(errno));
/* get the file size. */
*file_size = logger_loader_io_get_file_size(fd);
......
......@@ -154,8 +154,10 @@ size_t logger_particle_read(struct logger_particle *part,
}
}
/* Get the time of current record. */
if (times->next) {
/* Get the time of current record.
This check is required for the manipulating the file before
the initialization of the time_array. */
if (times->size != 0) {
part->time = time_array_get_time(times, offset);
} else
part->time = -1;
......
......@@ -47,7 +47,6 @@
#ifndef __LOGGER_LOGGER_READER_H__
#define __LOGGER_LOGGER_READER_H__
#include "logger_index.h"
#include "logger_loader_io.h"
#include "logger_logfile.h"
#include "logger_particle.h"
......@@ -66,9 +65,6 @@ struct logger_reader {
/* Time of each index file. #TODO */
double *times;
/* Information contained in the index file. */
struct logger_index index;
/* Informations contained in the file header. */
struct logger_logfile log;
......
......@@ -21,6 +21,51 @@
#include "logger_logfile.h"
#include "logger_reader.h"
/**
* @brief Check if enough space is available and increase it if required.
*
* @param t The #time_array.
*/
void time_array_ensure_size(struct time_array *t) {
/* Check if we still have some place. */
if (t->size < t->capacity) return;
/* Increase the size */
t->capacity *= 2;
t->time = realloc(t->time, sizeof(double) * t->capacity);
if (t->time == NULL) error("Failed to realloc time memory.");
t->int_time = realloc(t->int_time, sizeof(integertime_t) * t->capacity);
if (t->int_time == NULL) error("Failed to realloc integer time memory.");
t->offset = realloc(t->offset, sizeof(size_t) * t->capacity);
if (t->offset == NULL) error("Failed to realloc offset memory.");
}
/**
* @brief Add an element to the #time_array.
*
* @param t The #time_array.
* @param int_time The time in integer.
* @param time The time in double.
* @param offset The offset of the record.
*/
void time_array_append(struct time_array *t, const integertime_t int_time,
const double time, const size_t offset) {
/* Increase the available space if required */
time_array_ensure_size(t);
/* Copy the values */
t->time[t->size] = time;
t->int_time[t->size] = int_time;
t->offset[t->size] = offset;
/* Increase the size used. */
t->size += 1;
}
/**
* @brief read a time record.
*
......@@ -95,8 +140,19 @@ size_t time_offset_first_record(const struct header *h) {
* @param t #time_array to initialize.
*/
void time_array_init(struct time_array *t) {
t->next = NULL;
t->prev = NULL;
/* Allocate the arrays */
t->int_time = malloc(sizeof(integertime_t) * LOGGER_TIME_INIT_SIZE);
if (t->int_time == NULL) error("Failed to initialize the integer times.");
t->time = malloc(sizeof(double) * LOGGER_TIME_INIT_SIZE);
if (t->time == NULL) error("Failed to initialize the times.");
t->offset = malloc(sizeof(size_t) * LOGGER_TIME_INIT_SIZE);
if (t->offset == NULL) error("Failed to initialize the offsets.");
/* Initialize the sizes */
t->size = 0;
t->capacity = LOGGER_TIME_INIT_SIZE;
}
/**
......@@ -108,9 +164,6 @@ void time_array_init(struct time_array *t) {
void time_array_populate(struct time_array *t, struct logger_logfile *log) {
/* Initialize a few variables. */
t->next = NULL;
t->prev = NULL;
integertime_t int_time = 0;
double time = 0;
......@@ -121,81 +174,69 @@ void time_array_populate(struct time_array *t, struct logger_logfile *log) {
size_t offset = time_offset_first_record(&log->header);
while (offset < file_size) {
/* read current time record and store it. */
t->offset = offset;
size_t tmp_offset = offset;
time_read(&int_time, &time, log->reader, tmp_offset);
t->int_time = int_time;
t->time = time;
time_array_append(t, int_time, time, offset);
/* get next record. */
int test = tools_get_next_record(&log->header, log->log.map, &offset,
log->log.file_size);
if (test == -1) break;
/* allocate next time_array. */
struct time_array *tmp = malloc(sizeof(struct time_array));
tmp->prev = t;
tmp->next = NULL;
t->next = tmp;
t = tmp;
}
/* free unused time_array. */
struct time_array *tmp = t->prev;
tmp->next = NULL;
free(t);
}
/**
* @brief access the time of a given record (by its offset)
* @brief access the time of a given record (by its offset).
*
* @param t #time_array to access
* @param offset offset of the record
* @param t #time_array to access.
* @param offset offset of the record.
*
* @return integer time of the record
* @return integer time of the record.
*/
integertime_t time_array_get_integertime(struct time_array *t,
const size_t offset) {
const struct time_array *tmp = time_array_get_time_array(t, offset);
return tmp->int_time;
size_t ind = time_array_get_index(t, offset);
return t->int_time[ind];
}
/**
* @brief access the time of a given record (by its offset)
* @brief access the time of a given record (by its offset).
*
* @param t #time_array to access
* @param offset offset of the record
* @param t #time_array to access.
* @param offset offset of the record.
*
* @return time of the record
* @return time of the record.
*/
double time_array_get_time(const struct time_array *t, const size_t offset) {
const struct time_array *tmp = time_array_get_time_array(t, offset);
return tmp->time;
size_t ind = time_array_get_index(t, offset);
return t->time[ind];
}
/**
* @brief access the #time_array of a given record (by its offset)
* @brief Find the index of the last time record written before a given offset.
*
* @param t #time_array to access.
* @param offset offset of the record.
*
* @return pointer to the requested #time_array
* @return The index of the last time record.
*/
struct time_array *time_array_get_time_array(const struct time_array *t,
const size_t offset) {
size_t time_array_get_index(const struct time_array *t, const size_t offset) {
#ifdef SWIFT_DEBUG_CHECKS
if (!t) error("NULL pointer.");
#endif
const struct time_array *tmp;
/* Find the time_array with the correct offset. */
for (tmp = t; tmp->next && tmp->offset <= offset; tmp = tmp->next) {
}
for (size_t i = 1; i < t->size; i++) {
if (offset < t->offset[i]) {
return i - 1;
}
/* If providing the offset of a time_array, need to give it back. */
if (tmp->offset == offset) return (struct time_array *)tmp;
else if (offset == t->offset[i])
return i;
}
return (struct time_array *)tmp->prev;
error("Unable to find the required offset.");
}
/**
......@@ -204,11 +245,19 @@ struct time_array *time_array_get_time_array(const struct time_array *t,
* @param t #time_array to free
*/
void time_array_free(struct time_array *t) {
struct time_array *tmp;
for (tmp = t; t->next; t = tmp) {
tmp = t->next;
free(t);
}
/* Free the arrays */
free(t->int_time);
t->int_time = NULL;
free(t->time);
t->time = NULL;
free(t->offset);
t->offset = NULL;
/* Reset the counters */
t->size = 0;
t->capacity = 0;
}
/**
......@@ -217,21 +266,18 @@ void time_array_free(struct time_array *t) {
* @param t #time_array to print
*/
void time_array_print(const struct time_array *t) {
size_t threshold = 4;
const size_t threshold = 4;
size_t n = time_array_count(t);
size_t n = t->size;
size_t up_threshold = n - threshold;
printf("Times (size %lu): [%lli (%g)", n, t->int_time, t->time);
printf("Times (size %lu): [%lli (%g)", n, t->int_time[0], t->time[0]);
/* Loop over all elements. */
for (size_t i = 1; i < n; i++) {
if (!t->next) error("Next pointer not initialized %zi.", i);
t = t->next;
/* Skip the times at the center of the array. */
if (i < threshold || i > up_threshold)
printf(", %lli (%g)", t->int_time, t->time);
printf(", %lli (%g)", t->int_time[i], t->time[i]);
if (i == threshold) printf(", ...");
}
......@@ -245,37 +291,20 @@ void time_array_print(const struct time_array *t) {
* @param t #time_array to print
*/
void time_array_print_offset(const struct time_array *t) {
size_t threshold = 4;
const size_t threshold = 4;
size_t n = time_array_count(t);
size_t n = t->size;
size_t up_threshold = n - threshold;
printf("Times (size %lu): [%lu", n, t->offset);
printf("Times (size %lu): [%lu", n, t->offset[0]);
/* Loop over all elements. */
for (size_t i = 1; i < n; i++) {
t = t->next;
/* Skip the offset in the middle of the array. */
if (i < threshold || i > up_threshold) printf(", %lu", t->offset);
if (i < threshold || i > up_threshold) printf(", %lu", t->offset[i]);
if (i == threshold) printf(", ...");
}
printf("]\n");
}
/**
* @brief count number of element in #time_array
*
* @param t #time_array to count
*
* @return number of element
*/
size_t time_array_count(const struct time_array *t) {
size_t count = 1;
for (const struct time_array *tmp = t; tmp->next; tmp = tmp->next) {
count += 1;
}
return count;
}
......@@ -27,6 +27,8 @@ typedef long long integertime_t;
struct logger_reader;
#define LOGGER_TIME_INIT_SIZE 1024
/**
* @brief This structure contains all the time record.
*
......@@ -39,28 +41,27 @@ struct logger_reader;
*
* The time step of an offset can be obtained with
* #time_array_get_integertime, #time_array_get_time and
* #time_array_get_time_array.
*
* The size of the time array can be accessed with
* #time_array_count.
* #time_array_get_index.
*/
struct time_array {
/* Pointer to next element. */
void *next;
/* Integertime of the records. */
integertime_t *int_time;
/* Pointer to prev element. */
void *prev;
/* Double time of the records. */
double *time;
/* Integertime of this time record. */
integertime_t int_time;
/* Offset in the file of the time records. */
size_t *offset;
/* Double time of this time record. */
double time;
/* Number of element in the arrays. */
size_t size;
/* Offset in the file of this time record. */
size_t offset;
/* Maximum number of element available */
size_t capacity;
};
void time_array_append(struct time_array *t, const integertime_t int_time,
const double time, const size_t offset);
size_t time_read(integertime_t *int_time, double *time,
const struct logger_reader *reader, size_t offset);
......@@ -72,8 +73,7 @@ integertime_t time_array_get_integertime(struct time_array *t,
double time_array_get_time(const struct time_array *t, const size_t offset);
struct time_array *time_array_get_time_array(const struct time_array *t,
const size_t offset);
size_t time_array_get_index(const struct time_array *t, const size_t offset);
void time_array_free(struct time_array *t);
......@@ -81,8 +81,6 @@ void time_array_print(const struct time_array *t);
void time_array_print_offset(const struct time_array *t);
size_t time_array_count(const struct time_array *t);
size_t time_offset_first_record(const struct header *h);
#endif // __LOGGER_LOGGER_TIMELINE_H__
......@@ -20,17 +20,18 @@ AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/logger $(HDF5_CPPFLAGS) $(GSL_IN
AM_LDFLAGS = ../../src/.libs/libswiftsim.a ../.libs/liblogger.a $(HDF5_LDFLAGS) $(HDF5_LIBS) $(FFTW_LIBS) $(TCMALLOC_LIBS) $(JEMALLOC_LIBS) $(TBBMALLOC_LIBS) $(GRACKLE_LIBS) $(GSL_LIBS) $(PROFILER_LIBS)
# List of programs and scripts to run in the test suite
TESTS = testLogfileHeader testLogfileReader
TESTS = testLogfileHeader testLogfileReader testTimeArray
# List of test programs to compile
check_PROGRAMS = testLogfileHeader testLogfileReader
check_PROGRAMS = testLogfileHeader testLogfileReader testTimeArray
# Rebuild tests when SWIFT is updated.
$(check_PROGRAMS): ../../src/.libs/libswiftsim.a
$(check_PROGRAMS): ../../src/.libs/libswiftsim.a ../.libs/liblogger.a
# Sources for the individual programs
testLogfileHeader_SOURCES = testLogfileHeader.c
testLogfileReader_SOURCES = testLogfileReader.c
testTimeArray_SOURCES = testTimeArray.c
# Files necessary for distribution
EXTRA_DIST = testLogfileHeader.yml testLogfileReader.yml
/*******************************************************************************
* This file is part of SWIFT.
* Copyright (C) 2019 Loic Hausammann (loic.hausammann@epfl.ch)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
******************************************************************************/
#include "logger_time.h"
#include <time.h>
#include <stdlib.h>
#define NUMBER_OF_ELEMENT 10000
#define TIME_BASE 0.04
#define OFFSET_BASE 1000
int main(int argc, char *argv[]) {
if (NUMBER_OF_ELEMENT < LOGGER_TIME_INIT_SIZE) {
error("Not testing the reallocation.");
}
srand(100);
/* Initialize the time array */
struct time_array times;
time_array_init(&times);
/* Add elements */
for(size_t i = 0; i < NUMBER_OF_ELEMENT; i++) {
integertime_t int_time = i;
double time = i * TIME_BASE;
size_t offset = i * OFFSET_BASE;
time_array_append(&times, int_time, time, offset);
}
/* Check the elements */
for(size_t i = 0; i < NUMBER_OF_ELEMENT; i++) {
integertime_t int_time = i;
double time = i * TIME_BASE;
size_t offset = i * OFFSET_BASE;
/* Ensure that we can get the correct offset when looking
in between the records. */
int r = rand() % OFFSET_BASE;
size_t read_offset = offset + r;
/* The offset cannot be larger than the largest one */
if (i == NUMBER_OF_ELEMENT - 1) {
read_offset = offset;
}
/* Get the index from the offset */
size_t ind = time_array_get_index(&times, read_offset);
/* Check the values obtained */
assert(i == ind);
assert(int_time == times.int_time[ind]);
assert(time == times.time[ind]);
assert(offset == times.offset[ind]);
}
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment