github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/spanset/batch.go (about) 1 // Copyright 2017 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package spanset 12 13 import ( 14 "github.com/cockroachdb/cockroach/pkg/roachpb" 15 "github.com/cockroachdb/cockroach/pkg/storage" 16 "github.com/cockroachdb/cockroach/pkg/storage/enginepb" 17 "github.com/cockroachdb/cockroach/pkg/util/hlc" 18 "github.com/cockroachdb/cockroach/pkg/util/protoutil" 19 ) 20 21 // Iterator wraps an engine.Iterator and ensures that it can 22 // only be used to access spans in a SpanSet. 23 type Iterator struct { 24 i storage.Iterator 25 spans *SpanSet 26 27 // spansOnly controls whether or not timestamps associated with the 28 // spans are considered when ensuring access. If set to true, 29 // only span boundaries are checked. 30 spansOnly bool 31 32 // Timestamp the access is taking place. If timestamp is zero, access is 33 // considered non-MVCC. If spansOnly is set to true, ts is not consulted. 34 ts hlc.Timestamp 35 36 // Seeking to an invalid key puts the iterator in an error state. 37 err error 38 // Reaching an out-of-bounds key with Next/Prev invalidates the 39 // iterator but does not set err. 40 invalid bool 41 } 42 43 var _ storage.Iterator = &Iterator{} 44 var _ storage.MVCCIterator = &Iterator{} 45 46 // NewIterator constructs an iterator that verifies access of the underlying 47 // iterator against the given SpanSet. Timestamps associated with the spans 48 // in the spanset are not considered, only the span boundaries are checked. 49 func NewIterator(iter storage.Iterator, spans *SpanSet) *Iterator { 50 return &Iterator{i: iter, spans: spans, spansOnly: true} 51 } 52 53 // NewIteratorAt constructs an iterator that verifies access of the underlying 54 // iterator against the given SpanSet at the given timestamp. 55 func NewIteratorAt(iter storage.Iterator, spans *SpanSet, ts hlc.Timestamp) *Iterator { 56 return &Iterator{i: iter, spans: spans, ts: ts} 57 } 58 59 // Close is part of the engine.Iterator interface. 60 func (i *Iterator) Close() { 61 i.i.Close() 62 } 63 64 // Iterator returns the underlying engine.Iterator. 65 func (i *Iterator) Iterator() storage.Iterator { 66 return i.i 67 } 68 69 // Valid is part of the engine.Iterator interface. 70 func (i *Iterator) Valid() (bool, error) { 71 if i.err != nil { 72 return false, i.err 73 } 74 ok, err := i.i.Valid() 75 if err != nil { 76 return false, err 77 } 78 return ok && !i.invalid, nil 79 } 80 81 // SeekGE is part of the engine.Iterator interface. 82 func (i *Iterator) SeekGE(key storage.MVCCKey) { 83 i.i.SeekGE(key) 84 i.checkAllowed(roachpb.Span{Key: key.Key}, true) 85 } 86 87 // SeekLT is part of the engine.Iterator interface. 88 func (i *Iterator) SeekLT(key storage.MVCCKey) { 89 i.i.SeekLT(key) 90 // CheckAllowed{At} supports the span representation of [,key), which 91 // corresponds to the span [key.Prev(),). 92 i.checkAllowed(roachpb.Span{EndKey: key.Key}, true) 93 } 94 95 // Next is part of the engine.Iterator interface. 96 func (i *Iterator) Next() { 97 i.i.Next() 98 i.checkAllowed(roachpb.Span{Key: i.UnsafeKey().Key}, false) 99 } 100 101 // Prev is part of the engine.Iterator interface. 102 func (i *Iterator) Prev() { 103 i.i.Prev() 104 i.checkAllowed(roachpb.Span{Key: i.UnsafeKey().Key}, false) 105 } 106 107 // NextKey is part of the engine.Iterator interface. 108 func (i *Iterator) NextKey() { 109 i.i.NextKey() 110 i.checkAllowed(roachpb.Span{Key: i.UnsafeKey().Key}, false) 111 } 112 113 func (i *Iterator) checkAllowed(span roachpb.Span, errIfDisallowed bool) { 114 i.invalid = false 115 i.err = nil 116 if ok, _ := i.i.Valid(); !ok { 117 // If the iterator is invalid after the operation, there's nothing to 118 // check. We allow uses of iterators to exceed the declared span bounds 119 // as long as the iterator itself is configured with proper boundaries. 120 return 121 } 122 var err error 123 if i.spansOnly { 124 err = i.spans.CheckAllowed(SpanReadOnly, span) 125 } else { 126 err = i.spans.CheckAllowedAt(SpanReadOnly, span, i.ts) 127 } 128 if errIfDisallowed { 129 i.err = err 130 } else { 131 i.invalid = err != nil 132 } 133 } 134 135 // Key is part of the engine.Iterator interface. 136 func (i *Iterator) Key() storage.MVCCKey { 137 return i.i.Key() 138 } 139 140 // Value is part of the engine.Iterator interface. 141 func (i *Iterator) Value() []byte { 142 return i.i.Value() 143 } 144 145 // ValueProto is part of the engine.Iterator interface. 146 func (i *Iterator) ValueProto(msg protoutil.Message) error { 147 return i.i.ValueProto(msg) 148 } 149 150 // UnsafeKey is part of the engine.Iterator interface. 151 func (i *Iterator) UnsafeKey() storage.MVCCKey { 152 return i.i.UnsafeKey() 153 } 154 155 // UnsafeValue is part of the engine.Iterator interface. 156 func (i *Iterator) UnsafeValue() []byte { 157 return i.i.UnsafeValue() 158 } 159 160 // ComputeStats is part of the engine.Iterator interface. 161 func (i *Iterator) ComputeStats( 162 start, end roachpb.Key, nowNanos int64, 163 ) (enginepb.MVCCStats, error) { 164 if i.spansOnly { 165 if err := i.spans.CheckAllowed(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}); err != nil { 166 return enginepb.MVCCStats{}, err 167 } 168 } else { 169 if err := i.spans.CheckAllowedAt(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}, i.ts); err != nil { 170 return enginepb.MVCCStats{}, err 171 } 172 } 173 return i.i.ComputeStats(start, end, nowNanos) 174 } 175 176 // FindSplitKey is part of the engine.Iterator interface. 177 func (i *Iterator) FindSplitKey( 178 start, end, minSplitKey roachpb.Key, targetSize int64, 179 ) (storage.MVCCKey, error) { 180 if i.spansOnly { 181 if err := i.spans.CheckAllowed(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}); err != nil { 182 return storage.MVCCKey{}, err 183 } 184 } else { 185 if err := i.spans.CheckAllowedAt(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}, i.ts); err != nil { 186 return storage.MVCCKey{}, err 187 } 188 } 189 return i.i.FindSplitKey(start, end, minSplitKey, targetSize) 190 } 191 192 // CheckForKeyCollisions is part of the engine.Iterator interface. 193 func (i *Iterator) CheckForKeyCollisions( 194 sstData []byte, start, end roachpb.Key, 195 ) (enginepb.MVCCStats, error) { 196 return i.i.CheckForKeyCollisions(sstData, start, end) 197 } 198 199 // SetUpperBound is part of the engine.Iterator interface. 200 func (i *Iterator) SetUpperBound(key roachpb.Key) { 201 i.i.SetUpperBound(key) 202 } 203 204 // Stats is part of the engine.Iterator interface. 205 func (i *Iterator) Stats() storage.IteratorStats { 206 return i.i.Stats() 207 } 208 209 // MVCCOpsSpecialized is part of the engine.MVCCIterator interface. 210 func (i *Iterator) MVCCOpsSpecialized() bool { 211 if mvccIt, ok := i.i.(storage.MVCCIterator); ok { 212 return mvccIt.MVCCOpsSpecialized() 213 } 214 return false 215 } 216 217 // MVCCGet is part of the engine.MVCCIterator interface. 218 func (i *Iterator) MVCCGet( 219 key roachpb.Key, timestamp hlc.Timestamp, opts storage.MVCCGetOptions, 220 ) (*roachpb.Value, *roachpb.Intent, error) { 221 if i.spansOnly { 222 if err := i.spans.CheckAllowed(SpanReadOnly, roachpb.Span{Key: key}); err != nil { 223 return nil, nil, err 224 } 225 } else { 226 if err := i.spans.CheckAllowedAt(SpanReadOnly, roachpb.Span{Key: key}, timestamp); err != nil { 227 return nil, nil, err 228 } 229 } 230 return i.i.(storage.MVCCIterator).MVCCGet(key, timestamp, opts) 231 } 232 233 // MVCCScan is part of the engine.MVCCIterator interface. 234 func (i *Iterator) MVCCScan( 235 start, end roachpb.Key, timestamp hlc.Timestamp, opts storage.MVCCScanOptions, 236 ) (storage.MVCCScanResult, error) { 237 if i.spansOnly { 238 if err := i.spans.CheckAllowed(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}); err != nil { 239 return storage.MVCCScanResult{}, err 240 } 241 } else { 242 if err := i.spans.CheckAllowedAt(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}, timestamp); err != nil { 243 return storage.MVCCScanResult{}, err 244 } 245 } 246 return i.i.(storage.MVCCIterator).MVCCScan(start, end, timestamp, opts) 247 } 248 249 type spanSetReader struct { 250 r storage.Reader 251 spans *SpanSet 252 253 spansOnly bool 254 ts hlc.Timestamp 255 } 256 257 var _ storage.Reader = spanSetReader{} 258 259 func (s spanSetReader) Close() { 260 s.r.Close() 261 } 262 263 func (s spanSetReader) Closed() bool { 264 return s.r.Closed() 265 } 266 267 // ExportToSst is part of the engine.Reader interface. 268 func (s spanSetReader) ExportToSst( 269 startKey, endKey roachpb.Key, 270 startTS, endTS hlc.Timestamp, 271 exportAllRevisions bool, 272 targetSize, maxSize uint64, 273 io storage.IterOptions, 274 ) ([]byte, roachpb.BulkOpSummary, roachpb.Key, error) { 275 return s.r.ExportToSst(startKey, endKey, startTS, endTS, exportAllRevisions, targetSize, maxSize, io) 276 } 277 278 func (s spanSetReader) Get(key storage.MVCCKey) ([]byte, error) { 279 if s.spansOnly { 280 if err := s.spans.CheckAllowed(SpanReadOnly, roachpb.Span{Key: key.Key}); err != nil { 281 return nil, err 282 } 283 } else { 284 if err := s.spans.CheckAllowedAt(SpanReadOnly, roachpb.Span{Key: key.Key}, s.ts); err != nil { 285 return nil, err 286 } 287 } 288 //lint:ignore SA1019 implementing deprecated interface function (Get) is OK 289 return s.r.Get(key) 290 } 291 292 func (s spanSetReader) GetProto( 293 key storage.MVCCKey, msg protoutil.Message, 294 ) (bool, int64, int64, error) { 295 if s.spansOnly { 296 if err := s.spans.CheckAllowed(SpanReadOnly, roachpb.Span{Key: key.Key}); err != nil { 297 return false, 0, 0, err 298 } 299 } else { 300 if err := s.spans.CheckAllowedAt(SpanReadOnly, roachpb.Span{Key: key.Key}, s.ts); err != nil { 301 return false, 0, 0, err 302 } 303 } 304 //lint:ignore SA1019 implementing deprecated interface function (GetProto) is OK 305 return s.r.GetProto(key, msg) 306 } 307 308 func (s spanSetReader) Iterate( 309 start, end roachpb.Key, f func(storage.MVCCKeyValue) (bool, error), 310 ) error { 311 if s.spansOnly { 312 if err := s.spans.CheckAllowed(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}); err != nil { 313 return err 314 } 315 } else { 316 if err := s.spans.CheckAllowedAt(SpanReadOnly, roachpb.Span{Key: start, EndKey: end}, s.ts); err != nil { 317 return err 318 } 319 } 320 return s.r.Iterate(start, end, f) 321 } 322 323 func (s spanSetReader) NewIterator(opts storage.IterOptions) storage.Iterator { 324 if s.spansOnly { 325 return NewIterator(s.r.NewIterator(opts), s.spans) 326 } 327 return NewIteratorAt(s.r.NewIterator(opts), s.spans, s.ts) 328 } 329 330 // GetDBEngine recursively searches for the underlying rocksDB engine. 331 func GetDBEngine(reader storage.Reader, span roachpb.Span) storage.Reader { 332 switch v := reader.(type) { 333 case ReadWriter: 334 return GetDBEngine(getSpanReader(v, span), span) 335 case *spanSetBatch: 336 return GetDBEngine(getSpanReader(v.ReadWriter, span), span) 337 default: 338 return reader 339 } 340 } 341 342 // getSpanReader is a getter to access the engine.Reader field of the 343 // spansetReader. 344 func getSpanReader(r ReadWriter, span roachpb.Span) storage.Reader { 345 if err := r.spanSetReader.spans.CheckAllowed(SpanReadOnly, span); err != nil { 346 panic("Not in the span") 347 } 348 349 return r.spanSetReader.r 350 } 351 352 type spanSetWriter struct { 353 w storage.Writer 354 spans *SpanSet 355 356 spansOnly bool 357 ts hlc.Timestamp 358 } 359 360 var _ storage.Writer = spanSetWriter{} 361 362 func (s spanSetWriter) ApplyBatchRepr(repr []byte, sync bool) error { 363 // Assume that the constructor of the batch has bounded it correctly. 364 return s.w.ApplyBatchRepr(repr, sync) 365 } 366 367 func (s spanSetWriter) Clear(key storage.MVCCKey) error { 368 if s.spansOnly { 369 if err := s.spans.CheckAllowed(SpanReadWrite, roachpb.Span{Key: key.Key}); err != nil { 370 return err 371 } 372 } else { 373 if err := s.spans.CheckAllowedAt(SpanReadWrite, roachpb.Span{Key: key.Key}, s.ts); err != nil { 374 return err 375 } 376 } 377 return s.w.Clear(key) 378 } 379 380 func (s spanSetWriter) SingleClear(key storage.MVCCKey) error { 381 if s.spansOnly { 382 if err := s.spans.CheckAllowed(SpanReadWrite, roachpb.Span{Key: key.Key}); err != nil { 383 return err 384 } 385 } else { 386 if err := s.spans.CheckAllowedAt(SpanReadWrite, roachpb.Span{Key: key.Key}, s.ts); err != nil { 387 return err 388 } 389 } 390 return s.w.SingleClear(key) 391 } 392 393 func (s spanSetWriter) ClearRange(start, end storage.MVCCKey) error { 394 if s.spansOnly { 395 if err := s.spans.CheckAllowed(SpanReadWrite, roachpb.Span{Key: start.Key, EndKey: end.Key}); err != nil { 396 return err 397 } 398 } else { 399 if err := s.spans.CheckAllowedAt(SpanReadWrite, roachpb.Span{Key: start.Key, EndKey: end.Key}, s.ts); err != nil { 400 return err 401 } 402 } 403 return s.w.ClearRange(start, end) 404 } 405 406 func (s spanSetWriter) ClearIterRange(iter storage.Iterator, start, end roachpb.Key) error { 407 if s.spansOnly { 408 if err := s.spans.CheckAllowed(SpanReadWrite, roachpb.Span{Key: start, EndKey: end}); err != nil { 409 return err 410 } 411 } else { 412 if err := s.spans.CheckAllowedAt(SpanReadWrite, roachpb.Span{Key: start, EndKey: end}, s.ts); err != nil { 413 return err 414 } 415 } 416 return s.w.ClearIterRange(iter, start, end) 417 } 418 419 func (s spanSetWriter) Merge(key storage.MVCCKey, value []byte) error { 420 if s.spansOnly { 421 if err := s.spans.CheckAllowed(SpanReadWrite, roachpb.Span{Key: key.Key}); err != nil { 422 return err 423 } 424 } else { 425 if err := s.spans.CheckAllowedAt(SpanReadWrite, roachpb.Span{Key: key.Key}, s.ts); err != nil { 426 return err 427 } 428 } 429 return s.w.Merge(key, value) 430 } 431 432 func (s spanSetWriter) Put(key storage.MVCCKey, value []byte) error { 433 if s.spansOnly { 434 if err := s.spans.CheckAllowed(SpanReadWrite, roachpb.Span{Key: key.Key}); err != nil { 435 return err 436 } 437 } else { 438 if err := s.spans.CheckAllowedAt(SpanReadWrite, roachpb.Span{Key: key.Key}, s.ts); err != nil { 439 return err 440 } 441 } 442 return s.w.Put(key, value) 443 } 444 445 func (s spanSetWriter) LogData(data []byte) error { 446 return s.w.LogData(data) 447 } 448 449 func (s spanSetWriter) LogLogicalOp( 450 op storage.MVCCLogicalOpType, details storage.MVCCLogicalOpDetails, 451 ) { 452 s.w.LogLogicalOp(op, details) 453 } 454 455 // ReadWriter is used outside of the spanset package internally, in ccl. 456 type ReadWriter struct { 457 spanSetReader 458 spanSetWriter 459 } 460 461 var _ storage.ReadWriter = ReadWriter{} 462 463 func makeSpanSetReadWriter(rw storage.ReadWriter, spans *SpanSet) ReadWriter { 464 return ReadWriter{ 465 spanSetReader: spanSetReader{r: rw, spans: spans, spansOnly: true}, 466 spanSetWriter: spanSetWriter{w: rw, spans: spans, spansOnly: true}, 467 } 468 } 469 470 func makeSpanSetReadWriterAt(rw storage.ReadWriter, spans *SpanSet, ts hlc.Timestamp) ReadWriter { 471 return ReadWriter{ 472 spanSetReader: spanSetReader{r: rw, spans: spans, ts: ts}, 473 spanSetWriter: spanSetWriter{w: rw, spans: spans, ts: ts}, 474 } 475 } 476 477 // NewReadWriter returns an engine.ReadWriter that asserts access of the 478 // underlying ReadWriter against the given SpanSet. 479 func NewReadWriter(rw storage.ReadWriter, spans *SpanSet) storage.ReadWriter { 480 return makeSpanSetReadWriter(rw, spans) 481 } 482 483 // NewReadWriterAt returns an engine.ReadWriter that asserts access of the 484 // underlying ReadWriter against the given SpanSet at a given timestamp. 485 // If zero timestamp is provided, accesses are considered non-MVCC. 486 func NewReadWriterAt(rw storage.ReadWriter, spans *SpanSet, ts hlc.Timestamp) storage.ReadWriter { 487 return makeSpanSetReadWriterAt(rw, spans, ts) 488 } 489 490 type spanSetBatch struct { 491 ReadWriter 492 b storage.Batch 493 spans *SpanSet 494 495 spansOnly bool 496 ts hlc.Timestamp 497 } 498 499 var _ storage.Batch = spanSetBatch{} 500 501 func (s spanSetBatch) Commit(sync bool) error { 502 return s.b.Commit(sync) 503 } 504 505 func (s spanSetBatch) Distinct() storage.ReadWriter { 506 if s.spansOnly { 507 return NewReadWriter(s.b.Distinct(), s.spans) 508 } 509 return NewReadWriterAt(s.b.Distinct(), s.spans, s.ts) 510 } 511 512 func (s spanSetBatch) Empty() bool { 513 return s.b.Empty() 514 } 515 516 func (s spanSetBatch) Len() int { 517 return s.b.Len() 518 } 519 520 func (s spanSetBatch) Repr() []byte { 521 return s.b.Repr() 522 } 523 524 // NewBatch returns an engine.Batch that asserts access of the underlying 525 // Batch against the given SpanSet. We only consider span boundaries, associated 526 // timestamps are not considered. 527 func NewBatch(b storage.Batch, spans *SpanSet) storage.Batch { 528 return &spanSetBatch{ 529 ReadWriter: makeSpanSetReadWriter(b, spans), 530 b: b, 531 spans: spans, 532 spansOnly: true, 533 } 534 } 535 536 // NewBatchAt returns an engine.Batch that asserts access of the underlying 537 // Batch against the given SpanSet at the given timestamp. 538 // If the zero timestamp is used, all accesses are considered non-MVCC. 539 func NewBatchAt(b storage.Batch, spans *SpanSet, ts hlc.Timestamp) storage.Batch { 540 return &spanSetBatch{ 541 ReadWriter: makeSpanSetReadWriterAt(b, spans, ts), 542 b: b, 543 spans: spans, 544 ts: ts, 545 } 546 }