mirror of
https://github.com/ncruces/go-sqlite3.git
synced 2026-01-11 21:49:13 +00:00
Remove MinLevel.
This commit is contained in:
@@ -9,8 +9,7 @@ The `"litestream"` SQLite VFS implements Litestream
|
|||||||
|
|
||||||
See the [example](example_test.go) for how to use.
|
See the [example](example_test.go) for how to use.
|
||||||
|
|
||||||
To improve performance,
|
To improve performance, increase `PollInterval` as much as you can,
|
||||||
increase `PollInterval` (and `MinLevel`) as much as you can,
|
|
||||||
and set [`PRAGMA cache_size=N`](https://www.sqlite.org/pragma.html#pragma_cache_size)
|
and set [`PRAGMA cache_size=N`](https://www.sqlite.org/pragma.html#pragma_cache_size)
|
||||||
(or use `_pragma=cache_size(N)`).
|
(or use `_pragma=cache_size(N)`).
|
||||||
|
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ type ReplicaOptions struct {
|
|||||||
// used by the replica at MinLevel+1.
|
// used by the replica at MinLevel+1.
|
||||||
PollInterval time.Duration
|
PollInterval time.Duration
|
||||||
|
|
||||||
// Minimum compaction level to track.
|
|
||||||
MinLevel int
|
|
||||||
|
|
||||||
// CacheSize is the maximum size of the page cache in bytes.
|
// CacheSize is the maximum size of the page cache in bytes.
|
||||||
// Zero means DefaultCacheSize, negative disables caching.
|
// Zero means DefaultCacheSize, negative disables caching.
|
||||||
CacheSize int
|
CacheSize int
|
||||||
@@ -61,7 +58,6 @@ func NewReplica(name string, client ReplicaClient, options ReplicaOptions) {
|
|||||||
if options.CacheSize == 0 {
|
if options.CacheSize == 0 {
|
||||||
options.CacheSize = DefaultCacheSize
|
options.CacheSize = DefaultCacheSize
|
||||||
}
|
}
|
||||||
options.MinLevel = max(0, min(options.MinLevel, litestream.SnapshotLevel))
|
|
||||||
|
|
||||||
liteMtx.Lock()
|
liteMtx.Lock()
|
||||||
defer liteMtx.Unlock()
|
defer liteMtx.Unlock()
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ func (f *liteFile) Pragma(name, value string) (string, error) {
|
|||||||
if txid == 0 {
|
if txid == 0 {
|
||||||
// Outside transaction.
|
// Outside transaction.
|
||||||
f.db.mtx.Lock()
|
f.db.mtx.Lock()
|
||||||
txid = f.db.txids[f.db.opts.MinLevel]
|
txid = f.db.txids[0]
|
||||||
f.db.mtx.Unlock()
|
f.db.mtx.Unlock()
|
||||||
}
|
}
|
||||||
return txid.String(), nil
|
return txid.String(), nil
|
||||||
@@ -245,10 +245,10 @@ func (f *liteDB) pollReplica(ctx context.Context) (*pageIndex, ltx.TXID, error)
|
|||||||
|
|
||||||
// Limit polling interval.
|
// Limit polling interval.
|
||||||
if time.Since(f.lastPoll) < f.opts.PollInterval {
|
if time.Since(f.lastPoll) < f.opts.PollInterval {
|
||||||
return f.pages, f.txids[f.opts.MinLevel], nil
|
return f.pages, f.txids[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for level := range pollLevels(f.opts.MinLevel) {
|
for level := range []int{0, 1, litestream.SnapshotLevel} {
|
||||||
if err := f.updateLevel(ctx, level); err != nil {
|
if err := f.updateLevel(ctx, level); err != nil {
|
||||||
f.opts.Logger.Error("cannot poll replica", "error", err)
|
f.opts.Logger.Error("cannot poll replica", "error", err)
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@@ -256,7 +256,7 @@ func (f *liteDB) pollReplica(ctx context.Context) (*pageIndex, ltx.TXID, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
f.lastPoll = time.Now()
|
f.lastPoll = time.Now()
|
||||||
return f.pages, f.txids[f.opts.MinLevel], nil
|
return f.pages, f.txids[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// +checklocks:f.mtx
|
// +checklocks:f.mtx
|
||||||
@@ -313,26 +313,10 @@ func (f *liteDB) updateInfo(ctx context.Context, info *ltx.FileInfo) error {
|
|||||||
// Track the MaxTXID for each level.
|
// Track the MaxTXID for each level.
|
||||||
maxTXID := &f.txids[info.Level]
|
maxTXID := &f.txids[info.Level]
|
||||||
*maxTXID = max(*maxTXID, info.MaxTXID)
|
*maxTXID = max(*maxTXID, info.MaxTXID)
|
||||||
|
f.txids[0] = max(f.txids[0], *maxTXID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func pollLevels(minLevel int) (r []int) {
|
|
||||||
// Updating from lower to upper levels is non-racy,
|
|
||||||
// since LTX files are compacted into higher levels
|
|
||||||
// before the lower level LTX files are deleted.
|
|
||||||
|
|
||||||
// Also, only level 0 compactions and snapshots delete files,
|
|
||||||
// so the intermediate levels never need to be updated.
|
|
||||||
|
|
||||||
if minLevel <= 0 {
|
|
||||||
return append(r, 0, 1, litestream.SnapshotLevel)
|
|
||||||
}
|
|
||||||
if minLevel >= litestream.SnapshotLevel {
|
|
||||||
return append(r, litestream.SnapshotLevel)
|
|
||||||
}
|
|
||||||
return append(r, minLevel, litestream.SnapshotLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type aliases; these are a mouthful.
|
// Type aliases; these are a mouthful.
|
||||||
type pageIndex = wbt.Tree[uint32, ltx.PageIndexElem]
|
type pageIndex = wbt.Tree[uint32, ltx.PageIndexElem]
|
||||||
type levelTXIDs = [litestream.SnapshotLevel + 1]ltx.TXID
|
type levelTXIDs = [litestream.SnapshotLevel + 1]ltx.TXID
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
package litestream
|
|
||||||
|
|
||||||
import (
|
|
||||||
"slices"
|
|
||||||
"strconv"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/benbjohnson/litestream"
|
|
||||||
|
|
||||||
_ "github.com/ncruces/go-sqlite3/embed"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_pollLevels(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
minLevel int
|
|
||||||
want []int
|
|
||||||
}{
|
|
||||||
{minLevel: -1, want: []int{0, 1, litestream.SnapshotLevel}},
|
|
||||||
{minLevel: 0, want: []int{0, 1, litestream.SnapshotLevel}},
|
|
||||||
{minLevel: 1, want: []int{1, litestream.SnapshotLevel}},
|
|
||||||
{minLevel: 2, want: []int{2, litestream.SnapshotLevel}},
|
|
||||||
{minLevel: 3, want: []int{3, litestream.SnapshotLevel}},
|
|
||||||
{minLevel: litestream.SnapshotLevel, want: []int{litestream.SnapshotLevel}},
|
|
||||||
{minLevel: litestream.SnapshotLevel + 1, want: []int{litestream.SnapshotLevel}},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(strconv.Itoa(tt.minLevel), func(t *testing.T) {
|
|
||||||
got := pollLevels(tt.minLevel)
|
|
||||||
if !slices.Equal(got, tt.want) {
|
|
||||||
t.Errorf("pollLevels() = %v, want %v", got, tt.want)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user