0
Files
aleesa-telegram-go/vendor/github.com/cockroachdb/pebble/objstorage/shared_backing.go

146 lines
4.1 KiB
Go

// Copyright 2023 The LevelDB-Go and Pebble Authors. All rights reserved. Use
// of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
package objstorage
import (
"bytes"
"encoding/binary"
"io"
"github.com/cockroachdb/errors"
"github.com/cockroachdb/pebble/internal/base"
"github.com/cockroachdb/pebble/objstorage/sharedobjcat"
)
// SharedObjectBacking encodes the metadata necessary to incorporate a shared
// object into a different Pebble instance.
type SharedObjectBacking []byte
const (
tagCreatorID = 1
tagCreatorFileNum = 2
// Any new tags that don't have the tagNotSafeToIgnoreMask bit set must be
// followed by the length of the data (so they can be skipped).
// Any new tags that have the tagNotSafeToIgnoreMask bit set cause errors if
// they are encountered by earlier code that doesn't know the tag.
tagNotSafeToIgnoreMask = 64
)
// SharedObjectBacking encodes the shared object metadata.
func (meta *ObjectMetadata) SharedObjectBacking() (SharedObjectBacking, error) {
if !meta.IsShared() {
return nil, errors.AssertionFailedf("object %s not on shared storage", meta.FileNum)
}
buf := make([]byte, 0, binary.MaxVarintLen64*4)
buf = binary.AppendUvarint(buf, tagCreatorID)
buf = binary.AppendUvarint(buf, uint64(meta.Shared.CreatorID))
buf = binary.AppendUvarint(buf, tagCreatorFileNum)
buf = binary.AppendUvarint(buf, uint64(meta.Shared.CreatorFileNum))
return buf, nil
}
// fromSharedObjectBacking decodes the shared object metadata.
func fromSharedObjectBacking(
fileType base.FileType, fileNum base.FileNum, buf SharedObjectBacking,
) (ObjectMetadata, error) {
var creatorID uint64
var creatorFileNum uint64
br := bytes.NewReader(buf)
for {
tag, err := binary.ReadUvarint(br)
if err == io.EOF {
break
}
if err != nil {
return ObjectMetadata{}, err
}
switch tag {
case tagCreatorID:
creatorID, err = binary.ReadUvarint(br)
case tagCreatorFileNum:
creatorFileNum, err = binary.ReadUvarint(br)
// TODO(radu): encode file type as well?
default:
// Ignore unknown tags, unless they're not safe to ignore.
if tag&tagNotSafeToIgnoreMask != 0 {
return ObjectMetadata{}, errors.Newf("unknown tag %d", tag)
}
var dataLen uint64
dataLen, err = binary.ReadUvarint(br)
if err == nil {
_, err = br.Seek(int64(dataLen), io.SeekCurrent)
}
}
if err != nil {
return ObjectMetadata{}, err
}
}
if creatorID == 0 {
return ObjectMetadata{}, errors.Newf("shared object backing missing creator ID")
}
if creatorFileNum == 0 {
return ObjectMetadata{}, errors.Newf("shared object backing missing creator file num")
}
meta := ObjectMetadata{
FileNum: fileNum,
FileType: fileType,
}
meta.Shared.CreatorID = CreatorID(creatorID)
meta.Shared.CreatorFileNum = base.FileNum(creatorFileNum)
return meta, nil
}
// SharedObjectToAttach contains the arguments needed to attach an existing shared object.
type SharedObjectToAttach struct {
// FileNum is the file number that will be used to refer to this object (in
// the context of this instance).
FileNum base.FileNum
FileType base.FileType
// Backing contains the metadata for the share dobject backing (normally
// generated from a different instance).
Backing SharedObjectBacking
}
// AttachSharedObjects registers existing shared objects with this provider.
func (p *Provider) AttachSharedObjects(objs []SharedObjectToAttach) ([]ObjectMetadata, error) {
metas := make([]ObjectMetadata, len(objs))
for i, o := range objs {
meta, err := fromSharedObjectBacking(o.FileType, o.FileNum, o.Backing)
if err != nil {
return nil, err
}
metas[i] = meta
}
func() {
p.mu.Lock()
defer p.mu.Unlock()
for _, meta := range metas {
p.mu.shared.catalogBatch.AddObject(sharedobjcat.SharedObjectMetadata{
FileNum: meta.FileNum,
FileType: meta.FileType,
CreatorID: meta.Shared.CreatorID,
CreatorFileNum: meta.Shared.CreatorFileNum,
})
}
}()
if err := p.sharedSync(); err != nil {
return nil, err
}
p.mu.Lock()
defer p.mu.Unlock()
for _, meta := range metas {
p.mu.knownObjects[meta.FileNum] = meta
}
return metas, nil
}