src/server/pfs/server/driver.go
func headerDirToPutFileRecords(tree hashtree.HashTree, path string, node *hashtree.NodeProto) (*pfs.PutFileRecords, error) {
	if node.DirNode == nil || node.DirNode.Shared == nil {
		return nil, fmt.Errorf("headerDirToPutFileRecords only works on header/footer dirs")
	}
	s := node.DirNode.Shared
	pfr := &pfs.PutFileRecords{
		Split: true,
	}
	if s.Header != nil {
		pfr.Header = &pfs.PutFileRecord{
			SizeBytes:  s.HeaderSize,
			ObjectHash: s.Header.Hash,
		}
	}
	if s.Footer != nil {
		pfr.Footer = &pfs.PutFileRecord{
			SizeBytes:  s.FooterSize,
			ObjectHash: s.Footer.Hash,
		}
	}
	if err := tree.List(path, func(child *hashtree.NodeProto) error {
		if child.FileNode == nil {
			return fmt.Errorf("header/footer dir contains child subdirectory, " +
				"which is invalid--header/footer dirs must be created by PutFileSplit")
		}
		for i, o := range child.FileNode.Objects {
			// same hack as copyFile--set size of first object to the size of the
			// whole subtree (and size of other objects to 0). I don't think
			// PutFileSplit files can have more than one object, but that invariant
			// isn't necessary to this code's correctness, so don't verify it.
			var size int64
			if i == 0 {
				size = child.SubtreeSize
			}
			pfr.Records = append(pfr.Records, &pfs.PutFileRecord{
				SizeBytes:  size,
				ObjectHash: o.Hash,
			})
		}
		return nil
	}); err != nil {
		return nil, err
	}
	return pfr, nil // TODO(msteffen) put something real here
}
func headerDirToPutFileRecords(tree hashtree.HashTree, path string, node *hashtree.NodeProto) (*pfs.PutFileRecords, error) {
	if node.DirNode == nil || node.DirNode.Shared == nil {
		return nil, fmt.Errorf("headerDirToPutFileRecords only works on header/footer dirs")
	}
	s := node.DirNode.Shared
	pfr := &pfs.PutFileRecords{
		Split: true,
	}
	if s.Header != nil {
		pfr.Header = &pfs.PutFileRecord{
			SizeBytes:  s.HeaderSize,
			ObjectHash: s.Header.Hash,
		}
	}
	if s.Footer != nil {
		pfr.Footer = &pfs.PutFileRecord{
			SizeBytes:  s.FooterSize,
			ObjectHash: s.Footer.Hash,
		}
	}
	if err := tree.List(path, func(child *hashtree.NodeProto) error {
		if child.FileNode == nil {
			return fmt.Errorf("header/footer dir contains child subdirectory, " +
				"which is invalid--header/footer dirs must be created by PutFileSplit")
		}
		for i, o := range child.FileNode.Objects {
			// same hack as copyFile--set size of first object to the size of the
			// whole subtree (and size of other objects to 0). I don't think
			// PutFileSplit files can have more than one object, but that invariant
			// isn't necessary to this code's correctness, so don't verify it.
			var size int64
			if i == 0 {
				size = child.SubtreeSize
			}
			pfr.Records = append(pfr.Records, &pfs.PutFileRecord{
				SizeBytes:  size,
				ObjectHash: o.Hash,
			})
		}
		return nil
	}); err != nil {
		return nil, err
	}
	return pfr, nil // TODO(msteffen) put something real here
}
func headerDirToPutFileRecords ( tree hashtree . HashTree , path string , node * hashtree . NodeProto ) ( * pfs . PutFileRecords , error ) { if node . DirNode == nil || node . DirNode . Shared == nil { return nil , fmt . Errorf ( " " ) } s := node . DirNode . Shared pfr := & pfs . PutFileRecords { Split : true , } if s . Header != nil { pfr . Header = & pfs . PutFileRecord { SizeBytes : s . HeaderSize , ObjectHash : s . Header . Hash , } } if s . Footer != nil { pfr . Footer = & pfs . PutFileRecord { SizeBytes : s . FooterSize , ObjectHash : s . Footer . Hash , } } if err := tree . List ( path , func ( child * hashtree . NodeProto ) error { if child . FileNode == nil { return fmt . Errorf ( " " + " " ) } for i , o := range child . FileNode . Objects { // same hack as copyFile--set size of first object to the size of the // whole subtree (and size of other objects to 0). I don't think // PutFileSplit files can have more than one object, but that invariant // isn't necessary to this code's correctness, so don't verify it. var size int64 if i == 0 { size = child . SubtreeSize } pfr . Records = append ( pfr . Records , & pfs . PutFileRecord { SizeBytes : size , ObjectHash : o . Hash , } ) } return nil } ) ; err != nil { return nil , err } return pfr , nil // TODO(msteffen) put something real here }
// headerDirToPutFileRecords is a helper for copyFile that handles copying
// header/footer directories.
//
// Copy uses essentially the same codepath as putFile--it converts hashtree
// node(s) to PutFileRecords and then uses applyWrite to put the records back
// in the target hashtree. In putFile, the only way to create a headerDir is
// with PutFileSplit (PutFileRecord with Split==true). Rather than split the
// putFile codepath by adding a special case to applyWrite that was valid for
// copyFile but invalid for putFile, we use heaaderDirToPutFileRecords to
// convert a DirectoryNode to a PutFileRecord+Split==true, which applyWrite
// will correctly convert back to a header dir in the target hashtree via the
// regular putFile codepath.
headerDirToPutFileRecords is a helper for copyFile that handles copying header / footer directories . Copy uses essentially the same codepath as putFile -- it converts hashtree node ( s ) to PutFileRecords and then uses applyWrite to put the records back in the target hashtree . In putFile the only way to create a headerDir is with PutFileSplit ( PutFileRecord with Split == true ) . Rather than split the putFile codepath by adding a special case to applyWrite that was valid for copyFile but invalid for putFile we use heaaderDirToPutFileRecords to convert a DirectoryNode to a PutFileRecord + Split == true which applyWrite will correctly convert back to a header dir in the target hashtree via the regular putFile codepath .