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  }