From 5e127578f0c68ee9baa67d867d75c6a714bd1176 Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Tue, 27 Sep 2016 12:55:42 -0400 Subject: Add hal_ks_index_replace(). --- hal_internal.h | 10 ++++++++++ ks_flash.c | 7 +------ ks_index.c | 42 +++++++++++++++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/hal_internal.h b/hal_internal.h index 2318748..ef0d763 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -645,6 +645,16 @@ extern hal_error_t hal_ks_index_delete(hal_ks_index_t *ksi, const hal_uuid_t * const name, unsigned *blockno); +/* + * Replace a key block with a new one, return new block number. + * Name of block does not change. This is an optimization of + * a delete immediately followed by an add for the same name. + */ + +extern hal_error_t hal_ks_index_replace(hal_ks_index_t *ksi, + const hal_uuid_t * const name, + unsigned *blockno); + /* * RPC lowest-level send and receive routines. These are blocking, and * transport-specific (sockets, USB). diff --git a/ks_flash.c b/ks_flash.c index c53347b..895f7df 100644 --- a/ks_flash.c +++ b/ks_flash.c @@ -1012,16 +1012,11 @@ static hal_error_t update_pin_block(const unsigned b1, * the all-zeros UUID). Maybe later. */ - if ((err = hal_ks_index_delete(&db.ksi, &pin_uuid, &b2)) != HAL_OK) + if ((err = hal_ks_index_replace(&db.ksi, &pin_uuid, &b2)) != HAL_OK) return err; - if (b2 != b1) - return HAL_ERROR_IMPOSSIBLE; - block->pin = *new_data; - err = hal_ks_index_add(&db.ksi, &pin_uuid, &b2); - if (err == HAL_OK) cache_mark_used(block, b2); diff --git a/ks_index.c b/ks_index.c index b35d5e0..476faf9 100644 --- a/ks_index.c +++ b/ks_index.c @@ -170,7 +170,7 @@ hal_error_t hal_ks_index_add(hal_ks_index_t *ksi, /* * Grab first block on free list, which makes room to slide the - * index down by one slot so we can insert the new block number. + * index up by one slot so we can insert the new block number. */ const size_t len = (ksi->used - where) * sizeof(*ksi->index); @@ -215,14 +215,38 @@ hal_error_t hal_ks_index_delete(hal_ks_index_t *ksi, return HAL_OK; } -/* - * Might want a hal_ks_index_replace(), which would be an efficiency - * hack replacement (roughly 2x) for a delete followed by an add with - * the same name. Implementation would be to find the old existing - * block, pull the first block off the free list, sliding the free - * list down, drop the new block in instead of the old, put the old - * block at the end of the free list, and return the new block. - */ +hal_error_t hal_ks_index_replace(hal_ks_index_t *ksi, + const hal_uuid_t * const name, + unsigned *blockno) +{ + if (ksi == NULL || ksi->index == NULL || ksi->names == NULL || + ksi->size == 0 || ksi->used > ksi->size || name == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + if (ksi->used == ksi->size) + return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE; + + int where; + + if (ksi->used == 0 || !ks_find(ksi, name, &where)) + return HAL_ERROR_KEY_NOT_FOUND; + + /* + * Grab first block from free list, slide free list down, put old + * block at end of free list and replace old block with new block. + */ + + const size_t len = (ksi->size - ksi->used - 1) * sizeof(*ksi->index); + const uint16_t b = ksi->index[ksi->used]; + memmove(&ksi->index[ksi->used + 1], &ksi->index[ksi->used], len); + ksi->index[ksi->size - 1] = ksi->index[where]; + ksi->index[where] = b; + + if (blockno != NULL) + *blockno = b; + + return HAL_OK; +} /* * Local variables: -- cgit v1.2.3