storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/xl-storage-format-v1.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2020 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package cmd
    18  
    19  import (
    20  	"encoding/hex"
    21  	"encoding/json"
    22  	"fmt"
    23  	"time"
    24  
    25  	jsoniter "github.com/json-iterator/go"
    26  
    27  	"storj.io/minio/cmd/logger"
    28  )
    29  
    30  // XL constants.
    31  const (
    32  	// XL metadata file carries per object metadata.
    33  	xlStorageFormatFileV1 = "xl.json"
    34  )
    35  
    36  // Valid - tells us if the format is sane by validating
    37  // format version and erasure coding information.
    38  func (m *xlMetaV1Object) valid() bool {
    39  	return isXLMetaFormatValid(m.Version, m.Format) &&
    40  		isXLMetaErasureInfoValid(m.Erasure.DataBlocks, m.Erasure.ParityBlocks)
    41  }
    42  
    43  // Verifies if the backend format metadata is sane by validating
    44  // the version string and format style.
    45  func isXLMetaFormatValid(version, format string) bool {
    46  	return ((version == xlMetaVersion101 ||
    47  		version == xlMetaVersion100) &&
    48  		format == xlMetaFormat)
    49  }
    50  
    51  // Verifies if the backend format metadata is sane by validating
    52  // the ErasureInfo, i.e. data and parity blocks.
    53  func isXLMetaErasureInfoValid(data, parity int) bool {
    54  	return ((data >= parity) && (data != 0) && (parity != 0))
    55  }
    56  
    57  //go:generate msgp -file=$GOFILE -unexported
    58  
    59  // A xlMetaV1Object represents `xl.meta` metadata header.
    60  type xlMetaV1Object struct {
    61  	Version string   `json:"version"` // Version of the current `xl.meta`.
    62  	Format  string   `json:"format"`  // Format of the current `xl.meta`.
    63  	Stat    StatInfo `json:"stat"`    // Stat of the current object `xl.meta`.
    64  	// Erasure coded info for the current object `xl.meta`.
    65  	Erasure ErasureInfo `json:"erasure"`
    66  	// MinIO release tag for current object `xl.meta`.
    67  	Minio struct {
    68  		Release string `json:"release"`
    69  	} `json:"minio"`
    70  	// Metadata map for current object `xl.meta`.
    71  	Meta map[string]string `json:"meta,omitempty"`
    72  	// Captures all the individual object `xl.meta`.
    73  	Parts []ObjectPartInfo `json:"parts,omitempty"`
    74  
    75  	// Dummy values used for legacy use cases.
    76  	VersionID string `json:"versionId,omitempty"`
    77  	DataDir   string `json:"dataDir,omitempty"` // always points to "legacy"
    78  }
    79  
    80  // StatInfo - carries stat information of the object.
    81  type StatInfo struct {
    82  	Size    int64     `json:"size"`    // Size of the object `xl.meta`.
    83  	ModTime time.Time `json:"modTime"` // ModTime of the object `xl.meta`.
    84  }
    85  
    86  // ErasureInfo holds erasure coding and bitrot related information.
    87  type ErasureInfo struct {
    88  	// Algorithm is the string representation of erasure-coding-algorithm
    89  	Algorithm string `json:"algorithm"`
    90  	// DataBlocks is the number of data blocks for erasure-coding
    91  	DataBlocks int `json:"data"`
    92  	// ParityBlocks is the number of parity blocks for erasure-coding
    93  	ParityBlocks int `json:"parity"`
    94  	// BlockSize is the size of one erasure-coded block
    95  	BlockSize int64 `json:"blockSize"`
    96  	// Index is the index of the current disk
    97  	Index int `json:"index"`
    98  	// Distribution is the distribution of the data and parity blocks
    99  	Distribution []int `json:"distribution"`
   100  	// Checksums holds all bitrot checksums of all erasure encoded blocks
   101  	Checksums []ChecksumInfo `json:"checksum,omitempty"`
   102  }
   103  
   104  // BitrotAlgorithm specifies a algorithm used for bitrot protection.
   105  type BitrotAlgorithm uint
   106  
   107  const (
   108  	// SHA256 represents the SHA-256 hash function
   109  	SHA256 BitrotAlgorithm = 1 + iota
   110  	// HighwayHash256 represents the HighwayHash-256 hash function
   111  	HighwayHash256
   112  	// HighwayHash256S represents the Streaming HighwayHash-256 hash function
   113  	HighwayHash256S
   114  	// BLAKE2b512 represents the BLAKE2b-512 hash function
   115  	BLAKE2b512
   116  )
   117  
   118  // DefaultBitrotAlgorithm is the default algorithm used for bitrot protection.
   119  const (
   120  	DefaultBitrotAlgorithm = HighwayHash256S
   121  )
   122  
   123  // ObjectPartInfo Info of each part kept in the multipart metadata
   124  // file after CompleteMultipartUpload() is called.
   125  type ObjectPartInfo struct {
   126  	ETag       string `json:"etag,omitempty"`
   127  	Number     int    `json:"number"`
   128  	Size       int64  `json:"size"`
   129  	ActualSize int64  `json:"actualSize"`
   130  }
   131  
   132  // ChecksumInfo - carries checksums of individual scattered parts per disk.
   133  type ChecksumInfo struct {
   134  	PartNumber int
   135  	Algorithm  BitrotAlgorithm
   136  	Hash       []byte
   137  }
   138  
   139  type checksumInfoJSON struct {
   140  	Name      string `json:"name"`
   141  	Algorithm string `json:"algorithm"`
   142  	Hash      string `json:"hash,omitempty"`
   143  }
   144  
   145  // MarshalJSON marshals the ChecksumInfo struct
   146  func (c ChecksumInfo) MarshalJSON() ([]byte, error) {
   147  	info := checksumInfoJSON{
   148  		Name:      fmt.Sprintf("part.%d", c.PartNumber),
   149  		Algorithm: c.Algorithm.String(),
   150  		Hash:      hex.EncodeToString(c.Hash),
   151  	}
   152  	return json.Marshal(info)
   153  }
   154  
   155  // UnmarshalJSON - custom checksum info unmarshaller
   156  func (c *ChecksumInfo) UnmarshalJSON(data []byte) error {
   157  	var info checksumInfoJSON
   158  	var json = jsoniter.ConfigCompatibleWithStandardLibrary
   159  	if err := json.Unmarshal(data, &info); err != nil {
   160  		return err
   161  	}
   162  	sum, err := hex.DecodeString(info.Hash)
   163  	if err != nil {
   164  		return err
   165  	}
   166  	c.Algorithm = BitrotAlgorithmFromString(info.Algorithm)
   167  	c.Hash = sum
   168  	if _, err = fmt.Sscanf(info.Name, "part.%d", &c.PartNumber); err != nil {
   169  		return err
   170  	}
   171  
   172  	if !c.Algorithm.Available() {
   173  		logger.LogIf(GlobalContext, errBitrotHashAlgoInvalid)
   174  		return errBitrotHashAlgoInvalid
   175  	}
   176  	return nil
   177  }
   178  
   179  // constant and shouldn't be changed.
   180  const legacyDataDir = "legacy"
   181  
   182  func (m *xlMetaV1Object) ToFileInfo(volume, path string) (FileInfo, error) {
   183  	if !m.valid() {
   184  		return FileInfo{}, errFileCorrupt
   185  	}
   186  	fi := FileInfo{
   187  		Volume:    volume,
   188  		Name:      path,
   189  		ModTime:   m.Stat.ModTime,
   190  		Size:      m.Stat.Size,
   191  		Metadata:  m.Meta,
   192  		Parts:     m.Parts,
   193  		Erasure:   m.Erasure,
   194  		VersionID: m.VersionID,
   195  		DataDir:   m.DataDir,
   196  	}
   197  	if st, ok := m.Meta[ReservedMetadataPrefixLower+"transition-status"]; ok {
   198  		fi.TransitionStatus = st
   199  	}
   200  	return fi, nil
   201  }
   202  
   203  // XL metadata constants.
   204  const (
   205  	// XL meta version.
   206  	xlMetaVersion101 = "1.0.1"
   207  
   208  	// XL meta version.
   209  	xlMetaVersion100 = "1.0.0"
   210  
   211  	// XL meta format string.
   212  	xlMetaFormat = "xl"
   213  )