github.com/bartle-stripe/trillian@v1.2.1/storage/memory/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 memory
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/golang/glog"
    24  	"github.com/golang/protobuf/ptypes"
    25  	"github.com/google/trillian"
    26  	"github.com/google/trillian/storage"
    27  )
    28  
    29  // NewAdminStorage returns a storage.AdminStorage implementation backed by
    30  // memoryTreeStorage.
    31  func NewAdminStorage(ms storage.LogStorage) storage.AdminStorage {
    32  	return &memoryAdminStorage{ms.(*memoryLogStorage).memoryTreeStorage}
    33  }
    34  
    35  // memoryAdminStorage implements storage.AdminStorage
    36  type memoryAdminStorage struct {
    37  	ms *memoryTreeStorage
    38  }
    39  
    40  func (s *memoryAdminStorage) Snapshot(ctx context.Context) (storage.ReadOnlyAdminTX, error) {
    41  	return &adminTX{ms: s.ms}, nil
    42  }
    43  
    44  func (s *memoryAdminStorage) ReadWriteTransaction(ctx context.Context, f storage.AdminTXFunc) error {
    45  	tx := &adminTX{ms: s.ms}
    46  	defer tx.Close()
    47  	if err := f(ctx, tx); err != nil {
    48  		return err
    49  	}
    50  	return tx.Commit()
    51  }
    52  
    53  func (s *memoryAdminStorage) CheckDatabaseAccessible(ctx context.Context) error {
    54  	return nil
    55  }
    56  
    57  type adminTX struct {
    58  	ms *memoryTreeStorage
    59  	// mu guards reads/writes on closed, which happen only on
    60  	// Commit/Rollback/IsClosed/Close methods.
    61  	// We don't check closed on *all* methods (apart from the ones above),
    62  	// as we trust tx to keep tabs on its state (and consequently fail to do
    63  	// queries after closed).
    64  	mu     sync.RWMutex
    65  	closed bool
    66  }
    67  
    68  func (t *adminTX) Commit() error {
    69  	// TODO(al): The admin implementation isn't transactional
    70  	t.mu.Lock()
    71  	defer t.mu.Unlock()
    72  	t.closed = true
    73  	return nil
    74  }
    75  
    76  func (t *adminTX) Rollback() error {
    77  	// TODO(al): The admin implementation isn't transactional
    78  	t.mu.Lock()
    79  	defer t.mu.Unlock()
    80  	t.closed = true
    81  	return nil
    82  }
    83  
    84  func (t *adminTX) IsClosed() bool {
    85  	t.mu.RLock()
    86  	defer t.mu.RUnlock()
    87  	return t.closed
    88  }
    89  
    90  func (t *adminTX) Close() error {
    91  	// Acquire and release read lock manually, without defer, as if the txn
    92  	// is not closed Rollback() will attempt to acquire the rw lock.
    93  	t.mu.RLock()
    94  	closed := t.closed
    95  	t.mu.RUnlock()
    96  	if !closed {
    97  		err := t.Rollback()
    98  		if err != nil {
    99  			glog.Warningf("Rollback error on Close(): %v", err)
   100  		}
   101  		return err
   102  	}
   103  	return nil
   104  }
   105  
   106  func (t *adminTX) GetTree(ctx context.Context, treeID int64) (*trillian.Tree, error) {
   107  	tree := t.ms.getTree(treeID)
   108  	tree.RLock()
   109  	defer tree.RUnlock()
   110  
   111  	if tree == nil {
   112  		return nil, fmt.Errorf("no such treeID %d", treeID)
   113  	}
   114  	return tree.meta, nil
   115  }
   116  
   117  func (t *adminTX) ListTreeIDs(ctx context.Context, includeDeleted bool) ([]int64, error) {
   118  	t.ms.mu.RLock()
   119  	defer t.ms.mu.RUnlock()
   120  
   121  	var ret []int64
   122  	for _, v := range t.ms.trees {
   123  		ret = append(ret, v.meta.TreeId)
   124  	}
   125  	return ret, nil
   126  }
   127  
   128  func (t *adminTX) ListTrees(ctx context.Context, includeDeleted bool) ([]*trillian.Tree, error) {
   129  	t.ms.mu.RLock()
   130  	defer t.ms.mu.RUnlock()
   131  
   132  	var ret []*trillian.Tree
   133  	for _, v := range t.ms.trees {
   134  		ret = append(ret, v.meta)
   135  	}
   136  	return ret, nil
   137  }
   138  
   139  func (t *adminTX) CreateTree(ctx context.Context, tr *trillian.Tree) (*trillian.Tree, error) {
   140  	if err := storage.ValidateTreeForCreation(ctx, tr); err != nil {
   141  		return nil, err
   142  	}
   143  	if err := validateStorageSettings(tr); err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	id, err := storage.NewTreeID()
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	now := time.Now()
   153  
   154  	meta := *tr
   155  	meta.TreeId = id
   156  	meta.CreateTime, err = ptypes.TimestampProto(now)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  	meta.UpdateTime, err = ptypes.TimestampProto(now)
   161  	if err != nil {
   162  		return nil, err
   163  	}
   164  
   165  	t.ms.mu.Lock()
   166  	defer t.ms.mu.Unlock()
   167  	t.ms.trees[id] = newTree(meta)
   168  
   169  	glog.V(1).Infof("trees: %v", t.ms.trees)
   170  
   171  	return &meta, nil
   172  }
   173  
   174  func (t *adminTX) UpdateTree(ctx context.Context, treeID int64, updateFunc func(*trillian.Tree)) (*trillian.Tree, error) {
   175  	mTree := t.ms.getTree(treeID)
   176  	mTree.mu.Lock()
   177  	defer mTree.mu.Unlock()
   178  
   179  	tree := mTree.meta
   180  	beforeUpdate := *tree
   181  	updateFunc(tree)
   182  	if err := storage.ValidateTreeForUpdate(ctx, &beforeUpdate, tree); err != nil {
   183  		return nil, err
   184  	}
   185  	if err := validateStorageSettings(tree); err != nil {
   186  		return nil, err
   187  	}
   188  
   189  	var err error
   190  	tree.UpdateTime, err = ptypes.TimestampProto(time.Now())
   191  	if err != nil {
   192  		return nil, err
   193  	}
   194  	return tree, nil
   195  }
   196  
   197  func (t *adminTX) SoftDeleteTree(ctx context.Context, treeID int64) (*trillian.Tree, error) {
   198  	return nil, fmt.Errorf("method not supported: SoftDeleteTree")
   199  }
   200  
   201  func (t *adminTX) HardDeleteTree(ctx context.Context, treeID int64) error {
   202  	return fmt.Errorf("method not supported: HardDeleteTree")
   203  }
   204  
   205  func (t *adminTX) UndeleteTree(ctx context.Context, treeID int64) (*trillian.Tree, error) {
   206  	return nil, fmt.Errorf("method not supported: UndeleteTree")
   207  }
   208  
   209  func validateStorageSettings(tree *trillian.Tree) error {
   210  	if tree.StorageSettings != nil {
   211  		return fmt.Errorf("storage_settings not supported, but got %v", tree.StorageSettings)
   212  	}
   213  	return nil
   214  }