[Pkg-running-devel] [openambit] 67/131: Handle log buffer wraparounds correctly

Christian Perrier bubulle at moszumanska.debian.org
Thu Jul 17 20:19:12 UTC 2014


This is an automated email from the git hooks/post-receive script.

bubulle pushed a commit to branch master
in repository openambit.

commit 360acddf750b931a564db7a8cd081fd6588f7021
Author: Emil Ljungdahl <emil at kratern.se>
Date:   Thu Jan 23 23:16:35 2014 +0100

    Handle log buffer wraparounds correctly
---
 src/libambit/libambit_int.h |   3 +-
 src/libambit/pmem20.c       | 108 ++++++++++++++++++++++++++++++++------------
 2 files changed, 79 insertions(+), 32 deletions(-)

diff --git a/src/libambit/libambit_int.h b/src/libambit/libambit_int.h
index 880b9e7..4286859 100644
--- a/src/libambit/libambit_int.h
+++ b/src/libambit/libambit_int.h
@@ -50,8 +50,7 @@ struct ambit_object_s {
                 uint32_t prev;
             } current;
             uint8_t *buffer;
-            uint32_t prev_read;
-            uint32_t last_addr;
+            uint8_t *chunks_read;
         } log;
     } pmem20;
 };
diff --git a/src/libambit/pmem20.c b/src/libambit/pmem20.c
index 078cf66..b3646ea 100644
--- a/src/libambit/pmem20.c
+++ b/src/libambit/pmem20.c
@@ -29,10 +29,13 @@
 /*
  * Local definitions
  */
-#define PMEM20_LOG_START          0x000f4240
-#define PMEM20_LOG_SIZE           0x0029f630 /* 2 750 000 */
-#define PMEM20_LOG_HEADER_MIN_LEN        512 /* Header actually longer, but not interesting*/
-#define PMEM20_GPS_ORBIT_START    0x000704e0
+#define PMEM20_LOG_START                  0x000f4240
+#define PMEM20_LOG_SIZE                   0x0029f630 /* 2 750 000 */
+#define PMEM20_LOG_WRAP_START_OFFSET      0x00000012
+#define PMEM20_LOG_WRAP_BUFFER_MARGIN     0x00010000 /* Max theoretical size of sample */
+#define PMEM20_LOG_HEADER_MIN_LEN                512 /* Header actually longer, but not interesting*/
+
+#define PMEM20_GPS_ORBIT_START            0x000704e0
 
 typedef struct __attribute__((__packed__)) periodic_sample_spec_s {
     uint16_t type;
@@ -43,9 +46,9 @@ typedef struct __attribute__((__packed__)) periodic_sample_spec_s {
 /*
  * Static functions
  */
-static int parse_sample(uint8_t *buf, size_t *offset, uint8_t **spec, ambit_log_entry_t *log_entry, size_t *sample_count);
+static int parse_sample(uint8_t *buf, size_t offset, uint8_t **spec, ambit_log_entry_t *log_entry, size_t *sample_count);
 static int read_upto(ambit_object_t *object, uint32_t address, uint32_t length);
-static int read_log_chunk(ambit_object_t *object, uint32_t address, uint32_t length, uint8_t *buffer);
+static int read_log_chunk(ambit_object_t *object, uint32_t address);
 static int write_data_chunk(ambit_object_t *object, uint32_t address, size_t buffer_count, uint8_t **buffers, size_t *buffer_sizes);
 static void add_time(ambit_date_time_t *intime, int32_t offset, ambit_date_time_t *outtime);
 static int is_leap(unsigned int y);
@@ -76,15 +79,23 @@ int libambit_pmem20_log_init(ambit_object_t *object)
     if (object->pmem20.log.buffer != NULL) {
         free(object->pmem20.log.buffer);
     }
+    if (object->pmem20.log.chunks_read != NULL) {
+        free(object->pmem20.log.chunks_read);
+    }
     memset(&object->pmem20.log, 0, sizeof(object->pmem20.log));
-    object->pmem20.log.buffer = malloc(PMEM20_LOG_SIZE);
-    if (object->pmem20.log.buffer != NULL) {
+
+    object->pmem20.log.buffer = malloc(PMEM20_LOG_SIZE + PMEM20_LOG_WRAP_BUFFER_MARGIN);
+    object->pmem20.log.chunks_read = malloc((PMEM20_LOG_SIZE/object->pmem20.chunk_size)+1);
+
+    if (object->pmem20.log.buffer != NULL && object->pmem20.log.chunks_read != NULL) {
+        // Set all chunks to NOT read
+        memset(object->pmem20.log.chunks_read, 0, (PMEM20_LOG_SIZE/object->pmem20.chunk_size)+1);
+
         // Read initial log header
         LOG_INFO("Reading first log data chunk");
-        ret = read_log_chunk(object, PMEM20_LOG_START, object->pmem20.chunk_size, object->pmem20.log.buffer);
+        ret = read_log_chunk(object, PMEM20_LOG_START);
+        
         if (ret == 0) {
-            object->pmem20.log.prev_read = PMEM20_LOG_START;
-
             // Parse PMEM header
             offset = 0;
             object->pmem20.log.last_entry = read32inc(object->pmem20.log.buffer, &offset);
@@ -113,6 +124,9 @@ int libambit_pmem20_deinit(ambit_object_t *object)
     if (object->pmem20.log.buffer != NULL) {
         free(object->pmem20.log.buffer);
     }
+    if (object->pmem20.log.chunks_read != NULL) {
+        free(object->pmem20.log.chunks_read);
+    }
     memset(&object->pmem20.log, 0, sizeof(object->pmem20.log));
 
     return 0;
@@ -176,7 +190,7 @@ ambit_log_entry_t *libambit_pmem20_log_read_entry(ambit_object_t *object)
 {
     // Note! We assume that the caller has called libambit_pmem20_log_next_header just before
     uint8_t *periodic_sample_spec;
-    uint16_t tmp_len;
+    uint16_t tmp_len, sample_len;
     size_t buffer_offset, sample_count = 0, i;
     ambit_log_entry_t *log_entry;
     ambit_log_sample_t *last_periodic = NULL, *utcsource = NULL, *altisource = NULL;
@@ -226,12 +240,36 @@ ambit_log_entry_t *libambit_pmem20_log_read_entry(ambit_object_t *object)
 
     // OK, so we are at start of samples, get them all!
     while (sample_count < log_entry->samples_count) {
-        if (PMEM20_LOG_START + buffer_offset + 2 >= object->pmem20.log.last_addr ||
-            PMEM20_LOG_START + buffer_offset + 2 + read16(object->pmem20.log.buffer, buffer_offset) >= object->pmem20.log.last_addr) {
-            read_upto(object, PMEM20_LOG_START + buffer_offset, object->pmem20.chunk_size);
+        /* NOTE! The double reads below seems a bit unoptimized,
+           but if we need optimization, we should optimize read_upto
+           instead...
+           To ease the pain on wraparound we simply duplicate the sample
+           to the end of the buffer. */
+
+        // First check for log area wrap
+        if (buffer_offset >= PMEM20_LOG_SIZE - 1) {
+            read_upto(object, PMEM20_LOG_START + PMEM20_LOG_WRAP_START_OFFSET, 2);
+            sample_len = read16(object->pmem20.log.buffer, PMEM20_LOG_WRAP_START_OFFSET);
+        }
+        else if (buffer_offset == PMEM20_LOG_SIZE - 2) {
+            read_upto(object, PMEM20_LOG_START + PMEM20_LOG_WRAP_START_OFFSET, 1);
+            sample_len = object->pmem20.log.buffer[buffer_offset] | (object->pmem20.log.buffer[PMEM20_LOG_WRAP_START_OFFSET] << 8);
+        }
+        else {
+            read_upto(object, PMEM20_LOG_START + buffer_offset, 2);
+            sample_len = read16(object->pmem20.log.buffer, buffer_offset);
+        }
+
+        // Read all data
+        if (buffer_offset + 2 < (PMEM20_LOG_SIZE-1)) {
+            read_upto(object, PMEM20_LOG_START + buffer_offset + 2, sample_len);
+        }
+        if (buffer_offset + 2 + sample_len > PMEM20_LOG_SIZE) {
+            read_upto(object, PMEM20_LOG_START + PMEM20_LOG_WRAP_START_OFFSET, (buffer_offset + 2 + sample_len) - PMEM20_LOG_SIZE);
+            memcpy(object->pmem20.log.buffer + PMEM20_LOG_SIZE, object->pmem20.log.buffer + PMEM20_LOG_WRAP_START_OFFSET, (buffer_offset + 2 + sample_len) - PMEM20_LOG_SIZE);
         }
 
-        if (parse_sample(object->pmem20.log.buffer, &buffer_offset, &periodic_sample_spec, log_entry, &sample_count) == 1) {
+        if (parse_sample(object->pmem20.log.buffer, buffer_offset, &periodic_sample_spec, log_entry, &sample_count) == 1) {
             // Calculate times
             if (log_entry->samples[sample_count-1].type == ambit_log_sample_type_periodic) {
                 last_periodic = &log_entry->samples[sample_count-1];
@@ -277,6 +315,11 @@ ambit_log_entry_t *libambit_pmem20_log_read_entry(ambit_object_t *object)
                 altisource_index = sample_count-1;
             }
         }
+        buffer_offset += 2 + sample_len;
+        // Wrap
+        if (buffer_offset >= PMEM20_LOG_SIZE) {
+            buffer_offset = PMEM20_LOG_WRAP_START_OFFSET + (buffer_offset - PMEM20_LOG_SIZE);
+        }
     }
 
     // Loop through samples again and correct times etc
@@ -425,10 +468,10 @@ int libambit_pmem20_gps_orbit_write(ambit_object_t *object, uint8_t *data, size_
  * Parse the given sample
  * \return number of samples added (1 or 0)
  */
-static int parse_sample(uint8_t *buf, size_t *offset, uint8_t **spec, ambit_log_entry_t *log_entry, size_t *sample_count)
+static int parse_sample(uint8_t *buf, size_t offset, uint8_t **spec, ambit_log_entry_t *log_entry, size_t *sample_count)
 {
     int ret = 0;
-    size_t int_offset = *offset;
+    size_t int_offset = offset;
     uint16_t sample_len = read16inc(buf, &int_offset);
     uint8_t  sample_type = read8inc(buf, &int_offset);
     uint8_t  episodic_type;
@@ -439,11 +482,11 @@ static int parse_sample(uint8_t *buf, size_t *offset, uint8_t **spec, ambit_log_
     switch (sample_type) {
       case 0:   /* periodic sample specifier */
         // Update specifier on input
-        *spec = buf + *offset + 2;
+        *spec = buf + offset + 2;
         break;
       case 2:   /* periodic sample */
         log_entry->samples[*sample_count].type = ambit_log_sample_type_periodic;
-        log_entry->samples[*sample_count].time = read32(buf, *offset + sample_len - 2);
+        log_entry->samples[*sample_count].time = read32(buf, offset + sample_len - 2);
         
         // Loop through specifier and set corresponding fields
         spec_count = read16(*spec, 1);
@@ -691,27 +734,26 @@ static int parse_sample(uint8_t *buf, size_t *offset, uint8_t **spec, ambit_log_
             log_entry->samples[*sample_count].u.position.longitude = read32inc(buf, &int_offset);
             break;
           default:
-            LOG_WARNING("Found unknown episodic sample type (%02x)", episodic_type);
+            LOG_WARNING("Found unknown episodic sample type (0x%02x)", episodic_type);
             log_entry->samples[*sample_count].type = ambit_log_sample_type_unknown;
             log_entry->samples[*sample_count].u.unknown.datalen = sample_len;
             log_entry->samples[*sample_count].u.unknown.data = malloc(sample_len);
-            memcpy(log_entry->samples[*sample_count].u.unknown.data, buf + *offset + 2, sample_len);
+            memcpy(log_entry->samples[*sample_count].u.unknown.data, buf + offset + 2, sample_len);
             break;
         }
         ret = 1;
         break;
       default:
-        LOG_WARNING("Found unknown sample type (%02x)", sample_type);
+        LOG_WARNING("Found unknown sample type (0x%02x)", sample_type);
         log_entry->samples[*sample_count].type = ambit_log_sample_type_unknown;
         log_entry->samples[*sample_count].u.unknown.datalen = sample_len;
         log_entry->samples[*sample_count].u.unknown.data = malloc(sample_len);
-        memcpy(log_entry->samples[*sample_count].u.unknown.data, buf + *offset + 2, sample_len);
+        memcpy(log_entry->samples[*sample_count].u.unknown.data, buf + offset + 2, sample_len);
         ret = 1;
         break;
     }
 
     *sample_count += ret;
-    *offset += 2 + sample_len;
 
     return ret;
 }
@@ -721,12 +763,11 @@ static int read_upto(ambit_object_t *object, uint32_t address, uint32_t length)
     uint32_t start_address = address - ((address - PMEM20_LOG_START) % object->pmem20.chunk_size);
 
     while (start_address < address + length) {
-        if (object->pmem20.log.prev_read != start_address) {
-            if (read_log_chunk(object, start_address, object->pmem20.chunk_size, object->pmem20.log.buffer + (start_address - PMEM20_LOG_START)) != 0) {
+        if (object->pmem20.log.chunks_read[(start_address - PMEM20_LOG_START)/object->pmem20.chunk_size] == 0) {
+            if (read_log_chunk(object, start_address) != 0) {
                 return -1;
             }
-            object->pmem20.log.prev_read = start_address;
-            object->pmem20.log.last_addr = start_address + object->pmem20.chunk_size - 1;
+            object->pmem20.log.chunks_read[(start_address - PMEM20_LOG_START)/object->pmem20.chunk_size] = 1;
         }
         start_address += object->pmem20.chunk_size;
     }
@@ -734,10 +775,13 @@ static int read_upto(ambit_object_t *object, uint32_t address, uint32_t length)
     return 0;
 }
 
-static int read_log_chunk(ambit_object_t *object, uint32_t address, uint32_t length, uint8_t *buffer)
+static int read_log_chunk(ambit_object_t *object, uint32_t address)
 {
     int ret = -1;
 
+    uint8_t *buffer = object->pmem20.log.buffer + (address - PMEM20_LOG_START);
+    uint32_t length = object->pmem20.chunk_size;
+
     uint8_t *reply = NULL;
     size_t replylen = 0;
 
@@ -745,6 +789,10 @@ static int read_log_chunk(ambit_object_t *object, uint32_t address, uint32_t len
     uint32_t *_address = (uint32_t*)&send_data[0];
     uint32_t *_length = (uint32_t*)&send_data[4];
 
+    if ((address + object->pmem20.chunk_size) > (PMEM20_LOG_START + PMEM20_LOG_SIZE)) {
+        length = PMEM20_LOG_START + PMEM20_LOG_SIZE - address;
+    }
+
     *_address = htole32(address);
     *_length = htole32(length);
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-running/openambit.git



More information about the Pkg-running-devel mailing list