github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/storage/log_storage.go (about) 1 // Copyright 2016 Google Inc. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package storage 16 17 import ( 18 "context" 19 "time" 20 21 "github.com/google/trillian" 22 ) 23 24 // ReadOnlyLogTX provides a read-only view into log data. 25 // A ReadOnlyLogTX, unlike ReadOnlyLogTreeTX, is not tied to a particular tree. 26 type ReadOnlyLogTX interface { 27 LogMetadata 28 29 // Commit ensures the data read by the TX is consistent in the database. Only after Commit the 30 // data read should be regarded as valid. 31 Commit() error 32 33 // Rollback discards the read-only TX. 34 Rollback() error 35 36 // Close attempts to Rollback the TX if it's open, it's a noop otherwise. 37 Close() error 38 } 39 40 // ReadOnlyLogTreeTX provides a read-only view into the Log data. 41 // A ReadOnlyLogTreeTX can only read from the tree specified in its creation. 42 type ReadOnlyLogTreeTX interface { 43 ReadOnlyTreeTX 44 45 // GetSequencedLeafCount returns the total number of leaves that have been integrated into the 46 // tree via sequencing. 47 GetSequencedLeafCount(ctx context.Context) (int64, error) 48 // GetLeavesByIndex returns leaf metadata and data for a set of specified sequenced leaf indexes. 49 GetLeavesByIndex(ctx context.Context, leaves []int64) ([]*trillian.LogLeaf, error) 50 // GetLeavesByRange returns leaf data for a range of indexes. The returned 51 // slice is a contiguous prefix of leaves in [start, start+count) ordered by 52 // LeafIndex. It will be shorter than `count` if the requested range has 53 // missing entries (e.g., it extends beyond the size of a LOG tree), or 54 // `count` is too big to handle in one go. 55 // For PREORDERED_LOG trees, *must* return leaves beyond the tree size if 56 // they are stored, in order to allow integrating them into the tree. 57 GetLeavesByRange(ctx context.Context, start, count int64) ([]*trillian.LogLeaf, error) 58 // GetLeavesByHash looks up sequenced leaf metadata and data by their Merkle leaf hash. If the 59 // tree permits duplicate leaves callers must be prepared to handle multiple results with the 60 // same hash but different sequence numbers. If orderBySequence is true then the returned data 61 // will be in ascending sequence number order. 62 GetLeavesByHash(ctx context.Context, leafHashes [][]byte, orderBySequence bool) ([]*trillian.LogLeaf, error) 63 // LatestSignedLogRoot returns the most recent SignedLogRoot, if any. 64 LatestSignedLogRoot(ctx context.Context) (trillian.SignedLogRoot, error) 65 } 66 67 // LogTreeTX is the transactional interface for reading/updating a Log. 68 // It extends the basic TreeTX interface with Log specific methods. 69 // After a call to Commit or Rollback implementations must be in a clean state and have 70 // released any resources owned by the LogTX. 71 // A LogTreeTX can only modify the tree specified in its creation. 72 type LogTreeTX interface { 73 ReadOnlyLogTreeTX 74 TreeWriter 75 76 // StoreSignedLogRoot stores a freshly created SignedLogRoot. 77 StoreSignedLogRoot(ctx context.Context, root trillian.SignedLogRoot) error 78 // QueueLeaves enqueues leaves for later integration into the tree. 79 // If error is nil, the returned slice of leaves will be the same size as the 80 // input, and each entry will hold: 81 // - the existing leaf data (the LogLeaf fields not marked output-only) if 82 // a duplicate has been submitted 83 // - nil otherwise. 84 // Duplicates are only reported if the underlying tree does not permit duplicates, and are 85 // considered duplicate if their leaf.LeafIdentityHash matches. 86 QueueLeaves(ctx context.Context, leaves []*trillian.LogLeaf, queueTimestamp time.Time) ([]*trillian.LogLeaf, error) 87 // DequeueLeaves will return between [0, limit] leaves from the queue. 88 // Leaves which have been dequeued within a Rolled-back Tx will become available for dequeing again. 89 // Leaves queued more recently than the cutoff time will not be returned. This allows for 90 // guard intervals to be configured. 91 DequeueLeaves(ctx context.Context, limit int, cutoffTime time.Time) ([]*trillian.LogLeaf, error) 92 93 // TODO(pavelkalinnikov): Comment properly. 94 AddSequencedLeaves(ctx context.Context, leaves []*trillian.LogLeaf, timestamp time.Time) ([]*trillian.QueuedLogLeaf, error) 95 96 // UpdateSequencedLeaves associates the leaves with the sequence numbers 97 // assigned to them. 98 UpdateSequencedLeaves(ctx context.Context, leaves []*trillian.LogLeaf) error 99 } 100 101 // ReadOnlyLogStorage represents a narrowed read-only view into a LogStorage. 102 type ReadOnlyLogStorage interface { 103 DatabaseChecker 104 105 // Snapshot starts a read-only transaction not tied to any particular tree. 106 Snapshot(ctx context.Context) (ReadOnlyLogTX, error) 107 108 // SnapshotForTree starts a read-only transaction for the specified treeID. 109 // Commit must be called when the caller is finished with the returned object, 110 // and values read through it should only be propagated if Commit returns 111 // without error. 112 SnapshotForTree(ctx context.Context, tree *trillian.Tree) (ReadOnlyLogTreeTX, error) 113 } 114 115 // LogTXFunc is the func signature for passing into ReadWriteTransaction. 116 type LogTXFunc func(context.Context, LogTreeTX) error 117 118 // LogStorage should be implemented by concrete storage mechanisms which want to support Logs. 119 type LogStorage interface { 120 ReadOnlyLogStorage 121 122 // ReadWriteTransaction starts a RW transaction on the underlying storage, and 123 // calls f with it. 124 // If f fails and returns an error, the storage implementation may optionally 125 // retry with a new transaction, and f MUST NOT keep state across calls. 126 ReadWriteTransaction(ctx context.Context, tree *trillian.Tree, f LogTXFunc) error 127 128 // QueueLeaves enqueues leaves for later integration into the tree. 129 // If error is nil, the returned slice of leaves will be the same size as the 130 // input, and each entry will hold a passed-in leaf struct and a Status 131 // representing the outcome for that particular leaf: 132 // * a status of OK indicates that the leaf was successfully queued. 133 // * a status of AlreadyExists indicates that the leaf was a duplicate, in this case 134 // the returned leaf data is that of the original. 135 // Other status values may be returned in error cases. 136 // 137 // Duplicates are only reported if the underlying tree does not permit duplicates, and are 138 // considered duplicate if their leaf.LeafIdentityHash matches. 139 // 140 // Note that in contrast to LogTX.QueueLeaves, implementations of this func must not return 141 // slices with nil values. 142 QueueLeaves(ctx context.Context, tree *trillian.Tree, leaves []*trillian.LogLeaf, queueTimestamp time.Time) ([]*trillian.QueuedLogLeaf, error) 143 144 // AddSequencedLeaves stores the `leaves` and associates them with the log 145 // positions according to their `LeafIndex` field. The indices must be 146 // contiguous. 147 // 148 // If error is nil, the returned slice is the same size as the input, entries 149 // correspond to the `leaves` in the same order. Each entry describes the 150 // result of adding the corresponding leaf. 151 // 152 // Possible `QueuedLogLeaf.status` values with their semantics: 153 // - OK: The leaf has been successfully stored. 154 // - AlreadyExists: The storage already contains an identical leaf at the 155 // specified `LeafIndex`. That leaf is returned in `QueuedLogLeaf.leaf`. 156 // - FailedPrecondition: There is another leaf with the same `LeafIndex`, 157 // but a different value. That leaf is returned in `QueuedLogLeaf.leaf`. 158 // - OutOfRange: The leaf can not be stored at the specified `LeafIndex`. 159 // For example, the storage might not support non-sequential writes. 160 // - Internal, etc: A storage-specific error. 161 // 162 // TODO(pavelkalinnikov): Make returning the resulting/conflicting leaves 163 // optional. Channel these options to the top-level Log API. 164 // TODO(pavelkalinnikov): Not checking values of the occupied indices might 165 // be a good optimization. Could also be optional. 166 AddSequencedLeaves(ctx context.Context, tree *trillian.Tree, leaves []*trillian.LogLeaf, timestamp time.Time) ([]*trillian.QueuedLogLeaf, error) 167 } 168 169 // CountByLogID is a map of total number of items keyed by log ID. 170 type CountByLogID map[int64]int64 171 172 // LogMetadata provides access to information about the logs in storage 173 type LogMetadata interface { 174 // GetActiveLogIDs returns a list of the IDs of all the logs that are 175 // configured in storage and are eligible to have entries sequenced. 176 GetActiveLogIDs(ctx context.Context) ([]int64, error) 177 178 // GetUnsequencedCounts returns a map of the number of unsequenced entries 179 // by log ID. 180 // 181 // This call is likely to be VERY expensive and take a long time to complete. 182 // Consider carefully whether you really need to call it! 183 GetUnsequencedCounts(ctx context.Context) (CountByLogID, error) 184 }