github.com/dolthub/dolt/go@v0.40.5-0.20240520175717-68db7794bea6/store/prolly/message/address_map.go (about) 1 // Copyright 2021 Dolthub, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package message 16 17 import ( 18 "context" 19 "encoding/binary" 20 21 fb "github.com/dolthub/flatbuffers/v23/go" 22 23 "github.com/dolthub/dolt/go/gen/fb/serial" 24 "github.com/dolthub/dolt/go/store/hash" 25 "github.com/dolthub/dolt/go/store/pool" 26 ) 27 28 const ( 29 // This constant is mirrored from serial.AddressMap.KeyOffsetsLength() 30 // It is only as stable as the flatbuffers schema that defines it. 31 addressMapKeyItemsBytesVOffset fb.VOffsetT = 4 32 addressMapKeyItemsOffsetsVOffset fb.VOffsetT = 6 33 addressMapAddressArrayVOffset fb.VOffsetT = 8 34 ) 35 36 var addressMapFileID = []byte(serial.AddressMapFileID) 37 38 func NewAddressMapSerializer(pool pool.BuffPool) AddressMapSerializer { 39 return AddressMapSerializer{pool: pool} 40 } 41 42 type AddressMapSerializer struct { 43 pool pool.BuffPool 44 } 45 46 var _ Serializer = AddressMapSerializer{} 47 48 func (s AddressMapSerializer) Serialize(keys, addrs [][]byte, subtrees []uint64, level int) serial.Message { 49 var ( 50 keyArr, keyOffs fb.UOffsetT 51 addrArr, cardArr fb.UOffsetT 52 ) 53 54 keySz, addrSz, totalSz := estimateAddressMapSize(keys, addrs, subtrees) 55 b := getFlatbufferBuilder(s.pool, totalSz) 56 57 // keys 58 keyArr = writeItemBytes(b, keys, keySz) 59 serial.AddressMapStartKeyOffsetsVector(b, len(keys)+1) 60 keyOffs = writeItemOffsets(b, keys, keySz) 61 62 // addresses 63 addrArr = writeItemBytes(b, addrs, addrSz) 64 65 // subtree cardinalities 66 if level > 0 { 67 cardArr = writeCountArray(b, subtrees) 68 } 69 70 serial.AddressMapStart(b) 71 serial.AddressMapAddKeyItems(b, keyArr) 72 serial.AddressMapAddKeyOffsets(b, keyOffs) 73 serial.AddressMapAddAddressArray(b, addrArr) 74 75 if level > 0 { 76 serial.AddressMapAddSubtreeCounts(b, cardArr) 77 serial.AddressMapAddTreeCount(b, sumSubtrees(subtrees)) 78 } else { 79 serial.AddressMapAddTreeCount(b, uint64(len(keys))) 80 } 81 serial.AddressMapAddTreeLevel(b, uint8(level)) 82 83 return serial.FinishMessage(b, serial.AddressMapEnd(b), addressMapFileID) 84 } 85 86 func getAddressMapKeys(msg serial.Message) (keys ItemAccess, err error) { 87 var am serial.AddressMap 88 err = serial.InitAddressMapRoot(&am, msg, serial.MessagePrefixSz) 89 if err != nil { 90 return keys, err 91 } 92 keys.bufStart = lookupVectorOffset(addressMapKeyItemsBytesVOffset, am.Table()) 93 keys.bufLen = uint16(am.KeyItemsLength()) 94 keys.offStart = lookupVectorOffset(addressMapKeyItemsOffsetsVOffset, am.Table()) 95 keys.offLen = uint16(am.KeyOffsetsLength() * uint16Size) 96 return 97 } 98 99 func getAddressMapValues(msg serial.Message) (values ItemAccess, err error) { 100 var am serial.AddressMap 101 err = serial.InitAddressMapRoot(&am, msg, serial.MessagePrefixSz) 102 if err != nil { 103 return values, err 104 } 105 values.bufStart = lookupVectorOffset(addressMapAddressArrayVOffset, am.Table()) 106 values.bufLen = uint16(am.AddressArrayLength()) 107 values.itemWidth = hash.ByteLen 108 return 109 } 110 111 func walkAddressMapAddresses(ctx context.Context, msg serial.Message, cb func(ctx context.Context, addr hash.Hash) error) error { 112 var am serial.AddressMap 113 err := serial.InitAddressMapRoot(&am, msg, serial.MessagePrefixSz) 114 if err != nil { 115 return err 116 } 117 arr := am.AddressArrayBytes() 118 for i := 0; i < len(arr)/hash.ByteLen; i++ { 119 addr := hash.New(arr[i*addrSize : (i+1)*addrSize]) 120 if err := cb(ctx, addr); err != nil { 121 return err 122 } 123 } 124 return nil 125 } 126 127 func getAddressMapCount(msg serial.Message) (uint16, error) { 128 var am serial.AddressMap 129 err := serial.InitAddressMapRoot(&am, msg, serial.MessagePrefixSz) 130 if err != nil { 131 return 0, err 132 } 133 return uint16(am.KeyOffsetsLength() - 1), nil 134 } 135 136 func getAddressMapTreeLevel(msg serial.Message) (uint16, error) { 137 var am serial.AddressMap 138 err := serial.InitAddressMapRoot(&am, msg, serial.MessagePrefixSz) 139 if err != nil { 140 return 0, err 141 } 142 return uint16(am.TreeLevel()), nil 143 } 144 145 func getAddressMapTreeCount(msg serial.Message) (int, error) { 146 var am serial.AddressMap 147 err := serial.InitAddressMapRoot(&am, msg, serial.MessagePrefixSz) 148 if err != nil { 149 return 0, err 150 } 151 return int(am.TreeCount()), nil 152 } 153 154 func getAddressMapSubtrees(msg serial.Message) ([]uint64, error) { 155 sz, err := getAddressMapCount(msg) 156 if err != nil { 157 return nil, err 158 } 159 counts := make([]uint64, sz) 160 var am serial.AddressMap 161 err = serial.InitAddressMapRoot(&am, msg, serial.MessagePrefixSz) 162 if err != nil { 163 return nil, err 164 } 165 return decodeVarints(am.SubtreeCountsBytes(), counts), nil 166 } 167 168 func estimateAddressMapSize(keys, addresses [][]byte, subtrees []uint64) (keySz, addrSz, totalSz int) { 169 assertTrue(len(keys) == len(addresses), "num keys != num addresses for AddressMap") 170 for i := range keys { 171 keySz += len(keys[i]) 172 addrSz += len(addresses[i]) 173 } 174 totalSz += keySz + addrSz 175 totalSz += len(keys) * uint16Size 176 totalSz += len(subtrees) * binary.MaxVarintLen64 177 totalSz += 8 + 1 + 1 + 1 178 totalSz += 72 179 totalSz += serial.MessagePrefixSz 180 return 181 }