func TestAppendSingleBytesToEmpty(t *testing.T) { ds := mdtest.Mock() data := []byte("AB") nd := new(merkledag.Node) nd.Data = ft.FilePBData(nil, 0) dbp := &h.DagBuilderParams{ Dagserv: ds, Maxlinks: 4, } spl := chunk.SizeSplitterGen(500) blks, errs := chunk.Chan(spl(bytes.NewReader(data[:1]))) ctx := context.Background() nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) if err != nil { t.Fatal(err) } blks, errs = chunk.Chan(spl(bytes.NewReader(data[1:]))) nnode, err = TrickleAppend(ctx, nnode, dbp.New(blks, errs)) if err != nil { t.Fatal(err) } fread, err := uio.NewDagReader(ctx, nnode, ds) if err != nil { t.Fatal(err) } out, err := ioutil.ReadAll(fread) if err != nil { t.Fatal(err) } fmt.Println(out, data) err = arrComp(out, data) if err != nil { t.Fatal(err) } }
func buildTestDag(ds dag.DAGService, spl chunk.Splitter) (*dag.Node, error) { // Start the splitter blkch, errs := chunk.Chan(spl) dbp := h.DagBuilderParams{ Dagserv: ds, Maxlinks: h.DefaultLinksPerBlock, } return BalancedLayout(dbp.New(blkch, errs)) }
func BuildTrickleDagFromReader(ds dag.DAGService, spl chunk.Splitter, ncb h.NodeCB) (*dag.Node, error) { // Start the splitter blkch, errch := chunk.Chan(spl) dbp := h.DagBuilderParams{ Dagserv: ds, Maxlinks: h.DefaultLinksPerBlock, NodeCB: ncb, } return trickle.TrickleLayout(dbp.New(blkch, errch)) }
// This test appends one byte at a time to an empty file func TestMultipleAppends(t *testing.T) { ds := mdtest.Mock() // TODO: fix small size appends and make this number bigger nbytes := int64(1000) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) read := bytes.NewReader(nil) nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) if err != nil { t.Fatal(err) } dbp := &h.DagBuilderParams{ Dagserv: ds, Maxlinks: 4, } spl := chunk.SizeSplitterGen(500) ctx := context.Background() for i := 0; i < len(should); i++ { blks, errs := chunk.Chan(spl(bytes.NewReader(should[i : i+1]))) nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) if err != nil { t.Fatal(err) } err = VerifyTrickleDagStructure(nnode, ds, dbp.Maxlinks, layerRepeat) if err != nil { t.Fatal(err) } fread, err := uio.NewDagReader(ctx, nnode, ds) if err != nil { t.Fatal(err) } out, err := ioutil.ReadAll(fread) if err != nil { t.Fatal(err) } err = arrComp(out, should[:i+1]) if err != nil { t.Fatal(err) } } }
// expandSparse grows the file with zero blocks of 4096 // A small blocksize is chosen to aid in deduplication func (dm *DagModifier) expandSparse(size int64) error { r := io.LimitReader(zeroReader{}, size) spl := chunk.NewSizeSplitter(r, 4096) blks, errs := chunk.Chan(spl) nnode, err := dm.appendData(dm.curNode, blks, errs) if err != nil { return err } _, err = dm.dagserv.Add(nnode) if err != nil { return err } dm.curNode = nnode return nil }
func buildTestDag(ds merkledag.DAGService, spl chunk.Splitter) (*merkledag.Node, error) { // Start the splitter blkch, errs := chunk.Chan(spl) dbp := h.DagBuilderParams{ Dagserv: ds, Maxlinks: h.DefaultLinksPerBlock, } nd, err := TrickleLayout(dbp.New(blkch, errs)) if err != nil { return nil, err } return nd, VerifyTrickleDagStructure(nd, ds, dbp.Maxlinks, layerRepeat) }
func TestAppend(t *testing.T) { nbytes := int64(128 * 1024) should := make([]byte, nbytes) u.NewTimeSeededRand().Read(should) // Reader for half the bytes read := bytes.NewReader(should[:nbytes/2]) ds := mdtest.Mock() nd, err := buildTestDag(ds, chunk.NewSizeSplitter(read, 500)) if err != nil { t.Fatal(err) } dbp := &h.DagBuilderParams{ Dagserv: ds, Maxlinks: h.DefaultLinksPerBlock, } r := bytes.NewReader(should[nbytes/2:]) blks, errs := chunk.Chan(chunk.NewSizeSplitter(r, 500)) ctx := context.Background() nnode, err := TrickleAppend(ctx, nd, dbp.New(blks, errs)) if err != nil { t.Fatal(err) } err = VerifyTrickleDagStructure(nnode, ds, dbp.Maxlinks, layerRepeat) if err != nil { t.Fatal(err) } fread, err := uio.NewDagReader(ctx, nnode, ds) if err != nil { t.Fatal(err) } out, err := ioutil.ReadAll(fread) if err != nil { t.Fatal(err) } err = arrComp(out, should) if err != nil { t.Fatal(err) } }
// Sync writes changes to this dag to disk func (dm *DagModifier) Sync() error { // No buffer? Nothing to do if dm.wrBuf == nil { return nil } // If we have an active reader, kill it if dm.read != nil { dm.read = nil dm.readCancel() } // Number of bytes we're going to write buflen := dm.wrBuf.Len() // Grab key for unpinning after mod operation curk, err := dm.curNode.Key() if err != nil { return err } // overwrite existing dag nodes thisk, done, err := dm.modifyDag(dm.curNode, dm.writeStart, dm.wrBuf) if err != nil { return err } nd, err := dm.dagserv.Get(dm.ctx, thisk) if err != nil { return err } dm.curNode = nd // need to write past end of current dag if !done { blks, errs := chunk.Chan(dm.splitter(dm.wrBuf)) nd, err = dm.appendData(dm.curNode, blks, errs) if err != nil { return err } thisk, err = dm.dagserv.Add(nd) if err != nil { return err } dm.curNode = nd } // Finalize correct pinning, and flush pinner dm.mp.PinWithMode(thisk, pin.Recursive) dm.mp.RemovePinWithMode(curk, pin.Recursive) err = dm.mp.Flush() if err != nil { return err } dm.writeStart += uint64(buflen) dm.wrBuf = nil return nil }