package storage
import (
"context"
"fmt"
"github.com/google/trillian"
"github.com/google/trillian/monitoring"
"k8s.io/klog/v2"
)
const traceSpanRoot = "/trillian/storage"
func GetTree(ctx context.Context, admin AdminStorage, treeID int64) (*trillian.Tree, error) {
ctx, spanEnd := spanFor(ctx, "GetTree")
defer spanEnd()
var tree *trillian.Tree
err := RunInAdminSnapshot(ctx, admin, func(tx ReadOnlyAdminTX) error {
var err error
tree, err = tx.GetTree(ctx, treeID)
return err
})
return tree, err
}
func ListTrees(ctx context.Context, admin AdminStorage, includeDeleted bool) ([]*trillian.Tree, error) {
ctx, spanEnd := spanFor(ctx, "ListTrees")
defer spanEnd()
var resp []*trillian.Tree
err := RunInAdminSnapshot(ctx, admin, func(tx ReadOnlyAdminTX) error {
var err error
resp, err = tx.ListTrees(ctx, includeDeleted)
return err
})
return resp, err
}
func CreateTree(ctx context.Context, admin AdminStorage, tree *trillian.Tree) (*trillian.Tree, error) {
ctx, spanEnd := spanFor(ctx, "CreateTree")
defer spanEnd()
var createdTree *trillian.Tree
err := admin.ReadWriteTransaction(ctx, func(ctx context.Context, tx AdminTX) error {
var err error
createdTree, err = tx.CreateTree(ctx, tree)
return err
})
return createdTree, err
}
func UpdateTree(ctx context.Context, admin AdminStorage, treeID int64, fn func(*trillian.Tree)) (*trillian.Tree, error) {
ctx, spanEnd := spanFor(ctx, "UpdateTree")
defer spanEnd()
var updatedTree *trillian.Tree
err := admin.ReadWriteTransaction(ctx, func(ctx context.Context, tx AdminTX) error {
var err error
updatedTree, err = tx.UpdateTree(ctx, treeID, fn)
return err
})
return updatedTree, err
}
func SoftDeleteTree(ctx context.Context, admin AdminStorage, treeID int64) (*trillian.Tree, error) {
ctx, spanEnd := spanFor(ctx, "SoftDeleteTree")
defer spanEnd()
var tree *trillian.Tree
err := admin.ReadWriteTransaction(ctx, func(ctx context.Context, tx AdminTX) error {
var err error
tree, err = tx.SoftDeleteTree(ctx, treeID)
return err
})
return tree, err
}
func HardDeleteTree(ctx context.Context, admin AdminStorage, treeID int64) error {
ctx, spanEnd := spanFor(ctx, "HardDeleteTree")
defer spanEnd()
return admin.ReadWriteTransaction(ctx, func(ctx context.Context, tx AdminTX) error {
return tx.HardDeleteTree(ctx, treeID)
})
}
func UndeleteTree(ctx context.Context, admin AdminStorage, treeID int64) (*trillian.Tree, error) {
ctx, spanEnd := spanFor(ctx, "UndeleteTree")
defer spanEnd()
var tree *trillian.Tree
err := admin.ReadWriteTransaction(ctx, func(ctx context.Context, tx AdminTX) error {
var err error
tree, err = tx.UndeleteTree(ctx, treeID)
return err
})
return tree, err
}
func RunInAdminSnapshot(ctx context.Context, admin AdminStorage, fn func(tx ReadOnlyAdminTX) error) error {
tx, err := admin.Snapshot(ctx)
if err != nil {
return err
}
defer func() {
if err := tx.Close(); err != nil {
klog.Errorf("tx.Close(): %v", err)
}
}()
if err := fn(tx); err != nil {
return err
}
return tx.Commit()
}
func spanFor(ctx context.Context, name string) (context.Context, func()) {
return monitoring.StartSpan(ctx, fmt.Sprintf("%s.%s", traceSpanRoot, name))
}