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 }