Skip to content

Commit 458f1d6

Browse files
authored
Merge pull request #588 from onflow/fxamacker/remove-old-function-FixLoadedBrokenReferences
Remove unused storage function FixLoadedBrokenReferences
2 parents 2beb843 + 494bbe6 commit 458f1d6

File tree

2 files changed

+0
-2114
lines changed

2 files changed

+0
-2114
lines changed

storage.go

Lines changed: 0 additions & 228 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ package atree
2020

2121
import (
2222
"encoding/binary"
23-
"errors"
2423
"fmt"
2524
"sort"
2625
"strings"
@@ -1013,233 +1012,6 @@ func (s *PersistentSlabStorage) DeltasSizeWithoutTempAddresses() uint64 {
10131012
return size
10141013
}
10151014

1016-
// FixLoadedBrokenReferences traverses loaded slabs and fixes broken references in maps.
1017-
// A broken reference is a SlabID referencing a non-existent slab.
1018-
// To fix a map containing broken references, this function replaces broken map with
1019-
// empty map having the same SlabID and also removes all slabs in the old map.
1020-
// Limitations:
1021-
// - only fix broken references in map
1022-
// - only traverse loaded slabs in deltas and cache
1023-
// NOTE: The intended use case is to enable migration programs in onflow/flow-go to
1024-
// fix broken references. As of April 2024, only 10 registers in testnet (not mainnet)
1025-
// were found to have broken references and they seem to have resulted from a bug
1026-
// that was fixed 2 years ago by https://github.com/onflow/cadence/pull/1565.
1027-
func (s *PersistentSlabStorage) FixLoadedBrokenReferences(needToFix func(old Value) bool) (
1028-
fixedSlabIDs map[SlabID][]SlabID, // key: root slab ID, value: slab IDs containing broken refs
1029-
skippedSlabIDs map[SlabID][]SlabID, // key: root slab ID, value: slab IDs containing broken refs
1030-
err error,
1031-
) {
1032-
1033-
// parentOf is used to find root slab from non-root slab.
1034-
// Broken reference can be in non-root slab, and we need SlabID of root slab
1035-
// to replace broken map by creating an empty new map with same SlabID.
1036-
parentOf := make(map[SlabID]SlabID)
1037-
1038-
getRootSlabID := func(id SlabID) SlabID {
1039-
for {
1040-
parentID, ok := parentOf[id]
1041-
if ok {
1042-
id = parentID
1043-
} else {
1044-
return id
1045-
}
1046-
}
1047-
}
1048-
1049-
hasBrokenReferenceInSlab := func(id SlabID, slab Slab) bool {
1050-
if slab == nil {
1051-
return false
1052-
}
1053-
1054-
switch slab.(type) {
1055-
case *ArrayMetaDataSlab, *MapMetaDataSlab: // metadata slabs
1056-
var foundBrokenRef bool
1057-
1058-
for _, childStorable := range slab.ChildStorables() {
1059-
1060-
if slabIDStorable, ok := childStorable.(SlabIDStorable); ok {
1061-
1062-
childID := SlabID(slabIDStorable)
1063-
1064-
// Track parent-child relationship of root slabs and non-root slabs.
1065-
parentOf[childID] = id
1066-
1067-
if !s.existIfLoaded(childID) {
1068-
foundBrokenRef = true
1069-
}
1070-
1071-
// Continue with remaining child storables to track parent-child relationship.
1072-
}
1073-
}
1074-
1075-
return foundBrokenRef
1076-
1077-
default: // data slabs
1078-
childStorables := slab.ChildStorables()
1079-
1080-
for len(childStorables) > 0 {
1081-
1082-
var nextChildStorables []Storable
1083-
1084-
for _, childStorable := range childStorables {
1085-
1086-
if slabIDStorable, ok := childStorable.(SlabIDStorable); ok {
1087-
1088-
if !s.existIfLoaded(SlabID(slabIDStorable)) {
1089-
return true
1090-
}
1091-
1092-
continue
1093-
}
1094-
1095-
// Append child storables of this childStorable to
1096-
// handle nested SlabIDStorable, such as Cadence SomeValue.
1097-
nextChildStorables = append(
1098-
nextChildStorables,
1099-
childStorable.ChildStorables()...,
1100-
)
1101-
}
1102-
1103-
childStorables = nextChildStorables
1104-
}
1105-
1106-
return false
1107-
}
1108-
}
1109-
1110-
var brokenSlabIDs []SlabID
1111-
1112-
// Iterate delta slabs.
1113-
for id, slab := range s.deltas {
1114-
if hasBrokenReferenceInSlab(id, slab) {
1115-
brokenSlabIDs = append(brokenSlabIDs, id)
1116-
}
1117-
}
1118-
1119-
// Iterate cache slabs.
1120-
for id, slab := range s.cache {
1121-
if _, ok := s.deltas[id]; ok {
1122-
continue
1123-
}
1124-
if hasBrokenReferenceInSlab(id, slab) {
1125-
brokenSlabIDs = append(brokenSlabIDs, id)
1126-
}
1127-
}
1128-
1129-
if len(brokenSlabIDs) == 0 {
1130-
return nil, nil, nil
1131-
}
1132-
1133-
rootSlabIDsWithBrokenData := make(map[SlabID][]SlabID)
1134-
var errs []error
1135-
1136-
// Find SlabIDs of root slab for slabs containing broken references.
1137-
for _, id := range brokenSlabIDs {
1138-
rootID := getRootSlabID(id)
1139-
if rootID == SlabIDUndefined {
1140-
errs = append(errs, fmt.Errorf("failed to get root slab id for slab %s", id))
1141-
continue
1142-
}
1143-
rootSlabIDsWithBrokenData[rootID] = append(rootSlabIDsWithBrokenData[rootID], id)
1144-
}
1145-
1146-
for rootSlabID, brokenSlabIDs := range rootSlabIDsWithBrokenData {
1147-
rootSlab := s.RetrieveIfLoaded(rootSlabID)
1148-
if rootSlab == nil {
1149-
errs = append(errs, fmt.Errorf("failed to retrieve loaded root slab %s", rootSlabID))
1150-
continue
1151-
}
1152-
1153-
switch rootSlab := rootSlab.(type) {
1154-
case MapSlab:
1155-
value, err := rootSlab.StoredValue(s)
1156-
if err != nil {
1157-
errs = append(errs, fmt.Errorf("failed to convert slab %s into value", rootSlab.SlabID()))
1158-
continue
1159-
}
1160-
1161-
if needToFix(value) {
1162-
err := s.fixBrokenReferencesInMap(rootSlab)
1163-
if err != nil {
1164-
errs = append(errs, err)
1165-
continue
1166-
}
1167-
} else {
1168-
if skippedSlabIDs == nil {
1169-
skippedSlabIDs = make(map[SlabID][]SlabID)
1170-
}
1171-
skippedSlabIDs[rootSlabID] = brokenSlabIDs
1172-
}
1173-
1174-
default:
1175-
// IMPORTANT: Only handle map slabs for now. DO NOT silently fix currently unknown problems.
1176-
errs = append(errs, fmt.Errorf("failed to fix broken references in non-map slab %s (%T)", rootSlab.SlabID(), rootSlab))
1177-
}
1178-
}
1179-
1180-
for id := range skippedSlabIDs {
1181-
delete(rootSlabIDsWithBrokenData, id)
1182-
}
1183-
1184-
return rootSlabIDsWithBrokenData, skippedSlabIDs, errors.Join(errs...)
1185-
}
1186-
1187-
// fixBrokenReferencesInMap replaces replaces broken map with empty map
1188-
// having the same SlabID and also removes all slabs in the old map.
1189-
func (s *PersistentSlabStorage) fixBrokenReferencesInMap(old MapSlab) error {
1190-
id := old.SlabID()
1191-
1192-
oldExtraData := old.ExtraData()
1193-
1194-
// Create an empty map with the same StorgeID, type, and seed as the old map.
1195-
newMap := &MapDataSlab{
1196-
header: MapSlabHeader{
1197-
slabID: id,
1198-
size: mapRootDataSlabPrefixSize + hkeyElementsPrefixSize,
1199-
},
1200-
extraData: &MapExtraData{
1201-
TypeInfo: oldExtraData.TypeInfo,
1202-
Seed: oldExtraData.Seed,
1203-
},
1204-
elements: newHkeyElements(0),
1205-
}
1206-
1207-
// Store new empty map with the same SlabID.
1208-
err := s.Store(id, newMap)
1209-
if err != nil {
1210-
return err
1211-
}
1212-
1213-
// Remove all slabs and references in old map.
1214-
references, _, err := s.getAllChildReferences(old)
1215-
if err != nil {
1216-
return err
1217-
}
1218-
1219-
for _, childID := range references {
1220-
err = s.Remove(childID)
1221-
if err != nil {
1222-
return err
1223-
}
1224-
}
1225-
1226-
return nil
1227-
}
1228-
1229-
func (s *PersistentSlabStorage) existIfLoaded(id SlabID) bool {
1230-
// Check deltas.
1231-
if slab, ok := s.deltas[id]; ok {
1232-
return slab != nil
1233-
}
1234-
1235-
// Check read cache.
1236-
if slab, ok := s.cache[id]; ok {
1237-
return slab != nil
1238-
}
1239-
1240-
return false
1241-
}
1242-
12431015
// GetAllChildReferences returns child references of given slab (all levels),
12441016
// including nested container and theirs child references.
12451017
func (s *PersistentSlabStorage) GetAllChildReferences(id SlabID) (

0 commit comments

Comments
 (0)