Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libc/db/hash Fix hash iteration that deletes the current...



details:   https://anonhg.NetBSD.org/src/rev/2af452477a8b
branches:  trunk
changeset: 339027:2af452477a8b
user:      christos <christos%NetBSD.org@localhost>
date:      Mon Jun 22 21:16:02 2015 +0000

description:
Fix hash iteration that deletes the current element under the cursor by
adjusting the position of the iterator appropriately.
XXX: pullup 7

diffstat:

 lib/libc/db/hash/hash.c |  38 ++++++++++++++++++++++++++++++++++----
 1 files changed, 34 insertions(+), 4 deletions(-)

diffs (83 lines):

diff -r 63ee145d26bc -r 2af452477a8b lib/libc/db/hash/hash.c
--- a/lib/libc/db/hash/hash.c   Mon Jun 22 19:11:00 2015 +0000
+++ b/lib/libc/db/hash/hash.c   Mon Jun 22 21:16:02 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: hash.c,v 1.34 2015/06/22 18:50:06 christos Exp $       */
+/*     $NetBSD: hash.c,v 1.35 2015/06/22 21:16:02 christos Exp $       */
 
 /*-
  * Copyright (c) 1990, 1993, 1994
@@ -37,7 +37,7 @@
 #endif
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: hash.c,v 1.34 2015/06/22 18:50:06 christos Exp $");
+__RCSID("$NetBSD: hash.c,v 1.35 2015/06/22 21:16:02 christos Exp $");
 
 #include "namespace.h"
 #include <sys/param.h>
@@ -690,6 +690,27 @@
        case HASH_DELETE:
                if (__delpair(hashp, rbufp, ndx))
                        return (ERROR);
+               /*
+                * Our index lags 2 behind on the same page when we are
+                * deleting the element pointed to by the index; otherwise
+                * deleting randomly from an iterated hash produces undefined
+                * results.
+                */
+               if (ndx != hashp->cndx - 2 || rbufp != hashp->cpage)
+                       break;
+
+               if (hashp->cndx > 1) {
+                       /* Move back one element */
+                       hashp->cndx -= 2;
+               } else {
+                       /*
+                        * Move back one page, and indicate to go to the last
+                        * element of the previous page by setting cndx to -1
+                        */
+                       hashp->cbucket--;
+                       hashp->cpage = NULL;
+                       hashp->cndx = -1;
+               }
                break;
        default:
                abort();
@@ -725,7 +746,7 @@
                if (!(bufp = hashp->cpage)) {
                        for (bucket = hashp->cbucket;
                            bucket <= (uint32_t)hashp->MAX_BUCKET;
-                           bucket++, hashp->cndx = 1) {
+                           bucket++) {
                                bufp = __get_buf(hashp, bucket, NULL, 0);
                                if (!bufp)
                                        return (ERROR);
@@ -739,10 +760,18 @@
                                hashp->cbucket = -1;
                                return (ABNORMAL);
                        }
+                       if (hashp->cndx == -1) {
+                               /* move to the last element of the page */
+                               hashp->cndx = 1;
+                               while (bp[hashp->cndx - 1] != 0)
+                                       hashp->cndx += 2;
+                       } else {
+                               /* start on the first element */
+                               hashp->cndx = 1;
+                       }
                } else {
                        bp = (uint16_t *)(void *)hashp->cpage->page;
                        if (flag == R_NEXT || flag == 0) {
-                               hashp->cndx += 2;
                                if (hashp->cndx > bp[0]) {
                                        hashp->cpage = NULL;
                                        hashp->cbucket++;
@@ -781,6 +810,7 @@
                data->data = (uint8_t *)hashp->cpage->page + bp[ndx + 1];
                data->size = bp[ndx] - bp[ndx + 1];
        }
+       hashp->cndx += 2;
        return (SUCCESS);
 }
 



Home | Main Index | Thread Index | Old Index