From 1b6e1fdd33c955936834c2c126b3d5d1aa7d6435 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 31 Dec 2022 02:03:47 -0600 Subject: [PATCH] Fixed delete issue with cut starting in a red edge Though this is a bit of an ugly fix... Red edges mess everything up during deletion since we always need to go down red edges in case we need to do a red flip. This puts our algorithm into an awkward state. It would be easier to do away with colors completely when we start deleting (after all this branch of the tree _will_ be shrinking), but this conflicts with the ultimate goal of deduplicate rbyd append. --- lfs.c | 36 +++++++----- tests/test_rbyd.toml | 128 +++++++++++++++++++++---------------------- 2 files changed, 87 insertions(+), 77 deletions(-) diff --git a/lfs.c b/lfs.c index e9a3a68a..58c57a7c 100644 --- a/lfs.c +++ b/lfs.c @@ -1568,9 +1568,9 @@ static int lfs_rbyd_append(lfs_t *lfs, lfs_rbyd_t *rbyd_, // should've taken red alt? needs a flip if (lt < 0 || gt < 0) { - LFS_ASSERT(lfs_rtag_isblack(alt)); LFS_ASSERT(p_alts[0]); LFS_ASSERT(lfs_rtag_isred(p_alts[0])); + LFS_ASSERT(lfs_rtag_isblack(alt)); printf("rflip %s (%x,%x)\n", lfs_rtag_isparallel(alt, p_alts[0]) ? "parallel" : "perpendicular", @@ -1777,7 +1777,7 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, // queue of pending alts we can emulate rotations with lfs_rtag_t p_alts[3] = {0, 0, 0}; lfs_off_t p_jumps[3] = {0, 0, 0}; - lfs_off_t graft = 0; + lfs_off_t graft = lower_branch; // descend down tree, building alt pointers while (true) { @@ -1804,7 +1804,14 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, if (!cut && lfs_rtag_follow(alt, lower_lt, lower_gt) != lfs_rtag_follow(alt, upper_lt, upper_gt)) { printf("beginning cut\n"); + printf("lower, upper = (%x, %x), (%x, %x)\n", lower_lt, lower_gt, upper_lt, upper_gt); cut = true; + + // TODO do we need this if we flip red alts early? + if (p_alts[0] && lfs_rtag_isred(p_alts[0])) { + upper_branch = graft; + lfs_rtag_untrim(p_alts[0], &upper_lt, &upper_gt); + } } // prune? @@ -1847,7 +1854,7 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, } else { printf("ysplit nofollow\n"); - LFS_ASSERT(graft != 0); +// LFS_ASSERT(graft != 0); p_alts[0] = lfs_rtag_black( lfs_rtag_merge(alt, p_alts[0])); p_jumps[0] = graft; @@ -1855,7 +1862,7 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, lfs_rtag_trim(alt, <, >); lfs_rbyd_p_red(p_alts, p_jumps); - graft = 0; + graft = branch; branch = branch_; goto next; } @@ -1863,13 +1870,12 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, // should've taken red alt? needs a flip if (lt < 0 || gt < 0) { - LFS_ASSERT(lfs_rtag_isblack(alt)); - LFS_ASSERT(p_alts[0]); - LFS_ASSERT(lfs_rtag_isred(p_alts[0])); - printf("rflip %s (%x,%x)\n", lfs_rtag_isparallel(alt, p_alts[0]) ? "parallel" : "perpendicular", lt, gt); + LFS_ASSERT(p_alts[0]); + LFS_ASSERT(lfs_rtag_isred(p_alts[0])); + LFS_ASSERT(lfs_rtag_isblack(alt)); // if black alt would've been taken, it also needs a flip if (lfs_rtag_isparallel(alt, p_alts[0])) { @@ -1901,13 +1907,16 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, // TODO can this be combined with prune? maybe not? // cut? - if (cut && ((lower && lfs_rtag_isgt(alt)) - || (!lower && lfs_rtag_islt(alt)))) { - if (p_alts[0]) { + if (cut && lfs_rtag_isblack(alt) + && ((lower && lfs_rtag_isgt(alt)) + || (!lower && lfs_rtag_islt(alt)))) { + if (p_alts[0] && lfs_rtag_isred(p_alts[0])) { + printf("bcut\n"); p_alts[0] = lfs_rtag_black(p_alts[0]); if ((lower && lfs_rtag_isgt(alt)) || (!lower && lfs_rtag_islt(alt))) { + printf("rcut\n"); lfs_rbyd_p_pop(p_alts, p_jumps); } } @@ -1941,9 +1950,9 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, } // switch bounds we are following? - if (cut && lfs_rtag_isblack(alt) && !other_done) { - printf("switch bounds\n"); + if (cut && p_alts[0] && lfs_rtag_isblack(p_alts[0]) && !other_done) { lower = !lower; + printf("switch bounds -> %s\n", lower ? "lower" : "upper"); } // found end of tree? @@ -1985,6 +1994,7 @@ static int lfs_rbyd_delete(lfs_t *lfs, lfs_rbyd_t *rbyd_, if (cut && !other_done) { other_done = true; lower = !lower; + printf("switch bounds -> %s\n", lower ? "lower" : "upper"); continue; } diff --git a/tests/test_rbyd.toml b/tests/test_rbyd.toml index 2da72815..ce561019 100644 --- a/tests/test_rbyd.toml +++ b/tests/test_rbyd.toml @@ -2149,7 +2149,7 @@ code = ''' ### Insertion testing ### -[cases.test_rbyd_insert] +[cases.test_rbyd_create] in = 'lfs.c' code = ''' lfs_t lfs; @@ -2167,7 +2167,7 @@ code = ''' lfs_rbyd_t rbyd; uint8_t buffer[4]; - // try to insert one id + // try to create one id rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2184,7 +2184,7 @@ code = ''' => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - // try to insert two ids + // try to create two ids rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2204,7 +2204,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - // try to insert two in the other direction + // try to create two in the other direction rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2224,7 +2224,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - // insert a third to the right + // create a third to the right rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2249,7 +2249,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - // insert a third to the left + // create a third to the left rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2274,7 +2274,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - // insert a third in the middle + // create a third in the middle rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2300,7 +2300,7 @@ code = ''' assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); ''' -[cases.test_rbyd_multi_insert] +[cases.test_rbyd_multi_create] in = 'lfs.c' code = ''' lfs_t lfs; @@ -2318,7 +2318,7 @@ code = ''' lfs_rbyd_t rbyd; uint8_t buffer[4]; - // try to insert one id + // try to create one id rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2335,7 +2335,7 @@ code = ''' => 4; assert(memcmp(buffer, "\xaa\xaa\xaa\xaa", 4) == 0); - // try to insert two ids + // try to create two ids rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2356,7 +2356,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - // try to insert two in the other direction + // try to create two in the other direction rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2377,7 +2377,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) => 4; assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); - // insert a third to the right + // create a third to the right rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2404,7 +2404,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - // insert a third to the left + // create a third to the left rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2431,7 +2431,7 @@ code = ''' lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) => 4; assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); - // insert a third in the middle + // create a third in the middle rbyd = init_rbyd; lfs_bd_erase(&lfs, rbyd.block) => 0; lfs_rbyd_commit(&lfs, &rbyd, @@ -2459,7 +2459,7 @@ code = ''' assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); ''' -[cases.test_rbyd_insert_permutations] +[cases.test_rbyd_create_permutations] defines.N = 'range(1, 8)' in = 'lfs.c' code = ''' @@ -2556,7 +2556,7 @@ code = ''' } ''' -[cases.test_rbyd_multi_insert_permutations] +[cases.test_rbyd_multi_create_permutations] defines.N = 'range(1, 8)' in = 'lfs.c' code = ''' @@ -2649,7 +2649,7 @@ code = ''' } ''' -[cases.test_rbyd_insert_large] +[cases.test_rbyd_create_large] in = 'lfs.c' # ORDER: # 0 = in-order @@ -3024,53 +3024,53 @@ code = ''' // lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) // => LFS_ERR_NOENT; -// // try to delete the smallest of three -// rbyd = init_rbyd; -// lfs_bd_erase(&lfs, rbyd.block) => 0; -// lfs_rbyd_commit(&lfs, &rbyd, -// LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, -// LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa\xaa\xaa", 4, -// LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, -// LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb\xbb\xbb", 4, -// LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, -// LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc\xcc\xcc", 4, NULL))))))) => 0; -// lfs_rbyd_commit(&lfs, &rbyd, -// LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0; -// -// assert(rbyd.count == 2); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); -//// TODO -//// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) -//// => LFS_ERR_NOENT; -// -// lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; -// assert(rbyd.count == 2); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); -// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) -// => 4; -// assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); -//// TODO -//// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) -//// => LFS_ERR_NOENT; + // try to delete the smallest of three + rbyd = init_rbyd; + lfs_bd_erase(&lfs, rbyd.block) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(CREATEREG, 0, 1, "\xaa\xaa\xaa\xaa", 4, + LFS_MKRATTR(UATTR, 0, 1, "\xaa\xaa\xaa\xaa", 4, + LFS_MKRATTR(CREATEREG, 0, 2, "\xbb\xbb\xbb\xbb", 4, + LFS_MKRATTR(UATTR, 0, 2, "\xbb\xbb\xbb\xbb", 4, + LFS_MKRATTR(CREATEREG, 0, 3, "\xcc\xcc\xcc\xcc", 4, + LFS_MKRATTR(UATTR, 0, 3, "\xcc\xcc\xcc\xcc", 4, NULL))))))) => 0; + lfs_rbyd_commit(&lfs, &rbyd, + LFS_MKRATTR(DELETE, 0, 1, NULL, 0, NULL)) => 0; + + assert(rbyd.count == 2); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) + => 4; + assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + => 4; + assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) + => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); +// TODO +// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) +// => LFS_ERR_NOENT; + + lfs_rbyd_fetch(&lfs, &rbyd, rbyd.block, NULL) => 0; + assert(rbyd.count == 2); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 1), buffer, 4) + => 4; + assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 1), buffer, 4) + => 4; + assert(memcmp(buffer, "\xbb\xbb\xbb\xbb", 4) == 0); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 2), buffer, 4) + => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); + lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(UATTR, 0, 2), buffer, 4) + => 4; + assert(memcmp(buffer, "\xcc\xcc\xcc\xcc", 4) == 0); +// TODO +// lfs_rbyd_get(&lfs, &rbyd, LFS_MKRTAG(CREATEREG, 0, 3), buffer, 4) +// => LFS_ERR_NOENT; // try to delete the middle rbyd = init_rbyd;