-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathmap_slab.go
More file actions
135 lines (115 loc) · 3.5 KB
/
map_slab.go
File metadata and controls
135 lines (115 loc) · 3.5 KB
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/*
* Atree - Scalable Arrays and Ordered Maps
*
* Copyright Flow Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package atree
import "fmt"
type MapSlabHeader struct {
slabID SlabID // id is used to retrieve slab from storage
size uint32 // size is used to split and merge; leaf: size of all element; internal: size of all headers
firstKey Digest // firstKey (first hashed key) is used to lookup value
}
type MapSlab interface {
Slab
getElementAndNextKey(
storage SlabStorage,
digester Digester,
level uint,
hkey Digest,
comparator ValueComparator,
key Value,
) (MapKey, MapValue, MapKey, error)
Get(
storage SlabStorage,
digester Digester,
level uint,
hkey Digest,
comparator ValueComparator,
key Value,
) (MapKey, MapValue, error)
Set(
storage SlabStorage,
b DigesterBuilder,
digester Digester,
level uint,
hkey Digest,
comparator ValueComparator,
hip HashInputProvider,
key Value,
value Value,
) (MapKey, MapValue, error)
Remove(
storage SlabStorage,
digester Digester,
level uint,
hkey Digest,
comparator ValueComparator,
key Value,
) (MapKey, MapValue, error)
IsData() bool
IsFull() bool
IsUnderflow() (uint32, bool)
CanLendToLeft(size uint32) bool
CanLendToRight(size uint32) bool
SetSlabID(SlabID)
Header() MapSlabHeader
// canCopyWithoutSlabID returns true if
// - All elements can be copied, and
// - Slab doesn't have any references to other slabs (such as next slab ID).
canCopyWithoutSlabID() bool
// copyWithNewSlabID copies the MapSlab and uses the given newID as the the SlabID.
copyWithNewSlabID(newID SlabID) (MapSlab, error)
ExtraData() *MapExtraData
RemoveExtraData() *MapExtraData
SetExtraData(*MapExtraData)
PopIterate(SlabStorage, MapPopIterationFunc) error
Inlined() bool
Inlinable(maxInlineSize uint32) bool
Inline(SlabStorage) error
Uninline(SlabStorage) error
}
func getMapSlab(storage SlabStorage, id SlabID) (MapSlab, error) {
slab, found, err := storage.Retrieve(id)
if err != nil {
// Wrap err as external error (if needed) because err is returned by SlabStorage interface.
return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to retrieve slab %s", id))
}
if !found {
return nil, NewSlabNotFoundErrorf(id, "map slab not found")
}
mapSlab, ok := slab.(MapSlab)
if !ok {
return nil, NewSlabDataErrorf("slab %s isn't MapSlab", id)
}
return mapSlab, nil
}
func firstMapDataSlab(storage SlabStorage, slab MapSlab) (*MapDataSlab, error) {
switch slab := slab.(type) {
case *MapDataSlab:
return slab, nil
case *MapMetaDataSlab:
firstChildID := slab.childrenHeaders[0].slabID
firstChild, err := getMapSlab(storage, firstChildID)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by getMapSlab().
return nil, err
}
// Don't need to wrap error as external error because err is already categorized by firstMapDataSlab().
return firstMapDataSlab(storage, firstChild)
default:
return nil, NewUnreachableError()
}
}