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  }