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  }