From c4959f62043cbaa45d6b0197f04ec318fa1b5f55 Mon Sep 17 00:00:00 2001 From: Konstantin Osipov <kostja@tarantool.org> Date: Wed, 18 Feb 2015 20:52:25 +0300 Subject: [PATCH] recovery: if panic_if_wal_error == false, try to find the best matching xlog. If we can't find the closest xlog starting before the current vclock of recovery, return the first xlog with vclcok after the search pattern, to continue recovery, even though missing some rows, in case when of panic_if_wal_error is false. A test case will follow in a separate patch. --- src/box/recovery.cc | 4 +++- src/box/vclock.c | 6 ++++++ src/box/vclock.h | 38 ++++++++++++++++++++++++++++---------- test/unit/vclock.cc | 2 +- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/box/recovery.cc b/src/box/recovery.cc index b2868fc64d..0cfb9cfeb3 100644 --- a/src/box/recovery.cc +++ b/src/box/recovery.cc @@ -408,7 +408,9 @@ recover_remaining_wals(struct recovery_state *r) } while (1) { - current_vclock = vclockset_isearch(&r->wal_dir.index, &r->vclock); + current_vclock = vclockset_match(&r->wal_dir.index, + &r->vclock, + r->wal_dir.panic_if_error); if (current_vclock == NULL) break; /* No more WALs */ diff --git a/src/box/vclock.c b/src/box/vclock.c index 7e564fb578..a01a21dbd4 100644 --- a/src/box/vclock.c +++ b/src/box/vclock.c @@ -191,6 +191,12 @@ static int vclockset_node_compare(const struct vclock *a, const struct vclock *b) { int res = vclock_compare(a, b); + /* + * In a vclock set, we do not allow vclock objects which + * are note strictly ordered. + * See also xdir_scan(), in which we check & skip + * duplicate vclocks. + */ if (res == VCLOCK_ORDER_UNDEFINED) return 0; return res; diff --git a/src/box/vclock.h b/src/box/vclock.h index c041215f98..ae3a4b8a51 100644 --- a/src/box/vclock.h +++ b/src/box/vclock.h @@ -181,21 +181,39 @@ typedef rb_tree(struct vclock) vclockset_t; rb_proto(, vclockset_, vclockset_t, struct vclock); /** - * @brief Inclusive search - * @param set - * @param key + * A proximity search in a set of vclock objects. + * + * The set is normally the index of vclocks in the binary + * log files of the current directory. The task of the search is + * to find the first log, + * * @return a vclock that <= than \a key */ static inline struct vclock * -vclockset_isearch(vclockset_t *set, struct vclock *key) +vclockset_match(vclockset_t *set, struct vclock *key, + bool panic_if_error) { - struct vclock *res = vclockset_psearch(set, key); - while (res != NULL) { - if (vclock_compare(res, key) <= 0) - return res; - res = vclockset_prev(set, res); + struct vclock *match = vclockset_psearch(set, key); + /** + * vclockset comparator returns 0 for + * incomparable keys. So the match doesn't have to be + * strictly preceding the search key, it may be + * incomparable. If this is the case, unwind until + * we get to a key which is strictly below the search + * pattern. + */ + while (match != NULL) { + if (vclock_compare(match, key) <= 0) + return match; + /* The order is undefined, try the previous vclock. */ + match = vclockset_prev(set, match); } - return NULL; + /* + * There is no xlog which is strictly less than the search + * pattern. Return the fist successor log - it is either + * strictly greater, or incomparable with the key. + */ + return panic_if_error ? NULL: vclockset_first(set); } #if defined(__cplusplus) diff --git a/test/unit/vclock.cc b/test/unit/vclock.cc index 172d263748..282a88cac8 100644 --- a/test/unit/vclock.cc +++ b/test/unit/vclock.cc @@ -231,7 +231,7 @@ test_isearch() } int64_t check = *(query + NODE_N); - struct vclock *res = vclockset_isearch(&set, &vclock); + struct vclock *res = vclockset_match(&set, &vclock, true); int64_t value = res != NULL ? vclock_signature(res) : INT64_MAX; is(value, check, "query #%d", q + 1); } -- GitLab