gopkg.in/hugelgupf/u-root.v9@v9.0.0-20180831063832-3f6f1057f09b/cmds/init/bgbuild.go (about)

     1  // Copyright 2017 the u-root Authors. All rights reserved
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Build commands in background processes. This feature certainly makes a
     6  // non-busybox shell feel more realtime.
     7  package main
     8  
     9  import (
    10  	"io/ioutil"
    11  	"log"
    12  	"os"
    13  	"os/exec"
    14  	"runtime"
    15  	"sort"
    16  
    17  	"github.com/u-root/u-root/pkg/cmdline"
    18  )
    19  
    20  // Commands are built approximately in order from smallest to largest length of
    21  // the command name. So, two letter commands like `ls` and `cd` will be built
    22  // before `mknod` and `mount`. Generally, shorter commands are used more often
    23  // (that is why they were made short) and are more likely to be used first,
    24  // thus they should be built first.
    25  type cmdSlice []os.FileInfo
    26  
    27  func (p cmdSlice) Len() int {
    28  	return len(p)
    29  }
    30  
    31  func (p cmdSlice) Less(i, j int) bool {
    32  	return len(p[i].Name()) < len(p[j].Name())
    33  }
    34  
    35  func (p cmdSlice) Swap(i, j int) {
    36  	p[i], p[j] = p[j], p[i]
    37  }
    38  
    39  func worker(cmds chan string) {
    40  	for cmdName := range cmds {
    41  		args := []string{"--onlybuild", "--noforce", "--lowpri", cmdName}
    42  		cmd := exec.Command("installcommand", args...)
    43  		if err := cmd.Start(); err != nil {
    44  			log.Println("Cannot start:", err)
    45  			continue
    46  		}
    47  		if err := cmd.Wait(); err != nil {
    48  			log.Println("installcommand error:", err)
    49  		}
    50  	}
    51  }
    52  
    53  func startBgBuild() {
    54  	cmds := make(chan string)
    55  
    56  	// Start a worker for each CPU.
    57  	for i := 0; i < runtime.NumCPU(); i++ {
    58  		go worker(cmds)
    59  	}
    60  
    61  	// Create a slice of commands and order them by the aformentioned
    62  	// heuristic.
    63  	fis, err := ioutil.ReadDir("/buildbin")
    64  	if err != nil {
    65  		log.Print(err)
    66  		return
    67  	}
    68  	sort.Sort(cmdSlice(fis))
    69  
    70  	// Send the command by name to the workers.
    71  	for _, fi := range fis {
    72  		cmds <- fi.Name()
    73  	}
    74  	close(cmds)
    75  }
    76  
    77  func isBgBuildEnabled() bool {
    78  	return cmdline.ContainsFlag("uroot.bgbuild")
    79  }