Skip to content

Commit a109286

Browse files
committed
apply rebalance conflict/abort policy consistently across jobs
* make xaction descriptors more consistent with respect to rebalance - including rebalance that gets triggered by a powercycled target * update: - get-batch, copy bucket, move bucket, EC encode, - rechunk, and native bucket inventory creation * document the intended ConflictRebRes vs AbortByReb semantics * rename AbortRebRes => AbortByReb Signed-off-by: Alex Aizman <alex.aizman@gmail.com>
1 parent 26a8c83 commit a109286

3 files changed

Lines changed: 85 additions & 40 deletions

File tree

‎reb/globrun.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,8 @@ func (reb *Reb) Run(smap *meta.Smap, extArgs *ExtArgs) {
297297
nlog.Warningln(logHdr, "initializing - limited scope: [", extArgs.Bck.Cname(extArgs.Prefix), "]")
298298
}
299299

300-
// abort all running `dtor.AbortRebRes` xactions (download, dsort, etl)
300+
// abort all running xactions that have `AbortByReb: true`
301+
// in static descriptor table (xact.Table)
301302
xreg.AbortByNewReb(errors.New("reason: starting " + rargs.xreb.Name()))
302303

303304
// only one rebalance is running -----------------

‎xact/api_table.go‎

Lines changed: 81 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,48 @@ import (
1414
"github.com/NVIDIA/aistore/cmn/debug"
1515
)
1616

17+
// Static descriptor table (xact.Table) - one entry per xaction kind.
18+
// The table drives runtime decisions that would otherwise be scattered across the codebase:
19+
// what can be started, what aborts what, and which xactions can coexist.
20+
//
21+
// The table (below) is static, public, and global Kind => [] map that contains
22+
// xaction kinds and static properties, such as `Startable`, `Owned`, etc.
23+
//
24+
// In particular, "startability" is defined as ability to start xaction via `api.StartXaction`
25+
// (whereby copying bucket, for instance, requires a separate `api.CopyBucket`, etc.)
26+
//
27+
// Coexistence with rebalance and resilver
28+
// ---------------------------------------
29+
// Two flags govern the relationship between a given xaction kind and a cluster-wide
30+
// rebalance (or node-local resilver) run:
31+
//
32+
// ConflictRebRes - refuse to start this kind when rebalance/resilver is already in progress;
33+
// conversely, refuse to start rebalance/resilver when this kind is running.
34+
// Enforced at xreg renew time.
35+
//
36+
// AbortByReb - abort in-flight instances of this kind when a new rebalance starts.
37+
// Enforced by xreg.AbortByNewReb() at the top of reb.Run().
38+
//
39+
// In practice the two almost always travel together: if the target set must be stable to
40+
// start the xaction, it must remain stable to finish it. The exceptions are deliberate:
41+
//
42+
// AbortByReb without ConflictRebRes - ETLInline, BlobDl, Download.
43+
// These are long-running or on-demand and shouldn't be refused at start time just
44+
// because rebalance happens to be running, but they cannot correctly survive a
45+
// topology change mid-flight.
46+
//
47+
// ConflictRebRes without AbortByReb - IndexShard.
48+
// Builds a best-effort index; stale entries are detected via LOM checksum and fall
49+
// back to tar.Next() scan. Aborting a 90%-complete build is wasteful when the partial
50+
// output remains useful and a resumed build atomically skips already-indexed LOMs
51+
// (lom.md.flags&Indexed + index file as an atomic pair).
52+
//
53+
// Rebalance and Resilver flags
54+
// ----------------------------
55+
// Rebalance=true and Resilver=true mark the xactions that ARE the rebalance/resilver
56+
// themselves (plus ActMoveBck which performs a rebalance-like move). They are informational
57+
// and used by xreg to recognize self-conflicts.
58+
1759
const (
1860
ScopeG = iota + 1 // cluster
1961
ScopeB // bucket
@@ -33,8 +75,8 @@ type (
3375
// see xreg for "limited coexistence"
3476
Rebalance bool // moves data between nodes
3577
Resilver bool // moves data between mountpaths
36-
ConflictRebRes bool // conflicts with rebalance/resilver
37-
AbortRebRes bool // gets aborted upon rebalance/resilver - currently, all `ext`-ensions
78+
ConflictRebRes bool // starting this job would conflict with rebalance or resilver that's currently in progress
79+
AbortByReb bool // gets aborted upon rebalance (coincides with ConflictRebRes with very few exceptions)
3880

3981
// xaction has an intermediate `idle` state whereby it "idles" between requests
4082
// (see related: xact/demand.go)
@@ -54,17 +96,12 @@ type (
5496
// Descriptor //
5597
////////////////
5698

57-
// `xact.Table` is a static, public, and global Kind=>[Xaction Descriptor] map that contains
58-
// xaction kinds and static properties, such as `Startable`, `Owned`, etc.
59-
// In particular, "startability" is narrowly defined as ability to start xaction
60-
// via `api.StartXaction`
61-
// (whereby copying bucket, for instance, requires a separate `api.CopyBucket`, etc.)
6299
var Table = map[string]Descriptor{
63100
// bucket-less xactions that will typically have a 'cluster' scope (with resilver being a notable exception)
64101
apc.ActElection: {DisplayName: "elect-primary", Scope: ScopeG, Startable: false},
65102
apc.ActRebalance: {Scope: ScopeG, Startable: true, Metasync: true, Rebalance: true},
66103

67-
apc.ActETLInline: {Scope: ScopeG, Startable: false, AbortRebRes: true},
104+
apc.ActETLInline: {Scope: ScopeG, Startable: false, AbortByReb: true},
68105

69106
// (one bucket) | (all buckets)
70107
apc.ActLRU: {DisplayName: "lru-eviction", Scope: ScopeGB, Startable: true},
@@ -79,8 +116,8 @@ var Table = map[string]Descriptor{
79116

80117
// single target (node)
81118
apc.ActResilver: {Scope: ScopeT, Startable: true, Resilver: true},
82-
apc.ActRechunk: {Scope: ScopeB, Startable: true, RefreshCap: true, ConflictRebRes: true},
83-
apc.ActIndexShard: {Scope: ScopeB, Startable: true, RefreshCap: false, ConflictRebRes: true},
119+
apc.ActRechunk: {Scope: ScopeB, Startable: true, RefreshCap: true, ConflictRebRes: true, AbortByReb: true},
120+
apc.ActIndexShard: {Scope: ScopeB, Startable: true, RefreshCap: false, ConflictRebRes: true, AbortByReb: false},
84121

85122
// on-demand EC and n-way replication
86123
// (non-startable, triggered by PUT => erasure-coded or mirrored bucket)
@@ -90,30 +127,33 @@ var Table = map[string]Descriptor{
90127
apc.ActPutCopies: {Scope: ScopeB, Startable: false, RefreshCap: true, Idles: true},
91128

92129
//
93-
// on-demand multi-object (consider setting ConflictRebRes = true)
130+
// on-demand multi-object
94131
//
95132
apc.ActArchive: {Scope: ScopeB, Access: apc.AccessRW, Startable: false, RefreshCap: true, Idles: true},
96133
apc.ActCopyObjects: {
97-
DisplayName: "copy-objects",
98-
Scope: ScopeB,
99-
Access: apc.AccessRW, // apc.AceCreateBucket is checked as well but only if ais://dst doesn't exist
100-
Startable: false,
101-
RefreshCap: true,
102-
Idles: true,
134+
DisplayName: "copy-objects",
135+
Scope: ScopeB,
136+
Access: apc.AccessRW, // apc.AceCreateBucket is checked as well but only if ais://dst doesn't exist
137+
Startable: false,
138+
RefreshCap: true,
139+
Idles: true,
140+
ConflictRebRes: true,
141+
AbortByReb: true,
103142
},
104143
apc.ActETLObjects: {
105-
DisplayName: "etl-objects",
106-
Scope: ScopeB,
107-
Access: apc.AccessRW, // ditto
108-
Startable: false,
109-
RefreshCap: true,
110-
Idles: true,
111-
AbortRebRes: true,
144+
DisplayName: "etl-objects",
145+
Scope: ScopeB,
146+
Access: apc.AccessRW, // ditto
147+
Startable: false,
148+
RefreshCap: true,
149+
Idles: true,
150+
ConflictRebRes: true,
151+
AbortByReb: true,
112152
},
113153

114-
apc.ActBlobDl: {Access: apc.AccessRW, Scope: ScopeB, Startable: true, AbortRebRes: true, RefreshCap: true},
154+
apc.ActBlobDl: {Access: apc.AccessRW, Scope: ScopeB, Startable: true, AbortByReb: true, RefreshCap: true},
115155

116-
apc.ActDownload: {Access: apc.AccessRW, Scope: ScopeG, Startable: false, Idles: true, AbortRebRes: true},
156+
apc.ActDownload: {Access: apc.AccessRW, Scope: ScopeG, Startable: false, Idles: true, AbortByReb: true},
117157

118158
// in its own class
119159
apc.ActDsort: {
@@ -122,9 +162,9 @@ var Table = map[string]Descriptor{
122162
Access: apc.AccessRW,
123163
Startable: false,
124164
RefreshCap: true,
125-
ConflictRebRes: true,
126165
ExtendedStats: true,
127-
AbortRebRes: true,
166+
ConflictRebRes: true,
167+
AbortByReb: true,
128168
},
129169

130170
// multi-object
@@ -173,6 +213,7 @@ var Table = map[string]Descriptor{
173213
Metasync: true,
174214
RefreshCap: true,
175215
ConflictRebRes: true,
216+
AbortByReb: true,
176217
},
177218
apc.ActMakeNCopies: {
178219
DisplayName: "mirror",
@@ -190,6 +231,7 @@ var Table = map[string]Descriptor{
190231
Metasync: true,
191232
Rebalance: true,
192233
ConflictRebRes: true,
234+
AbortByReb: true,
193235
},
194236
apc.ActCopyBck: {
195237
DisplayName: "copy-bucket",
@@ -199,22 +241,24 @@ var Table = map[string]Descriptor{
199241
Metasync: true,
200242
RefreshCap: true,
201243
ConflictRebRes: true,
244+
AbortByReb: true,
202245
},
203246
apc.ActETLBck: {
204-
DisplayName: "etl-bucket",
205-
Scope: ScopeB,
206-
Access: apc.AccessRW, // ditto
207-
Startable: false, // ditto
208-
Metasync: true,
209-
RefreshCap: true,
210-
AbortRebRes: true,
247+
DisplayName: "etl-bucket",
248+
Scope: ScopeB,
249+
Access: apc.AccessRW, // ditto
250+
Startable: false, // ditto
251+
Metasync: true,
252+
RefreshCap: true,
253+
ConflictRebRes: true,
254+
AbortByReb: true,
211255
},
212256

213257
apc.ActList: {Scope: ScopeB, Access: apc.AceObjLIST, Startable: false, Metasync: false, Idles: true, QuietBrief: true},
214258

215-
apc.ActGetBatch: {Scope: ScopeGB, Startable: false, Metasync: false, ConflictRebRes: true, Idles: true, QuietBrief: true}, // x-moss
259+
apc.ActGetBatch: {Scope: ScopeGB, Startable: false, Metasync: false, ConflictRebRes: true, AbortByReb: true, Idles: true, QuietBrief: true}, // x-moss
216260

217-
apc.ActCreateNBI: {Scope: ScopeB, Startable: false, Metasync: false, ConflictRebRes: true, Idles: false},
261+
apc.ActCreateNBI: {Scope: ScopeB, Startable: false, Metasync: false, ConflictRebRes: true, AbortByReb: true, Idles: false},
218262

219263
// cache management, internal usage
220264
apc.ActLoadLomCache: {DisplayName: "warm-up-metadata", Scope: ScopeB, Startable: true},

‎xact/xreg/xreg.go‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ type (
9797
kind string // criteria: all of a kind
9898
bcks []*meta.Bck // buckets to apply
9999
scope []int // { ScopeG, ScopeB, ... } enum
100-
newreb bool // (rebalance is starting) vs (dtor.AbortRebRes)
100+
newreb bool // this abort is triggered by a new rebalance (ie., select via AbortByReb() rather than a kind/bck/scope)
101101
}
102102

103103
entries struct {
@@ -384,7 +384,7 @@ func (args *abortArgs) do(entry Renewable) bool {
384384
debug.Assertf(args.scope == nil && args.kind == "", "scope %v, kind %q", args.scope, args.kind)
385385
_, dtor, err := xact.GetDescriptor(xctn.Kind())
386386
debug.AssertNoErr(err)
387-
if dtor.AbortRebRes {
387+
if dtor.AbortByReb {
388388
abort = true
389389
}
390390
case len(args.bcks) > 0:

0 commit comments

Comments
 (0)