aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hal_internal.h10
-rw-r--r--ks_flash.c7
-rw-r--r--ks_index.c42
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
@@ -646,6 +646,16 @@ extern hal_error_t hal_ks_index_delete(hal_ks_index_t *ksi,
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: