unverifiedblockstore.go 2.06 KB
Newer Older
1 2 3 4 5 6 7 8
package unverifiedblockstore

import (
	"fmt"

	ipld "github.com/ipld/go-ipld-prime"
)

9 10 11 12
type settableWriter interface {
	SetBytes([]byte) error
}

13 14 15 16
// UnverifiedBlockStore holds an in memory cache of receied blocks from the network
// that have not been verified to be part of a traversal
type UnverifiedBlockStore struct {
	inMemoryBlocks map[ipld.Link][]byte
17
	storer         ipld.Storer
18 19 20 21
}

// New initializes a new unverified store with the given storer function for writing
// to permaneant storage if the block is verified
22
func New(storer ipld.Storer) *UnverifiedBlockStore {
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
	return &UnverifiedBlockStore{
		inMemoryBlocks: make(map[ipld.Link][]byte),
		storer:         storer,
	}
}

// AddUnverifiedBlock adds a new unverified block to the in memory cache as it
// comes in as part of a traversal.
func (ubs *UnverifiedBlockStore) AddUnverifiedBlock(lnk ipld.Link, data []byte) {
	ubs.inMemoryBlocks[lnk] = data
}

// PruneBlocks removes blocks from the unverified store without committing them,
// if the passed in function returns true for the given link
func (ubs *UnverifiedBlockStore) PruneBlocks(shouldPrune func(ipld.Link) bool) {
	for link := range ubs.inMemoryBlocks {
		if shouldPrune(link) {
			delete(ubs.inMemoryBlocks, link)
		}
	}
}

45 46 47 48 49
// PruneBlock deletes an individual block from the store
func (ubs *UnverifiedBlockStore) PruneBlock(link ipld.Link) {
	delete(ubs.inMemoryBlocks, link)
}

50 51 52 53 54 55 56 57
// VerifyBlock verifies the data for the given link as being part of a traversal,
// removes it from the unverified store, and writes it to permaneant storage.
func (ubs *UnverifiedBlockStore) VerifyBlock(lnk ipld.Link) ([]byte, error) {
	data, ok := ubs.inMemoryBlocks[lnk]
	if !ok {
		return nil, fmt.Errorf("Block not found")
	}
	delete(ubs.inMemoryBlocks, lnk)
58
	buffer, committer, err := ubs.storer(ipld.LinkContext{})
59 60 61
	if err != nil {
		return nil, err
	}
62 63 64 65 66
	if settable, ok := buffer.(settableWriter); ok {
		err = settable.SetBytes(data)
	} else {
		_, err = buffer.Write(data)
	}
67 68 69 70 71 72 73 74 75
	if err != nil {
		return nil, err
	}
	err = committer(lnk)
	if err != nil {
		return nil, err
	}
	return data, nil
}