Code

Added upstream patch bts499350-data-corruption.
authorSebastian Harl <sh@tokkee.org>
Sat, 20 Sep 2008 18:47:58 +0000 (20:47 +0200)
committerSebastian Harl <sh@tokkee.org>
Sat, 20 Sep 2008 18:54:56 +0000 (20:54 +0200)
This fixes data corruption when updating multiple values in one go.

Closes: #499350
debian/changelog
debian/patches/bts499350-data-corruption [new file with mode: 0644]
debian/patches/series

index 702068c65a6d4d390da93583463de05fdda02f59..8ad64ff90597e713ca995a5d3e547615f9c3e8d4 100644 (file)
@@ -1,3 +1,11 @@
+rrdtool (1.3.1-4) unstable; urgency=low
+
+  * debian/patches:
+    - Added upstream patch bts499350-data-corruption to fix data corruption
+      when updating multiple values in one go (Closes: #499350).
+
+ -- Sebastian Harl <sh@tokkee.org>  Sat, 20 Sep 2008 20:41:28 +0200
+
 rrdtool (1.3.1-3) unstable; urgency=low
 
   * Added "libxml2-dev" to librrd-dev's dependencies (Closes: #493342).
diff --git a/debian/patches/bts499350-data-corruption b/debian/patches/bts499350-data-corruption
new file mode 100644 (file)
index 0000000..a2425e4
--- /dev/null
@@ -0,0 +1,158 @@
+diff a/src/rrd_update.c b/src/rrd_update.c
+--- a/src/rrd_update.c
++++ b/src/rrd_update.c
+@@ -780,12 +780,10 @@ static int process_arg(
+     }
+     /* seek to the beginning of the rra's */
+     if (*rra_current != rra_begin) {
+-#ifndef HAVE_MMAP
+         if (rrd_seek(rrd_file, rra_begin, SEEK_SET) != 0) {
+             rrd_set_error("seek error in rrd");
+             return -1;
+         }
+-#endif
+         *rra_current = rra_begin;
+     }
+     rra_start = rra_begin;
+@@ -1868,95 +1866,70 @@ static int write_to_rras(
+ {
+     unsigned long rra_idx;
+     unsigned long rra_start;
+-    unsigned long rra_pos_tmp;  /* temporary byte pointer. */
+     time_t    rra_time = 0; /* time of update for a RRA */
++    unsigned long ds_cnt = rrd->stat_head->ds_cnt;
++    
+     /* Ready to write to disk */
+     rra_start = rra_begin;
++
+     for (rra_idx = 0; rra_idx < rrd->stat_head->rra_cnt; rra_idx++) {
+-        /* skip unless there's something to write */
+-        if (rra_step_cnt[rra_idx]) {
+-            /* write the first row */
++        rra_def_t *rra_def = &rrd->rra_def[rra_idx];
++        rra_ptr_t *rra_ptr = &rrd->rra_ptr[rra_idx];
++
++        /* for cdp_prep */
++        unsigned short scratch_idx;
++        unsigned long step_subtract;
++
++        for (scratch_idx = CDP_primary_val,
++                 step_subtract = 1;
++             rra_step_cnt[rra_idx] > 0;
++             rra_step_cnt[rra_idx]--,
++                 scratch_idx = CDP_secondary_val,
++                 step_subtract = 2) {
++
++            unsigned long rra_pos_new;
+ #ifdef DEBUG
+             fprintf(stderr, "  -- RRA Preseek %ld\n", rrd_file->pos);
+ #endif
+-            rrd->rra_ptr[rra_idx].cur_row++;
+-            if (rrd->rra_ptr[rra_idx].cur_row >=
+-                rrd->rra_def[rra_idx].row_cnt)
+-                rrd->rra_ptr[rra_idx].cur_row = 0;  /* wrap around */
+-            /* position on the first row */
+-            rra_pos_tmp = rra_start +
+-                (rrd->stat_head->ds_cnt) * (rrd->rra_ptr[rra_idx].cur_row) *
+-                sizeof(rrd_value_t);
+-            if (rra_pos_tmp != *rra_current) {
+-                if (rrd_seek(rrd_file, rra_pos_tmp, SEEK_SET) != 0) {
++            /* increment, with wrap-around */
++            if (++rra_ptr->cur_row >= rra_def->row_cnt)
++              rra_ptr->cur_row = 0;
++
++            /* we know what our position should be */
++            rra_pos_new = rra_start
++              + ds_cnt * rra_ptr->cur_row * sizeof(rrd_value_t);
++
++            /* re-seek if the position is wrong or we wrapped around */
++            if (rra_pos_new != *rra_current || rra_ptr->cur_row == 0) {
++                if (rrd_seek(rrd_file, rra_pos_new, SEEK_SET) != 0) {
+                     rrd_set_error("seek error in rrd");
+                     return -1;
+                 }
+-                *rra_current = rra_pos_tmp;
++                *rra_current = rra_pos_new;
+             }
+ #ifdef DEBUG
+             fprintf(stderr, "  -- RRA Postseek %ld\n", rrd_file->pos);
+ #endif
+-            if (!skip_update[rra_idx]) {
+-                if (*pcdp_summary != NULL) {
+-                    rra_time = (current_time - current_time
+-                                % (rrd->rra_def[rra_idx].pdp_cnt *
+-                                   rrd->stat_head->pdp_step))
+-                        -
+-                        ((rra_step_cnt[rra_idx] -
+-                          1) * rrd->rra_def[rra_idx].pdp_cnt *
+-                         rrd->stat_head->pdp_step);
+-                }
+-                if (write_RRA_row
+-                    (rrd_file, rrd, rra_idx, rra_current, CDP_primary_val,
+-                     pcdp_summary, rra_time) == -1)
+-                    return -1;
+-            }
+-            /* write other rows of the bulk update, if any */
+-            for (; rra_step_cnt[rra_idx] > 1; rra_step_cnt[rra_idx]--) {
+-                if (++rrd->rra_ptr[rra_idx].cur_row ==
+-                    rrd->rra_def[rra_idx].row_cnt) {
+-#ifdef DEBUG
+-                    fprintf(stderr,
+-                            "Wraparound for RRA %s, %lu updates left\n",
+-                            rrd->rra_def[rra_idx].cf_nam,
+-                            rra_step_cnt[rra_idx] - 1);
+-#endif
+-                    /* wrap */
+-                    rrd->rra_ptr[rra_idx].cur_row = 0;
+-                    /* seek back to beginning of current rra */
+-                    if (rrd_seek(rrd_file, rra_start, SEEK_SET) != 0) {
+-                        rrd_set_error("seek error in rrd");
+-                        return -1;
+-                    }
+-#ifdef DEBUG
+-                    fprintf(stderr, "  -- Wraparound Postseek %ld\n",
+-                            rrd_file->pos);
+-#endif
+-                    *rra_current = rra_start;
+-                }
+-                if (!skip_update[rra_idx]) {
+-                    if (*pcdp_summary != NULL) {
+-                        rra_time = (current_time - current_time
+-                                    % (rrd->rra_def[rra_idx].pdp_cnt *
+-                                       rrd->stat_head->pdp_step))
+-                            -
+-                            ((rra_step_cnt[rra_idx] -
+-                              2) * rrd->rra_def[rra_idx].pdp_cnt *
+-                             rrd->stat_head->pdp_step);
+-                    }
+-                    if (write_RRA_row(rrd_file, rrd, rra_idx, rra_current,
+-                                      CDP_secondary_val, pcdp_summary,
+-                                      rra_time) == -1)
+-                        return -1;
+-                }
++            if (skip_update[rra_idx])
++                continue;
++
++            if (*pcdp_summary != NULL) {
++                unsigned long step_time = rra_def->pdp_cnt * rrd->stat_head->pdp_step;
++
++                rra_time = (current_time - current_time % step_time)
++                    - ((rra_step_cnt[rra_idx] - step_subtract) * step_time);
+             }
++
++            if (write_RRA_row
++                (rrd_file, rrd, rra_idx, rra_current, scratch_idx,
++                 pcdp_summary, rra_time) == -1)
++                return -1;
+         }
+-        rra_start += rrd->rra_def[rra_idx].row_cnt * rrd->stat_head->ds_cnt *
+-            sizeof(rrd_value_t);
+-    }                   /* RRA LOOP */
++
++        rra_start += rra_def->row_cnt * ds_cnt * sizeof(rrd_value_t);
++    } /* RRA LOOP */
+     return 0;
+ }
index cd2055ff4d695918576215725094f431f4bcfec6..a900298d1986ff063b94b9c8cf0facde178da40d 100644 (file)
@@ -4,3 +4,4 @@ setup.py-module-name
 no-rpath-for-ruby
 no-rpath-for-perl
 implicit-decl-fix
+bts499350-data-corruption