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  }