From 5982d7c88de38c0dc98d22ebe9ce6452e17f4e45 Mon Sep 17 00:00:00 2001 From: hihihuhu Date: Mon, 23 Jan 2023 14:44:20 -0800 Subject: [PATCH 1/5] cache schema version by timestamp --- infoschema/cache.go | 69 ++++++++++++++++++++++++++++++++++------ infoschema/cache_test.go | 58 +++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 10 deletions(-) diff --git a/infoschema/cache.go b/infoschema/cache.go index 34cc08eca2231..af5975ab95efc 100644 --- a/infoschema/cache.go +++ b/infoschema/cache.go @@ -15,6 +15,7 @@ package infoschema import ( + "fmt" "sort" "sync" @@ -38,13 +39,22 @@ type InfoCache struct { mu sync.RWMutex // cache is sorted by SchemaVersion in descending order cache []InfoSchema - // record SnapshotTS of the latest schema Insert. - maxUpdatedSnapshotTS uint64 + + // keep ts to version mapping + tsToVersion map[uint64]int64 + versionToTs map[int64]uint64 + // maintain the order everytime the cahce is updated + descSortedTs []uint64 } // NewCache creates a new InfoCache. func NewCache(capacity int) *InfoCache { - return &InfoCache{cache: make([]InfoSchema, 0, capacity)} + return &InfoCache{ + cache: make([]InfoSchema, 0, capacity), + tsToVersion: make(map[uint64]int64), + versionToTs: make(map[int64]uint64), + descSortedTs: make([]uint64, 0, capacity), + } } // Reset resets the cache. @@ -52,6 +62,9 @@ func (h *InfoCache) Reset(capacity int) { h.mu.Lock() defer h.mu.Unlock() h.cache = make([]InfoSchema, 0, capacity) + h.tsToVersion = make(map[uint64]int64) + h.versionToTs = make(map[int64]uint64) + h.descSortedTs = make([]uint64, 0, capacity) } // GetLatest gets the newest information schema. @@ -66,10 +79,26 @@ func (h *InfoCache) GetLatest() InfoSchema { return nil } +// GetVersionByTimestamp returns the schema version used at the specific timestamp +func (h *InfoCache) GetVersionByTimestamp(ts uint64) (int64, error) { + h.mu.RLock() + defer h.mu.RUnlock() + + i := sort.Search(len(h.descSortedTs), func(i int) bool { + return h.descSortedTs[i] <= ts + }) + if i < len(h.descSortedTs) { + return h.tsToVersion[h.descSortedTs[i]], nil + } + + return 0, fmt.Errorf("no schema cached for timestamp %d", ts) +} + // GetByVersion gets the information schema based on schemaVersion. Returns nil if it is not loaded. func (h *InfoCache) GetByVersion(version int64) InfoSchema { h.mu.RLock() defer h.mu.RUnlock() + getVersionCounter.Inc() i := sort.Search(len(h.cache), func(i int) bool { return h.cache[i].SchemaMetaVersion() <= version @@ -108,11 +137,9 @@ func (h *InfoCache) GetBySnapshotTS(snapshotTS uint64) InfoSchema { defer h.mu.RUnlock() getTSCounter.Inc() - if snapshotTS >= h.maxUpdatedSnapshotTS { - if len(h.cache) > 0 { - hitTSCounter.Inc() - return h.cache[0] - } + if version, err := h.GetVersionByTimestamp(snapshotTS); err == nil { + hitTSCounter.Inc() + return h.GetByVersion(version) } return nil } @@ -129,9 +156,31 @@ func (h *InfoCache) Insert(is InfoSchema, snapshotTS uint64) bool { return h.cache[i].SchemaMetaVersion() <= version }) - if h.maxUpdatedSnapshotTS < snapshotTS { - h.maxUpdatedSnapshotTS = snapshotTS + // maintain ts to version mapping + ts, ok := h.versionToTs[version] + if ok { + // version exists, only update ts if the new one is smaller + if snapshotTS < ts { + h.versionToTs[version] = snapshotTS + delete(h.tsToVersion, ts) + h.tsToVersion[snapshotTS] = version + pos := sort.Search(len(h.descSortedTs), func(i int) bool { + return h.descSortedTs[i] < ts + }) + if pos > 0 { + h.descSortedTs[pos-1] = snapshotTS + } + } + } else { + // add the version + h.versionToTs[version] = snapshotTS + h.tsToVersion[snapshotTS] = version + h.descSortedTs = append(h.descSortedTs, snapshotTS) } + sort.Slice(h.descSortedTs, func(i, j int) bool { + // reverse the order + return h.descSortedTs[i] > h.descSortedTs[j] + }) // cached entry if i < len(h.cache) && h.cache[i].SchemaMetaVersion() == version { diff --git a/infoschema/cache_test.go b/infoschema/cache_test.go index 83506bc4794d8..46b41722df0f9 100644 --- a/infoschema/cache_test.go +++ b/infoschema/cache_test.go @@ -129,3 +129,61 @@ func TestGetLatest(t *testing.T) { ic.Insert(is0, 0) require.Equal(t, is2, ic.GetLatest()) } + +func TestGetByTimestamp(t *testing.T) { + ic := infoschema.NewCache(16) + require.NotNil(t, ic) + require.Nil(t, ic.GetLatest()) + + is1 := infoschema.MockInfoSchemaWithSchemaVer(nil, 1) + ic.Insert(is1, 1) + require.Equal(t, is1, ic.GetLatest()) + _, err := ic.GetVersionByTimestamp(0) + require.NotNil(t, err) + ver, err := ic.GetVersionByTimestamp(1) + require.Nil(t, err) + require.Equal(t, int64(1), ver) + require.Equal(t, is1, ic.GetBySnapshotTS(1)) + ver, err = ic.GetVersionByTimestamp(2) + require.Nil(t, err) + require.Equal(t, int64(1), ver) + require.Equal(t, is1, ic.GetBySnapshotTS(2)) + + is2 := infoschema.MockInfoSchemaWithSchemaVer(nil, 2) + ic.Insert(is2, 2) + require.Equal(t, is2, ic.GetLatest()) + _, err = ic.GetVersionByTimestamp(0) + require.NotNil(t, err) + ver, err = ic.GetVersionByTimestamp(1) + require.Nil(t, err) + require.Equal(t, int64(1), ver) + require.Equal(t, is1, ic.GetBySnapshotTS(1)) + ver, err = ic.GetVersionByTimestamp(2) + require.Nil(t, err) + require.Equal(t, int64(2), ver) + require.Equal(t, is2, ic.GetBySnapshotTS(2)) + ver, err = ic.GetVersionByTimestamp(3) + require.Nil(t, err) + require.Equal(t, int64(2), ver) + require.Equal(t, is2, ic.GetBySnapshotTS(3)) + + is0 := infoschema.MockInfoSchemaWithSchemaVer(nil, 0) + ic.Insert(is0, 0) + require.Equal(t, is2, ic.GetLatest()) + ver, err = ic.GetVersionByTimestamp(0) + require.Nil(t, err) + require.Equal(t, int64(0), ver) + require.Equal(t, is0, ic.GetBySnapshotTS(0)) + ver, err = ic.GetVersionByTimestamp(1) + require.Nil(t, err) + require.Equal(t, int64(1), ver) + require.Equal(t, is1, ic.GetBySnapshotTS(1)) + ver, err = ic.GetVersionByTimestamp(2) + require.Nil(t, err) + require.Equal(t, int64(2), ver) + require.Equal(t, is2, ic.GetBySnapshotTS(2)) + ver, err = ic.GetVersionByTimestamp(3) + require.Nil(t, err) + require.Equal(t, int64(2), ver) + require.Equal(t, is2, ic.GetBySnapshotTS(3)) +} From b01a24b0c804dcf972ff842e5f402eb944e1ee4f Mon Sep 17 00:00:00 2001 From: hihihuhu Date: Wed, 25 Jan 2023 10:51:47 -0800 Subject: [PATCH 2/5] fix test --- infoschema/cache_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/infoschema/cache_test.go b/infoschema/cache_test.go index 46b41722df0f9..884211e26a7bb 100644 --- a/infoschema/cache_test.go +++ b/infoschema/cache_test.go @@ -42,7 +42,7 @@ func TestInsert(t *testing.T) { ic.Insert(is5, 5) require.Equal(t, is5, ic.GetByVersion(5)) require.Equal(t, is2, ic.GetByVersion(2)) - require.Nil(t, ic.GetBySnapshotTS(2)) + require.Equal(t, is2, ic.GetBySnapshotTS(2)) require.Equal(t, is5, ic.GetBySnapshotTS(10)) // older @@ -59,7 +59,7 @@ func TestInsert(t *testing.T) { require.Equal(t, is5, ic.GetByVersion(5)) require.Equal(t, is2, ic.GetByVersion(2)) require.Nil(t, ic.GetByVersion(0)) - require.Nil(t, ic.GetBySnapshotTS(2)) + require.Equal(t, is2, ic.GetBySnapshotTS(2)) require.Equal(t, is6, ic.GetBySnapshotTS(10)) // replace 2, drop 2 @@ -91,7 +91,7 @@ func TestInsert(t *testing.T) { require.Nil(t, ic.GetByVersion(2)) require.Nil(t, ic.GetByVersion(0)) require.Nil(t, ic.GetBySnapshotTS(2)) - require.Nil(t, ic.GetBySnapshotTS(5)) + require.Equal(t, is5, ic.GetBySnapshotTS(5)) require.Equal(t, is6, ic.GetBySnapshotTS(10)) } From 611f7e70c0f29efcf984c68d0f663d3d396efd6e Mon Sep 17 00:00:00 2001 From: hihihuhu Date: Tue, 31 Jan 2023 18:17:12 -0800 Subject: [PATCH 3/5] avoid recursive locking --- infoschema/cache.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/infoschema/cache.go b/infoschema/cache.go index af5975ab95efc..52b5a2484bf2e 100644 --- a/infoschema/cache.go +++ b/infoschema/cache.go @@ -83,7 +83,10 @@ func (h *InfoCache) GetLatest() InfoSchema { func (h *InfoCache) GetVersionByTimestamp(ts uint64) (int64, error) { h.mu.RLock() defer h.mu.RUnlock() + return h.getVersionByTimestampNoLock(ts) +} +func (h *InfoCache) getVersionByTimestampNoLock(ts uint64) (int64, error) { i := sort.Search(len(h.descSortedTs), func(i int) bool { return h.descSortedTs[i] <= ts }) @@ -98,7 +101,10 @@ func (h *InfoCache) GetVersionByTimestamp(ts uint64) (int64, error) { func (h *InfoCache) GetByVersion(version int64) InfoSchema { h.mu.RLock() defer h.mu.RUnlock() + return h.getByVersionNoLock(version) +} +func (h *InfoCache) getByVersionNoLock(version int64) InfoSchema { getVersionCounter.Inc() i := sort.Search(len(h.cache), func(i int) bool { return h.cache[i].SchemaMetaVersion() <= version @@ -137,9 +143,9 @@ func (h *InfoCache) GetBySnapshotTS(snapshotTS uint64) InfoSchema { defer h.mu.RUnlock() getTSCounter.Inc() - if version, err := h.GetVersionByTimestamp(snapshotTS); err == nil { + if version, err := h.getVersionByTimestampNoLock(snapshotTS); err == nil { hitTSCounter.Inc() - return h.GetByVersion(version) + return h.getByVersionNoLock(version) } return nil } From 4da7ca73c9387a6745958dd7397956fb3d24a39b Mon Sep 17 00:00:00 2001 From: hihihuhu Date: Wed, 1 Feb 2023 17:24:48 -0800 Subject: [PATCH 4/5] address comment --- infoschema/cache.go | 77 ++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/infoschema/cache.go b/infoschema/cache.go index 52b5a2484bf2e..fcdf735ab0a09 100644 --- a/infoschema/cache.go +++ b/infoschema/cache.go @@ -39,21 +39,20 @@ type InfoCache struct { mu sync.RWMutex // cache is sorted by SchemaVersion in descending order cache []InfoSchema + // schema versions sorted by tiemstamp + sortedTS []versionAndTimestamp +} - // keep ts to version mapping - tsToVersion map[uint64]int64 - versionToTs map[int64]uint64 - // maintain the order everytime the cahce is updated - descSortedTs []uint64 +type versionAndTimestamp struct { + version int64 + timestamp int64 } // NewCache creates a new InfoCache. func NewCache(capacity int) *InfoCache { return &InfoCache{ - cache: make([]InfoSchema, 0, capacity), - tsToVersion: make(map[uint64]int64), - versionToTs: make(map[int64]uint64), - descSortedTs: make([]uint64, 0, capacity), + cache: make([]InfoSchema, 0, capacity), + sortedTS: make([]versionAndTimestamp, 0, capacity), } } @@ -62,9 +61,7 @@ func (h *InfoCache) Reset(capacity int) { h.mu.Lock() defer h.mu.Unlock() h.cache = make([]InfoSchema, 0, capacity) - h.tsToVersion = make(map[uint64]int64) - h.versionToTs = make(map[int64]uint64) - h.descSortedTs = make([]uint64, 0, capacity) + h.sortedTS = make([]versionAndTimestamp, 0, capacity) } // GetLatest gets the newest information schema. @@ -87,11 +84,11 @@ func (h *InfoCache) GetVersionByTimestamp(ts uint64) (int64, error) { } func (h *InfoCache) getVersionByTimestampNoLock(ts uint64) (int64, error) { - i := sort.Search(len(h.descSortedTs), func(i int) bool { - return h.descSortedTs[i] <= ts + i := sort.Search(len(h.sortedTS), func(i int) bool { + return uint64(h.sortedTS[i].timestamp) <= ts }) - if i < len(h.descSortedTs) { - return h.tsToVersion[h.descSortedTs[i]], nil + if i < len(h.sortedTS) { + return h.sortedTS[i].version, nil } return 0, fmt.Errorf("no schema cached for timestamp %d", ts) @@ -158,34 +155,34 @@ func (h *InfoCache) Insert(is InfoSchema, snapshotTS uint64) bool { defer h.mu.Unlock() version := is.SchemaMetaVersion() - i := sort.Search(len(h.cache), func(i int) bool { - return h.cache[i].SchemaMetaVersion() <= version - }) - // maintain ts to version mapping - ts, ok := h.versionToTs[version] - if ok { - // version exists, only update ts if the new one is smaller - if snapshotTS < ts { - h.versionToTs[version] = snapshotTS - delete(h.tsToVersion, ts) - h.tsToVersion[snapshotTS] = version - pos := sort.Search(len(h.descSortedTs), func(i int) bool { - return h.descSortedTs[i] < ts - }) - if pos > 0 { - h.descSortedTs[pos-1] = snapshotTS - } + i := sort.Search(len(h.sortedTS), func(i int) bool { + return h.sortedTS[i].version <= version + }) + if i < len(h.sortedTS) && h.sortedTS[i].version == version { + // find the version, update the schema timestamp if the new timestamp is earlier + if snapshotTS < uint64(h.sortedTS[i].timestamp) { + h.sortedTS[i].timestamp = int64(snapshotTS) } } else { - // add the version - h.versionToTs[version] = snapshotTS - h.tsToVersion[snapshotTS] = version - h.descSortedTs = append(h.descSortedTs, snapshotTS) + if len(h.sortedTS) < cap(h.sortedTS) { + h.sortedTS = h.sortedTS[:len(h.sortedTS)+1] + copy(h.sortedTS[i+1:], h.sortedTS[i:]) + h.sortedTS[i] = versionAndTimestamp{ + version: version, + timestamp: int64(snapshotTS), + } + } else if i < len(h.sortedTS) { + copy(h.sortedTS[i+1:], h.sortedTS[i:]) + h.sortedTS[i] = versionAndTimestamp{ + version: version, + timestamp: int64(snapshotTS), + } + } } - sort.Slice(h.descSortedTs, func(i, j int) bool { - // reverse the order - return h.descSortedTs[i] > h.descSortedTs[j] + + i = sort.Search(len(h.cache), func(i int) bool { + return h.cache[i].SchemaMetaVersion() <= version }) // cached entry From 1710996a562527ff6b5ebad9f536305eb12b7854 Mon Sep 17 00:00:00 2001 From: hihihuhu Date: Thu, 2 Feb 2023 12:31:48 -0800 Subject: [PATCH 5/5] optimize the code --- infoschema/cache.go | 93 ++++++++++++++++------------------------ infoschema/cache_test.go | 40 ++++++++--------- 2 files changed, 57 insertions(+), 76 deletions(-) diff --git a/infoschema/cache.go b/infoschema/cache.go index fcdf735ab0a09..3ceab0bffb00d 100644 --- a/infoschema/cache.go +++ b/infoschema/cache.go @@ -37,22 +37,19 @@ var ( // It only promised to cache the infoschema, if it is newer than all the cached. type InfoCache struct { mu sync.RWMutex - // cache is sorted by SchemaVersion in descending order - cache []InfoSchema - // schema versions sorted by tiemstamp - sortedTS []versionAndTimestamp + // cache is sorted by both SchemaVersion and timestamp in descending order, assume they have same order + cache []schemaAndTimestamp } -type versionAndTimestamp struct { - version int64 - timestamp int64 +type schemaAndTimestamp struct { + infoschema InfoSchema + timestamp int64 } // NewCache creates a new InfoCache. func NewCache(capacity int) *InfoCache { return &InfoCache{ - cache: make([]InfoSchema, 0, capacity), - sortedTS: make([]versionAndTimestamp, 0, capacity), + cache: make([]schemaAndTimestamp, 0, capacity), } } @@ -60,8 +57,7 @@ func NewCache(capacity int) *InfoCache { func (h *InfoCache) Reset(capacity int) { h.mu.Lock() defer h.mu.Unlock() - h.cache = make([]InfoSchema, 0, capacity) - h.sortedTS = make([]versionAndTimestamp, 0, capacity) + h.cache = make([]schemaAndTimestamp, 0, capacity) } // GetLatest gets the newest information schema. @@ -71,27 +67,27 @@ func (h *InfoCache) GetLatest() InfoSchema { getLatestCounter.Inc() if len(h.cache) > 0 { hitLatestCounter.Inc() - return h.cache[0] + return h.cache[0].infoschema } return nil } -// GetVersionByTimestamp returns the schema version used at the specific timestamp -func (h *InfoCache) GetVersionByTimestamp(ts uint64) (int64, error) { +// GetSchemaByTimestamp returns the schema used at the specific timestamp +func (h *InfoCache) GetSchemaByTimestamp(ts uint64) (InfoSchema, error) { h.mu.RLock() defer h.mu.RUnlock() - return h.getVersionByTimestampNoLock(ts) + return h.getSchemaByTimestampNoLock(ts) } -func (h *InfoCache) getVersionByTimestampNoLock(ts uint64) (int64, error) { - i := sort.Search(len(h.sortedTS), func(i int) bool { - return uint64(h.sortedTS[i].timestamp) <= ts +func (h *InfoCache) getSchemaByTimestampNoLock(ts uint64) (InfoSchema, error) { + i := sort.Search(len(h.cache), func(i int) bool { + return uint64(h.cache[i].timestamp) <= ts }) - if i < len(h.sortedTS) { - return h.sortedTS[i].version, nil + if i < len(h.cache) { + return h.cache[i].infoschema, nil } - return 0, fmt.Errorf("no schema cached for timestamp %d", ts) + return nil, fmt.Errorf("no schema cached for timestamp %d", ts) } // GetByVersion gets the information schema based on schemaVersion. Returns nil if it is not loaded. @@ -104,7 +100,7 @@ func (h *InfoCache) GetByVersion(version int64) InfoSchema { func (h *InfoCache) getByVersionNoLock(version int64) InfoSchema { getVersionCounter.Inc() i := sort.Search(len(h.cache), func(i int) bool { - return h.cache[i].SchemaMetaVersion() <= version + return h.cache[i].infoschema.SchemaMetaVersion() <= version }) // `GetByVersion` is allowed to load the latest schema that is less than argument `version`. @@ -125,9 +121,9 @@ func (h *InfoCache) getByVersionNoLock(version int64) InfoSchema { // } // ``` - if i < len(h.cache) && (i != 0 || h.cache[i].SchemaMetaVersion() == version) { + if i < len(h.cache) && (i != 0 || h.cache[i].infoschema.SchemaMetaVersion() == version) { hitVersionCounter.Inc() - return h.cache[i] + return h.cache[i].infoschema } return nil } @@ -140,9 +136,9 @@ func (h *InfoCache) GetBySnapshotTS(snapshotTS uint64) InfoSchema { defer h.mu.RUnlock() getTSCounter.Inc() - if version, err := h.getVersionByTimestampNoLock(snapshotTS); err == nil { + if schema, err := h.getSchemaByTimestampNoLock(snapshotTS); err == nil { hitTSCounter.Inc() - return h.getByVersionNoLock(version) + return schema } return nil } @@ -156,37 +152,16 @@ func (h *InfoCache) Insert(is InfoSchema, snapshotTS uint64) bool { version := is.SchemaMetaVersion() - i := sort.Search(len(h.sortedTS), func(i int) bool { - return h.sortedTS[i].version <= version - }) - if i < len(h.sortedTS) && h.sortedTS[i].version == version { - // find the version, update the schema timestamp if the new timestamp is earlier - if snapshotTS < uint64(h.sortedTS[i].timestamp) { - h.sortedTS[i].timestamp = int64(snapshotTS) - } - } else { - if len(h.sortedTS) < cap(h.sortedTS) { - h.sortedTS = h.sortedTS[:len(h.sortedTS)+1] - copy(h.sortedTS[i+1:], h.sortedTS[i:]) - h.sortedTS[i] = versionAndTimestamp{ - version: version, - timestamp: int64(snapshotTS), - } - } else if i < len(h.sortedTS) { - copy(h.sortedTS[i+1:], h.sortedTS[i:]) - h.sortedTS[i] = versionAndTimestamp{ - version: version, - timestamp: int64(snapshotTS), - } - } - } - - i = sort.Search(len(h.cache), func(i int) bool { - return h.cache[i].SchemaMetaVersion() <= version + // assume this is the timestamp order as well + i := sort.Search(len(h.cache), func(i int) bool { + return h.cache[i].infoschema.SchemaMetaVersion() <= version }) // cached entry - if i < len(h.cache) && h.cache[i].SchemaMetaVersion() == version { + if i < len(h.cache) && h.cache[i].infoschema.SchemaMetaVersion() == version { + if h.cache[i].timestamp > int64(snapshotTS) { + h.cache[i].timestamp = int64(snapshotTS) + } return true } @@ -194,12 +169,18 @@ func (h *InfoCache) Insert(is InfoSchema, snapshotTS uint64) bool { // has free space, grown the slice h.cache = h.cache[:len(h.cache)+1] copy(h.cache[i+1:], h.cache[i:]) - h.cache[i] = is + h.cache[i] = schemaAndTimestamp{ + infoschema: is, + timestamp: int64(snapshotTS), + } return true } else if i < len(h.cache) { // drop older schema copy(h.cache[i+1:], h.cache[i:]) - h.cache[i] = is + h.cache[i] = schemaAndTimestamp{ + infoschema: is, + timestamp: int64(snapshotTS), + } return true } // older than all cached schemas, refuse to cache it diff --git a/infoschema/cache_test.go b/infoschema/cache_test.go index 884211e26a7bb..5d6e0e7f4e1b1 100644 --- a/infoschema/cache_test.go +++ b/infoschema/cache_test.go @@ -138,52 +138,52 @@ func TestGetByTimestamp(t *testing.T) { is1 := infoschema.MockInfoSchemaWithSchemaVer(nil, 1) ic.Insert(is1, 1) require.Equal(t, is1, ic.GetLatest()) - _, err := ic.GetVersionByTimestamp(0) + _, err := ic.GetSchemaByTimestamp(0) require.NotNil(t, err) - ver, err := ic.GetVersionByTimestamp(1) + schema, err := ic.GetSchemaByTimestamp(1) require.Nil(t, err) - require.Equal(t, int64(1), ver) + require.Equal(t, int64(1), schema.SchemaMetaVersion()) require.Equal(t, is1, ic.GetBySnapshotTS(1)) - ver, err = ic.GetVersionByTimestamp(2) + schema, err = ic.GetSchemaByTimestamp(2) require.Nil(t, err) - require.Equal(t, int64(1), ver) + require.Equal(t, int64(1), schema.SchemaMetaVersion()) require.Equal(t, is1, ic.GetBySnapshotTS(2)) is2 := infoschema.MockInfoSchemaWithSchemaVer(nil, 2) ic.Insert(is2, 2) require.Equal(t, is2, ic.GetLatest()) - _, err = ic.GetVersionByTimestamp(0) + _, err = ic.GetSchemaByTimestamp(0) require.NotNil(t, err) - ver, err = ic.GetVersionByTimestamp(1) + schema, err = ic.GetSchemaByTimestamp(1) require.Nil(t, err) - require.Equal(t, int64(1), ver) + require.Equal(t, int64(1), schema.SchemaMetaVersion()) require.Equal(t, is1, ic.GetBySnapshotTS(1)) - ver, err = ic.GetVersionByTimestamp(2) + schema, err = ic.GetSchemaByTimestamp(2) require.Nil(t, err) - require.Equal(t, int64(2), ver) + require.Equal(t, int64(2), schema.SchemaMetaVersion()) require.Equal(t, is2, ic.GetBySnapshotTS(2)) - ver, err = ic.GetVersionByTimestamp(3) + schema, err = ic.GetSchemaByTimestamp(3) require.Nil(t, err) - require.Equal(t, int64(2), ver) + require.Equal(t, int64(2), schema.SchemaMetaVersion()) require.Equal(t, is2, ic.GetBySnapshotTS(3)) is0 := infoschema.MockInfoSchemaWithSchemaVer(nil, 0) ic.Insert(is0, 0) require.Equal(t, is2, ic.GetLatest()) - ver, err = ic.GetVersionByTimestamp(0) + schema, err = ic.GetSchemaByTimestamp(0) require.Nil(t, err) - require.Equal(t, int64(0), ver) + require.Equal(t, int64(0), schema.SchemaMetaVersion()) require.Equal(t, is0, ic.GetBySnapshotTS(0)) - ver, err = ic.GetVersionByTimestamp(1) + schema, err = ic.GetSchemaByTimestamp(1) require.Nil(t, err) - require.Equal(t, int64(1), ver) + require.Equal(t, int64(1), schema.SchemaMetaVersion()) require.Equal(t, is1, ic.GetBySnapshotTS(1)) - ver, err = ic.GetVersionByTimestamp(2) + schema, err = ic.GetSchemaByTimestamp(2) require.Nil(t, err) - require.Equal(t, int64(2), ver) + require.Equal(t, int64(2), schema.SchemaMetaVersion()) require.Equal(t, is2, ic.GetBySnapshotTS(2)) - ver, err = ic.GetVersionByTimestamp(3) + schema, err = ic.GetSchemaByTimestamp(3) require.Nil(t, err) - require.Equal(t, int64(2), ver) + require.Equal(t, int64(2), schema.SchemaMetaVersion()) require.Equal(t, is2, ic.GetBySnapshotTS(3)) }