-
Notifications
You must be signed in to change notification settings - Fork 669
/
db.go
105 lines (92 loc) · 2.88 KB
/
db.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package archivedb
import (
"context"
"errors"
"io"
"github.com/ava-labs/avalanchego/api/health"
"github.com/ava-labs/avalanchego/database"
)
var (
ErrNotImplemented = errors.New("feature not implemented")
ErrInvalidValue = errors.New("invalid data value")
_ database.Compacter = (*Database)(nil)
_ health.Checker = (*Database)(nil)
_ io.Closer = (*Database)(nil)
)
// Database implements an ArchiveDB on top of a database.Database. An ArchiveDB
// is an append only database which stores all state changes happening at every
// height. Each record is stored in such way to perform both fast insertions and
// lookups.
//
// The API is quite simple, it has two main functions, one to create a Batch
// write with a given height, inside this batch entries can be added with a
// given value or they can be deleted.
//
// The way it works is as follows:
// - NewBatch(10)
// batch.Put(foo, "foo's value is bar")
// batch.Put(bar, "bar's value is bar")
// - NewBatch(100)
// batch.Put(foo, "updatedfoo's value is bar")
// - NewBatch(1000)
// batch.Put(bar, "updated bar's value is bar")
// batch.Delete(foo)
//
// The other primary function is to read data at a given height.
//
// The way it works is as follows:
// - Open(10)
// reader.Get(foo)
// reader.Get(bar)
// - Open(99)
// reader.GetHeight(foo)
// - Open(100)
// reader.Get(foo)
// - Open(1000)
// reader.Get(foo)
//
// Requesting `reader.Get(foo)` at height 1000 will return ErrNotFound because
// foo was deleted at height 1000. When calling `reader.GetHeight(foo)` at
// height 99 it will return a tuple `("foo's value is bar", 10)` returning the
// value of `foo` at height 99 (which was set at height 10).
type Database struct {
db database.Database
}
func New(db database.Database) *Database {
return &Database{
db: db,
}
}
// Height returns the last written height.
func (db *Database) Height() (uint64, error) {
return database.GetUInt64(db.db, heightKey)
}
// Open returns a reader for the state at the given height.
func (db *Database) Open(height uint64) *Reader {
return &Reader{
db: db,
height: height,
}
}
// NewBatch creates a write batch to perform changes at a given height.
//
// Note: Committing multiple batches at the same height, or at a lower height
// than the currently committed height will not error. It is left up to the
// caller to enforce any guarantees they need around height consistency.
func (db *Database) NewBatch(height uint64) *batch {
return &batch{
db: db,
height: height,
}
}
func (db *Database) Compact(start []byte, limit []byte) error {
return db.db.Compact(start, limit)
}
func (db *Database) HealthCheck(ctx context.Context) (interface{}, error) {
return db.db.HealthCheck(ctx)
}
func (db *Database) Close() error {
return db.db.Close()
}