github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/daemon/exec/exec.go (about)

     1  package exec
     2  
     3  import (
     4  	"sync"
     5  	"time"
     6  
     7  	"github.com/docker/docker/daemon/execdriver"
     8  	derr "github.com/docker/docker/errors"
     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  
    29  	// waitStart will be closed immediately after the exec is really started.
    30  	waitStart chan struct{}
    31  }
    32  
    33  // NewConfig initializes the a new exec configuration
    34  func NewConfig() *Config {
    35  	return &Config{
    36  		ID:           stringid.GenerateNonCryptoID(),
    37  		StreamConfig: runconfig.NewStreamConfig(),
    38  		waitStart:    make(chan struct{}),
    39  	}
    40  }
    41  
    42  // Store keeps track of the exec configurations.
    43  type Store struct {
    44  	commands map[string]*Config
    45  	sync.RWMutex
    46  }
    47  
    48  // NewStore initializes a new exec store.
    49  func NewStore() *Store {
    50  	return &Store{commands: make(map[string]*Config, 0)}
    51  }
    52  
    53  // Commands returns the exec configurations in the store.
    54  func (e *Store) Commands() map[string]*Config {
    55  	return e.commands
    56  }
    57  
    58  // Add adds a new exec configuration to the store.
    59  func (e *Store) Add(id string, Config *Config) {
    60  	e.Lock()
    61  	e.commands[id] = Config
    62  	e.Unlock()
    63  }
    64  
    65  // Get returns an exec configuration by its id.
    66  func (e *Store) Get(id string) *Config {
    67  	e.RLock()
    68  	res := e.commands[id]
    69  	e.RUnlock()
    70  	return res
    71  }
    72  
    73  // Delete removes an exec configuration from the store.
    74  func (e *Store) Delete(id string) {
    75  	e.Lock()
    76  	delete(e.commands, id)
    77  	e.Unlock()
    78  }
    79  
    80  // List returns the list of exec ids in the store.
    81  func (e *Store) List() []string {
    82  	var IDs []string
    83  	e.RLock()
    84  	for id := range e.commands {
    85  		IDs = append(IDs, id)
    86  	}
    87  	e.RUnlock()
    88  	return IDs
    89  }
    90  
    91  // Wait waits until the exec process finishes or there is an error in the error channel.
    92  func (c *Config) Wait(cErr chan error) error {
    93  	// Exec should not return until the process is actually running
    94  	select {
    95  	case <-c.waitStart:
    96  	case err := <-cErr:
    97  		return err
    98  	}
    99  	return nil
   100  }
   101  
   102  // Close closes the wait channel for the progress.
   103  func (c *Config) Close() {
   104  	close(c.waitStart)
   105  }
   106  
   107  // Resize changes the size of the terminal for the exec process.
   108  func (c *Config) Resize(h, w int) error {
   109  	select {
   110  	case <-c.waitStart:
   111  	case <-time.After(time.Second):
   112  		return derr.ErrorCodeExecResize.WithArgs(c.ID)
   113  	}
   114  	return c.ProcessConfig.Terminal.Resize(h, w)
   115  }