Unverified 提交 95daef4e 作者: Whyrusleeping 提交者: GitHub

Merge pull request #4664 from ipfs/doc/golint-unixfs

Golint-ify unixfs module
// Package archive provides utilities to archive and compress a [Unixfs] DAG.
package archive package archive
import ( import (
......
// Package tar provides functionality to write a unixfs merkledag
// as a tar archive.
package tar package tar
import ( import (
...@@ -69,6 +71,7 @@ func (w *Writer) writeFile(nd *mdag.ProtoNode, pb *upb.Data, fpath string) error ...@@ -69,6 +71,7 @@ func (w *Writer) writeFile(nd *mdag.ProtoNode, pb *upb.Data, fpath string) error
return nil return nil
} }
// WriteNode adds a node to the archive.
func (w *Writer) WriteNode(nd ipld.Node, fpath string) error { func (w *Writer) WriteNode(nd ipld.Node, fpath string) error {
switch nd := nd.(type) { switch nd := nd.(type) {
case *mdag.ProtoNode: case *mdag.ProtoNode:
...@@ -106,6 +109,7 @@ func (w *Writer) WriteNode(nd ipld.Node, fpath string) error { ...@@ -106,6 +109,7 @@ func (w *Writer) WriteNode(nd ipld.Node, fpath string) error {
} }
} }
// Close closes the tar writer.
func (w *Writer) Close() error { func (w *Writer) Close() error {
return w.TarW.Close() return w.TarW.Close()
} }
......
...@@ -94,7 +94,7 @@ func TestOrderConsistency(t *testing.T) { ...@@ -94,7 +94,7 @@ func TestOrderConsistency(t *testing.T) {
} }
} }
func validateOpSetCompletion(t *testing.T, s *HamtShard, keep, temp []string) error { func validateOpSetCompletion(t *testing.T, s *Shard, keep, temp []string) error {
ctx := context.TODO() ctx := context.TODO()
for _, n := range keep { for _, n := range keep {
_, err := s.Find(ctx, n) _, err := s.Find(ctx, n)
...@@ -113,9 +113,9 @@ func validateOpSetCompletion(t *testing.T, s *HamtShard, keep, temp []string) er ...@@ -113,9 +113,9 @@ func validateOpSetCompletion(t *testing.T, s *HamtShard, keep, temp []string) er
return nil return nil
} }
func executeOpSet(t *testing.T, ds ipld.DAGService, width int, ops []testOp) (*HamtShard, error) { func executeOpSet(t *testing.T, ds ipld.DAGService, width int, ops []testOp) (*Shard, error) {
ctx := context.TODO() ctx := context.TODO()
s, err := NewHamtShard(ds, width) s, err := NewShard(ds, width)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -189,9 +189,9 @@ func genOpSet(seed int64, keep, temp []string) []testOp { ...@@ -189,9 +189,9 @@ func genOpSet(seed int64, keep, temp []string) []testOp {
} }
// executes the given op set with a repl to allow easier debugging // executes the given op set with a repl to allow easier debugging
/*func debugExecuteOpSet(ds node.DAGService, width int, ops []testOp) (*HamtShard, error) { /*func debugExecuteOpSet(ds node.DAGService, width int, ops []testOp) (*Shard, error) {
s, err := NewHamtShard(ds, width) s, err := NewShard(ds, width)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -244,7 +244,7 @@ mainloop: ...@@ -244,7 +244,7 @@ mainloop:
} }
case "restart": case "restart":
var err error var err error
s, err = NewHamtShard(ds, width) s, err = NewShard(ds, width)
if err != nil { if err != nil {
panic(err) panic(err)
} }
......
...@@ -26,14 +26,14 @@ func shuffle(seed int64, arr []string) { ...@@ -26,14 +26,14 @@ func shuffle(seed int64, arr []string) {
} }
} }
func makeDir(ds ipld.DAGService, size int) ([]string, *HamtShard, error) { func makeDir(ds ipld.DAGService, size int) ([]string, *Shard, error) {
return makeDirWidth(ds, size, 256) return makeDirWidth(ds, size, 256)
} }
func makeDirWidth(ds ipld.DAGService, size, width int) ([]string, *HamtShard, error) { func makeDirWidth(ds ipld.DAGService, size, width int) ([]string, *Shard, error) {
ctx := context.Background() ctx := context.Background()
s, _ := NewHamtShard(ds, width) s, _ := NewShard(ds, width)
var dirs []string var dirs []string
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
...@@ -54,7 +54,7 @@ func makeDirWidth(ds ipld.DAGService, size, width int) ([]string, *HamtShard, er ...@@ -54,7 +54,7 @@ func makeDirWidth(ds ipld.DAGService, size, width int) ([]string, *HamtShard, er
return dirs, s, nil return dirs, s, nil
} }
func assertLink(s *HamtShard, name string, found bool) error { func assertLink(s *Shard, name string, found bool) error {
_, err := s.Find(context.Background(), name) _, err := s.Find(context.Background(), name)
switch err { switch err {
case os.ErrNotExist: case os.ErrNotExist:
...@@ -74,7 +74,7 @@ func assertLink(s *HamtShard, name string, found bool) error { ...@@ -74,7 +74,7 @@ func assertLink(s *HamtShard, name string, found bool) error {
} }
} }
func assertSerializationWorks(ds ipld.DAGService, s *HamtShard) error { func assertSerializationWorks(ds ipld.DAGService, s *Shard) error {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
nd, err := s.Node() nd, err := s.Node()
...@@ -141,7 +141,7 @@ func TestBasicSet(t *testing.T) { ...@@ -141,7 +141,7 @@ func TestBasicSet(t *testing.T) {
func TestDirBuilding(t *testing.T) { func TestDirBuilding(t *testing.T) {
ds := mdtest.Mock() ds := mdtest.Mock()
_, _ = NewHamtShard(ds, 256) _, _ = NewShard(ds, 256)
_, s, err := makeDir(ds, 200) _, s, err := makeDir(ds, 200)
if err != nil { if err != nil {
...@@ -164,7 +164,7 @@ func TestDirBuilding(t *testing.T) { ...@@ -164,7 +164,7 @@ func TestDirBuilding(t *testing.T) {
func TestShardReload(t *testing.T) { func TestShardReload(t *testing.T) {
ds := mdtest.Mock() ds := mdtest.Mock()
_, _ = NewHamtShard(ds, 256) _, _ = NewShard(ds, 256)
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
...@@ -307,7 +307,7 @@ func TestSetAfterMarshal(t *testing.T) { ...@@ -307,7 +307,7 @@ func TestSetAfterMarshal(t *testing.T) {
func TestDuplicateAddShard(t *testing.T) { func TestDuplicateAddShard(t *testing.T) {
ds := mdtest.Mock() ds := mdtest.Mock()
dir, _ := NewHamtShard(ds, 256) dir, _ := NewShard(ds, 256)
nd := new(dag.ProtoNode) nd := new(dag.ProtoNode)
ctx := context.Background() ctx := context.Background()
...@@ -430,7 +430,7 @@ func TestRemoveElemsAfterMarshal(t *testing.T) { ...@@ -430,7 +430,7 @@ func TestRemoveElemsAfterMarshal(t *testing.T) {
func TestBitfieldIndexing(t *testing.T) { func TestBitfieldIndexing(t *testing.T) {
ds := mdtest.Mock() ds := mdtest.Mock()
s, _ := NewHamtShard(ds, 256) s, _ := NewShard(ds, 256)
set := func(i int) { set := func(i int) {
s.bitfield.SetBit(s.bitfield, i, 1) s.bitfield.SetBit(s.bitfield, i, 1)
...@@ -466,7 +466,7 @@ func TestSetHamtChild(t *testing.T) { ...@@ -466,7 +466,7 @@ func TestSetHamtChild(t *testing.T) {
ctx := context.Background() ctx := context.Background()
ds := mdtest.Mock() ds := mdtest.Mock()
s, _ := NewHamtShard(ds, 256) s, _ := NewShard(ds, 256)
e := ft.EmptyDirNode() e := ft.EmptyDirNode()
ds.Add(ctx, e) ds.Add(ctx, e)
...@@ -527,7 +527,7 @@ func BenchmarkHAMTSet(b *testing.B) { ...@@ -527,7 +527,7 @@ func BenchmarkHAMTSet(b *testing.B) {
ctx := context.Background() ctx := context.Background()
ds := mdtest.Mock() ds := mdtest.Mock()
sh, _ := NewHamtShard(ds, 256) sh, _ := NewShard(ds, 256)
nd, err := sh.Node() nd, err := sh.Node()
if err != nil { if err != nil {
b.Fatal(err) b.Fatal(err)
...@@ -560,7 +560,7 @@ func BenchmarkHAMTSet(b *testing.B) { ...@@ -560,7 +560,7 @@ func BenchmarkHAMTSet(b *testing.B) {
} }
func TestHamtBadSize(t *testing.T) { func TestHamtBadSize(t *testing.T) {
_, err := NewHamtShard(nil, 7) _, err := NewShard(nil, 7)
if err == nil { if err == nil {
t.Fatal("should have failed to construct hamt with bad size") t.Fatal("should have failed to construct hamt with bad size")
} }
......
...@@ -6,25 +6,32 @@ import ( ...@@ -6,25 +6,32 @@ import (
"io" "io"
) )
type bufDagReader struct { // BufDagReader implements a DagReader that reads from a byte slice
// using a bytes.Reader. It is used for RawNodes.
type BufDagReader struct {
*bytes.Reader *bytes.Reader
} }
func NewBufDagReader(b []byte) *bufDagReader { // NewBufDagReader returns a DAG reader for the given byte slice.
return &bufDagReader{bytes.NewReader(b)} // BufDagReader is used to read RawNodes.
func NewBufDagReader(b []byte) *BufDagReader {
return &BufDagReader{bytes.NewReader(b)}
} }
var _ DagReader = (*bufDagReader)(nil) var _ DagReader = (*BufDagReader)(nil)
func (*bufDagReader) Close() error { // Close is a nop.
func (*BufDagReader) Close() error {
return nil return nil
} }
func (rd *bufDagReader) CtxReadFull(ctx context.Context, b []byte) (int, error) { // CtxReadFull reads the slice onto b.
func (rd *BufDagReader) CtxReadFull(ctx context.Context, b []byte) (int, error) {
return rd.Read(b) return rd.Read(b)
} }
func (rd *bufDagReader) Offset() int64 { // Offset returns the current offset.
func (rd *BufDagReader) Offset() int64 {
of, err := rd.Seek(0, io.SeekCurrent) of, err := rd.Seek(0, io.SeekCurrent)
if err != nil { if err != nil {
panic("this should never happen " + err.Error()) panic("this should never happen " + err.Error())
...@@ -32,7 +39,8 @@ func (rd *bufDagReader) Offset() int64 { ...@@ -32,7 +39,8 @@ func (rd *bufDagReader) Offset() int64 {
return of return of
} }
func (rd *bufDagReader) Size() uint64 { // Size returns the size of the buffer.
func (rd *BufDagReader) Size() uint64 {
s := rd.Reader.Size() s := rd.Reader.Size()
if s < 0 { if s < 0 {
panic("size smaller than 0 (impossible!!)") panic("size smaller than 0 (impossible!!)")
......
...@@ -14,10 +14,15 @@ import ( ...@@ -14,10 +14,15 @@ import (
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format" ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
) )
var ErrIsDir = errors.New("this dag node is a directory") // Common errors
var (
var ErrCantReadSymlinks = errors.New("cannot currently read symlinks") ErrIsDir = errors.New("this dag node is a directory")
ErrCantReadSymlinks = errors.New("cannot currently read symlinks")
)
// A DagReader provides read-only read and seek acess to a unixfs file.
// Different implementations of readers are used for the different
// types of unixfs/protobuf-encoded nodes.
type DagReader interface { type DagReader interface {
ReadSeekCloser ReadSeekCloser
Size() uint64 Size() uint64
...@@ -25,6 +30,7 @@ type DagReader interface { ...@@ -25,6 +30,7 @@ type DagReader interface {
Offset() int64 Offset() int64
} }
// A ReadSeekCloser implements interfaces to read, copy, seek and close.
type ReadSeekCloser interface { type ReadSeekCloser interface {
io.Reader io.Reader
io.Seeker io.Seeker
......
...@@ -102,7 +102,7 @@ func TestSeekAndReadLarge(t *testing.T) { ...@@ -102,7 +102,7 @@ func TestSeekAndReadLarge(t *testing.T) {
t.Fatal("seeked read failed") t.Fatal("seeked read failed")
} }
pbdr := reader.(*pbDagReader) pbdr := reader.(*PBDagReader)
var count int var count int
for i, p := range pbdr.promises { for i, p := range pbdr.promises {
if i > 20 && i < 30 { if i > 20 && i < 30 {
......
...@@ -8,8 +8,8 @@ import ( ...@@ -8,8 +8,8 @@ import (
mdag "github.com/ipfs/go-ipfs/merkledag" mdag "github.com/ipfs/go-ipfs/merkledag"
format "github.com/ipfs/go-ipfs/unixfs" format "github.com/ipfs/go-ipfs/unixfs"
hamt "github.com/ipfs/go-ipfs/unixfs/hamt" hamt "github.com/ipfs/go-ipfs/unixfs/hamt"
cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
cid "gx/ipfs/QmcZfnkapfECQGcLZaf9B79NRg7cRa9EnZh4LSbkCzwNvY/go-cid"
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format" ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
) )
...@@ -25,11 +25,14 @@ var UseHAMTSharding = false ...@@ -25,11 +25,14 @@ var UseHAMTSharding = false
// DefaultShardWidth is the default value used for hamt sharding width. // DefaultShardWidth is the default value used for hamt sharding width.
var DefaultShardWidth = 256 var DefaultShardWidth = 256
// Directory allows to work with UnixFS directory nodes, adding and removing
// children. It allows to work with different directory schemes,
// like the classic or the HAMT one.
type Directory struct { type Directory struct {
dserv ipld.DAGService dserv ipld.DAGService
dirnode *mdag.ProtoNode dirnode *mdag.ProtoNode
shard *hamt.HamtShard shard *hamt.Shard
} }
// NewDirectory returns a Directory. It needs a DAGService to add the Children // NewDirectory returns a Directory. It needs a DAGService to add the Children
...@@ -37,7 +40,7 @@ func NewDirectory(dserv ipld.DAGService) *Directory { ...@@ -37,7 +40,7 @@ func NewDirectory(dserv ipld.DAGService) *Directory {
db := new(Directory) db := new(Directory)
db.dserv = dserv db.dserv = dserv
if UseHAMTSharding { if UseHAMTSharding {
s, err := hamt.NewHamtShard(dserv, DefaultShardWidth) s, err := hamt.NewShard(dserv, DefaultShardWidth)
if err != nil { if err != nil {
panic(err) // will only panic if DefaultShardWidth is a bad value panic(err) // will only panic if DefaultShardWidth is a bad value
} }
...@@ -113,7 +116,7 @@ func (d *Directory) AddChild(ctx context.Context, name string, nd ipld.Node) err ...@@ -113,7 +116,7 @@ func (d *Directory) AddChild(ctx context.Context, name string, nd ipld.Node) err
} }
func (d *Directory) switchToSharding(ctx context.Context) error { func (d *Directory) switchToSharding(ctx context.Context) error {
s, err := hamt.NewHamtShard(d.dserv, DefaultShardWidth) s, err := hamt.NewShard(d.dserv, DefaultShardWidth)
if err != nil { if err != nil {
return err return err
} }
...@@ -136,6 +139,7 @@ func (d *Directory) switchToSharding(ctx context.Context) error { ...@@ -136,6 +139,7 @@ func (d *Directory) switchToSharding(ctx context.Context) error {
return nil return nil
} }
// ForEachLink applies the given function to Links in the directory.
func (d *Directory) ForEachLink(ctx context.Context, f func(*ipld.Link) error) error { func (d *Directory) ForEachLink(ctx context.Context, f func(*ipld.Link) error) error {
if d.shard == nil { if d.shard == nil {
for _, l := range d.dirnode.Links() { for _, l := range d.dirnode.Links() {
...@@ -149,6 +153,7 @@ func (d *Directory) ForEachLink(ctx context.Context, f func(*ipld.Link) error) e ...@@ -149,6 +153,7 @@ func (d *Directory) ForEachLink(ctx context.Context, f func(*ipld.Link) error) e
return d.shard.ForEachLink(ctx, f) return d.shard.ForEachLink(ctx, f)
} }
// Links returns the all the links in the directory node.
func (d *Directory) Links(ctx context.Context) ([]*ipld.Link, error) { func (d *Directory) Links(ctx context.Context) ([]*ipld.Link, error) {
if d.shard == nil { if d.shard == nil {
return d.dirnode.Links(), nil return d.dirnode.Links(), nil
...@@ -157,6 +162,8 @@ func (d *Directory) Links(ctx context.Context) ([]*ipld.Link, error) { ...@@ -157,6 +162,8 @@ func (d *Directory) Links(ctx context.Context) ([]*ipld.Link, error) {
return d.shard.EnumLinks(ctx) return d.shard.EnumLinks(ctx)
} }
// Find returns the root node of the file named 'name' within this directory.
// In the case of HAMT-directories, it will traverse the tree.
func (d *Directory) Find(ctx context.Context, name string) (ipld.Node, error) { func (d *Directory) Find(ctx context.Context, name string) (ipld.Node, error) {
if d.shard == nil { if d.shard == nil {
lnk, err := d.dirnode.GetNodeLink(name) lnk, err := d.dirnode.GetNodeLink(name)
...@@ -179,6 +186,7 @@ func (d *Directory) Find(ctx context.Context, name string) (ipld.Node, error) { ...@@ -179,6 +186,7 @@ func (d *Directory) Find(ctx context.Context, name string) (ipld.Node, error) {
return lnk.GetNode(ctx, d.dserv) return lnk.GetNode(ctx, d.dserv)
} }
// RemoveChild removes the child with the given name.
func (d *Directory) RemoveChild(ctx context.Context, name string) error { func (d *Directory) RemoveChild(ctx context.Context, name string) error {
if d.shard == nil { if d.shard == nil {
return d.dirnode.RemoveNodeLink(name) return d.dirnode.RemoveNodeLink(name)
......
// package unixfs/io implements convenience objects for working with the ipfs // Package io implements convenience objects for working with the ipfs
// unixfs data format. // unixfs data format.
package io package io
...@@ -15,8 +15,8 @@ import ( ...@@ -15,8 +15,8 @@ import (
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format" ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
) )
// DagReader provides a way to easily read the data contained in a dag. // PBDagReader provides a way to easily read the data contained in a dag.
type pbDagReader struct { type PBDagReader struct {
serv ipld.NodeGetter serv ipld.NodeGetter
// the node being read // the node being read
...@@ -48,13 +48,13 @@ type pbDagReader struct { ...@@ -48,13 +48,13 @@ type pbDagReader struct {
cancel func() cancel func()
} }
var _ DagReader = (*pbDagReader)(nil) var _ DagReader = (*PBDagReader)(nil)
// NewPBFileReader constructs a new PBFileReader. // NewPBFileReader constructs a new PBFileReader.
func NewPBFileReader(ctx context.Context, n *mdag.ProtoNode, pb *ftpb.Data, serv ipld.NodeGetter) *pbDagReader { func NewPBFileReader(ctx context.Context, n *mdag.ProtoNode, pb *ftpb.Data, serv ipld.NodeGetter) *PBDagReader {
fctx, cancel := context.WithCancel(ctx) fctx, cancel := context.WithCancel(ctx)
curLinks := getLinkCids(n) curLinks := getLinkCids(n)
return &pbDagReader{ return &PBDagReader{
node: n, node: n,
serv: serv, serv: serv,
buf: NewBufDagReader(pb.GetData()), buf: NewBufDagReader(pb.GetData()),
...@@ -68,7 +68,7 @@ func NewPBFileReader(ctx context.Context, n *mdag.ProtoNode, pb *ftpb.Data, serv ...@@ -68,7 +68,7 @@ func NewPBFileReader(ctx context.Context, n *mdag.ProtoNode, pb *ftpb.Data, serv
const preloadSize = 10 const preloadSize = 10
func (dr *pbDagReader) preloadNextNodes(ctx context.Context) { func (dr *PBDagReader) preloadNextNodes(ctx context.Context) {
beg := dr.linkPosition beg := dr.linkPosition
end := beg + preloadSize end := beg + preloadSize
if end >= len(dr.links) { if end >= len(dr.links) {
...@@ -82,7 +82,7 @@ func (dr *pbDagReader) preloadNextNodes(ctx context.Context) { ...@@ -82,7 +82,7 @@ func (dr *pbDagReader) preloadNextNodes(ctx context.Context) {
// precalcNextBuf follows the next link in line and loads it from the // precalcNextBuf follows the next link in line and loads it from the
// DAGService, setting the next buffer to read from // DAGService, setting the next buffer to read from
func (dr *pbDagReader) precalcNextBuf(ctx context.Context) error { func (dr *PBDagReader) precalcNextBuf(ctx context.Context) error {
if dr.buf != nil { if dr.buf != nil {
dr.buf.Close() // Just to make sure dr.buf.Close() // Just to make sure
dr.buf = nil dr.buf = nil
...@@ -145,17 +145,17 @@ func getLinkCids(n ipld.Node) []*cid.Cid { ...@@ -145,17 +145,17 @@ func getLinkCids(n ipld.Node) []*cid.Cid {
} }
// Size return the total length of the data from the DAG structured file. // Size return the total length of the data from the DAG structured file.
func (dr *pbDagReader) Size() uint64 { func (dr *PBDagReader) Size() uint64 {
return dr.pbdata.GetFilesize() return dr.pbdata.GetFilesize()
} }
// Read reads data from the DAG structured file // Read reads data from the DAG structured file
func (dr *pbDagReader) Read(b []byte) (int, error) { func (dr *PBDagReader) Read(b []byte) (int, error) {
return dr.CtxReadFull(dr.ctx, b) return dr.CtxReadFull(dr.ctx, b)
} }
// CtxReadFull reads data from the DAG structured file // CtxReadFull reads data from the DAG structured file
func (dr *pbDagReader) CtxReadFull(ctx context.Context, b []byte) (int, error) { func (dr *PBDagReader) CtxReadFull(ctx context.Context, b []byte) (int, error) {
if dr.buf == nil { if dr.buf == nil {
if err := dr.precalcNextBuf(ctx); err != nil { if err := dr.precalcNextBuf(ctx); err != nil {
return 0, err return 0, err
...@@ -189,7 +189,8 @@ func (dr *pbDagReader) CtxReadFull(ctx context.Context, b []byte) (int, error) { ...@@ -189,7 +189,8 @@ func (dr *pbDagReader) CtxReadFull(ctx context.Context, b []byte) (int, error) {
} }
} }
func (dr *pbDagReader) WriteTo(w io.Writer) (int64, error) { // WriteTo writes to the given writer.
func (dr *PBDagReader) WriteTo(w io.Writer) (int64, error) {
if dr.buf == nil { if dr.buf == nil {
if err := dr.precalcNextBuf(dr.ctx); err != nil { if err := dr.precalcNextBuf(dr.ctx); err != nil {
return 0, err return 0, err
...@@ -220,12 +221,14 @@ func (dr *pbDagReader) WriteTo(w io.Writer) (int64, error) { ...@@ -220,12 +221,14 @@ func (dr *pbDagReader) WriteTo(w io.Writer) (int64, error) {
} }
} }
func (dr *pbDagReader) Close() error { // Close closes the reader.
func (dr *PBDagReader) Close() error {
dr.cancel() dr.cancel()
return nil return nil
} }
func (dr *pbDagReader) Offset() int64 { // Offset returns the current reader offset
func (dr *PBDagReader) Offset() int64 {
return dr.offset return dr.offset
} }
...@@ -233,7 +236,7 @@ func (dr *pbDagReader) Offset() int64 { ...@@ -233,7 +236,7 @@ func (dr *pbDagReader) Offset() int64 {
// interface matches standard unix seek // interface matches standard unix seek
// TODO: check if we can do relative seeks, to reduce the amount of dagreader // TODO: check if we can do relative seeks, to reduce the amount of dagreader
// recreations that need to happen. // recreations that need to happen.
func (dr *pbDagReader) Seek(offset int64, whence int) (int64, error) { func (dr *PBDagReader) Seek(offset int64, whence int) (int64, error) {
switch whence { switch whence {
case io.SeekStart: case io.SeekStart:
if offset < 0 { if offset < 0 {
...@@ -259,11 +262,11 @@ func (dr *pbDagReader) Seek(offset int64, whence int) (int64, error) { ...@@ -259,11 +262,11 @@ func (dr *pbDagReader) Seek(offset int64, whence int) (int64, error) {
dr.linkPosition = 0 dr.linkPosition = 0
dr.offset = offset dr.offset = offset
return offset, nil return offset, nil
} else {
// skip past root block data
left -= int64(len(pb.Data))
} }
// skip past root block data
left -= int64(len(pb.Data))
// iterate through links and find where we need to be // iterate through links and find where we need to be
for i := 0; i < len(pb.Blocksizes); i++ { for i := 0; i < len(pb.Blocksizes); i++ {
if pb.Blocksizes[i] > uint64(left) { if pb.Blocksizes[i] > uint64(left) {
......
// Package mod provides DAG modification utilities to, for example,
// insert additional nodes in a unixfs DAG or truncate them.
package mod package mod
import ( import (
"bytes" "bytes"
"context" "context"
"errors" "errors"
"fmt"
"io" "io"
chunk "github.com/ipfs/go-ipfs/importer/chunk" chunk "github.com/ipfs/go-ipfs/importer/chunk"
...@@ -19,8 +20,12 @@ import ( ...@@ -19,8 +20,12 @@ import (
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format" ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
) )
var ErrSeekFail = errors.New("failed to seek properly") // Common errors
var ErrUnrecognizedWhence = errors.New("unrecognized whence") var (
ErrSeekFail = errors.New("failed to seek properly")
ErrUnrecognizedWhence = errors.New("unrecognized whence")
ErrNotUnixfs = errors.New("dagmodifier only supports unixfs nodes (proto or raw)")
)
// 2MB // 2MB
var writebufferSize = 1 << 21 var writebufferSize = 1 << 21
...@@ -46,8 +51,6 @@ type DagModifier struct { ...@@ -46,8 +51,6 @@ type DagModifier struct {
read uio.DagReader read uio.DagReader
} }
var ErrNotUnixfs = fmt.Errorf("dagmodifier only supports unixfs nodes (proto or raw)")
// NewDagModifier returns a new DagModifier, the Cid prefix for newly // NewDagModifier returns a new DagModifier, the Cid prefix for newly
// created nodes will be inherted from the passed in node. If the Cid // created nodes will be inherted from the passed in node. If the Cid
// version if not 0 raw leaves will also be enabled. The Prefix and // version if not 0 raw leaves will also be enabled. The Prefix and
...@@ -412,7 +415,7 @@ func (dm *DagModifier) readPrep() error { ...@@ -412,7 +415,7 @@ func (dm *DagModifier) readPrep() error {
return nil return nil
} }
// Read data from this dag starting at the current offset // CtxReadFull reads data from this dag starting at the current offset
func (dm *DagModifier) CtxReadFull(ctx context.Context, b []byte) (int, error) { func (dm *DagModifier) CtxReadFull(ctx context.Context, b []byte) (int, error) {
err := dm.readPrep() err := dm.readPrep()
if err != nil { if err != nil {
...@@ -438,6 +441,8 @@ func (dm *DagModifier) HasChanges() bool { ...@@ -438,6 +441,8 @@ func (dm *DagModifier) HasChanges() bool {
return dm.wrBuf != nil return dm.wrBuf != nil
} }
// Seek modifies the offset according to whence. See unixfs/io for valid whence
// values.
func (dm *DagModifier) Seek(offset int64, whence int) (int64, error) { func (dm *DagModifier) Seek(offset int64, whence int) (int64, error) {
err := dm.Sync() err := dm.Sync()
if err != nil { if err != nil {
...@@ -479,6 +484,8 @@ func (dm *DagModifier) Seek(offset int64, whence int) (int64, error) { ...@@ -479,6 +484,8 @@ func (dm *DagModifier) Seek(offset int64, whence int) (int64, error) {
return int64(dm.curWrOff), nil return int64(dm.curWrOff), nil
} }
// Truncate truncates the current Node to 'size' and replaces it with the
// new one.
func (dm *DagModifier) Truncate(size int64) error { func (dm *DagModifier) Truncate(size int64) error {
err := dm.Sync() err := dm.Sync()
if err != nil { if err != nil {
......
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format" ipld "gx/ipfs/Qme5bWv7wtjUNGsK2BNGVUFPKiuxWrsqrtvYwCLRw8YFES/go-ipld-format"
) )
// SizeSplitterGen creates a generator.
func SizeSplitterGen(size int64) chunk.SplitterGen { func SizeSplitterGen(size int64) chunk.SplitterGen {
return func(r io.Reader) chunk.Splitter { return func(r io.Reader) chunk.Splitter {
return chunk.NewSizeSplitter(r, size) return chunk.NewSizeSplitter(r, size)
...@@ -41,10 +42,13 @@ type NodeOpts struct { ...@@ -41,10 +42,13 @@ type NodeOpts struct {
RawLeavesUsed bool RawLeavesUsed bool
} }
var UseProtoBufLeaves = NodeOpts{Prefix: mdag.V0CidPrefix()} // Some shorthands for NodeOpts.
var UseRawLeaves = NodeOpts{Prefix: mdag.V0CidPrefix(), ForceRawLeaves: true, RawLeavesUsed: true} var (
var UseCidV1 = NodeOpts{Prefix: mdag.V1CidPrefix(), RawLeavesUsed: true} UseProtoBufLeaves = NodeOpts{Prefix: mdag.V0CidPrefix()}
var UseBlake2b256 NodeOpts UseRawLeaves = NodeOpts{Prefix: mdag.V0CidPrefix(), ForceRawLeaves: true, RawLeavesUsed: true}
UseCidV1 = NodeOpts{Prefix: mdag.V1CidPrefix(), RawLeavesUsed: true}
UseBlake2b256 NodeOpts
)
func init() { func init() {
UseBlake2b256 = UseCidV1 UseBlake2b256 = UseCidV1
...@@ -88,6 +92,7 @@ func GetRandomNode(t testing.TB, dserv ipld.DAGService, size int64, opts NodeOpt ...@@ -88,6 +92,7 @@ func GetRandomNode(t testing.TB, dserv ipld.DAGService, size int64, opts NodeOpt
return buf, node return buf, node
} }
// ArrComp checks if two byte slices are the same.
func ArrComp(a, b []byte) error { func ArrComp(a, b []byte) error {
if len(a) != len(b) { if len(a) != len(b) {
return fmt.Errorf("Arrays differ in length. %d != %d", len(a), len(b)) return fmt.Errorf("Arrays differ in length. %d != %d", len(a), len(b))
......
// Package format implements a data format for files in the IPFS filesystem It // Package unixfs implements a data format for files in the IPFS filesystem It
// is not the only format in ipfs, but it is the one that the filesystem // is not the only format in ipfs, but it is the one that the filesystem
// assumes // assumes
package unixfs package unixfs
...@@ -6,11 +6,13 @@ package unixfs ...@@ -6,11 +6,13 @@ package unixfs
import ( import (
"errors" "errors"
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
dag "github.com/ipfs/go-ipfs/merkledag" dag "github.com/ipfs/go-ipfs/merkledag"
pb "github.com/ipfs/go-ipfs/unixfs/pb" pb "github.com/ipfs/go-ipfs/unixfs/pb"
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
) )
// Shorthands for protobuffer types
const ( const (
TRaw = pb.Data_Raw TRaw = pb.Data_Raw
TFile = pb.Data_File TFile = pb.Data_File
...@@ -20,10 +22,14 @@ const ( ...@@ -20,10 +22,14 @@ const (
THAMTShard = pb.Data_HAMTShard THAMTShard = pb.Data_HAMTShard
) )
var ErrMalformedFileFormat = errors.New("malformed data in file format") // Common errors
var ErrInvalidDirLocation = errors.New("found directory node in unexpected place") var (
var ErrUnrecognizedType = errors.New("unrecognized node type") ErrMalformedFileFormat = errors.New("malformed data in file format")
ErrInvalidDirLocation = errors.New("found directory node in unexpected place")
ErrUnrecognizedType = errors.New("unrecognized node type")
)
// FromBytes unmarshals a byte slice as protobuf Data.
func FromBytes(data []byte) (*pb.Data, error) { func FromBytes(data []byte) (*pb.Data, error) {
pbdata := new(pb.Data) pbdata := new(pb.Data)
err := proto.Unmarshal(data, pbdata) err := proto.Unmarshal(data, pbdata)
...@@ -33,6 +39,8 @@ func FromBytes(data []byte) (*pb.Data, error) { ...@@ -33,6 +39,8 @@ func FromBytes(data []byte) (*pb.Data, error) {
return pbdata, nil return pbdata, nil
} }
// FilePBData creates a protobuf File with the given
// byte slice and returns the marshaled protobuf bytes representing it.
func FilePBData(data []byte, totalsize uint64) []byte { func FilePBData(data []byte, totalsize uint64) []byte {
pbfile := new(pb.Data) pbfile := new(pb.Data)
typ := pb.Data_File typ := pb.Data_File
...@@ -98,6 +106,7 @@ func SymlinkData(path string) ([]byte, error) { ...@@ -98,6 +106,7 @@ func SymlinkData(path string) ([]byte, error) {
return out, nil return out, nil
} }
// UnwrapData unmarshals a protobuf messages and returns the contents.
func UnwrapData(data []byte) ([]byte, error) { func UnwrapData(data []byte) ([]byte, error) {
pbdata := new(pb.Data) pbdata := new(pb.Data)
err := proto.Unmarshal(data, pbdata) err := proto.Unmarshal(data, pbdata)
...@@ -107,6 +116,10 @@ func UnwrapData(data []byte) ([]byte, error) { ...@@ -107,6 +116,10 @@ func UnwrapData(data []byte) ([]byte, error) {
return pbdata.GetData(), nil return pbdata.GetData(), nil
} }
// DataSize returns the size of the contents in protobuf wrapped slice.
// For raw data it simply provides the length of it. For Data_Files, it
// will return the associated filesize. Note that Data_Directories will
// return an error.
func DataSize(data []byte) (uint64, error) { func DataSize(data []byte) (uint64, error) {
pbdata := new(pb.Data) pbdata := new(pb.Data)
err := proto.Unmarshal(data, pbdata) err := proto.Unmarshal(data, pbdata)
...@@ -116,16 +129,17 @@ func DataSize(data []byte) (uint64, error) { ...@@ -116,16 +129,17 @@ func DataSize(data []byte) (uint64, error) {
switch pbdata.GetType() { switch pbdata.GetType() {
case pb.Data_Directory: case pb.Data_Directory:
return 0, errors.New("Cant get data size of directory!") return 0, errors.New("Cant get data size of directory")
case pb.Data_File: case pb.Data_File:
return pbdata.GetFilesize(), nil return pbdata.GetFilesize(), nil
case pb.Data_Raw: case pb.Data_Raw:
return uint64(len(pbdata.GetData())), nil return uint64(len(pbdata.GetData())), nil
default: default:
return 0, errors.New("Unrecognized node data type!") return 0, errors.New("Unrecognized node data type")
} }
} }
// An FSNode represents a filesystem object.
type FSNode struct { type FSNode struct {
Data []byte Data []byte
...@@ -139,6 +153,7 @@ type FSNode struct { ...@@ -139,6 +153,7 @@ type FSNode struct {
Type pb.Data_DataType Type pb.Data_DataType
} }
// FSNodeFromBytes unmarshal a protobuf message onto an FSNode.
func FSNodeFromBytes(b []byte) (*FSNode, error) { func FSNodeFromBytes(b []byte) (*FSNode, error) {
pbn := new(pb.Data) pbn := new(pb.Data)
err := proto.Unmarshal(b, pbn) err := proto.Unmarshal(b, pbn)
...@@ -160,11 +175,13 @@ func (n *FSNode) AddBlockSize(s uint64) { ...@@ -160,11 +175,13 @@ func (n *FSNode) AddBlockSize(s uint64) {
n.blocksizes = append(n.blocksizes, s) n.blocksizes = append(n.blocksizes, s)
} }
// RemoveBlockSize removes the given child block's size.
func (n *FSNode) RemoveBlockSize(i int) { func (n *FSNode) RemoveBlockSize(i int) {
n.subtotal -= n.blocksizes[i] n.subtotal -= n.blocksizes[i]
n.blocksizes = append(n.blocksizes[:i], n.blocksizes[i+1:]...) n.blocksizes = append(n.blocksizes[:i], n.blocksizes[i+1:]...)
} }
// GetBytes marshals this node as a protobuf message.
func (n *FSNode) GetBytes() ([]byte, error) { func (n *FSNode) GetBytes() ([]byte, error) {
pbn := new(pb.Data) pbn := new(pb.Data)
pbn.Type = &n.Type pbn.Type = &n.Type
...@@ -180,16 +197,19 @@ func (n *FSNode) FileSize() uint64 { ...@@ -180,16 +197,19 @@ func (n *FSNode) FileSize() uint64 {
return uint64(len(n.Data)) + n.subtotal return uint64(len(n.Data)) + n.subtotal
} }
// NumChildren returns the number of child blocks of this node
func (n *FSNode) NumChildren() int { func (n *FSNode) NumChildren() int {
return len(n.blocksizes) return len(n.blocksizes)
} }
// Metadata is used to store additional FSNode information.
type Metadata struct { type Metadata struct {
MimeType string MimeType string
Size uint64 Size uint64
} }
//MetadataFromBytes Unmarshals a protobuf message into Metadata. // MetadataFromBytes Unmarshals a protobuf Data message into Metadata.
// The provided slice should have been encoded with BytesForMetadata().
func MetadataFromBytes(b []byte) (*Metadata, error) { func MetadataFromBytes(b []byte) (*Metadata, error) {
pbd := new(pb.Data) pbd := new(pb.Data)
err := proto.Unmarshal(b, pbd) err := proto.Unmarshal(b, pbd)
...@@ -210,12 +230,16 @@ func MetadataFromBytes(b []byte) (*Metadata, error) { ...@@ -210,12 +230,16 @@ func MetadataFromBytes(b []byte) (*Metadata, error) {
return md, nil return md, nil
} }
// Bytes marshals Metadata as a protobuf message of Metadata type.
func (m *Metadata) Bytes() ([]byte, error) { func (m *Metadata) Bytes() ([]byte, error) {
pbm := new(pb.Metadata) pbm := new(pb.Metadata)
pbm.MimeType = &m.MimeType pbm.MimeType = &m.MimeType
return proto.Marshal(pbm) return proto.Marshal(pbm)
} }
// BytesForMetadata wraps the given Metadata as a profobuf message of Data type,
// setting the DataType to Metadata. The wrapped bytes are itself the
// result of calling m.Bytes().
func BytesForMetadata(m *Metadata) ([]byte, error) { func BytesForMetadata(m *Metadata) ([]byte, error) {
pbd := new(pb.Data) pbd := new(pb.Data)
pbd.Filesize = proto.Uint64(m.Size) pbd.Filesize = proto.Uint64(m.Size)
...@@ -230,6 +254,7 @@ func BytesForMetadata(m *Metadata) ([]byte, error) { ...@@ -230,6 +254,7 @@ func BytesForMetadata(m *Metadata) ([]byte, error) {
return proto.Marshal(pbd) return proto.Marshal(pbd)
} }
// EmptyDirNode creates an empty folder Protonode.
func EmptyDirNode() *dag.ProtoNode { func EmptyDirNode() *dag.ProtoNode {
return dag.NodeWithData(FolderPBData()) return dag.NodeWithData(FolderPBData())
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论