@@ -1210,11 +1210,15 @@ type ValueSeparationPolicy struct {
1210
1210
// SpanPolicy contains policies that can vary by key range. The zero value for
1211
1211
// all fields, other than the KeyRange, is the default policy.
1212
1212
type SpanPolicy struct {
1213
- // KeyRange defines the key range for which this policy is valid. The end
1214
- // key can be empty, in which case the policy is valid for the entire
1215
- // keyspace after KeyRange.Start. The Start and End keys are not required to
1216
- // encompass the whole KeyRange over which this policy applies, i.e., they
1217
- // should be interpreted as a subset of the real interval for the policy.
1213
+ // KeyRange defines the key range for which this policy is valid.
1214
+ //
1215
+ // If Start is empty, the policy is valid for the entire keyspace up to End.
1216
+ // If End is empty, the policy is valid for the entire keyspace after Start.
1217
+ // If both are empty, this is the only policy across the entire keyspace.
1218
+ //
1219
+ // The Start and End keys are not required to encompass the whole KeyRange over
1220
+ // which this policy applies, i.e., they should be interpreted as a subset of
1221
+ // the real interval for the policy.
1218
1222
KeyRange KeyRange
1219
1223
1220
1224
// Prefer a faster compression algorithm for the keys in this span.
@@ -1254,6 +1258,17 @@ type SpanPolicy struct {
1254
1258
// Pebble will remember the set of (KeyRange, SpanID) pairs that it has seen
1255
1259
// in its history, for error checking the aforementioned invariant.
1256
1260
TieringPolicy TieringPolicyAndExtractor
1261
+
1262
+ // NOTE: update the IsDefault() method if you add new fields to this struct.
1263
+ }
1264
+
1265
+ // IsDefault returns true if the SpanPolicy is the default policy, i.e. none of
1266
+ // the fields other than KeyRange are set.
1267
+ func (p * SpanPolicy ) IsDefault () bool {
1268
+ return ! p .PreferFastCompression &&
1269
+ ! p .DisableValueSeparationBySuffix &&
1270
+ p .ValueStoragePolicy == ValueStorageDefault &&
1271
+ p .TieringPolicy == nil
1257
1272
}
1258
1273
1259
1274
// String returns a string representation of the SpanPolicy.
@@ -1299,12 +1314,21 @@ const (
1299
1314
1300
1315
// SpanPolicyFunc is used to determine the SpanPolicy for a key region.
1301
1316
//
1302
- // The returned policy is valid over the interval in SpanPolicy.KeyRange,
1303
- // which must include the startKey specified by the caller.
1317
+ // The returned policy is valid over the interval in policy.KeyRange, which
1318
+ // must include the bounds.Start key specified by the caller. Specifically,
1319
+ // policy.KeyRange.Start is empty or is <= bounds.Start.
1320
+ // If policy.KeyRange.End is before bounds.End, then the policy is only valid up
1321
+ // to that point.
1304
1322
//
1305
1323
// A flush or compaction will call this function once for the first key to be
1306
- // output. If the compaction reaches the end key, the current output sst is
1307
- // finished and the function is called again.
1324
+ // output. If the compaction reaches policy.KeyRange.End, the current output sst
1325
+ // is finished and the function is called again (with the first key >=
1326
+ // policy.KeyRange.End).
1327
+ //
1328
+ // Correctness must never depend on having a specific span policy. The function
1329
+ // is allowed to change the returned policy arbitrarily.
1330
+ //
1331
+ // If this function returns an error, the flush or compaction will be aborted.
1308
1332
//
1309
1333
// TODO(sumeer): since there is a single TieringPolicy per SpanPolicy, we will
1310
1334
// split sstables at tiering policy boundaries. Historically, SpanPolicys have
@@ -1315,20 +1339,23 @@ const (
1315
1339
// apply to the sstable as a whole (e.g. PreferFastCompression) to determine
1316
1340
// whether to split at the end. This will require some restructuring of the
1317
1341
// compact.Runner interface, so we will do this later.
1318
- type SpanPolicyFunc func (startKey []byte ) (policy SpanPolicy , err error )
1319
-
1320
- // MakeStaticSpanPolicyFunc returns a SpanPolicyFunc that applies a given
1321
- // policy to the given span (and the default policy outside the span). The
1322
- // supplied policies must be non-overlapping in key range. This method must
1323
- // not be called with inputPolicies that have an empty KeyRange.End to signify
1324
- // extending to the end of the keyspace. The empty slice is assumed to be a
1325
- // valid key that sorts before all other keys.
1342
+ type SpanPolicyFunc func (bounds base.UserKeyBounds ) (policy SpanPolicy , err error )
1343
+
1344
+ // MakeStaticSpanPolicyFunc returns a SpanPolicyFunc that applies a given policy
1345
+ // to the given span (and the default policy outside the span). The supplied
1346
+ // policies must be non-overlapping in key range. This method must not be called
1347
+ // with inputPolicies that have an empty KeyRange.Start or End to signify
1348
+ // extending to the start/end of the keyspace.
1326
1349
func MakeStaticSpanPolicyFunc (cmp base.Compare , inputPolicies ... SpanPolicy ) SpanPolicyFunc {
1327
1350
// Collect all the boundaries of the input policies, sort and deduplicate them.
1328
1351
uniqueKeys := make ([][]byte , 0 , 2 * len (inputPolicies ))
1329
1352
for i := range inputPolicies {
1330
- uniqueKeys = append (uniqueKeys , inputPolicies [i ].KeyRange .Start )
1331
- uniqueKeys = append (uniqueKeys , inputPolicies [i ].KeyRange .End )
1353
+ r := inputPolicies [i ].KeyRange
1354
+ if len (r .Start ) == 0 || len (r .End ) == 0 || cmp (r .Start , r .End ) >= 0 {
1355
+ panic ("invalid key range in input policy" )
1356
+ }
1357
+ uniqueKeys = append (uniqueKeys , r .Start )
1358
+ uniqueKeys = append (uniqueKeys , r .End )
1332
1359
}
1333
1360
slices .SortFunc (uniqueKeys , cmp )
1334
1361
uniqueKeys = slices .CompactFunc (uniqueKeys , func (a , b []byte ) bool { return cmp (a , b ) == 0 })
@@ -1343,13 +1370,16 @@ func MakeStaticSpanPolicyFunc(cmp base.Compare, inputPolicies ...SpanPolicy) Spa
1343
1370
// Populate the non-default policies.
1344
1371
for _ , p := range inputPolicies {
1345
1372
idx , _ := slices .BinarySearchFunc (uniqueKeys , p .KeyRange .Start , cmp )
1373
+ if cmp (p .KeyRange .End , uniqueKeys [idx + 1 ]) != 0 {
1374
+ panic ("overlapping key ranges in input policies" )
1375
+ }
1346
1376
policies [idx ] = p
1347
1377
policies [idx ].KeyRange = KeyRange {Start : uniqueKeys [idx ], End : uniqueKeys [idx + 1 ]}
1348
1378
}
1349
1379
1350
- return func (startKey [] byte ) (_ SpanPolicy , _ error ) {
1380
+ return func (bounds base. UserKeyBounds ) (_ SpanPolicy , _ error ) {
1351
1381
// Find the policy that applies to the start key.
1352
- idx , eq := slices .BinarySearchFunc (uniqueKeys , startKey , cmp )
1382
+ idx , eq := slices .BinarySearchFunc (uniqueKeys , bounds . Start , cmp )
1353
1383
switch idx {
1354
1384
case len (uniqueKeys ):
1355
1385
// The start key is after the last policy.
0 commit comments