[PATCH 2/2] Cochran: Using rbstream for reads now.

John Van Ostrand john at vanostrand.com
Sun Jul 2 19:05:12 PDT 2017


Per-dive reading of the DC takes too long because of latency on
read commands. Rbstream solves this by reading ahead in large
blocks.
---
 src/cochran_commander.c | 77 +++++++++++++++++++------------------------------
 1 file changed, 30 insertions(+), 47 deletions(-)

diff --git a/src/cochran_commander.c b/src/cochran_commander.c
index ef9c5e4..5020792 100644
--- a/src/cochran_commander.c
+++ b/src/cochran_commander.c
@@ -29,6 +29,7 @@
 #include "serial.h"
 #include "array.h"
 #include "ringbuffer.h"
+#include "rbstream.h"
 
 #define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array))
 
@@ -471,22 +472,6 @@ cochran_commander_read (cochran_commander_device_t *device, dc_event_progress_t
 	return DC_STATUS_SUCCESS;
 }
 
-static unsigned int
-cochran_commander_read_retry (cochran_commander_device_t *device, dc_event_progress_t *progress, unsigned int address, unsigned char data[], unsigned int size)
-{
-	unsigned int saved_current = progress->current;
-	dc_status_t rc;
-
-	for (unsigned int tries = 0; tries < 3; tries++) {
-		rc = cochran_commander_read (device, progress, address, data, size);
-		if (rc != DC_STATUS_SUCCESS)
-			progress->current = saved_current;
-		else
-			break;
-	}
-	return rc;
-}
-
 
 /*
  *  For corrupt dives the end-of-samples pointer is 0xFFFFFFFF
@@ -549,7 +534,7 @@ cochran_commander_find_fingerprint(cochran_commander_device_t *device, cochran_d
 		dive_count = device->layout->rb_logbook_entry_count;
 	dive_count--;
 
-	int sample_read_size = 0;
+	unsigned int sample_read_size = 0;
 	data->invalid_profile_dive_num = -1;
 
 	// Remove the pre-dive events that occur after the last dive
@@ -596,12 +581,9 @@ cochran_commander_find_fingerprint(cochran_commander_device_t *device, cochran_d
 		}
 
 		unsigned int profile_pre = array_uint32_le(log_entry + device->layout->pt_profile_pre);
-		unsigned int profile_begin = array_uint32_le(log_entry + device->layout->pt_profile_begin);
-		unsigned int profile_end = array_uint32_le(log_entry + device->layout->pt_profile_end);
 
 		unsigned int sample_size = cochran_commander_profile_size(device, data, i, profile_pre, last_profile_pre);
 		last_profile_pre = profile_pre;
-		unsigned int read_size = cochran_commander_profile_size(device, data, i, profile_begin, profile_end);
 
 		// Determine if sample exists
 		if (profile_capacity_remaining > 0) {
@@ -612,7 +594,7 @@ cochran_commander_find_fingerprint(cochran_commander_device_t *device, cochran_d
 				data->invalid_profile_dive_num = i;
 			}
 			// Accumulate read size for progress bar
-			sample_read_size += read_size;
+			sample_read_size += sample_size;
 		}
 	}
 
@@ -949,6 +931,11 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
 	// Number of dives to read
 	dive_count = (rb_logbook_entry_count + head_dive - tail_dive) % rb_logbook_entry_count;
 
+	// Create rbstream
+	unsigned int last_start_address = array_uint32_le( data.logbook + ((head_dive - 1) * layout->rb_logbook_entry_size) + layout->pt_profile_end );
+	dc_rbstream_t *rbstream = NULL;
+	rc = dc_rbstream_new (&rbstream, abstract, 1, 131072, layout->rb_profile_begin, layout->rb_profile_end, last_start_address );
+
 	int invalid_profile_flag = 0;
 
 	// Loop through each dive
@@ -960,14 +947,17 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
 		unsigned int sample_start_address = array_uint32_le (log_entry + layout->pt_profile_begin);
 		unsigned int sample_end_address = array_uint32_le (log_entry + layout->pt_profile_end);
 
-		int sample_size = 0;
+		int sample_size = 0, pre_size = 0;
 
 		// Determine if profile exists
 		if (i == data.invalid_profile_dive_num)
 			invalid_profile_flag = 1;
 
-		if (!invalid_profile_flag)
+		if (!invalid_profile_flag) {
 			sample_size = cochran_commander_profile_size(device, &data, i, sample_start_address, sample_end_address);
+			pre_size = cochran_commander_profile_size(device, &data, i, sample_end_address, last_start_address);
+			last_start_address = sample_start_address;
+		}
 
 		// Build dive blob
 		unsigned int dive_size = layout->rb_logbook_entry_size + sample_size;
@@ -981,38 +971,30 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
 
 		// Read profile data
 		if (sample_size) {
-			if (sample_end_address == 0xFFFFFFFF)
-				// Corrupt dive, guess the end address
-				sample_end_address = cochran_commander_guess_sample_end_address(device, &data, i);
-
-			if (sample_start_address <= sample_end_address) {
-				rc = cochran_commander_read_retry (device, &progress, sample_start_address, dive + layout->rb_logbook_entry_size, sample_size);
-				if (rc != DC_STATUS_SUCCESS) {
-					ERROR (abstract->context, "Failed to read the sample data.");
-					status = rc;
-					free(dive);
+			if (pre_size) {
+				// Read throwaway sample data, pre-dive events and post-dive surface sample
+				unsigned char *pre = (unsigned char *) malloc (pre_size);
+				if (pre == NULL) {
+					status = DC_STATUS_NOMEMORY;
 					goto error;
 				}
-			} else {
-				// It wrapped the buffer, copy two sections
-				unsigned int size = layout->rb_profile_end - sample_start_address;
-
-				rc = cochran_commander_read_retry (device, &progress, sample_start_address, dive + layout->rb_logbook_entry_size, size);
+				rc = dc_rbstream_read(rbstream, &progress, pre, pre_size);
+				free(pre);
 				if (rc != DC_STATUS_SUCCESS) {
-					ERROR (abstract->context, "Failed to read the sample data.");
-					status = rc;
-					free(dive);
-					goto error;
-				}
-
-				rc = cochran_commander_read_retry (device, &progress, layout->rb_profile_begin, dive + layout->rb_logbook_entry_size + size, sample_end_address - layout->rb_profile_begin);
-				if (rc != DC_STATUS_SUCCESS) {
-					ERROR (abstract->context, "Failed to read the sample data.");
+					ERROR (abstract->context, "Cailed to read the pre-dive event data.");
 					status = rc;
 					free(dive);
 					goto error;
 				}
 			}
+			// read sample data
+			rc = dc_rbstream_read(rbstream, &progress, dive + layout->rb_logbook_entry_size, sample_size);
+			if (rc != DC_STATUS_SUCCESS) {
+				ERROR (abstract->context, "Failed to read the sample data.");
+				status = rc;
+				free(dive);
+				goto error;
+			}
 		}
 
 		if (callback && !callback (dive, dive_size, dive + layout->pt_fingerprint, layout->fingerprint_size, userdata)) {
@@ -1024,6 +1006,7 @@ cochran_commander_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
 	}
 
 error:
+	dc_rbstream_free(rbstream);
 	free(data.logbook);
 	return status;
 }
-- 
2.4.11



More information about the devel mailing list