github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/importer/balanced/builder.go (about) 1 package balanced 2 3 import ( 4 "errors" 5 6 h "github.com/ipfs/go-ipfs/importer/helpers" 7 dag "github.com/ipfs/go-ipfs/merkledag" 8 ) 9 10 func BalancedLayout(db *h.DagBuilderHelper) (*dag.Node, error) { 11 var root *h.UnixfsNode 12 for level := 0; !db.Done(); level++ { 13 14 nroot := h.NewUnixfsNode() 15 16 // add our old root as a child of the new root. 17 if root != nil { // nil if it's the first node. 18 if err := nroot.AddChild(root, db); err != nil { 19 return nil, err 20 } 21 } 22 23 // fill it up. 24 if err := fillNodeRec(db, nroot, level); err != nil { 25 return nil, err 26 } 27 28 root = nroot 29 } 30 if root == nil { 31 root = h.NewUnixfsNode() 32 } 33 34 out, err := db.Add(root) 35 if err != nil { 36 return nil, err 37 } 38 39 err = db.Close() 40 if err != nil { 41 return nil, err 42 } 43 44 return out, nil 45 } 46 47 // fillNodeRec will fill the given node with data from the dagBuilders input 48 // source down to an indirection depth as specified by 'depth' 49 // it returns the total dataSize of the node, and a potential error 50 // 51 // warning: **children** pinned indirectly, but input node IS NOT pinned. 52 func fillNodeRec(db *h.DagBuilderHelper, node *h.UnixfsNode, depth int) error { 53 if depth < 0 { 54 return errors.New("attempt to fillNode at depth < 0") 55 } 56 57 // Base case 58 if depth <= 0 { // catch accidental -1's in case error above is removed. 59 return db.FillNodeWithData(node) 60 } 61 62 // while we have room AND we're not done 63 for node.NumChildren() < db.Maxlinks() && !db.Done() { 64 child := h.NewUnixfsNode() 65 66 if err := fillNodeRec(db, child, depth-1); err != nil { 67 return err 68 } 69 70 if err := node.AddChild(child, db); err != nil { 71 return err 72 } 73 } 74 75 return nil 76 }