github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/dbnode/persist/fs/snapshot_metadata_read.go (about)

     1  // Copyright (c) 2018 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package fs
    22  
    23  import (
    24  	"fmt"
    25  	"os"
    26  
    27  	"github.com/m3db/m3/src/dbnode/digest"
    28  	"github.com/m3db/m3/src/dbnode/generated/proto/snapshot"
    29  	"github.com/m3db/m3/src/dbnode/persist"
    30  
    31  	"github.com/pborman/uuid"
    32  )
    33  
    34  // NewSnapshotMetadataReader returns a new SnapshotMetadataReader.
    35  func NewSnapshotMetadataReader(opts Options) *SnapshotMetadataReader {
    36  	return &SnapshotMetadataReader{
    37  		opts: opts,
    38  
    39  		metadataReader: digest.NewFdWithDigestReader(opts.InfoReaderBufferSize()),
    40  	}
    41  }
    42  
    43  // SnapshotMetadataReader is a reader for SnapshotMetadata.
    44  type SnapshotMetadataReader struct {
    45  	opts Options
    46  
    47  	metadataReader digest.FdWithDigestReader
    48  }
    49  
    50  func (w *SnapshotMetadataReader) Read(id SnapshotMetadataIdentifier) (SnapshotMetadata, error) {
    51  	var (
    52  		prefix         = w.opts.FilePathPrefix()
    53  		checkpointPath = snapshotMetadataCheckpointFilePathFromIdentifier(prefix, id)
    54  		metadataPath   = snapshotMetadataFilePathFromIdentifier(prefix, id)
    55  	)
    56  
    57  	expectedDigest, err := readCheckpointFile(checkpointPath, digest.NewBuffer())
    58  	if err != nil {
    59  		return SnapshotMetadata{}, err
    60  	}
    61  
    62  	metadataFile, err := os.Open(metadataPath)
    63  	if err != nil {
    64  		return SnapshotMetadata{}, err
    65  	}
    66  
    67  	w.metadataReader.Reset(metadataFile)
    68  
    69  	metadataFileInfo, err := metadataFile.Stat()
    70  	if err != nil {
    71  		return SnapshotMetadata{}, err
    72  	}
    73  
    74  	var (
    75  		size = metadataFileInfo.Size()
    76  		buf  = make([]byte, int(size))
    77  	)
    78  	n, err := w.metadataReader.ReadAllAndValidate(buf, expectedDigest)
    79  	if err != nil {
    80  		return SnapshotMetadata{}, err
    81  	}
    82  
    83  	if int64(n) != size {
    84  		// Should never happen
    85  		return SnapshotMetadata{}, fmt.Errorf("read: %d bytes of metadata file, but expected: %d",
    86  			n, size)
    87  	}
    88  
    89  	protoMetadata := &snapshot.Metadata{}
    90  	err = protoMetadata.Unmarshal(buf[:n])
    91  	if err != nil {
    92  		return SnapshotMetadata{}, err
    93  	}
    94  
    95  	parsedUUID, err := uuid.ParseBytes(protoMetadata.SnapshotUUID)
    96  	if err != nil {
    97  		return SnapshotMetadata{}, fmt.Errorf("unable to parse UUID: %v, err: %v", protoMetadata.SnapshotUUID, err)
    98  	}
    99  
   100  	return SnapshotMetadata{
   101  		ID: SnapshotMetadataIdentifier{
   102  			Index: protoMetadata.SnapshotIndex,
   103  			UUID:  parsedUUID,
   104  		},
   105  		CommitlogIdentifier: persist.CommitLogFile{
   106  			FilePath: protoMetadata.CommitlogID.FilePath,
   107  			Index:    protoMetadata.CommitlogID.Index,
   108  		},
   109  		MetadataFilePath:   snapshotMetadataFilePathFromIdentifier(prefix, id),
   110  		CheckpointFilePath: snapshotMetadataCheckpointFilePathFromIdentifier(prefix, id),
   111  	}, nil
   112  }