-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add basic proc management infrastructure
- Loading branch information
Showing
9 changed files
with
270 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package appserver | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/skycoin/skycoin/src/util/logging" | ||
"github.com/skycoin/skywire/pkg/app2" | ||
) | ||
|
||
type App struct { | ||
config app2.Config | ||
log *logging.Logger | ||
proc *app2.Proc | ||
rpcS *Server | ||
} | ||
|
||
func NewApp(log *logging.Logger, c app2.Config, dir string, args []string) (*App, error) { | ||
appKey := app2.GenerateAppKey() | ||
|
||
rpcS, err := New(logging.MustGetLogger(fmt.Sprintf("app_rpc_server_%s", appKey)), c.SockFile, appKey) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
p := app2.NewProc(c, dir, args) | ||
|
||
return &App{ | ||
config: c, | ||
log: log, | ||
proc: p, | ||
rpcS: rpcS, | ||
}, nil | ||
} | ||
|
||
func (a *App) PID() app2.ProcID { | ||
return a.proc.ID() | ||
} | ||
|
||
func (a *App) Run() error { | ||
go func() { | ||
if err := a.rpcS.ListenAndServe(); err != nil { | ||
a.log.WithError(err).Error("error serving RPC") | ||
} | ||
}() | ||
|
||
err := a.proc.Run() | ||
if err != nil { | ||
a.closeRPCServer() | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (a *App) Stop() error { | ||
a.closeRPCServer() | ||
|
||
return a.proc.Stop() | ||
} | ||
|
||
func (a *App) Wait() error { | ||
|
||
return a.proc.Wait() | ||
} | ||
|
||
func (a *App) closeRPCServer() { | ||
if err := a.rpcS.Close(); err != nil { | ||
a.log.WithError(err).Error("error closing RPC server") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package appserver | ||
|
||
import ( | ||
"sync" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
var ( | ||
ErrAppExists = errors.New("app with such pid already exists") | ||
) | ||
|
||
type AppManager struct { | ||
apps map[string]*App | ||
mx sync.RWMutex | ||
} | ||
|
||
func NewAppManager() *AppManager { | ||
return &AppManager{} | ||
} | ||
|
||
func (m *AppManager) Add(a *App) error { | ||
m.mx.Lock() | ||
if _, ok := m.apps[a.config.Name]; ok { | ||
m.mx.Unlock() | ||
return ErrAppExists | ||
} | ||
m.apps[a.config.Name] = a | ||
m.mx.Unlock() | ||
|
||
return nil | ||
} | ||
|
||
func (m *AppManager) App(name string) (*App, bool) { | ||
m.mx.RLock() | ||
a, ok := m.apps[name] | ||
m.mx.RUnlock() | ||
return a, ok | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package app2 | ||
|
||
// Config defines configuration parameters for App | ||
type Config struct { | ||
Name string `json:"name"` | ||
Version string `json:"version"` | ||
SockFile string `json:"sock_file"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package app2 | ||
|
||
import "github.com/skycoin/dmsg/cipher" | ||
|
||
type Key string | ||
|
||
func GenerateAppKey() Key { | ||
raw, _ := cipher.GenerateKeyPair() | ||
return Key(raw.Hex()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package app2 | ||
|
||
import ( | ||
"fmt" | ||
"os/exec" | ||
"path/filepath" | ||
"sync" | ||
) | ||
|
||
type Proc struct { | ||
id ProcID | ||
cmd *exec.Cmd | ||
mx sync.RWMutex | ||
} | ||
|
||
func NewProc(c Config, dir string, args []string) *Proc { | ||
cmd := cmd(c, dir, args) | ||
|
||
return &Proc{ | ||
cmd: cmd, | ||
} | ||
} | ||
|
||
func (p *Proc) ID() ProcID { | ||
p.mx.RLock() | ||
id := p.id | ||
p.mx.RUnlock() | ||
return id | ||
} | ||
|
||
func (p *Proc) Run() error { | ||
if err := p.cmd.Run(); err != nil { | ||
return err | ||
} | ||
|
||
p.mx.Lock() | ||
p.id = ProcID(p.cmd.Process.Pid) | ||
p.mx.Unlock() | ||
|
||
return nil | ||
} | ||
|
||
func (p *Proc) Stop() error { | ||
return p.cmd.Process.Kill() | ||
} | ||
|
||
func (p *Proc) Wait() error { | ||
return p.cmd.Wait() | ||
} | ||
|
||
func cmd(config Config, dir string, args []string) *exec.Cmd { | ||
binaryPath := getBinaryPath(dir, config.Name, config.Version) | ||
cmd := exec.Command(binaryPath, args...) // nolint:gosec | ||
|
||
const ( | ||
appKeyEnvFormat = "APP_KEY=%s" | ||
sockFileEnvFormat = "SW_UNIX=%s" | ||
) | ||
|
||
env := make([]string, 0, 2) | ||
env = append(env, fmt.Sprintf(appKeyEnvFormat, config.Key)) | ||
env = append(env, fmt.Sprintf(sockFileEnvFormat, config.SockFile)) | ||
|
||
cmd.Env = env | ||
|
||
return cmd | ||
} | ||
|
||
func getBinaryPath(dir, name, ver string) string { | ||
const binaryNameFormat = "%s.v%s" | ||
return filepath.Join(dir, fmt.Sprintf(binaryNameFormat, name, ver)) | ||
} |
Oops, something went wrong.