forked from x/ContextOS
mac add context.deal
添加消息处理,异常链,函数链,简化了模块创建与消息派生的操作接口
This commit is contained in:
parent
5a692b1aa5
commit
585ee2434b
@ -1,14 +1,11 @@
|
|||||||
package cli // {{{
|
package cli
|
||||||
// }}}
|
|
||||||
import ( // {{{
|
import ( // {{{
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
"runtime/debug"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -26,8 +23,8 @@ type CLI struct {
|
|||||||
|
|
||||||
history []map[string]string
|
history []map[string]string
|
||||||
alias map[string]string
|
alias map[string]string
|
||||||
exit chan bool
|
|
||||||
next string
|
next string
|
||||||
|
exit bool
|
||||||
|
|
||||||
target *ctx.Context
|
target *ctx.Context
|
||||||
*ctx.Context
|
*ctx.Context
|
||||||
@ -58,6 +55,7 @@ func (cli *CLI) parse() bool { // {{{
|
|||||||
l := len(cli.ins)
|
l := len(cli.ins)
|
||||||
if l == 1 {
|
if l == 1 {
|
||||||
cli.echo("\n%s\n", cli.Conf("结束语"))
|
cli.echo("\n%s\n", cli.Conf("结束语"))
|
||||||
|
return false
|
||||||
ls = "exit"
|
ls = "exit"
|
||||||
e = nil
|
e = nil
|
||||||
} else {
|
} else {
|
||||||
@ -125,8 +123,7 @@ func (cli *CLI) parse() bool { // {{{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("%d spawn: %s->%s %v", cli.Resource[0].Code, msg.Context.Name, msg.Target.Name, msg.Meta["detail"])
|
msg.Post(cli.Context)
|
||||||
cli.Post(msg)
|
|
||||||
|
|
||||||
for _, v := range msg.Meta["result"] {
|
for _, v := range msg.Meta["result"] {
|
||||||
cli.echo(v)
|
cli.echo(v)
|
||||||
@ -135,53 +132,6 @@ func (cli *CLI) parse() bool { // {{{
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
|
||||||
func (cli *CLI) deal(msg *ctx.Message) bool { // {{{
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
msg.Echo("%s\n", e)
|
|
||||||
|
|
||||||
if e == io.EOF {
|
|
||||||
panic(e)
|
|
||||||
} else {
|
|
||||||
debug.PrintStack()
|
|
||||||
log.Println(e)
|
|
||||||
msg.End(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
detail := msg.Meta["detail"]
|
|
||||||
if len(detail) == 0 {
|
|
||||||
msg.End(true)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if a, ok := cli.alias[detail[0]]; ok {
|
|
||||||
detail[0] = a
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := cli.Commands[detail[0]]; ok {
|
|
||||||
cli.next = cli.Cmd(msg, detail...)
|
|
||||||
} else if _, ok := msg.Target.Commands[detail[0]]; ok {
|
|
||||||
cli.next = msg.Cmd()
|
|
||||||
} else {
|
|
||||||
cmd := exec.Command(detail[0], detail[1:]...)
|
|
||||||
v, e := cmd.CombinedOutput()
|
|
||||||
if e != nil {
|
|
||||||
msg.Echo("%s\n", e)
|
|
||||||
}
|
|
||||||
msg.Echo(string(v))
|
|
||||||
}
|
|
||||||
msg.End(true)
|
|
||||||
|
|
||||||
cli.history = append(cli.history, map[string]string{
|
|
||||||
"time": time.Now().Format("15:04:05"),
|
|
||||||
"index": fmt.Sprintf("%d", len(cli.history)),
|
|
||||||
"cli": strings.Join(detail, " "),
|
|
||||||
})
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (cli *CLI) echo(str string, arg ...interface{}) { // {{{
|
func (cli *CLI) echo(str string, arg ...interface{}) { // {{{
|
||||||
if len(cli.ins) == 1 || cli.Conf("slient") != "yes" {
|
if len(cli.ins) == 1 || cli.Conf("slient") != "yes" {
|
||||||
@ -191,18 +141,15 @@ func (cli *CLI) echo(str string, arg ...interface{}) { // {{{
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
func (cli *CLI) Begin() ctx.Server { // {{{
|
func (cli *CLI) Begin(m *ctx.Message) ctx.Server { // {{{
|
||||||
cli.history = make([]map[string]string, 0, 100)
|
cli.history = make([]map[string]string, 0, 100)
|
||||||
cli.alias = make(map[string]string, 10)
|
cli.alias = make(map[string]string, 10)
|
||||||
cli.exit = make(chan bool)
|
|
||||||
|
|
||||||
cli.target = cli.Context
|
cli.target = cli.Context
|
||||||
return cli.Server
|
return cli.Server
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (cli *CLI) Start(m *ctx.Message) bool { // {{{
|
func (cli *CLI) Start(m *ctx.Message) bool { // {{{
|
||||||
|
|
||||||
if detail, ok := m.Data["detail"]; ok {
|
if detail, ok := m.Data["detail"]; ok {
|
||||||
io := detail.(io.ReadWriteCloser)
|
io := detail.(io.ReadWriteCloser)
|
||||||
cli.out = io
|
cli.out = io
|
||||||
@ -214,21 +161,40 @@ func (cli *CLI) Start(m *ctx.Message) bool { // {{{
|
|||||||
cli.push(f)
|
cli.push(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go cli.Safe(m, func(c *ctx.Context, m *ctx.Message) {
|
||||||
defer recover()
|
|
||||||
for cli.parse() {
|
for cli.parse() {
|
||||||
}
|
}
|
||||||
}()
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for cli.deal(cli.Get()) {
|
for cli.Deal(func(msg *ctx.Message) bool {
|
||||||
|
arg := msg.Meta["detail"]
|
||||||
|
if a, ok := cli.alias[arg[0]]; ok {
|
||||||
|
arg[0] = a
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}, func(msg *ctx.Message) bool {
|
||||||
|
arg := msg.Meta["detail"]
|
||||||
|
cli.history = append(cli.history, map[string]string{
|
||||||
|
"time": time.Now().Format("15:04:05"),
|
||||||
|
"index": fmt.Sprintf("%d", len(cli.history)),
|
||||||
|
"cli": strings.Join(arg, " "),
|
||||||
|
})
|
||||||
|
|
||||||
|
if cli.exit == true {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (cli *CLI) Spawn(c *ctx.Context, arg ...string) ctx.Server { // {{{
|
func (cli *CLI) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server { // {{{
|
||||||
c.Caches = map[string]*ctx.Cache{
|
c.Caches = map[string]*ctx.Cache{
|
||||||
"status": &ctx.Cache{Name: "status", Value: "stop", Help: "服务状态"},
|
"status": &ctx.Cache{Name: "status", Value: "stop", Help: "服务状态"},
|
||||||
}
|
}
|
||||||
@ -244,6 +210,14 @@ func (cli *CLI) Spawn(c *ctx.Context, arg ...string) ctx.Server { // {{{
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
func (cli *CLI) Exit(m *ctx.Message, arg ...string) bool { // {{{
|
||||||
|
if cli.Context != Index {
|
||||||
|
delete(cli.Context.Context.Contexts, cli.Name)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "cli", Help: "本地控制",
|
var Index = &ctx.Context{Name: "cli", Help: "本地控制",
|
||||||
@ -303,18 +277,19 @@ var Index = &ctx.Context{Name: "cli", Help: "本地控制",
|
|||||||
msg.Target = msg.Context
|
msg.Target = msg.Context
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
if cs := msg.Target.Find(strings.Split(arg[1], ".")); cs != nil {
|
// if cs := msg.Target.Find(strings.Split(arg[1], ".")); cs != nil {
|
||||||
|
if cs := c.Root.Search(arg[1]); cs != nil && len(cs) > 0 {
|
||||||
if ok {
|
if ok {
|
||||||
cli.target = cs
|
cli.target = cs[0]
|
||||||
} else {
|
} else {
|
||||||
msg.Target = cs
|
msg.Target = cs[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case 3, 4:
|
case 3, 4:
|
||||||
switch arg[1] {
|
switch arg[1] {
|
||||||
case "spawn":
|
case "spawn":
|
||||||
msg.Target.Spawn(arg[2])
|
msg.Target.Spawn(msg, arg[2])
|
||||||
case "find":
|
case "find":
|
||||||
cs := msg.Target.Find(strings.Split(arg[2], "."))
|
cs := msg.Target.Find(strings.Split(arg[2], "."))
|
||||||
if cs != nil {
|
if cs != nil {
|
||||||
@ -505,7 +480,19 @@ var Index = &ctx.Context{Name: "cli", Help: "本地控制",
|
|||||||
// }}}
|
// }}}
|
||||||
}},
|
}},
|
||||||
"exit": &ctx.Command{"exit", "退出", func(c *ctx.Context, m *ctx.Message, arg ...string) string {
|
"exit": &ctx.Command{"exit", "退出", func(c *ctx.Context, m *ctx.Message, arg ...string) string {
|
||||||
panic(io.EOF)
|
cli, ok := m.Target.Server.(*CLI)
|
||||||
|
if !ok {
|
||||||
|
cli, ok = m.Context.Server.(*CLI)
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
if !cli.exit {
|
||||||
|
m.Echo(c.Conf("结束语"))
|
||||||
|
cli.Context.Exit(m)
|
||||||
|
}
|
||||||
|
cli.exit = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
}},
|
}},
|
||||||
"remote": &ctx.Command{"remote master|slave listen|dial address protocol", "建立远程连接", func(c *ctx.Context, m *ctx.Message, arg ...string) string {
|
"remote": &ctx.Command{"remote master|slave listen|dial address protocol", "建立远程连接", func(c *ctx.Context, m *ctx.Message, arg ...string) string {
|
||||||
switch len(arg) { // {{{
|
switch len(arg) { // {{{
|
||||||
@ -518,7 +505,7 @@ var Index = &ctx.Context{Name: "cli", Help: "本地控制",
|
|||||||
} else {
|
} else {
|
||||||
if arg[2] == "listen" {
|
if arg[2] == "listen" {
|
||||||
s := c.Root.Find(strings.Split(arg[4], "."))
|
s := c.Root.Find(strings.Split(arg[4], "."))
|
||||||
m.Message.Spawn(s, arg[3], 0).Add("detail", "listen", arg[3]).Post(c)
|
m.Message.Spawn(s, arg[3]).Cmd("listen", arg[3])
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package ctx // {{{
|
package ctx
|
||||||
// }}}
|
|
||||||
import ( // {{{
|
import ( // {{{
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -46,24 +48,25 @@ type Message struct { // {{{
|
|||||||
Data map[string]interface{}
|
Data map[string]interface{}
|
||||||
Wait chan bool
|
Wait chan bool
|
||||||
|
|
||||||
*Context
|
|
||||||
Name string
|
Name string
|
||||||
Target *Context
|
*Context
|
||||||
Index int
|
Index int
|
||||||
|
Target *Context
|
||||||
|
|
||||||
Messages []*Message
|
Messages []*Message
|
||||||
Message *Message
|
Message *Message
|
||||||
Root *Message
|
Root *Message
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) Spawn(c *Context, key string, index int) *Message { // {{{
|
func (m *Message) Spawn(c *Context, key string) *Message { // {{{
|
||||||
msg := &Message{
|
msg := &Message{
|
||||||
Code: m.Capi("nmessage", 1),
|
Code: m.Capi("nmessage", 1),
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
Target: c,
|
|
||||||
Name: key,
|
Name: key,
|
||||||
|
Index: 0,
|
||||||
|
Target: c,
|
||||||
Message: m,
|
Message: m,
|
||||||
Root: m.Root,
|
Root: Pulse,
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.Context = m.Target
|
msg.Context = m.Target
|
||||||
@ -82,6 +85,7 @@ func (m *Message) Spawn(c *Context, key string, index int) *Message { // {{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
func (m *Message) Add(key string, value ...string) *Message { // {{{
|
func (m *Message) Add(key string, value ...string) *Message { // {{{
|
||||||
if m.Meta == nil {
|
if m.Meta == nil {
|
||||||
m.Meta = make(map[string][]string)
|
m.Meta = make(map[string][]string)
|
||||||
@ -132,8 +136,7 @@ func (m *Message) Echo(str string, arg ...interface{}) *Message { // {{{
|
|||||||
m.Meta["result"] = make([]string, 0, 3)
|
m.Meta["result"] = make([]string, 0, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := fmt.Sprintf(str, arg...)
|
m.Meta["result"] = append(m.Meta["result"], fmt.Sprintf(str, arg...))
|
||||||
m.Meta["result"] = append(m.Meta["result"], s)
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,12 +149,25 @@ func (m *Message) End(s bool) { // {{{
|
|||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (m *Message) Cmd() string { // {{{
|
|
||||||
|
func (m *Message) Cmd(arg ...string) string { // {{{
|
||||||
|
if len(arg) > 0 {
|
||||||
|
if m.Meta == nil {
|
||||||
|
m.Meta = make(map[string][]string)
|
||||||
|
}
|
||||||
|
m.Meta["detail"] = arg
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("%s command(%s->%s): %v", m.Target.Name, m.Context.Name, m.Target.Name, m.Meta["detail"])
|
||||||
return m.Target.Cmd(m, m.Meta["detail"]...)
|
return m.Target.Cmd(m, m.Meta["detail"]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (m *Message) Post(c *Context) bool { // {{{
|
func (m *Message) Post(c *Context, arg ...string) bool { // {{{
|
||||||
|
if len(arg) > 0 {
|
||||||
|
m.Meta["detail"] = arg
|
||||||
|
}
|
||||||
|
|
||||||
if c.Messages == nil {
|
if c.Messages == nil {
|
||||||
c.Messages = make(chan *Message, c.Confi("MessageQueueSize"))
|
c.Messages = make(chan *Message, c.Confi("MessageQueueSize"))
|
||||||
}
|
}
|
||||||
@ -166,22 +182,26 @@ func (m *Message) Post(c *Context) bool { // {{{
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (m *Message) Start(arg ...string) bool { // {{{
|
func (m *Message) Start(arg ...string) bool { // {{{
|
||||||
s := m.Target.Spawn(arg...).Begin()
|
if len(arg) > 0 {
|
||||||
m.Target = s
|
m.Meta["detail"] = arg
|
||||||
go s.Start(m)
|
}
|
||||||
|
|
||||||
|
go m.Target.Spawn(m, m.Meta["detail"]...).Begin(m).Start(m)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
// }}}
|
// }}}
|
||||||
type Server interface { // {{{
|
type Server interface { // {{{
|
||||||
Begin() Server
|
Begin(m *Message) Server
|
||||||
Start(m *Message) bool
|
Start(m *Message) bool
|
||||||
Spawn(c *Context, arg ...string) Server
|
Spawn(c *Context, m *Message, arg ...string) Server
|
||||||
|
Exit(m *Message, arg ...string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
type Context struct { // {{{
|
type Context struct {
|
||||||
Name string
|
Name string
|
||||||
Help string
|
Help string
|
||||||
|
|
||||||
@ -207,78 +227,182 @@ type Context struct { // {{{
|
|||||||
func (c *Context) Check(e error) bool { // {{{
|
func (c *Context) Check(e error) bool { // {{{
|
||||||
if e != nil {
|
if e != nil {
|
||||||
log.Println(c.Name, "error:", e)
|
log.Println(c.Name, "error:", e)
|
||||||
if c.Conf("debug") == "on" {
|
|
||||||
debug.PrintStack()
|
|
||||||
}
|
|
||||||
panic(e)
|
panic(e)
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (c *Context) Register(s *Context, self Server) bool { // {{{
|
func (c *Context) Safe(m *Message, hand ...func(c *Context, m *Message)) (ok bool) { // {{{
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
if c.Conf("debug") == "on" {
|
||||||
|
log.Println(c.Name, "error:", e)
|
||||||
|
if e != io.EOF {
|
||||||
|
debug.PrintStack()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e == io.EOF {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(hand) > 0 {
|
||||||
|
c.Safe(m, hand[1:]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pulse.Wait <- true
|
||||||
|
}()
|
||||||
|
|
||||||
|
if len(hand) > 0 {
|
||||||
|
hand[0](c, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
func (c *Context) Register(s *Context, x Server) *Context { // {{{
|
||||||
if c.Contexts == nil {
|
if c.Contexts == nil {
|
||||||
c.Contexts = make(map[string]*Context)
|
c.Contexts = make(map[string]*Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
if x, ok := c.Contexts[s.Name]; ok {
|
if x, ok := c.Contexts[s.Name]; ok {
|
||||||
panic(errors.New(c.Name + " 上下文已存在" + x.Name))
|
panic(errors.New(c.Name + " 上下文已存在" + x.Name))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Contexts[s.Name] = s
|
c.Contexts[s.Name] = s
|
||||||
s.Context = c
|
|
||||||
s.Root = c.Root
|
s.Root = c.Root
|
||||||
s.Server = self
|
s.Context = c
|
||||||
|
s.Server = x
|
||||||
|
|
||||||
|
log.Printf("%s register(%d): %s", c.Name, Index.Capi("ncontext", 1), s.Name)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
func (c *Context) Begin(m *Message) *Context { // {{{
|
||||||
|
for _, v := range c.Configs {
|
||||||
|
if v.Hand != nil {
|
||||||
|
v.Hand(c, v.Value)
|
||||||
|
log.Println(c.Name, "config:", v.Name, v.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Server != nil {
|
||||||
|
c.Server.Begin(m)
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
func (c *Context) Start(m *Message) bool { // {{{
|
||||||
|
if c.Server != nil && c.Cap("status") != "start" {
|
||||||
|
c.Safe(m, func(c *Context, m *Message) {
|
||||||
|
c.Cap("status", "start")
|
||||||
|
defer c.Cap("status", "stop")
|
||||||
|
|
||||||
|
log.Printf("%d start(%d): %s", m.Code, Index.Capi("nserver", 1), c.Name)
|
||||||
|
defer Index.Capi("nserver", -1)
|
||||||
|
defer log.Printf("%d stop(%d): %s %s", m.Code, Index.Capi("nserver", 0), c.Name, c.Help)
|
||||||
|
|
||||||
|
c.Resource = []*Message{m}
|
||||||
|
c.Server.Start(m)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
log.Println(c.Name, "register:", s.Name)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (c *Context) Init(arg ...string) { // {{{
|
func (c *Context) Spawn(m *Message, arg ...string) *Context { // {{{
|
||||||
if c.Root != nil {
|
s := &Context{Name: arg[0], Help: c.Help}
|
||||||
return
|
m.Target = s
|
||||||
}
|
c.Register(s, c.Server.Spawn(s, m, arg...)).Begin(m)
|
||||||
|
return s
|
||||||
root := c
|
|
||||||
for root.Context != nil {
|
|
||||||
root = root.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
cs := []*Context{root}
|
|
||||||
|
|
||||||
for i := 0; i < len(cs); i++ {
|
|
||||||
cs[i].Root = root
|
|
||||||
cs[i].Begin()
|
|
||||||
|
|
||||||
for _, v := range cs[i].Contexts {
|
|
||||||
cs = append(cs, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Pulse.Root = Pulse
|
|
||||||
Pulse.Target = Index
|
|
||||||
Pulse.Context = Index
|
|
||||||
|
|
||||||
for _, s := range root.Contexts {
|
|
||||||
if ok, _ := regexp.MatchString(root.Conf("start"), s.Name); ok {
|
|
||||||
go s.Start(Pulse.Spawn(s, s.Name, 0).Put("detail", os.Stdout))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Pulse.Wait = make(chan bool)
|
|
||||||
for {
|
|
||||||
<-Pulse.Wait
|
|
||||||
if Index.Capi("nserver", 0) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (c *Context) Find(name []string) (s *Context) { // {{{
|
func (c *Context) Deal(pre func(m *Message) bool, post func(m *Message) bool) (live bool) { // {{{
|
||||||
log.Println(c.Name, "find:", name)
|
|
||||||
|
|
||||||
|
if c.Messages == nil {
|
||||||
|
c.Messages = make(chan *Message, c.Confi("MessageQueueSize"))
|
||||||
|
}
|
||||||
|
m := <-c.Messages
|
||||||
|
defer m.End(true)
|
||||||
|
|
||||||
|
if len(m.Meta["detail"]) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if pre != nil && !pre(m) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Safe(m, func(c *Context, m *Message) {
|
||||||
|
c.Cmd(m, m.Meta["detail"]...)
|
||||||
|
log.Printf("%s command(%s->%s): %v", c.Name, m.Context.Name, m.Target.Name, m.Meta["detail"])
|
||||||
|
|
||||||
|
}, func(c *Context, m *Message) {
|
||||||
|
m.Cmd()
|
||||||
|
|
||||||
|
}, func(c *Context, m *Message) {
|
||||||
|
log.Printf("system command(%s->%s): %v", m.Context.Name, m.Target.Name, m.Meta["detail"])
|
||||||
|
arg := m.Meta["detail"]
|
||||||
|
cmd := exec.Command(arg[0], arg[1:]...)
|
||||||
|
v, e := cmd.CombinedOutput()
|
||||||
|
if e != nil {
|
||||||
|
m.Echo("%s\n", e)
|
||||||
|
} else {
|
||||||
|
m.Echo(string(v))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if post != nil && !post(m) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
func (c *Context) Exit(m *Message, arg ...string) { // {{{
|
||||||
|
if m.Target == c {
|
||||||
|
for _, v := range c.Session {
|
||||||
|
if v.Name != "" {
|
||||||
|
c.Server.Exit(v, arg...)
|
||||||
|
|
||||||
|
v.Name = ""
|
||||||
|
log.Println(c.Name, c.Help, "exit: session", v.Code, v.Target.Name, v.Target.Help)
|
||||||
|
v.Cmd("exit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range c.Resource {
|
||||||
|
if v.Index != -1 {
|
||||||
|
c.Server.Exit(v, arg...)
|
||||||
|
|
||||||
|
v.Index = -1
|
||||||
|
log.Println(c.Name, c.Help, "exit: resource", v.Code, v.Context.Name, v.Context.Help)
|
||||||
|
v.Context.Cmd(v, "exit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if m.Context == c {
|
||||||
|
if m.Name != "" {
|
||||||
|
c.Server.Exit(m, arg...)
|
||||||
|
|
||||||
|
m.Name = ""
|
||||||
|
m.Cmd("exit")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.Server.Exit(m, arg...)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
|
func (c *Context) Find(name []string) (s *Context) { // {{{
|
||||||
cs := c.Contexts
|
cs := c.Contexts
|
||||||
for _, v := range name {
|
for _, v := range name {
|
||||||
if x, ok := cs[v]; ok {
|
if x, ok := cs[v]; ok {
|
||||||
@ -478,79 +602,6 @@ func (c *Context) Del(arg ...string) { // {{{
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
func (c *Context) Begin() *Context { // {{{
|
|
||||||
c.Root.Capi("ncontext", 1)
|
|
||||||
for _, v := range c.Configs {
|
|
||||||
if v.Hand != nil {
|
|
||||||
v.Hand(c, v.Value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Server != nil {
|
|
||||||
c.Server.Begin()
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
func (c *Context) Start(m *Message) bool { // {{{
|
|
||||||
defer func() {
|
|
||||||
if e := recover(); e != nil {
|
|
||||||
log.Println(e)
|
|
||||||
}
|
|
||||||
Pulse.Wait <- true
|
|
||||||
}()
|
|
||||||
|
|
||||||
if c.Server != nil && c.Cap("status") != "start" {
|
|
||||||
|
|
||||||
c.Cap("status", "status", "start", "服务状态")
|
|
||||||
defer c.Cap("status", "stop")
|
|
||||||
|
|
||||||
c.Root.Capi("nserver", 1)
|
|
||||||
defer c.Root.Capi("nserver", -1)
|
|
||||||
|
|
||||||
c.Resource = []*Message{m}
|
|
||||||
log.Println(m.Code, "start:", c.Name)
|
|
||||||
c.Server.Start(m)
|
|
||||||
log.Println(m.Code, "stop:", c.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
func (c *Context) Spawn(arg ...string) *Context { // {{{
|
|
||||||
s := &Context{Name: arg[0], Help: c.Help}
|
|
||||||
c.Register(s, c.Server.Spawn(s, arg...))
|
|
||||||
s.Begin()
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
func (c *Context) Post(m *Message) bool { // {{{
|
|
||||||
if c.Messages == nil {
|
|
||||||
c.Messages = make(chan *Message, c.Confi("MessageQueueSize"))
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Messages <- m
|
|
||||||
if m.Wait != nil {
|
|
||||||
return <-m.Wait
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
func (c *Context) Get() *Message { // {{{
|
|
||||||
if c.Messages == nil {
|
|
||||||
c.Messages = make(chan *Message, c.Confi("MessageQueueSize"))
|
|
||||||
}
|
|
||||||
|
|
||||||
return <-c.Messages
|
|
||||||
}
|
|
||||||
|
|
||||||
// }}}
|
|
||||||
|
|
||||||
func (c *Context) Cmd(m *Message, arg ...string) string { // {{{
|
func (c *Context) Cmd(m *Message, arg ...string) string { // {{{
|
||||||
if x, ok := c.Commands[arg[0]]; ok {
|
if x, ok := c.Commands[arg[0]]; ok {
|
||||||
return x.Hand(c, m, arg...)
|
return x.Hand(c, m, arg...)
|
||||||
@ -663,7 +714,6 @@ func (c *Context) Capi(key string, value int) int { // {{{
|
|||||||
return n + value
|
return n + value
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
var Index = &Context{Name: "ctx", Help: "根上下文",
|
var Index = &Context{Name: "ctx", Help: "根上下文",
|
||||||
@ -683,7 +733,7 @@ var Index = &Context{Name: "ctx", Help: "根上下文",
|
|||||||
"cert": &Config{Name: "cert", Value: "etc/cert.pem", Help: "证书文件"},
|
"cert": &Config{Name: "cert", Value: "etc/cert.pem", Help: "证书文件"},
|
||||||
"key": &Config{Name: "key", Value: "etc/key.pem", Help: "私钥文件"},
|
"key": &Config{Name: "key", Value: "etc/key.pem", Help: "私钥文件"},
|
||||||
|
|
||||||
"debug": &Config{Name: "debug", Value: "on", Help: "调试模式"},
|
"debug": &Config{Name: "debug", Value: "off", Help: "调试模式"},
|
||||||
"start": &Config{Name: "start", Value: "cli", Help: "默认启动模块"},
|
"start": &Config{Name: "start", Value: "cli", Help: "默认启动模块"},
|
||||||
"init.sh": &Config{Name: "init.sh", Value: "etc/init.sh", Help: "默认启动脚本"},
|
"init.sh": &Config{Name: "init.sh", Value: "etc/init.sh", Help: "默认启动脚本"},
|
||||||
"bench.log": &Config{Name: "bench.log", Value: "var/bench.log", Help: "默认日志文件", Hand: func(c *Context, arg string) string {
|
"bench.log": &Config{Name: "bench.log", Value: "var/bench.log", Help: "默认日志文件", Hand: func(c *Context, arg string) string {
|
||||||
@ -715,8 +765,35 @@ func init() {
|
|||||||
if len(os.Args) > 3 {
|
if len(os.Args) > 3 {
|
||||||
Index.Conf("start", os.Args[3])
|
Index.Conf("start", os.Args[3])
|
||||||
}
|
}
|
||||||
|
log.Println("\n\n\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start() {
|
func Start() {
|
||||||
Index.Init()
|
Pulse.Root = Pulse
|
||||||
|
Pulse.Target = Index
|
||||||
|
Pulse.Context = Index
|
||||||
|
Pulse.Wait = make(chan bool, 10)
|
||||||
|
|
||||||
|
cs := []*Context{Index}
|
||||||
|
for i := 0; i < len(cs); i++ {
|
||||||
|
cs[i].Root = Index
|
||||||
|
cs[i].Begin(nil)
|
||||||
|
|
||||||
|
for _, v := range cs[i].Contexts {
|
||||||
|
cs = append(cs, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, s := range Index.Contexts {
|
||||||
|
if ok, _ := regexp.MatchString(Index.Conf("start"), s.Name); ok {
|
||||||
|
go s.Start(Pulse.Spawn(s, s.Name).Put("detail", os.Stdout))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
<-Pulse.Wait
|
||||||
|
if Index.Capi("nserver", 0) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package tcp // {{{
|
package tcp
|
||||||
// }}}
|
|
||||||
import ( // {{{
|
import ( // {{{
|
||||||
"context"
|
"context"
|
||||||
"log"
|
"log"
|
||||||
@ -13,7 +13,7 @@ type TCP struct {
|
|||||||
*ctx.Context
|
*ctx.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tcp *TCP) Begin() ctx.Server { // {{{
|
func (tcp *TCP) Begin(m *ctx.Message) ctx.Server { // {{{
|
||||||
return tcp
|
return tcp
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,25 +26,29 @@ func (tcp *TCP) Start(m *ctx.Message) bool { // {{{
|
|||||||
l, e := net.Listen("tcp", tcp.Conf("address"))
|
l, e := net.Listen("tcp", tcp.Conf("address"))
|
||||||
tcp.Check(e)
|
tcp.Check(e)
|
||||||
tcp.listener = l
|
tcp.listener = l
|
||||||
tcp.Capi("nlisten", 1)
|
|
||||||
log.Println(tcp.Name, "listen:", l.Addr())
|
log.Printf("%s listen(%d): %v", tcp.Name, tcp.Capi("nlisten", 1), l.Addr())
|
||||||
|
defer tcp.Capi("nlisten", -1)
|
||||||
|
defer log.Println("%s close(%d): %v", tcp.Name, tcp.Capi("nlisten", 0), l.Addr())
|
||||||
|
|
||||||
for {
|
for {
|
||||||
c, e := l.Accept()
|
c, e := l.Accept()
|
||||||
log.Println(tcp.Name, "accept:", c.LocalAddr(), "<-", c.RemoteAddr())
|
|
||||||
tcp.Check(e)
|
tcp.Check(e)
|
||||||
|
log.Printf("%s accept(%d): %v<-%v", tcp.Name, tcp.Capi("nclient", 1), c.LocalAddr(), c.RemoteAddr())
|
||||||
|
// defer log.Println(tcp.Name, "close:", tcp.Capi("nclient", -1), c.LocalAddr(), "<-", c.RemoteAddr())
|
||||||
|
|
||||||
m := m.Spawn(m.Context, c.RemoteAddr().String(), 0)
|
msg := m.Spawn(m.Context, c.RemoteAddr().String()).Put("detail", c)
|
||||||
m.Add("detail", "accept", c.RemoteAddr().String(), "tcp").Put("detail", c).Cmd()
|
msg.Cmd("accept", c.RemoteAddr().String(), "tcp")
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
func (tcp *TCP) Spawn(c *ctx.Context, arg ...string) ctx.Server { // {{{
|
func (tcp *TCP) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server { // {{{
|
||||||
c.Caches = map[string]*ctx.Cache{
|
c.Caches = map[string]*ctx.Cache{
|
||||||
"nclient": &ctx.Cache{Name: "nclient", Value: "0", Help: "连接数量"},
|
"nclient": &ctx.Cache{Name: "nclient", Value: "0", Help: "连接数量"},
|
||||||
|
"status": &ctx.Cache{Name: "status", Value: "stop", Help: "服务状态"},
|
||||||
}
|
}
|
||||||
c.Configs = map[string]*ctx.Config{
|
c.Configs = map[string]*ctx.Config{
|
||||||
"address": &ctx.Config{Name: "address", Value: arg[0], Help: "监听地址"},
|
"address": &ctx.Config{Name: "address", Value: arg[0], Help: "监听地址"},
|
||||||
@ -56,6 +60,23 @@ func (tcp *TCP) Spawn(c *ctx.Context, arg ...string) ctx.Server { // {{{
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
func (tcp *TCP) Exit(m *ctx.Message, arg ...string) bool { // {{{
|
||||||
|
|
||||||
|
if c, ok := m.Data["result"].(net.Conn); ok && m.Target == tcp.Context {
|
||||||
|
c.Close()
|
||||||
|
delete(m.Data, "result")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if c, ok := m.Data["detail"].(net.Conn); ok && m.Context == tcp.Context {
|
||||||
|
c.Close()
|
||||||
|
delete(m.Data, "detail")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
var Index = &ctx.Context{Name: "tcp", Help: "网络连接",
|
var Index = &ctx.Context{Name: "tcp", Help: "网络连接",
|
||||||
@ -95,6 +116,17 @@ var Index = &ctx.Context{Name: "tcp", Help: "网络连接",
|
|||||||
return ""
|
return ""
|
||||||
// }}}
|
// }}}
|
||||||
}},
|
}},
|
||||||
|
"exit": &ctx.Command{"exit", "退出", func(c *ctx.Context, m *ctx.Message, arg ...string) string {
|
||||||
|
tcp, ok := m.Target.Server.(*TCP)
|
||||||
|
if !ok {
|
||||||
|
tcp, ok = m.Context.Server.(*TCP)
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
tcp.Context.Exit(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
_ "context/cli"
|
_ "context/cli"
|
||||||
_ "context/tcp"
|
_ "context/tcp"
|
||||||
// _ "context/ssh"
|
|
||||||
// _ "context/web"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user