github.com/minio/mc@v0.0.0-20240507152021-646712d5e5fb/cmd/admin-heal-result-item.go (about)

     1  // Copyright (c) 2015-2022 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package cmd
    19  
    20  import (
    21  	"fmt"
    22  
    23  	"github.com/minio/madmin-go/v3"
    24  )
    25  
    26  type hri struct {
    27  	*madmin.HealResultItem
    28  }
    29  
    30  func newHRI(i *madmin.HealResultItem) *hri {
    31  	return &hri{i}
    32  }
    33  
    34  // getObjectHCCChange - returns before and after color change for
    35  // objects
    36  func (h hri) getObjectHCCChange() (b, a col, err error) {
    37  	parityShards := h.ParityBlocks
    38  	dataShards := h.DataBlocks
    39  
    40  	onlineBefore, onlineAfter := h.GetOnlineCounts()
    41  	surplusShardsBeforeHeal := onlineBefore - dataShards
    42  	surplusShardsAfterHeal := onlineAfter - dataShards
    43  
    44  	b, err = getHColCode(surplusShardsBeforeHeal, parityShards)
    45  	if err != nil {
    46  		err = fmt.Errorf("%w: surplusShardsBeforeHeal: %d, parityShards: %d",
    47  			err, surplusShardsBeforeHeal, parityShards)
    48  		return
    49  	}
    50  	a, err = getHColCode(surplusShardsAfterHeal, parityShards)
    51  	if err != nil {
    52  		err = fmt.Errorf("%w: surplusShardsBeforeHeal: %d, parityShards: %d",
    53  			err, surplusShardsAfterHeal, parityShards)
    54  	}
    55  	return
    56  }
    57  
    58  // getReplicatedFileHCCChange - fetches health color code for metadata
    59  // files that are replicated.
    60  func (h hri) getReplicatedFileHCCChange() (b, a col, err error) {
    61  	getColCode := func(numAvail int) (c col, err error) {
    62  		// calculate color code for replicated object similar
    63  		// to erasure coded objects
    64  		var quorum, surplus, parity int
    65  		if h.SetCount > 0 {
    66  			quorum = h.DiskCount/h.SetCount/2 + 1
    67  			surplus = numAvail/h.SetCount - quorum
    68  			parity = h.DiskCount/h.SetCount - quorum
    69  		} else {
    70  			// in case of bucket healing, disk count is for the node
    71  			// also explicitly set count would be set to invalid value of -1
    72  			quorum = h.DiskCount/2 + 1
    73  			surplus = numAvail - quorum
    74  			parity = h.DiskCount - quorum
    75  		}
    76  		c, err = getHColCode(surplus, parity)
    77  		return
    78  	}
    79  
    80  	onlineBefore, onlineAfter := h.GetOnlineCounts()
    81  	b, err = getColCode(onlineBefore)
    82  	if err != nil {
    83  		return
    84  	}
    85  	a, err = getColCode(onlineAfter)
    86  	return
    87  }
    88  
    89  func (h hri) makeHealEntityString() string {
    90  	switch h.Type {
    91  	case madmin.HealItemObject:
    92  		return h.Bucket + "/" + h.Object
    93  	case madmin.HealItemBucket:
    94  		return h.Bucket
    95  	case madmin.HealItemMetadata:
    96  		return "[disk-format]"
    97  	case madmin.HealItemBucketMetadata:
    98  		return fmt.Sprintf("[bucket-metadata]%s/%s", h.Bucket, h.Object)
    99  	}
   100  	return "** unexpected **"
   101  }
   102  
   103  func (h hri) getHRTypeAndName() (typ, name string) {
   104  	name = fmt.Sprintf("%s/%s", h.Bucket, h.Object)
   105  	switch h.Type {
   106  	case madmin.HealItemMetadata:
   107  		typ = "system"
   108  		name = h.Detail
   109  	case madmin.HealItemBucketMetadata:
   110  		typ = "system"
   111  		name = "bucket-metadata:" + name
   112  	case madmin.HealItemBucket:
   113  		typ = "bucket"
   114  	case madmin.HealItemObject:
   115  		typ = "object"
   116  	default:
   117  		typ = fmt.Sprintf("!! Unknown heal result record %#v !!", h)
   118  		name = typ
   119  	}
   120  	return
   121  }
   122  
   123  func (h hri) getHealResultStr() string {
   124  	typ, name := h.getHRTypeAndName()
   125  
   126  	switch h.Type {
   127  	case madmin.HealItemMetadata, madmin.HealItemBucketMetadata:
   128  		return typ + ":" + name
   129  	default:
   130  		return name
   131  	}
   132  }