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