Skip to content
Snippets Groups Projects
Commit c739e843 authored by Loic Hausammann's avatar Loic Hausammann
Browse files

Improve the time array

parent e1367e66
No related branches found
No related tags found
1 merge request!685Logger loader
......@@ -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;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment