internal/gitaly/storage/kv.go (39 lines of code) (raw):
package storage
import (
"fmt"
"os"
"gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage/keyvalue"
"gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb"
"google.golang.org/protobuf/encoding/protodelim"
)
// RepositoryKeyPrefix is the prefix used for storing keys recording repository
// existence in a partition.
const RepositoryKeyPrefix = "r/"
// kvStateFileName is the filename the kv state is written to
var kvStateFileName = "kv-state"
// RepositoryKey generates the database key for recording repository existence in a partition.
func RepositoryKey(relativePath string) []byte {
return []byte(RepositoryKeyPrefix + relativePath)
}
// CreateKvFile creates a file storing the transaction snapshot's kv state
func CreateKvFile(tx Transaction) (kvFile *os.File, returnErr error) {
kvFile, err := os.CreateTemp("", kvStateFileName)
if err != nil {
return nil, fmt.Errorf("create temp file for KV entries: %w", err)
}
if err := os.Remove(kvFile.Name()); err != nil {
return nil, fmt.Errorf("remove temp KV file: %w", err)
}
kvIter := tx.KV().NewIterator(keyvalue.IteratorOptions{})
defer kvIter.Close()
for kvIter.Rewind(); kvIter.Valid(); kvIter.Next() {
item := kvIter.Item()
if err := item.Value(func(v []byte) error {
if _, err := protodelim.MarshalTo(kvFile, &gitalypb.KVPair{Key: item.Key(), Value: v}); err != nil {
return fmt.Errorf("write KV entry to temp file: %w", err)
}
return nil
}); err != nil {
return nil, fmt.Errorf("get KV value: %w", err)
}
}
// Rewind the temp file to the beginning before reading from it.
if _, err := kvFile.Seek(0, 0); err != nil {
return nil, fmt.Errorf("rewind KV entries file: %w", err)
}
return kvFile, nil
}