/* * Minio Cloud Storage, (C) 2016 Minio, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cmd import "encoding/hex" // Heals the erasure coded file. reedsolomon.Reconstruct() is used to reconstruct the missing parts. func erasureHealFile(latestDisks []StorageAPI, outDatedDisks []StorageAPI, volume, path, healBucket, healPath string, size int64, blockSize int64, dataBlocks int, parityBlocks int, algo string) (checkSums []string, err error) { var offset int64 remainingSize := size // Hash for bitrot protection. hashWriters := newHashWriters(len(outDatedDisks), bitRotAlgo) for remainingSize > 0 { curBlockSize := blockSize if remainingSize < curBlockSize { curBlockSize = remainingSize } // Calculate the block size that needs to be read from each disk. curEncBlockSize := getChunkSize(curBlockSize, dataBlocks) // Memory for reading data from disks and reconstructing missing data using erasure coding. enBlocks := make([][]byte, len(latestDisks)) // Read data from the latest disks. // FIXME: no need to read from all the disks. dataBlocks+1 is enough. for index, disk := range latestDisks { if disk == nil { continue } enBlocks[index] = make([]byte, curEncBlockSize) _, err := disk.ReadFile(volume, path, offset, enBlocks[index]) if err != nil { enBlocks[index] = nil } } // Reconstruct missing data. err := decodeData(enBlocks, dataBlocks, parityBlocks) if err != nil { return nil, err } // Write to the healPath file. for index, disk := range outDatedDisks { if disk == nil { continue } err := disk.AppendFile(healBucket, healPath, enBlocks[index]) if err != nil { return nil, traceError(err) } hashWriters[index].Write(enBlocks[index]) } remainingSize -= curBlockSize offset += curEncBlockSize } // Checksums for the bit rot. checkSums = make([]string, len(outDatedDisks)) for index, disk := range outDatedDisks { if disk == nil { continue } checkSums[index] = hex.EncodeToString(hashWriters[index].Sum(nil)) } return checkSums, nil }