]> git.neil.brown.name Git - wiggle.git/commitdiff
bestmatch: improve poor matches.
authorNeilBrown <neilb@suse.de>
Thu, 14 Feb 2013 05:30:29 +0000 (16:30 +1100)
committerNeilBrown <neilb@suse.de>
Thu, 14 Feb 2013 05:30:29 +0000 (16:30 +1100)
If the bestmatch doens't include all of the lines in a hunk, try to
find matches between the unmatch parts of the hunk, and surrounding
text in the original.

This is particularly useful when some of the context is just blank
lines.  The best-match algorithm might ignore blank lines because they
aren't big enough to justify much distance from the rest of the match.

This makes tests/linux/raid1-A/merge a lot nicer.

Signed-off-by: NeilBrown <neilb@suse.de>
bestmatch.c
tests/linux/md-resync/merge
tests/linux/raid1-A/merge

index e839cb0246b9b6ee2a64d944ba79bf97a522400a..578dc0bc956f6298e032a704a57e643bc11adb01 100644 (file)
@@ -468,6 +468,7 @@ struct csl *pdiff(struct file a, struct file b, int chunks)
        struct best *best = xmalloc(sizeof(struct best)*(chunks+1));
        int i;
        struct file asmall, bsmall;
+       int xmin;
 
        asmall = reduce(a);
        bsmall = reduce(b);
@@ -484,12 +485,70 @@ struct csl *pdiff(struct file a, struct file b, int chunks)
                free(bsmall.list);
 
        csl1 = NULL;
+       xmin = 0;
        for (i = 1; i <= chunks; i++)
                if (best[i].val > 0) {
+                       /* If we there are any newlines in the hunk before
+                        * ylo, then extend xlo back that many newlines if
+                        * possible and diff_partial the extended regions.
+                        */
+                       int lines = 0;
+                       int ylo = best[i].ylo;
+                       int yhi;
+                       while (ylo > 0 && b.list[ylo-1].start[0]) {
+                               ylo--;
+                               lines += !!ends_line(b.list[ylo]);
+                       }
+                       if (lines) {
+                               int xlo = best[i].xlo;
+                               while (lines && xlo > xmin) {
+                                       xlo--;
+                                       lines -= !!ends_line(a.list[xlo]);
+                               }
+                               while (xlo > xmin && !ends_line(a.list[xlo-1]))
+                                       xlo--;
+                               csl2 = diff_partial(a, b,
+                                                   xlo, best[i].xlo,
+                                                   ylo, best[i].ylo);
+                               csl1 = csl_join(csl1, csl2);
+                       }
+
+                       /* Now diff_partial the good bit of the hunk with the
+                        * good match
+                        */
                        csl2 = diff_partial(a, b,
                                            best[i].xlo, best[i].xhi,
                                            best[i].ylo, best[i].yhi);
                        csl1 = csl_join(csl1, csl2);
+
+                       /* Now if there are newlines at the end of the
+                        * hunk that weren't matched, find as many in
+                        * original and diff_partial those bits
+                        */
+                       lines = 0;
+                       yhi = best[i].yhi;
+                       while (yhi < b.elcnt && b.list[yhi].start[0]) {
+                               lines += !!ends_line(b.list[yhi]);
+                               yhi++;
+                       }
+                       xmin = best[i].xhi;
+                       if (lines) {
+                               int xhi = best[i].xhi;
+                               int xmax = a.elcnt;
+                               if (i < chunks)
+                                       xmax = best[i+1].xlo;
+                               while (lines && xhi < xmax) {
+                                       lines -= !!ends_line(a.list[xhi]);
+                                       xhi++;
+                               }
+                               csl2 = diff_partial(a, b,
+                                                   best[i].xhi, xhi,
+                                                   best[i].yhi, yhi);
+                               csl1 = csl_join(csl1, csl2);
+                               xmin = xhi;
+                       }
+               } else {
+                       /* FIXME we just lost a hunk!! */;
                }
        if (csl1) {
                for (csl2 = csl1; csl2->len; csl2++)
index b3d93fbc8b00b81db80ff449b46b557c25091a0a..8118461d59df9bf7bf8bb9f1205f50b707e912af 100644 (file)
@@ -1474,11 +1474,15 @@ nomem:
        raid1_shrink_buffers(conf);
        return -ENOMEM;
 }
+
+static void end_sync_read(struct buffer_head *bh, int uptodate)
 |||||||
        if (!sector_nr)
                if (init_resync(conf))
                        return -ENOMEM;
        /*
+        * If there is non-resync activity waiting for us then
+        * put in a delay to throttle resync.
 =======
        if (sector_nr == 0)
                if (init_resync(conf))
@@ -1491,9 +1495,9 @@ nomem:
        }
 
        /*
+        * If there is non-resync activity waiting for us then
+        * put in a delay to throttle resync.
 >>>>>>>
-
-static void end_sync_read(struct buffer_head *bh, int uptodate)
 {
        struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private);
 
@@ -1516,11 +1520,25 @@ static void end_sync_write(struct buffer_head *bh, int uptodate)
                md_error (r1_bh->mddev, bh->b_dev);
        if (atomic_dec_and_test(&r1_bh->remaining)) {
                mddev_t *mddev = r1_bh->mddev;
+<<<<<<<
                unsigned long sect = bh->b_blocknr;
                int size = bh->b_size;
                raid1_free_buf(r1_bh);
                sync_request_done(sect, mddev_to_conf(mddev));
                md_done_sync(mddev,size>>9, uptodate);
+|||||||
+       r1_bio->sector = sector_nr;
+       r1_bio->cmd = SPECIAL;
+
+       max_sector = mddev->sb->size << 1;
+       if (sector_nr >= max_sector)
+               BUG();
+
+=======
+       r1_bio->sector = sector_nr;
+       r1_bio->cmd = SPECIAL;
+
+>>>>>>>
        }
 }
 
index 8361ac4a1a206e92eb0d2d4786979f7743250b0b..eac97180884975e212ef02e314269a9da431be63 100644 (file)
@@ -936,12 +936,14 @@ static int make_request(mddev_t *mddev, struct bio * bio)
                bio_list_add(&conf->pending_bio_list, mbio);
                spin_unlock_irqrestore(&conf->device_lock, flags);
        }
+       r1_bio_write_done(r1_bio);
 |||||||
                                test_bit(R1BIO_BehindIO, &r1_bio->state));
        spin_lock_irqsave(&conf->device_lock, flags);
        bio_list_merge(&conf->pending_bio_list, &bl);
        bio_list_init(&bl);
 
+       blk_plug_device(mddev->queue);
 =======
                                test_bit(R1BIO_BehindIO, &r1_bio->state));
        spin_lock_irqsave(&conf->device_lock, flags);
@@ -949,8 +951,8 @@ static int make_request(mddev_t *mddev, struct bio * bio)
        conf->pending_count += bl_count;
        bio_list_init(&bl);
 
+       blk_plug_device(mddev->queue);
 >>>>>>>
-       r1_bio_write_done(r1_bio);
 
        /* In case raid1d snuck in to freeze_array */
        wake_up(&conf->wait_barrier);
@@ -1954,6 +1956,16 @@ static conf_t *setup_conf(mddev_t *mddev)
 
        conf->last_used = -1;
        for (i = 0; i < conf->raid_disks; i++) {
+|||||||
+       bio_list_init(&conf->flushing_bio_list);
+
+
+=======
+       conf->pending_count = 0;
+       bio_list_init(&conf->flushing_bio_list);
+
+
+>>>>>>>
 
                disk = conf->mirrors + i;
 
@@ -2317,13 +2329,3 @@ MODULE_ALIAS("md-raid1");
 MODULE_ALIAS("md-level-1");
 
 module_param(max_queued, int, S_IRUGO|S_IWUSR);
-|||||||
-       bio_list_init(&conf->flushing_bio_list);
-
-
-=======
-       conf->pending_count = 0;
-       bio_list_init(&conf->flushing_bio_list);
-
-
->>>>>>>