storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/cmd/bitrot-whole.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2019 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  	"context"
    21  	"fmt"
    22  	"hash"
    23  	"io"
    24  
    25  	"storj.io/minio/cmd/logger"
    26  )
    27  
    28  // Implementation to calculate bitrot for the whole file.
    29  type wholeBitrotWriter struct {
    30  	disk      StorageAPI
    31  	volume    string
    32  	filePath  string
    33  	shardSize int64 // This is the shard size of the erasure logic
    34  	hash.Hash       // For bitrot hash
    35  }
    36  
    37  func (b *wholeBitrotWriter) Write(p []byte) (int, error) {
    38  	err := b.disk.AppendFile(context.TODO(), b.volume, b.filePath, p)
    39  	if err != nil {
    40  		logger.LogIf(GlobalContext, fmt.Errorf("Disk: %s returned %w", b.disk, err))
    41  		return 0, err
    42  	}
    43  	_, err = b.Hash.Write(p)
    44  	if err != nil {
    45  		logger.LogIf(GlobalContext, fmt.Errorf("Disk: %s returned %w", b.disk, err))
    46  		return 0, err
    47  	}
    48  	return len(p), nil
    49  }
    50  
    51  func (b *wholeBitrotWriter) Close() error {
    52  	return nil
    53  }
    54  
    55  // Returns whole-file bitrot writer.
    56  func newWholeBitrotWriter(disk StorageAPI, volume, filePath string, algo BitrotAlgorithm, shardSize int64) io.WriteCloser {
    57  	return &wholeBitrotWriter{disk, volume, filePath, shardSize, algo.New()}
    58  }
    59  
    60  // Implementation to verify bitrot for the whole file.
    61  type wholeBitrotReader struct {
    62  	disk       StorageAPI
    63  	volume     string
    64  	filePath   string
    65  	verifier   *BitrotVerifier // Holds the bit-rot info
    66  	tillOffset int64           // Affects the length of data requested in disk.ReadFile depending on Read()'s offset
    67  	buf        []byte          // Holds bit-rot verified data
    68  }
    69  
    70  func (b *wholeBitrotReader) ReadAt(buf []byte, offset int64) (n int, err error) {
    71  	if b.buf == nil {
    72  		b.buf = make([]byte, b.tillOffset-offset)
    73  		if _, err := b.disk.ReadFile(context.TODO(), b.volume, b.filePath, offset, b.buf, b.verifier); err != nil {
    74  			logger.LogIf(GlobalContext, fmt.Errorf("Disk: %s -> %s/%s returned %w", b.disk, b.volume, b.filePath, err))
    75  			return 0, err
    76  		}
    77  	}
    78  	if len(b.buf) < len(buf) {
    79  		logger.LogIf(GlobalContext, fmt.Errorf("Disk: %s -> %s/%s returned %w", b.disk, b.volume, b.filePath, errLessData))
    80  		return 0, errLessData
    81  	}
    82  	n = copy(buf, b.buf)
    83  	b.buf = b.buf[n:]
    84  	return n, nil
    85  }
    86  
    87  // Returns whole-file bitrot reader.
    88  func newWholeBitrotReader(disk StorageAPI, volume, filePath string, algo BitrotAlgorithm, tillOffset int64, sum []byte) *wholeBitrotReader {
    89  	return &wholeBitrotReader{
    90  		disk:       disk,
    91  		volume:     volume,
    92  		filePath:   filePath,
    93  		verifier:   &BitrotVerifier{algo, sum},
    94  		tillOffset: tillOffset,
    95  		buf:        nil,
    96  	}
    97  }