Bug fix in the TNG library to improve reading.
authorMagnus Lundborg <lundborg.magnus@gmail.com>
Mon, 26 May 2014 15:59:55 +0000 (17:59 +0200)
committerDavid van der Spoel <davidvanderspoel@gmail.com>
Sat, 31 May 2014 08:05:00 +0000 (10:05 +0200)
Reading single frame frame sets did not work properly.
Fixes #1502 and partial fix of #1510.

Reread frame set after getting stride length.

Extra check to avoid reading past end of file when
checking what data blocks are present.

Change-Id: I5275382bd49b5b46ebfdebe535c53d2f09015bc0

src/external/tng_io/src/lib/tng_io.c

index efcaaabea07076b444ca15a998f5f66ac5a93051..b6c6f22227e791677bc752ec05d48e5f88a5debe 100644 (file)
@@ -1029,6 +1029,41 @@ static tng_function_status tng_block_header_read
 //     return(TNG_SUCCESS);
 // }
 */
+
+static tng_function_status tng_reread_frame_set_at_file_pos
+                (tng_trajectory_t tng_data,
+                 const int64_t pos)
+{
+    tng_gen_block_t block;
+    tng_function_status stat;
+
+    tng_block_init(&block);
+
+    fseek(tng_data->input_file, pos, SEEK_SET);
+    if(pos > 0)
+    {
+        stat = tng_block_header_read(tng_data, block);
+        if(stat == TNG_CRITICAL || block->id != TNG_TRAJECTORY_FRAME_SET)
+        {
+            fprintf(stderr, "TNG library: Cannot read block header at pos %"PRId64". %s: %d\n", pos,
+                    __FILE__, __LINE__);
+            tng_block_destroy(&block);
+            return(TNG_FAILURE);
+        }
+
+        if(tng_block_read_next(tng_data, block,
+                               TNG_SKIP_HASH) != TNG_SUCCESS)
+        {
+            tng_block_destroy(&block);
+            return(TNG_CRITICAL);
+        }
+    }
+
+    tng_block_destroy(&block);
+
+    return(TNG_SUCCESS);
+}
+
 /** Write the header of a data block, regardless of its type
  * @param tng_data is a trajectory data container.
  * @param block is a general block container.
@@ -16007,7 +16042,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
     tng_function_status stat;
     tng_non_particle_data_t np_data;
     tng_particle_data_t p_data;
-    long file_pos;
+    long orig_file_pos, file_pos;
     int is_particle_data;
 
     if(tng_data->current_trajectory_frame_set_input_file_pos <= 0)
@@ -16023,6 +16058,7 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
             return(stat);
         }
     }
+    orig_file_pos = tng_data->current_trajectory_frame_set_input_file_pos;
     stat = tng_data_find(tng_data, block_id, &np_data);
     if(stat != TNG_SUCCESS)
     {
@@ -16042,6 +16078,8 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
             }
             if(stat != TNG_SUCCESS)
             {
+                tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
+
                 return(stat);
             }
             stat = tng_data_find(tng_data, block_id, &np_data);
@@ -16050,6 +16088,8 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
                 stat = tng_particle_data_find(tng_data, block_id, &p_data);
                 if(stat != TNG_SUCCESS)
                 {
+                    tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
+
                     return(stat);
                 }
                 else
@@ -16079,6 +16119,8 @@ tng_function_status DECLSPECDLLEXPORT tng_data_get_stride_length
     {
         *stride_length = np_data->stride_length;
     }
+    tng_reread_frame_set_at_file_pos(tng_data, orig_file_pos);
+
     return(TNG_SUCCESS);
 }
 
@@ -16572,7 +16614,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_particle_data_next_frame_read
     }
     else
     {
-        i = data->last_retrieved_frame + data->stride_length;
+        if(data->n_frames == 1)
+        {
+            i = data->last_retrieved_frame + 1;
+        }
+        else
+        {
+            i = data->last_retrieved_frame + data->stride_length;
+        }
         if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
         {
             stat = tng_frame_set_of_frame_find(tng_data, i);
@@ -16725,7 +16774,14 @@ tng_function_status DECLSPECDLLEXPORT tng_util_non_particle_data_next_frame_read
     }
     else
     {
-        i = data->last_retrieved_frame + data->stride_length;
+        if(data->n_frames == 1)
+        {
+            i = data->last_retrieved_frame + 1;
+        }
+        else
+        {
+            i = data->last_retrieved_frame + data->stride_length;
+        }
         if(i < frame_set->first_frame || i >= frame_set->first_frame + frame_set->n_frames)
         {
             stat = tng_frame_set_of_frame_find(tng_data, i);
@@ -18319,33 +18375,38 @@ tng_function_status DECLSPECDLLEXPORT tng_util_trajectory_next_frame_present_dat
         }
     }
 
-    if(frame_set->n_particle_data_blocks <= 0 || frame_set->n_data_blocks <= 0)
+    /* If no data blocks have been found in the frame set check what data blocks
+     * are present. If they have already been found do not read them again. */
+    if(frame_set->n_particle_data_blocks <= 0 && frame_set->n_data_blocks <= 0)
     {
-        tng_block_init(&block);
         file_pos = ftell(tng_data->input_file);
         /* Read all blocks until next frame set block */
-        stat = tng_block_header_read(tng_data, block);
-        while(file_pos < tng_data->input_file_len &&
-            stat != TNG_CRITICAL &&
-            block->id != TNG_TRAJECTORY_FRAME_SET)
+        if(file_pos < tng_data->input_file_len)
         {
-            stat = tng_block_read_next(tng_data, block,
-                                       TNG_USE_HASH);
-            if(stat != TNG_CRITICAL)
+            tng_block_init(&block);
+            stat = tng_block_header_read(tng_data, block);
+            while(file_pos < tng_data->input_file_len &&
+                stat != TNG_CRITICAL &&
+                block->id != TNG_TRAJECTORY_FRAME_SET)
             {
-                file_pos = ftell(tng_data->input_file);
-                if(file_pos < tng_data->input_file_len)
+                stat = tng_block_read_next(tng_data, block,
+                                        TNG_USE_HASH);
+                if(stat != TNG_CRITICAL)
                 {
-                    stat = tng_block_header_read(tng_data, block);
+                    file_pos = ftell(tng_data->input_file);
+                    if(file_pos < tng_data->input_file_len)
+                    {
+                        stat = tng_block_header_read(tng_data, block);
+                    }
                 }
             }
-        }
-        tng_block_destroy(&block);
-        if(stat == TNG_CRITICAL)
-        {
-            fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
-                    file_pos, __FILE__, __LINE__);
-            return(stat);
+            tng_block_destroy(&block);
+            if(stat == TNG_CRITICAL)
+            {
+                fprintf(stderr, "TNG library: Cannot read block header at pos %ld. %s: %d\n",
+                        file_pos, __FILE__, __LINE__);
+                return(stat);
+            }
         }
         read_all = 1;
     }