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 }