github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/mirror/utils.go (about)

     1  // Package mirror provides local mirroring and replica management
     2  /*
     3   * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package mirror
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/NVIDIA/aistore/cmn/nlog"
    11  	"github.com/NVIDIA/aistore/core"
    12  	"github.com/NVIDIA/aistore/fs"
    13  )
    14  
    15  // is under lock
    16  func delCopies(lom *core.LOM, copies int) (size int64, err error) {
    17  	// force reloading metadata
    18  	lom.UncacheUnless()
    19  	if err := lom.Load(false /*cache it*/, true /*locked*/); err != nil {
    20  		return 0, err
    21  	}
    22  
    23  	ndel := lom.NumCopies() - copies
    24  	if ndel <= 0 {
    25  		return
    26  	}
    27  
    28  	copiesFQN := make([]string, 0, ndel)
    29  	for copyFQN := range lom.GetCopies() {
    30  		if copyFQN == lom.FQN {
    31  			continue
    32  		}
    33  		copiesFQN = append(copiesFQN, copyFQN)
    34  		ndel--
    35  		if ndel == 0 {
    36  			break
    37  		}
    38  	}
    39  
    40  	size = int64(len(copiesFQN)) * lom.SizeBytes()
    41  	if err = lom.DelCopies(copiesFQN...); err != nil {
    42  		return
    43  	}
    44  	err = lom.Persist()
    45  	return
    46  }
    47  
    48  // under LOM's w-lock => TODO: a finer-grade mechanism to write-protect
    49  // metadata only, md.copies in this case
    50  func addCopies(lom *core.LOM, copies int, buf []byte) (size int64, err error) {
    51  	// Reload metadata, it is necessary to have it fresh.
    52  	lom.UncacheUnless()
    53  	if err := lom.Load(false /*cache it*/, true /*locked*/); err != nil {
    54  		return 0, err
    55  	}
    56  
    57  	// Recheck if we still need to create the copy.
    58  	if lom.NumCopies() >= copies {
    59  		return 0, nil
    60  	}
    61  
    62  	//  While copying we may find out that some copies do not exist -
    63  	//  these copies will be removed and `NumCopies()` will decrease.
    64  	for lom.NumCopies() < copies {
    65  		var mi *fs.Mountpath
    66  		if mi = lom.LeastUtilNoCopy(); mi == nil {
    67  			err = fmt.Errorf("%s (copies=%d): cannot find dst mountpath", lom, lom.NumCopies())
    68  			return
    69  		}
    70  		if err = lom.Copy(mi, buf); err != nil {
    71  			nlog.Errorln(err)
    72  			return
    73  		}
    74  		size += lom.SizeBytes()
    75  	}
    76  	return
    77  }
    78  
    79  func drainWorkCh(workCh chan core.LIF) (n int) {
    80  	for {
    81  		select {
    82  		case <-workCh:
    83  			n++
    84  		default:
    85  			return
    86  		}
    87  	}
    88  }