github.com/letsencrypt/trillian@v1.1.2-0.20180615153820-ae375a99d36a/storage/admin_storage.go (about) 1 // Copyright 2017 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 20 "github.com/google/trillian" 21 ) 22 23 // ReadOnlyAdminTX is a transaction capable only of read operations in the 24 // AdminStorage. 25 type ReadOnlyAdminTX interface { 26 AdminReader 27 28 // Commit applies the operations performed to the underlying storage, or 29 // returns an error. 30 // A commit must be performed before any reads from storage are 31 // considered consistent. 32 Commit() error 33 34 // Rollback aborts any performed operations, or returns an error. 35 // See Close() for a way to automatically manage transactions. 36 Rollback() error 37 38 // IsClosed returns true if the transaction is closed. 39 // A transaction is closed when either Commit() or Rollback() are 40 // called. 41 IsClosed() bool 42 43 // Close rolls back the transaction if it's not yet closed. 44 // It's advisable to call "defer tx.Close()" after the creation of 45 // transaction to ensure that it's always rolled back if not explicitly 46 // committed. 47 Close() error 48 } 49 50 // AdminTX is a transaction capable of read and write operations in the 51 // AdminStorage. 52 type AdminTX interface { 53 ReadOnlyAdminTX 54 AdminWriter 55 } 56 57 // AdminTXFunc is the signature for functions passed to ReadWriteTransaction. 58 type AdminTXFunc func(context.Context, AdminTX) error 59 60 // AdminStorage represents the persistent storage of tree data. 61 type AdminStorage interface { 62 // Snapshot starts a read-only transaction. 63 // A transaction must be explicitly committed before the data read by it 64 // is considered consistent. 65 Snapshot(ctx context.Context) (ReadOnlyAdminTX, error) 66 67 // ReadWriteTransaction creates a transaction, and runs f with it. 68 // Some storage implementations may retry aborted transactions, so 69 // f MUST be idempotent. 70 ReadWriteTransaction(ctx context.Context, f AdminTXFunc) error 71 72 // CheckDatabaseAccessible checks whether we are able to connect to / open the 73 // underlying storage. 74 CheckDatabaseAccessible(ctx context.Context) error 75 } 76 77 // AdminReader provides a read-only interface for tree data. 78 type AdminReader interface { 79 // GetTree returns the tree corresponding to treeID or an error. 80 GetTree(ctx context.Context, treeID int64) (*trillian.Tree, error) 81 82 // ListTreeIDs returns the IDs of all trees in storage. 83 // Note that there's no authorization restriction on the IDs returned, 84 // so it should be used with caution in production code. 85 ListTreeIDs(ctx context.Context, includeDeleted bool) ([]int64, error) 86 87 // ListTrees returns all trees in storage. 88 // Note that there's no authorization restriction on the trees returned, 89 // so it should be used with caution in production code. 90 ListTrees(ctx context.Context, includeDeleted bool) ([]*trillian.Tree, error) 91 } 92 93 // AdminWriter provides a write-only interface for tree data. 94 type AdminWriter interface { 95 // CreateTree inserts the specified tree in storage, returning a tree 96 // with all storage-generated fields set. 97 // Note that treeID and timestamps will be automatically generated by 98 // the storage layer, thus may be ignored by the implementation. 99 // Remaining fields must be set to valid values. 100 // Returns an error if the tree is invalid or creation fails. 101 CreateTree(ctx context.Context, tree *trillian.Tree) (*trillian.Tree, error) 102 103 // UpdateTree updates the specified tree in storage, returning a tree 104 // with all storage-generated fields set. 105 // updateFunc is called to perform the desired tree modifications. Refer 106 // to trillian.Tree for details on which fields are mutable and what is 107 // considered valid. 108 // Returns an error if the tree is invalid or the update cannot be 109 // performed. 110 UpdateTree(ctx context.Context, treeID int64, updateFunc func(*trillian.Tree)) (*trillian.Tree, error) 111 112 // SoftDeleteTree soft deletes the specified tree. 113 // The tree must exist and not be already soft deleted, otherwise an error is returned. 114 // Soft deletion may be undone via UndeleteTree. 115 SoftDeleteTree(ctx context.Context, treeID int64) (*trillian.Tree, error) 116 117 // HardDeleteTree hard deletes (i.e. completely removes from storage) the specified tree and all 118 // records related to it. 119 // The tree must exist and currently be soft deleted, as per SoftDeletedTree, otherwise an error 120 // is returned. 121 // Hard deleted trees cannot be recovered. 122 HardDeleteTree(ctx context.Context, treeID int64) error 123 124 // UndeleteTree undeletes a soft-deleted tree. 125 // The tree must exist and currently be soft deleted, as per SoftDeletedTree, otherwise an error 126 // is returned. 127 UndeleteTree(ctx context.Context, treeID int64) (*trillian.Tree, error) 128 } 129 130 // RunInAdminSnapshot runs fn against a ReadOnlyAdminTX and commits if no error is returned. 131 func RunInAdminSnapshot(ctx context.Context, admin AdminStorage, fn func(tx ReadOnlyAdminTX) error) error { 132 tx, err := admin.Snapshot(ctx) 133 if err != nil { 134 return err 135 } 136 defer tx.Close() 137 if err := fn(tx); err != nil { 138 return err 139 } 140 return tx.Commit() 141 }