github.com/endocode/docker@v1.4.2-0.20160113120958-46eb4700391e/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  	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  	return e.commands
    57  }
    58  
    59  // Add adds a new exec configuration to the store.
    60  func (e *Store) Add(id string, Config *Config) {
    61  	e.Lock()
    62  	e.commands[id] = Config
    63  	e.Unlock()
    64  }
    65  
    66  // Get returns an exec configuration by its id.
    67  func (e *Store) Get(id string) *Config {
    68  	e.RLock()
    69  	res := e.commands[id]
    70  	e.RUnlock()
    71  	return res
    72  }
    73  
    74  // Delete removes an exec configuration from the store.
    75  func (e *Store) Delete(id string) {
    76  	e.Lock()
    77  	delete(e.commands, id)
    78  	e.Unlock()
    79  }
    80  
    81  // List returns the list of exec ids in the store.
    82  func (e *Store) List() []string {
    83  	var IDs []string
    84  	e.RLock()
    85  	for id := range e.commands {
    86  		IDs = append(IDs, id)
    87  	}
    88  	e.RUnlock()
    89  	return IDs
    90  }
    91  
    92  // Wait waits until the exec process finishes or there is an error in the error channel.
    93  func (c *Config) Wait(cErr chan error) error {
    94  	// Exec should not return until the process is actually running
    95  	select {
    96  	case <-c.waitStart:
    97  	case err := <-cErr:
    98  		return err
    99  	}
   100  	return nil
   101  }
   102  
   103  // Close closes the wait channel for the progress.
   104  func (c *Config) Close() {
   105  	close(c.waitStart)
   106  }
   107  
   108  // Resize changes the size of the terminal for the exec process.
   109  func (c *Config) Resize(h, w int) error {
   110  	select {
   111  	case <-c.waitStart:
   112  	case <-time.After(time.Second):
   113  		return derr.ErrorCodeExecResize.WithArgs(c.ID)
   114  	}
   115  	return c.ProcessConfig.Terminal.Resize(h, w)
   116  }