github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/kv/kvserver/protectedts/protectedts.go (about)

     1  // Copyright 2019 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 protectedts exports the interface to the protected timestamp
    12  // subsystem which allows clients to prevent GC of expired data.
    13  package protectedts
    14  
    15  import (
    16  	"context"
    17  
    18  	"github.com/cockroachdb/cockroach/pkg/kv"
    19  	"github.com/cockroachdb/cockroach/pkg/kv/kvserver/protectedts/ptpb"
    20  	"github.com/cockroachdb/cockroach/pkg/roachpb"
    21  	"github.com/cockroachdb/cockroach/pkg/util/hlc"
    22  	"github.com/cockroachdb/cockroach/pkg/util/stop"
    23  	"github.com/cockroachdb/cockroach/pkg/util/uuid"
    24  	"github.com/cockroachdb/errors"
    25  )
    26  
    27  // ErrNotExists is returned from Get or Release if the record does
    28  // not exist.
    29  var ErrNotExists = errors.New("protected timestamp record does not exist")
    30  
    31  // ErrExists returned from Protect when trying to protect a record
    32  // with an ID which already exists.
    33  var ErrExists = errors.New("protected timestamp record already exists")
    34  
    35  // Provider is the central coordinator for the protectedts subsystem.
    36  // It exists to abstract interaction with subsystem.
    37  type Provider interface {
    38  	Storage
    39  	Cache
    40  	Verifier
    41  
    42  	Start(context.Context, *stop.Stopper) error
    43  }
    44  
    45  // Storage provides clients with a mechanism to transactionally protect and
    46  // release protected timestamps for a set of spans.
    47  //
    48  // Clients may provide a txn object which will allow them to write the id
    49  // of this new protection transactionally into their own state.
    50  // It is the caller's responsibility to ensure that a timestamp is ultimately
    51  // released.
    52  type Storage interface {
    53  
    54  	// Protect will durably create a protected timestamp, if no error is returned
    55  	// then no data in the specified spans which are live at the specified
    56  	// timestamp can be garbage collected until this Record is released.
    57  	//
    58  	// Protect may succeed and yet data may be or already have been garbage
    59  	// collected in the spans specified by the Record. However, the protected
    60  	// timestamp subsystem guarantees that if all possible zone configs which
    61  	// could have applied have GC TTLs which would not have allowed data at
    62  	// the timestamp which the passed Txn commits to be GC'd then that
    63  	// data will not be GC'd until this *Record is released.
    64  	//
    65  	// An error will be returned if the ID of the provided record already exists
    66  	// so callers should be sure to generate new IDs when creating records.
    67  	Protect(context.Context, *kv.Txn, *ptpb.Record) error
    68  
    69  	// GetRecord retreives the record with the specified UUID as well as the MVCC
    70  	// timestamp at which it was written. If no corresponding record exists
    71  	// ErrNotExists is returned.
    72  	//
    73  	// GetRecord exists to work in coordination with verification. In order
    74  	// to use Verifier.Verify a client must provide both the timestamp which
    75  	// should be protected as well as the timestamp at which the Record providing
    76  	// that protection is known to be alive. The ReadTimestamp of the Txn used in
    77  	// this method can be used to provide such a timestamp.
    78  	GetRecord(context.Context, *kv.Txn, uuid.UUID) (*ptpb.Record, error)
    79  
    80  	// MarkVerified will mark a protected timestamp as verified.
    81  	//
    82  	// This method is generally used by an implementation of Verifier.
    83  	MarkVerified(context.Context, *kv.Txn, uuid.UUID) error
    84  
    85  	// Release allows spans which were previously protected to now be garbage
    86  	// collected.
    87  	//
    88  	// If the specified UUID does not exist ErrNotFound is returned but the
    89  	// passed txn remains safe for future use.
    90  	Release(context.Context, *kv.Txn, uuid.UUID) error
    91  
    92  	// GetMetadata retreives the metadata with the provided Txn.
    93  	GetMetadata(context.Context, *kv.Txn) (ptpb.Metadata, error)
    94  
    95  	// GetState retreives the entire state of protectedts.Storage with the
    96  	// provided Txn.
    97  	GetState(context.Context, *kv.Txn) (ptpb.State, error)
    98  }
    99  
   100  // Iterator iterates records in a cache until wantMore is false or all Records
   101  // in the requested range have been seen.
   102  type Iterator func(*ptpb.Record) (wantMore bool)
   103  
   104  // Cache is used in the storage package to determine a safe timestamp for
   105  // garbage collection of expired data. A storage.Replica can remove data when
   106  // it has a proof from the Cache that there was no Record providing
   107  // protection. For example, a Replica which determines that it is not protected
   108  // by any Records at a given asOf can move its GC threshold up to that
   109  // timestamp less its GC TTL.
   110  type Cache interface {
   111  
   112  	// Iterate examines the records with spans which overlap with [from, to).
   113  	// Nil values for from or to are equivalent to Key{}. The order of records
   114  	// between independent calls to Iterate is not defined; the order of records
   115  	// may differ even for the same key range that occurs at the same timestamp.
   116  	// The Records passed to the iterator are safe to be retained but must not be
   117  	// modified.
   118  	Iterate(_ context.Context, from, to roachpb.Key, it Iterator) (asOf hlc.Timestamp)
   119  
   120  	// QueryRecord determines whether a Record with the provided ID exists in
   121  	// the Cache state and returns the timestamp corresponding to that state.
   122  	QueryRecord(_ context.Context, id uuid.UUID) (exists bool, asOf hlc.Timestamp)
   123  
   124  	// Refresh forces the cache to update to at least asOf.
   125  	Refresh(_ context.Context, asOf hlc.Timestamp) error
   126  }
   127  
   128  // Verifier provides a mechanism to verify that a created Record will certainly
   129  // apply.
   130  type Verifier interface {
   131  
   132  	// Verify returns an error if the record of the provided ID cannot be
   133  	// verified. If nil is returned then the record has been proven to apply
   134  	// until it is removed.
   135  	Verify(context.Context, uuid.UUID) error
   136  }
   137  
   138  // EmptyCache returns a Cache which always returns the current time and no
   139  // records. This is often useful in testing where you want a cache which
   140  // holds nothing and is always up-to-date.
   141  func EmptyCache(c *hlc.Clock) Cache {
   142  	return (*emptyCache)(c)
   143  }
   144  
   145  type emptyCache hlc.Clock
   146  
   147  func (c *emptyCache) Iterate(
   148  	_ context.Context, from, to roachpb.Key, it Iterator,
   149  ) (asOf hlc.Timestamp) {
   150  	return (*hlc.Clock)(c).Now()
   151  }
   152  
   153  func (c *emptyCache) QueryRecord(
   154  	_ context.Context, id uuid.UUID,
   155  ) (exists bool, asOf hlc.Timestamp) {
   156  	return false, (*hlc.Clock)(c).Now()
   157  }
   158  
   159  func (c *emptyCache) Refresh(_ context.Context, asOf hlc.Timestamp) error {
   160  	return nil
   161  }