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 }