From 28edd851f8b7675fdadb51ebf906ae9cf8494dc8 Mon Sep 17 00:00:00 2001 From: Magnus Lundborg Date: Wed, 27 Nov 2013 12:32:40 +0100 Subject: Fixed opening files for appending (might still not be perfect). Flush file when writing trajectory frame set. diff --git a/include/tng_io.h b/include/tng_io.h index 845ad2b..5347101 100644 --- a/include/tng_io.h +++ b/include/tng_io.h @@ -654,6 +654,22 @@ tng_function_status DECLSPECDLLEXPORT tng_output_file_set const char *file_name); /** + * @brief Set the name of the output file for appending. The output file + * will not be overwritten. + * @param tng_data the trajectory of which to set the output file name. + * @param file_name the name of the output file to append to. + * @pre \code tng_data != 0 \endcode The trajectory container (tng_data) + * must be initialised before using it. + * @pre \code file_name != 0 \endcode The pointer to the file name string + * must not be a NULL pointer. + * @return TNG_SUCCESS (0) if successful or TNG_CRITICAL (2) if a major + * error has occured. + */ +tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set + (tng_trajectory_t tng_data, + const char *file_name); + +/** * @brief Get the endianness of the output file. * @param tng_data the trajectory of which to get the endianness of the current * output file. @@ -2195,6 +2211,27 @@ tng_function_status DECLSPECDLLEXPORT tng_frame_set_write const char hash_mode); /** + * @brief Write one frame set even if it does not have as many frames as + * expected. The function also writes mapping and related data blocks + * to the output_file of tng_data. + * @param tng_data is a trajectory data container. + * @details tng_data->output_file_path specifies + * which file to write to. If the file (output_file) is not open it will be + * opened. + * @param hash_mode is an option to decide whether to use the md5 hash or not. + * If hash_mode == TNG_USE_HASH an md5 hash for each header block will be generated. + * @pre \code tng_data != 0 \endcode The trajectory container (tng_data) + * must be initialised before using it. + * @details The number of frames in the frame set is set to the number of + * frames of the data blocks before writing it to disk. + * @return TNG_SUCCESS (0) if successful, TNG_FAILURE (1) if a minor error + * has occurred or TNG_CRITICAL (2) if a major error has occured. + */ +tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write + (tng_trajectory_t tng_data, + const char hash_mode); + +/** * @brief Create and initialise a frame set. * @param tng_data is the trajectory data container in which to add the frame * set. diff --git a/src/lib/tng_io.c b/src/lib/tng_io.c index 9c6ce0f..11a2b4e 100644 --- a/src/lib/tng_io.c +++ b/src/lib/tng_io.c @@ -9249,6 +9249,52 @@ tng_function_status DECLSPECDLLEXPORT tng_output_file_set(tng_trajectory_t tng_d return(tng_output_file_init(tng_data)); } +tng_function_status DECLSPECDLLEXPORT tng_output_append_file_set + (tng_trajectory_t tng_data, + const char *file_name) +{ + int len; + char *temp; + + TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup."); + TNG_ASSERT(file_name, "TNG library: file_name must not be a NULL pointer"); + + if(tng_data->output_file_path && + strcmp(tng_data->output_file_path, file_name) == 0) + { + return(TNG_SUCCESS); + } + + if(tng_data->output_file) + { + fclose(tng_data->output_file); + } + + len = tng_min_i((int)strlen(file_name) + 1, TNG_MAX_STR_LEN); + temp = realloc(tng_data->output_file_path, len); + if(!temp) + { + printf("TNG library: Cannot allocate memory (%d bytes). %s: %d\n", len, + __FILE__, __LINE__); + free(tng_data->output_file_path); + tng_data->output_file_path = 0; + return(TNG_CRITICAL); + } + tng_data->output_file_path = temp; + + strncpy(tng_data->output_file_path, file_name, len); + + tng_data->output_file = fopen(tng_data->output_file_path, "r+"); + if(!tng_data->output_file) + { + printf("TNG library: Cannot open file %s. %s: %d\n", + tng_data->output_file_path, __FILE__, __LINE__); + return(TNG_CRITICAL); + } + + return(TNG_SUCCESS); +} + tng_function_status DECLSPECDLLEXPORT tng_output_file_endianness_get (tng_trajectory_t tng_data, tng_file_endianness *endianness) { @@ -11691,9 +11737,30 @@ tng_function_status tng_frame_set_write(tng_trajectory_t tng_data, frame_set->n_unwritten_frames = 0; + fflush(tng_data->output_file); + return(stat); } +tng_function_status DECLSPECDLLEXPORT tng_frame_set_premature_write + (tng_trajectory_t tng_data, + const char hash_mode) +{ + tng_trajectory_frame_set_t frame_set; + + TNG_ASSERT(tng_data, "TNG library: Trajectory container not properly setup."); + + frame_set = &tng_data->current_trajectory_frame_set; + + if(frame_set->n_unwritten_frames == 0) + { + return(TNG_SUCCESS); + } + frame_set->n_frames = frame_set->n_unwritten_frames; + + return(tng_frame_set_write(tng_data, hash_mode)); +} + tng_function_status DECLSPECDLLEXPORT tng_frame_set_new (tng_trajectory_t tng_data, const int64_t first_frame, @@ -15111,6 +15178,9 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open const char mode, tng_trajectory_t *tng_data_p) { + tng_function_status stat; + tng_gen_block_t block; + TNG_ASSERT(filename, "TNG library: filename must not be a NULL pointer."); if(mode != 'r' && mode != 'w' && mode != 'a') @@ -15132,10 +15202,56 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_open tng_file_headers_read(*tng_data_p, TNG_USE_HASH); } - if(mode == 'w' || mode == 'a') + if(mode == 'w') { tng_output_file_set(*tng_data_p, filename); } + else if(mode == 'a') + { + fseek((*tng_data_p)->input_file, + (long)(*tng_data_p)->last_trajectory_frame_set_input_file_pos, + SEEK_SET); + + tng_block_init(&block); + + stat = tng_block_header_read(*tng_data_p, block); + if(stat != TNG_SUCCESS || block->id != TNG_TRAJECTORY_FRAME_SET) + { + printf("TNG library: Cannot read trajectory frame set block header at pos %"PRId64". %s: %d\n", + (*tng_data_p)->last_trajectory_frame_set_input_file_pos, __FILE__, __LINE__); + tng_block_destroy(&block); + return(stat); + } + stat = tng_block_read_next(*tng_data_p, block, TNG_USE_HASH); + tng_block_destroy(&block); + if(stat != TNG_SUCCESS) + { + printf("TNG library: Error reading trajectory frame set block. %s: %d\n", + __FILE__, __LINE__); + return(stat); + } + + (*tng_data_p)->first_trajectory_frame_set_output_file_pos = + (*tng_data_p)->first_trajectory_frame_set_input_file_pos; + (*tng_data_p)->last_trajectory_frame_set_output_file_pos = + (*tng_data_p)->last_trajectory_frame_set_input_file_pos; + (*tng_data_p)->current_trajectory_frame_set_output_file_pos = + (*tng_data_p)->current_trajectory_frame_set_input_file_pos; + (*tng_data_p)->first_trajectory_frame_set_input_file_pos = -1; + (*tng_data_p)->last_trajectory_frame_set_input_file_pos = -1; + (*tng_data_p)->current_trajectory_frame_set_input_file_pos = -1; + if((*tng_data_p)->input_file) + { + fclose((*tng_data_p)->input_file); + (*tng_data_p)->input_file = 0; + } + if((*tng_data_p)->input_file_path) + { + free((*tng_data_p)->input_file_path); + (*tng_data_p)->input_file_path = 0; + } + tng_output_append_file_set(*tng_data_p, filename); + } return(TNG_SUCCESS); } -- cgit v0.10.1