Fix hash iteration that deletes the current element under the cursor by
adjusting the position of the iterator appropriately. XXX: pullup 7
This commit is contained in:
parent
2906f58b81
commit
25bda9e7c1
|
@ -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 @@ found:
|
|||
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 @@ next_bucket:
|
|||
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 @@ next_bucket:
|
|||
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 @@ next_bucket:
|
|||
data->data = (uint8_t *)hashp->cpage->page + bp[ndx + 1];
|
||||
data->size = bp[ndx] - bp[ndx + 1];
|
||||
}
|
||||
hashp->cndx += 2;
|
||||
return (SUCCESS);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue