github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/inode/cache.go (about)

     1  // Copyright (c) 2015-2021, NVIDIA CORPORATION.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package inode
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/swiftstack/ProxyFS/conf"
    11  	"github.com/swiftstack/ProxyFS/logger"
    12  	"github.com/swiftstack/ProxyFS/platform"
    13  )
    14  
    15  func adoptVolumeGroupReadCacheParameters(confMap conf.ConfMap) (err error) {
    16  	var (
    17  		readCacheLineCount     uint64
    18  		readCacheMemSize       uint64
    19  		readCacheQuotaFraction float64
    20  		readCacheTotalSize     uint64
    21  		readCacheWeightSum     uint64
    22  		totalMemSize           uint64
    23  		volumeGroup            *volumeGroupStruct
    24  	)
    25  
    26  	readCacheWeightSum = 0
    27  
    28  	for _, volumeGroup = range globals.volumeGroupMap {
    29  		if 0 < volumeGroup.numServed {
    30  			readCacheWeightSum += volumeGroup.readCacheWeight
    31  		}
    32  	}
    33  
    34  	readCacheQuotaFraction, err = confMap.FetchOptionValueFloat64("Peer:"+globals.whoAmI, "ReadCacheQuotaFraction")
    35  	if nil != err {
    36  		return
    37  	}
    38  	if (0 > readCacheQuotaFraction) || (1 < readCacheQuotaFraction) {
    39  		err = fmt.Errorf("%s.ReadCacheQuotaFraction (%v) must be between 0 and 1", globals.whoAmI, readCacheQuotaFraction)
    40  		return
    41  	}
    42  
    43  	totalMemSize = platform.MemSize()
    44  
    45  	readCacheMemSize = uint64(float64(totalMemSize) * readCacheQuotaFraction / platform.GoHeapAllocationMultiplier)
    46  
    47  	logger.Infof("Adopting ReadCache Parameters: ReadCacheQuotaFraction(%v) of memSize(0x%016X) totals 0x%016X",
    48  		readCacheQuotaFraction, totalMemSize, readCacheMemSize)
    49  
    50  	for _, volumeGroup = range globals.volumeGroupMap {
    51  		if 0 < volumeGroup.numServed {
    52  			readCacheTotalSize = readCacheMemSize * volumeGroup.readCacheWeight / readCacheWeightSum
    53  
    54  			readCacheLineCount = readCacheTotalSize / volumeGroup.readCacheLineSize
    55  			if 0 == readCacheLineCount {
    56  				logger.Infof("Computed 0 ReadCacheLines for Volume Group %v; increasing to 1",
    57  					volumeGroup.name)
    58  				readCacheLineCount = 1
    59  			}
    60  
    61  			volumeGroup.Lock()
    62  			volumeGroup.readCacheLineCount = readCacheLineCount
    63  			volumeGroup.capReadCacheWhileLocked()
    64  			volumeGroup.Unlock()
    65  
    66  			logger.Infof("Volume Group %s: %d cache lines (each of size 0x%08X) totalling 0x%016X",
    67  				volumeGroup.name,
    68  				volumeGroup.readCacheLineCount, volumeGroup.readCacheLineSize,
    69  				volumeGroup.readCacheLineCount*volumeGroup.readCacheLineSize)
    70  		}
    71  	}
    72  
    73  	err = nil
    74  	return
    75  }
    76  
    77  func startInodeCacheDiscard(confMap conf.ConfMap, volume *volumeStruct, volumeSectionName string) (err error) {
    78  	var (
    79  		LRUCacheMaxBytes       uint64
    80  		LRUDiscardTimeInterval time.Duration
    81  	)
    82  
    83  	LRUCacheMaxBytes, err = confMap.FetchOptionValueUint64(volumeSectionName, "MaxBytesInodeCache")
    84  	if nil != err {
    85  		LRUCacheMaxBytes = 10485760 // TODO - Remove setting a default value
    86  		err = nil
    87  	}
    88  	volume.inodeCacheLRUMaxBytes = LRUCacheMaxBytes
    89  
    90  	LRUDiscardTimeInterval, err = confMap.FetchOptionValueDuration(volumeSectionName, "InodeCacheEvictInterval")
    91  	if nil != err {
    92  		LRUDiscardTimeInterval = 1 * time.Second // TODO - Remove setting a default value
    93  		err = nil
    94  	}
    95  
    96  	if LRUDiscardTimeInterval != 0 {
    97  		volume.inodeCacheLRUTickerInterval = LRUDiscardTimeInterval
    98  		volume.inodeCacheLRUTicker = time.NewTicker(volume.inodeCacheLRUTickerInterval)
    99  
   100  		logger.Infof("Inode cache discard ticker for 'volume: %v' is: %v MaxBytesInodeCache: %v",
   101  			volume.volumeName, volume.inodeCacheLRUTickerInterval, volume.inodeCacheLRUMaxBytes)
   102  
   103  		// Start ticker for inode cache discard thread
   104  		volume.inodeCacheWG.Add(1)
   105  		go func() {
   106  			for {
   107  				select {
   108  				case _ = <-volume.inodeCacheLRUTicker.C:
   109  					_, _, _, _ = volume.inodeCacheDiscard()
   110  				case _, _ = <-volume.inodeCacheStopChan:
   111  					volume.inodeCacheWG.Done()
   112  					return
   113  				}
   114  			}
   115  		}()
   116  	} else {
   117  		logger.Infof("Inode cache discard ticker for 'volume: %v' is disabled.",
   118  			volume.volumeName)
   119  		return
   120  	}
   121  
   122  	return
   123  }
   124  
   125  func stopInodeCacheDiscard(volume *volumeStruct) {
   126  	if volume.inodeCacheLRUTicker != nil {
   127  		volume.inodeCacheLRUTicker.Stop()
   128  		close(volume.inodeCacheStopChan)
   129  		volume.inodeCacheWG.Wait()
   130  		logger.Infof("Inode cache discard ticker for 'volume: %v' stopped.",
   131  			volume.volumeName)
   132  	}
   133  }