github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/daemon/exec/exec.go (about)

     1  package exec
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  	"time"
     7  
     8  	"github.com/docker/docker/daemon/execdriver"
     9  	"github.com/docker/docker/pkg/stringid"
    10  	"github.com/docker/docker/runconfig"
    11  )
    12  
    13  // Config holds the configurations for execs. The Daemon keeps
    14  // track of both running and finished execs so that they can be
    15  // examined both during and after completion.
    16  type Config struct {
    17  	sync.Mutex
    18  	*runconfig.StreamConfig
    19  	ID            string
    20  	Running       bool
    21  	ExitCode      *int
    22  	ProcessConfig *execdriver.ProcessConfig
    23  	OpenStdin     bool
    24  	OpenStderr    bool
    25  	OpenStdout    bool
    26  	CanRemove     bool
    27  	ContainerID   string
    28  	DetachKeys    []byte
    29  
    30  	// waitStart will be closed immediately after the exec is really started.
    31  	waitStart chan struct{}
    32  }
    33  
    34  // NewConfig initializes the a new exec configuration
    35  func NewConfig() *Config {
    36  	return &Config{
    37  		ID:           stringid.GenerateNonCryptoID(),
    38  		StreamConfig: runconfig.NewStreamConfig(),
    39  		waitStart:    make(chan struct{}),
    40  	}
    41  }
    42  
    43  // Store keeps track of the exec configurations.
    44  type Store struct {
    45  	commands map[string]*Config
    46  	sync.RWMutex
    47  }
    48  
    49  // NewStore initializes a new exec store.
    50  func NewStore() *Store {
    51  	return &Store{commands: make(map[string]*Config, 0)}
    52  }
    53  
    54  // Commands returns the exec configurations in the store.
    55  func (e *Store) Commands() map[string]*Config {
    56  	e.RLock()
    57  	commands := make(map[string]*Config, len(e.commands))
    58  	for id, config := range e.commands {
    59  		commands[id] = config
    60  	}
    61  	e.RUnlock()
    62  	return commands
    63  }
    64  
    65  // Add adds a new exec configuration to the store.
    66  func (e *Store) Add(id string, Config *Config) {
    67  	e.Lock()
    68  	e.commands[id] = Config
    69  	e.Unlock()
    70  }
    71  
    72  // Get returns an exec configuration by its id.
    73  func (e *Store) Get(id string) *Config {
    74  	e.RLock()
    75  	res := e.commands[id]
    76  	e.RUnlock()
    77  	return res
    78  }
    79  
    80  // Delete removes an exec configuration from the store.
    81  func (e *Store) Delete(id string) {
    82  	e.Lock()
    83  	delete(e.commands, id)
    84  	e.Unlock()
    85  }
    86  
    87  // List returns the list of exec ids in the store.
    88  func (e *Store) List() []string {
    89  	var IDs []string
    90  	e.RLock()
    91  	for id := range e.commands {
    92  		IDs = append(IDs, id)
    93  	}
    94  	e.RUnlock()
    95  	return IDs
    96  }
    97  
    98  // Wait waits until the exec process finishes or there is an error in the error channel.
    99  func (c *Config) Wait(cErr chan error) error {
   100  	// Exec should not return until the process is actually running
   101  	select {
   102  	case <-c.waitStart:
   103  	case err := <-cErr:
   104  		return err
   105  	}
   106  	return nil
   107  }
   108  
   109  // Close closes the wait channel for the progress.
   110  func (c *Config) Close() {
   111  	close(c.waitStart)
   112  }
   113  
   114  // Resize changes the size of the terminal for the exec process.
   115  func (c *Config) Resize(h, w int) error {
   116  	select {
   117  	case <-c.waitStart:
   118  	case <-time.After(time.Second):
   119  		return fmt.Errorf("Exec %s is not running, so it can not be resized.", c.ID)
   120  	}
   121  	return c.ProcessConfig.Terminal.Resize(h, w)
   122  }