github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/disk_limiter.go (about)

     1  package libkbfs
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/keybase/client/go/protocol/keybase1"
     7  	"golang.org/x/net/context"
     8  )
     9  
    10  type diskLimitTrackerType int
    11  
    12  func (d diskLimitTrackerType) String() string {
    13  	switch d {
    14  	case unknownLimitTrackerType:
    15  		return "unknown"
    16  	case journalLimitTrackerType:
    17  		return "journal"
    18  	case workingSetCacheLimitTrackerType:
    19  		return "workingSet"
    20  	case syncCacheLimitTrackerType:
    21  		return "sync"
    22  	case crDirtyBlockCacheLimitTrackerType:
    23  		return "cr"
    24  	default:
    25  		return "undefined"
    26  	}
    27  }
    28  
    29  type unknownTrackerTypeError struct {
    30  	typ diskLimitTrackerType
    31  }
    32  
    33  func (e unknownTrackerTypeError) Error() string {
    34  	return fmt.Sprintf("Unknown tracker type: %d", e.typ)
    35  }
    36  
    37  const (
    38  	unknownLimitTrackerType diskLimitTrackerType = iota
    39  	journalLimitTrackerType
    40  	workingSetCacheLimitTrackerType
    41  	syncCacheLimitTrackerType
    42  	crDirtyBlockCacheLimitTrackerType // allow unlimited bytes for CR
    43  )
    44  
    45  // simpleResourceTracker is an interface for limiting a single resource type.
    46  // It is mostly used to limit bytes.
    47  type simpleResourceTracker interface {
    48  	onEnable(usedResources int64) int64
    49  	onDisable(usedResources int64)
    50  	updateFree(freeResources int64)
    51  	usedResources() int64
    52  	reserve(ctx context.Context, resources int64) (available int64, err error)
    53  	tryReserve(resources int64) (available int64)
    54  	commit(resources int64)
    55  	rollback(resources int64)
    56  	commitOrRollback(resources int64, shouldCommit bool)
    57  	release(resources int64)
    58  }
    59  
    60  // DiskLimiter is an interface for limiting disk usage.
    61  type DiskLimiter interface {
    62  	// onSimpleByteTrackerEnable is called when a byte tracker is enabled to
    63  	// begin accounting. This should be called by consumers of disk space that
    64  	// only track bytes (i.e. not the journal tracker).
    65  	onSimpleByteTrackerEnable(ctx context.Context, typ diskLimitTrackerType,
    66  		cacheBytes int64)
    67  
    68  	// onSimpleByteTrackerDisable is called when a byte tracker is disabled to
    69  	// stop accounting. This should be called by consumers of disk space that
    70  	// only track bytes (i.e. not the journal tracker).
    71  	onSimpleByteTrackerDisable(ctx context.Context, typ diskLimitTrackerType,
    72  		cacheBytes int64)
    73  
    74  	// onJournalEnable is called when initializing a TLF journal
    75  	// with that journal's current disk usage. Both journalBytes
    76  	// and journalFiles must be >= 0. The updated available byte
    77  	// and file count must be returned.
    78  	onJournalEnable(ctx context.Context,
    79  		journalStoredBytes, journalUnflushedBytes, journalFiles int64,
    80  		chargedTo keybase1.UserOrTeamID) (
    81  		availableBytes, availableFiles int64)
    82  
    83  	// onJournalDisable is called when shutting down a TLF journal
    84  	// with that journal's current disk usage. Both journalBytes
    85  	// and journalFiles must be >= 0.
    86  	onJournalDisable(ctx context.Context,
    87  		journalStoredBytes, journalUnflushedBytes, journalFiles int64,
    88  		chargedTo keybase1.UserOrTeamID)
    89  
    90  	// reserveWithBackpressure is called before using disk storage of the given
    91  	// byte and file count, both of which must be > 0. It may block, but must
    92  	// return immediately with a (possibly-wrapped) ctx.Err() if ctx is
    93  	// cancelled. The updated available byte and file count must be returned,
    94  	// even if err is non-nil.
    95  	reserveWithBackpressure(ctx context.Context, typ diskLimitTrackerType,
    96  		blockBytes, blockFiles int64, chargedTo keybase1.UserOrTeamID) (
    97  		availableBytes, availableFiles int64, err error)
    98  
    99  	// reserveBytes is called a number of bytes equal to `blockBytes` by a
   100  	// consumer of disk space that only tracks bytes, before actually using
   101  	// that disk space. It returns the total number of available bytes.
   102  	// reserveBytes() should not block. If there aren't enough bytes available,
   103  	// no reservation is made, and a negative number is returned indicating how
   104  	// much space must be freed to make the requested reservation possible.
   105  	reserveBytes(ctx context.Context, typ diskLimitTrackerType, blockBytes int64) (
   106  		availableBytes int64, err error)
   107  
   108  	// commitOrRollback is called after using disk storage of the given byte
   109  	// and file count, which must match the corresponding call to
   110  	// beforeBlockPut. `shouldCommit` reflects whether we should commit. A
   111  	// false value will cause a rollback instead. If the `typ` is a type that
   112  	// only tracks bytes, `blockFiles` is ignored.
   113  	commitOrRollback(ctx context.Context, typ diskLimitTrackerType, blockBytes,
   114  		blockFiles int64, shouldCommit bool, chargedTo keybase1.UserOrTeamID)
   115  
   116  	// release is called after releasing byte and/or file usage, both of which
   117  	// must be >= 0. Unlike reserve and commitOrRollback, this is a one-step
   118  	// operation.
   119  	release(ctx context.Context, typ diskLimitTrackerType, blockBytes,
   120  		blockFiles int64)
   121  
   122  	// onBlocksFlush is called after flushing blocks of the given
   123  	// byte count, which must be >= 0. (Flushing a block with a
   124  	// zero byte count shouldn't happen, but may as well let it go
   125  	// through.)
   126  	onBlocksFlush(ctx context.Context, blockBytes int64,
   127  		chargedTo keybase1.UserOrTeamID)
   128  
   129  	// getQuotaInfo returns the quota info as known by the disk
   130  	// limiter.
   131  	getQuotaInfo(chargedTo keybase1.UserOrTeamID) (
   132  		usedQuotaBytes, quotaBytes int64)
   133  
   134  	// getDiskLimitInfo returns the usage and limit info for the disk,
   135  	// as known by the disk limiter.
   136  	getDiskLimitInfo() (usedBytes int64, limitBytes float64,
   137  		usedFiles int64, limitFiles float64)
   138  
   139  	// getStatus returns an object that's marshallable into JSON
   140  	// for use in displaying status.
   141  	getStatus(ctx context.Context, chargedTo keybase1.UserOrTeamID) interface{}
   142  }