Implement streaming functions for local backend

This commit is contained in:
Alexander Neumann 2015-02-11 19:50:29 +01:00
parent 64f7b4e5e9
commit 0a45ec1d3a
2 changed files with 93 additions and 0 deletions

View file

@ -3,6 +3,7 @@ package backend
import (
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
@ -223,6 +224,54 @@ func (b *Local) Create(t Type, data []byte) (ID, error) {
return id, nil
}
// CreateFrom reads content from rd and stores it as type t. Returned is the
// storage ID. If the blob is already present, returns ErrAlreadyPresent and
// the blob's ID.
func (b *Local) CreateFrom(t Type, rd io.Reader) (ID, error) {
// TODO: make sure that tempfile is removed upon error
// check hash while writing
hr := NewHashingReader(rd, newHash())
// create tempfile in backend
file, err := b.tempFile()
if err != nil {
return nil, err
}
// write data to tempfile
_, err = io.Copy(file, hr)
if err != nil {
return nil, err
}
err = file.Close()
if err != nil {
return nil, err
}
// get ID
id := ID(hr.Sum(nil))
// check for duplicate ID
res, err := b.Test(t, id)
if err != nil {
return nil, arrar.Annotate(err, "test for presence")
}
if res {
return id, ErrAlreadyPresent
}
// rename file
err = b.renameFile(file, t, id)
if err != nil {
return nil, err
}
return id, nil
}
// Construct path for given Type and ID.
func (b *Local) filename(t Type, id ID) string {
return filepath.Join(b.dirname(t, id), id.String())
@ -256,6 +305,23 @@ func (b *Local) Get(t Type, id ID) ([]byte, error) {
return buf, nil
}
// GetReader returns a reader that yields the content stored under the given
// ID. The content is not verified. The reader should be closed after draining
// it.
func (b *Local) GetReader(t Type, id ID) (io.ReadCloser, error) {
if id == nil {
return nil, errors.New("unable to load nil ID")
}
// try to open file
file, err := os.Open(b.filename(t, id))
if err != nil {
return nil, err
}
return file, nil
}
// Test returns true if a blob of the given type and ID exists in the backend.
func (b *Local) Test(t Type, id ID) (bool, error) {
// try to open file