unverifiedblockstore.go 1.76 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
package unverifiedblockstore

import (
	"fmt"

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

// 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
13
	storer         ipld.Storer
14 15 16 17
}

// New initializes a new unverified store with the given storer function for writing
// to permaneant storage if the block is verified
18
func New(storer ipld.Storer) *UnverifiedBlockStore {
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
	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)
		}
	}
}

// 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)
49
	buffer, committer, err := ubs.storer(ipld.LinkContext{})
50 51 52 53 54 55 56 57 58 59 60 61 62
	if err != nil {
		return nil, err
	}
	_, err = buffer.Write(data)
	if err != nil {
		return nil, err
	}
	err = committer(lnk)
	if err != nil {
		return nil, err
	}
	return data, nil
}