1
0
forked from x/ContextOS

mac mod message.ccc 将模块的操作接口移动消息上

This commit is contained in:
shaoying 2017-11-13 08:45:10 +08:00
parent c293a1bd95
commit 954dd13717
3 changed files with 323 additions and 286 deletions

View File

@ -1,6 +1,7 @@
~aaa # @debug on
login root 94ca7394d007fa189cc4be0a2625d716 root # ~aaa
login root root # login root 94ca7394d007fa189cc4be0a2625d716 root
# login root root
~cli #
remote slave listen :9393 tcp # ~cli
# remote slave listen :9393 tcp

View File

@ -46,7 +46,7 @@ func (cli *CLI) push(f io.ReadCloser) { // {{{
// }}} // }}}
func (cli *CLI) parse(m *ctx.Message) bool { // {{{ func (cli *CLI) parse(m *ctx.Message) bool { // {{{
if len(cli.ins) == 1 && cli.Owner == nil { if false && len(cli.ins) == 1 && cli.Owner == nil {
username := "" username := ""
fmt.Fprintf(cli.out, "username>") fmt.Fprintf(cli.out, "username>")
@ -69,12 +69,12 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{
} }
cli.Owner = msg.Target cli.Owner = msg.Target
cli.Cap("user", msg.Target.Cap("username")) m.Cap("user", msg.Cap("username"))
} }
} }
if len(cli.ins) == 1 || cli.Conf("slient") != "yes" { if len(cli.ins) == 1 || m.Conf("slient") != "yes" {
cli.echo(cli.Conf("PS1")) cli.echo(m.Conf("PS1"))
} }
line := "" line := ""
@ -95,10 +95,10 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{
return true return true
} }
} }
cli.Assert(e) m.Assert(e)
line = ls line = ls
if len(cli.ins) > 1 || cli.Conf("slient") != "yes" { if len(cli.ins) > 1 || m.Conf("slient") != "yes" {
cli.echo(line) cli.echo(line)
} }
@ -113,7 +113,7 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{
line = cli.next line = cli.next
cli.next = "" cli.next = ""
if cli.Conf("slient") != "yes" { if m.Conf("slient") != "yes" {
cli.echo(line) cli.echo(line)
cli.echo("\n") cli.echo("\n")
} }
@ -174,9 +174,9 @@ back:
// }}} // }}}
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 || m.Conf("slient") != "yes" {
fmt.Fprintf(cli.out, str, arg...) fmt.Fprintf(cli.out, str, arg...)
} // }
} }
// }}} // }}}
@ -194,7 +194,7 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
cli.target = cli.Context cli.target = cli.Context
cli.Caches["nhistory"] = &ctx.Cache{Name: "历史命令数量", Value: "0", Help: "当前终端已经执行命令的数量", Hand: func(c *ctx.Context, x *ctx.Cache, arg ...string) string { cli.Caches["nhistory"] = &ctx.Cache{Name: "历史命令数量", Value: "0", Help: "当前终端已经执行命令的数量", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string {
x.Value = fmt.Sprintf("%d", len(cli.history)) x.Value = fmt.Sprintf("%d", len(cli.history))
return x.Value return x.Value
}} }}
@ -205,14 +205,14 @@ func (cli *CLI) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
// }}} // }}}
func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
cli.Owner = nil cli.Owner = nil
cli.Capi("nterm", 1) m.Capi("nterm", 1)
defer cli.Capi("nterm", -1) defer m.Capi("nterm", -1)
if cli.Messages == nil { if cli.Messages == nil {
cli.Messages = make(chan *ctx.Message, cli.Confi("MessageQueueSize")) cli.Messages = make(chan *ctx.Message, m.Confi("MessageQueueSize"))
} }
if len(arg) > 0 { if len(arg) > 0 {
cli.Conf("init.sh", "启动脚本", arg[0], "模块启动时自动运行的脚本") m.Conf("init.sh", "启动脚本", arg[0], "模块启动时自动运行的脚本")
} }
if stream, ok := m.Data["io"]; ok { if stream, ok := m.Data["io"]; ok {
@ -220,7 +220,7 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
cli.out = io cli.out = io
cli.push(io) cli.push(io)
if f, e := os.Open(cli.Conf("init.sh")); e == nil { if f, e := os.Open(m.Conf("init.sh")); e == nil {
cli.push(f) cli.push(f)
} }
@ -232,7 +232,7 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
}) })
} }
for cli.Deal(func(msg *ctx.Message, arg ...string) bool { for m.Deal(func(msg *ctx.Message, arg ...string) bool {
if a, ok := cli.alias[arg[0]]; ok { if a, ok := cli.alias[arg[0]]; ok {
arg[0] = a arg[0] = a
} }
@ -273,7 +273,7 @@ func (cli *CLI) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server
// }}} // }}}
func (cli *CLI) Exit(m *ctx.Message, arg ...string) bool { // {{{ func (cli *CLI) Exit(m *ctx.Message, arg ...string) bool { // {{{
if cli.Context != Index { if cli.Context != Index {
delete(cli.Context.Context.Contexts, cli.Name) // delete(cli.Context.Context.Contexts, cli.Name)
} }
return true return true
} }
@ -291,15 +291,15 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
// "hello": &ctx.Config{Name: "开场白", Value: "\n~~~ Hello Context & Message World ~~~\n", Help: "模块启动时输出的信息"}, // "hello": &ctx.Config{Name: "开场白", Value: "\n~~~ Hello Context & Message World ~~~\n", Help: "模块启动时输出的信息"},
// "byebye": &ctx.Config{Name: "结束语", Value: "\n~~~ Byebye Context & Message World ~~~\n", Help: "模块停止时输出的信息"}, // "byebye": &ctx.Config{Name: "结束语", Value: "\n~~~ Byebye Context & Message World ~~~\n", Help: "模块停止时输出的信息"},
"PS1": &ctx.Config{Name: "命令行提示符(target/detail)", Value: "target", Help: "命令行提示符target:显示当前模块detail:显示详细信息", Hand: func(c *ctx.Context, x *ctx.Config, arg ...string) string { "PS1": &ctx.Config{Name: "命令行提示符(target/detail)", Value: "target", Help: "命令行提示符target:显示当前模块detail:显示详细信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string {
cli, ok := c.Server.(*CLI) // {{{ cli, ok := m.Target.Server.(*CLI) // {{{
if ok && cli.target != nil { if ok && cli.target != nil {
// c = cli.target // c = cli.target
switch x.Value { switch x.Value {
case "target": case "target":
return fmt.Sprintf("%s[%s]\033[32m%s\033[0m> ", c.Cap("nhistory"), time.Now().Format("15:04:05"), cli.target.Name) return fmt.Sprintf("%s[%s]\033[32m%s\033[0m> ", m.Cap("nhistory"), time.Now().Format("15:04:05"), cli.target.Name)
case "detail": case "detail":
return fmt.Sprintf("%s[%s](%s,%s,%s)\033[32m%s\033[0m> ", c.Cap("nhistory"), time.Now().Format("15:04:05"), c.Cap("ncontext"), c.Cap("nmessage"), c.Cap("nserver"), c.Name) return fmt.Sprintf("%s[%s](%s,%s,%s)\033[32m%s\033[0m> ", m.Cap("nhistory"), time.Now().Format("15:04:05"), m.Cap("ncontext"), m.Cap("nmessage"), m.Cap("nserver"), m.Target.Name)
} }
} }
@ -310,7 +310,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
}, },
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
"context": &ctx.Command{Name: "context [root|back|home] [[find|search] name] [show|spawn|start|switch][args]", Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块args:启动参数", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string { "context": &ctx.Command{Name: "context [root|back|home] [[find|search] name] [show|spawn|start|switch][args]", Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块args:启动参数", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
cli, ok := m.Context.Server.(*CLI) // {{{ cli, ok := m.Source.Server.(*CLI) // {{{
if !ok { if !ok {
cli, ok = c.Server.(*CLI) cli, ok = c.Server.(*CLI)
if !ok { if !ok {
@ -321,7 +321,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
switch len(arg) { switch len(arg) {
case 0: case 0:
m.Target.Root.Travel(func(c *ctx.Context) bool { m.Target.Root.Travel(func(c *ctx.Context) bool {
if c.Context != nil && m.Context.Check(c) { if c.Context != nil && m.Source.Check(c) {
m.Echo("%s: %s(%s)\n", c.Context.Name, c.Name, c.Help) m.Echo("%s: %s(%s)\n", c.Context.Name, c.Name, c.Help)
} }
return true return true
@ -330,7 +330,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
} }
target := m.Target target := m.Target
switch c.Conf("default") { switch m.Conf("default") {
case "root": case "root":
target = target.Root target = target.Root
case "back": case "back":
@ -388,7 +388,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
} }
for _, v := range cs { for _, v := range cs {
if !m.Context.Check(v) { if !m.Source.Check(v) {
continue continue
} }
@ -409,7 +409,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
} }
m.Echo("索引模块:\n") m.Echo("索引模块:\n")
for i, v := range v.Requests { for i, v := range v.Requests {
m.Echo("\t%d(%d): %s %s\n", i, v.Code, v.Context.Name, v.Context.Help) m.Echo("\t%d(%d): %s %s\n", i, v.Code, v.Source.Name, v.Source.Help)
} }
} }
} }
@ -420,7 +420,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
"message": &ctx.Command{Name: "message", Help: "查看上下文", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string { "message": &ctx.Command{Name: "message", Help: "查看上下文", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
ms := []*ctx.Message{ctx.Pulse} // {{{ ms := []*ctx.Message{ctx.Pulse} // {{{
for i := 0; i < len(ms); i++ { for i := 0; i < len(ms); i++ {
m.Echo("%d %s.%s -> %s.%d: %s %v\n", ms[i].Code, ms[i].Context.Name, ms[i].Name, ms[i].Target.Name, ms[i].Index, ms[i].Time.Format("15:04:05"), ms[i].Meta["detail"]) m.Echo("%d %s.%s -> %s.%d: %s %v\n", ms[i].Code, ms[i].Source.Name, ms[i].Name, ms[i].Target.Name, ms[i].Index, ms[i].Time.Format("15:04:05"), ms[i].Meta["detail"])
ms = append(ms, ms[i].Messages...) ms = append(ms, ms[i].Messages...)
} }
return "" return ""
@ -455,7 +455,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
switch len(arg) { switch len(arg) {
case 1: case 1:
f, e := os.Open(arg[0]) f, e := os.Open(arg[0])
c.Assert(e) m.Assert(e)
cli.push(f) cli.push(f)
} }
@ -555,16 +555,16 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
switch arg[0] { switch arg[0] {
case "void": case "void":
s.Conf(arg[1], "") m.Conf(arg[1], "")
case "delete": case "delete":
if _, ok := s.Configs[arg[1]]; ok { if _, ok := s.Configs[arg[1]]; ok {
delete(s.Configs, arg[1]) delete(s.Configs, arg[1])
} }
default: default:
s.Conf(arg[0], arg[1]) m.Conf(arg[0], arg[1])
} }
case 4: case 4:
s.Conf(arg[0], arg[1:]...) m.Conf(arg[0], arg[1:]...)
return false return false
} }
return all return all
@ -601,11 +601,11 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
} }
default: default:
if _, ok := s.Caches[arg[0]]; ok { if _, ok := s.Caches[arg[0]]; ok {
m.Echo("%s: %s\n", arg[0], s.Cap(arg[0], arg[1:]...)) m.Echo("%s: %s\n", arg[0], m.Cap(arg[0], arg[1:]...))
} }
} }
case 4: case 4:
s.Cap(arg[0], arg[1:]...) m.Cap(arg[0], arg[1:]...)
return false return false
} }
@ -625,7 +625,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
"exit": &ctx.Command{Name: "exit", Help: "退出", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string { "exit": &ctx.Command{Name: "exit", Help: "退出", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
cli, ok := m.Target.Server.(*CLI) // {{{ cli, ok := m.Target.Server.(*CLI) // {{{
if !ok { if !ok {
cli, ok = m.Context.Server.(*CLI) cli, ok = m.Source.Server.(*CLI)
} }
if ok { if ok {
if !cli.exit { if !cli.exit {
@ -663,7 +663,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
Options: map[string]string{"io": "读写流"}, Options: map[string]string{"io": "读写流"},
Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string { // {{{ Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string { // {{{
if m.Has("io") { if m.Has("io") {
m.Start(fmt.Sprintf("PTS%d", c.Capi("nterm")), arg[1]) m.Start(fmt.Sprintf("PTS%d", m.Capi("nterm")), arg[1])
} else { } else {
switch arg[1] { switch arg[1] {
case "tcp": case "tcp":

View File

@ -17,23 +17,21 @@ import ( // {{{
// }}} // }}}
type Cache struct { // {{{ type Cache struct {
Name string Name string
Value string Value string
Help string Help string
Hand func(c *Context, x *Cache, arg ...string) string Hand func(m *Message, x *Cache, arg ...string) string
} }
// }}} type Config struct {
type Config struct { // {{{
Name string Name string
Value string Value string
Help string Help string
Hand func(c *Context, x *Config, arg ...string) string Hand func(m *Message, x *Config, arg ...string) string
} }
// }}} type Command struct {
type Command struct { // {{{
Name string Name string
Help string Help string
Options map[string]string Options map[string]string
@ -41,8 +39,6 @@ type Command struct { // {{{
Hand func(c *Context, m *Message, key string, arg ...string) string Hand func(c *Context, m *Message, key string, arg ...string) string
} }
// }}}
type Message struct { type Message struct {
Code int Code int
Time time.Time Time time.Time
@ -51,10 +47,11 @@ type Message struct {
Data map[string]interface{} Data map[string]interface{}
Wait chan bool Wait chan bool
Name string
*Context
Index int Index int
Target *Context Target *Context
Master *Context
Source *Context
Name string
Messages []*Message Messages []*Message
Message *Message Message *Message
@ -82,10 +79,11 @@ func (m *Message) Spawn(c *Context, key ...string) *Message { // {{{
msg := &Message{ msg := &Message{
Time: time.Now(), Time: time.Now(),
Target: c, Target: c,
Master: c,
Message: m, Message: m,
Root: m.Root, Root: m.Root,
} }
msg.Context = m.Target msg.Source = m.Target
if len(key) == 0 { if len(key) == 0 {
return msg return msg
@ -97,13 +95,13 @@ func (m *Message) Spawn(c *Context, key ...string) *Message { // {{{
m.Messages = append(m.Messages, msg) m.Messages = append(m.Messages, msg)
msg.Code = m.Capi("nmessage", 1) msg.Code = m.Capi("nmessage", 1)
if msg.Sessions == nil { if msg.Source.Sessions == nil {
msg.Sessions = make(map[string]*Message) msg.Source.Sessions = make(map[string]*Message)
} }
msg.Sessions[key[0]] = msg msg.Source.Sessions[key[0]] = msg
msg.Name = key[0] msg.Name = key[0]
log.Printf("%d spawn %d: %s.%s->%s.%d", m.Code, msg.Code, msg.Context.Name, msg.Name, msg.Target.Name, msg.Index) log.Printf("%d spawn %d: %s.%s->%s.%d", m.Code, msg.Code, msg.Source.Name, msg.Name, msg.Target.Name, msg.Index)
return msg return msg
} }
@ -204,6 +202,38 @@ func (m *Message) End(s bool) { // {{{
// }}} // }}}
func (m *Message) Check(s *Context, arg ...string) bool { // {{{
if m.Source.Owner != s.Owner && m.Source.Owner != s.Root.Owner {
if len(arg) != 2 {
return false
}
g, ok := s.Index[m.Source.Group]
if !ok {
if g, ok = s.Index["void"]; !ok {
return false
}
}
switch arg[0] {
case "commands":
_, ok = g.Commands[arg[0]]
case "configs":
_, ok = g.Configs[arg[0]]
case "caches":
_, ok = g.Caches[arg[0]]
}
if !ok {
return false
}
}
return true
}
// }}}
func (m *Message) Start(key string, arg ...string) bool { // {{{ func (m *Message) Start(key string, arg ...string) bool { // {{{
if len(arg) > 0 { if len(arg) > 0 {
if m.Meta == nil { if m.Meta == nil {
@ -246,21 +276,197 @@ func (m *Message) Cmd(arg ...string) string { // {{{
} }
m.Meta["detail"] = arg m.Meta["detail"] = arg
} }
arg = m.Meta["detail"]
return m.Target.Cmd(m, m.Meta["detail"][0], m.Meta["detail"][1:]...) if m.Code != 0 {
log.Printf("%d cmd(%s:%s->%s.%d): %v", m.Code, m.Source.Name, m.Name, m.Master.Name, m.Index, arg)
} else {
log.Printf("%d cmd(%s->%s): %v", m.Code, m.Source.Name, m.Master.Name, arg)
}
for s := m.Master; s != nil; s = s.Context {
if !m.Check(s, "commands", arg[0]) {
panic(errors.New(fmt.Sprintf("没有权限:" + arg[0])))
}
if x, ok := s.Commands[arg[0]]; ok {
if x.Options != nil {
for _, v := range m.Meta["option"] {
if _, ok := x.Options[v]; !ok {
panic(errors.New(fmt.Sprintf("未知参数:" + v)))
}
}
}
m.Meta["result"] = nil
m.Master.AssertOne(m, true, func(c *Context, m *Message) {
ret := x.Hand(c, m, arg[0], arg[1:]...)
if ret != "" {
m.Echo(ret)
}
})
if x.Appends != nil {
for _, v := range m.Meta["append"] {
if _, ok := x.Appends[v]; !ok {
panic(errors.New(fmt.Sprintf("未知参数:" + v)))
}
}
}
return m.Get("result")
}
}
panic(errors.New(fmt.Sprintf("未知命令:" + arg[0])))
}
// }}}
func (m *Message) Conf(key string, arg ...string) string { // {{{
for s := m.Target; s != nil; s = s.Context {
if !m.Check(s, "configs", key) {
panic(errors.New(fmt.Sprintf("没有权限:" + key)))
}
if x, ok := s.Configs[key]; ok {
switch len(arg) {
case 0:
if x.Hand != nil {
return x.Hand(m, x)
}
return x.Value
case 1:
if m.Code != 0 {
log.Printf("%d conf(%s:%s->%s.%d): %s %v", m.Code, m.Source.Name, m.Name, m.Master.Name, m.Index, key, arg)
} else {
log.Printf("%d conf(%s->%s): %s %v", m.Code, m.Source.Name, m.Master.Name, key, arg)
}
x.Value = arg[0]
if x.Hand != nil {
x.Hand(m, x, x.Value)
}
return x.Value
case 3:
if m.Code != 0 {
log.Printf("%d conf(%s:%s->%s.%d): %s %v", m.Code, m.Source.Name, m.Name, m.Master.Name, m.Index, key, arg)
} else {
log.Printf("%d conf(%s->%s): %s %v", m.Code, m.Source.Name, m.Master.Name, key, arg)
}
if s == m.Target {
panic(errors.New(key + "配置项已存在"))
}
if m.Target.Configs == nil {
m.Target.Configs = make(map[string]*Config)
}
m.Target.Configs[key] = &Config{Name: arg[0], Value: arg[1], Help: arg[2], Hand: x.Hand}
return arg[1]
default:
panic(errors.New(key + "配置项参数错误"))
}
}
}
if len(arg) == 3 {
log.Println(m.Target.Name, "conf:", key, arg)
if m.Target.Configs == nil {
m.Target.Configs = make(map[string]*Config)
}
m.Target.Configs[key] = &Config{Name: arg[0], Value: arg[1], Help: arg[2]}
return arg[1]
}
panic(errors.New(key + "配置项不存在"))
}
// }}}
func (m *Message) Confi(key string, arg ...int) int { // {{{
if len(arg) > 0 {
n, e := strconv.Atoi(m.Conf(key, fmt.Sprintf("%d", arg[0])))
m.Assert(e)
return n
}
n, e := strconv.Atoi(m.Conf(key))
m.Assert(e)
return n
}
// }}}
func (m *Message) Cap(key string, arg ...string) string { // {{{
// if m.Code != 0 {
// log.Printf("%d cap(%s:%s->%s.%d): %s %v", m.Code, m.Context.Name, m.Name, m.Master.Name, m.Index, key, arg)
// } else {
// log.Printf("%d cap(%s->%s): %s %v", m.Code, m.Context.Name, m.Master.Name, key, arg)
// }
//
for s := m.Target; s != nil; s = s.Context {
if !m.Check(s, "caches", key) {
panic(errors.New(fmt.Sprintf("没有权限:" + key)))
}
if x, ok := s.Caches[key]; ok {
switch len(arg) {
case 0:
if x.Hand != nil {
x.Value = x.Hand(m, x)
}
return x.Value
case 1:
if x.Hand != nil {
x.Value = x.Hand(m, x, arg[0])
} else {
x.Value = arg[0]
}
return x.Value
case 3:
log.Println(m.Target.Name, "cap:", key, arg)
if s == m.Target {
panic(errors.New(key + "缓存项已存在"))
}
if m.Target.Caches == nil {
m.Target.Caches = make(map[string]*Cache)
}
m.Target.Caches[key] = &Cache{arg[0], arg[1], arg[2], x.Hand}
return arg[1]
default:
panic(errors.New(key + "缓存项参数错误"))
}
}
}
if len(arg) == 3 {
log.Println(m.Target.Name, "cap:", key, arg)
if m.Target.Caches == nil {
m.Target.Caches = make(map[string]*Cache)
}
m.Target.Caches[key] = &Cache{arg[0], arg[1], arg[2], nil}
return arg[1]
}
panic(errors.New(key + "缓存项不存在"))
}
// }}}
func (m *Message) Capi(key string, arg ...int) int { // {{{
n, e := strconv.Atoi(m.Cap(key))
m.Assert(e)
if len(arg) > 0 {
n += arg[0]
m.Cap(key, strconv.Itoa(n))
}
return n
} }
// }}} // }}}
type Server interface { // {{{ type Server interface {
Begin(m *Message, arg ...string) Server Begin(m *Message, arg ...string) Server
Start(m *Message, arg ...string) bool Start(m *Message, arg ...string) bool
Spawn(c *Context, m *Message, arg ...string) Server Spawn(c *Context, m *Message, arg ...string) Server
Exit(m *Message, arg ...string) bool Exit(m *Message, arg ...string) bool
} }
// }}}
type Context struct { type Context struct {
Name string Name string
Help string Help string
@ -277,31 +483,20 @@ type Context struct {
Sessions map[string]*Message Sessions map[string]*Message
Owner *Context Owner *Context
Group string
Index map[string]*Context Index map[string]*Context
Groups map[string]*Context Groups map[string]*Context
Contexts map[string]*Context contexts map[string]*Context
Context *Context Context *Context
Root *Context Root *Context
} }
func (c *Context) Assert(e error) bool { // {{{
if e != nil {
log.Println(c.Name, "error:", e)
if c.Conf("debug") == "on" {
fmt.Println(c.Name, "error:", e)
}
panic(e)
}
return true
}
// }}}
func (c *Context) AssertOne(m *Message, safe bool, hand ...func(c *Context, m *Message)) *Context { // {{{ func (c *Context) AssertOne(m *Message, safe bool, hand ...func(c *Context, m *Message)) *Context { // {{{
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
log.Println(c.Name, e) log.Println(c.Name, e)
if c.Conf("debug") == "on" && e != io.EOF { if m.Conf("debug") == "on" && e != io.EOF {
fmt.Println(c.Name, "error:", e) fmt.Println(c.Name, "error:", e)
debug.PrintStack() debug.PrintStack()
} }
@ -332,27 +527,28 @@ func (c *Context) AssertOne(m *Message, safe bool, hand ...func(c *Context, m *M
// }}} // }}}
func (c *Context) Register(s *Context, x Server) *Context { // {{{ func (c *Context) Register(s *Context, x Server) *Context { // {{{
if c.Contexts == nil {
c.Contexts = make(map[string]*Context) if c.contexts == nil {
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.Root = c.Root s.Root = c.Root
s.Context = c s.Context = c
s.Server = x s.Server = x
log.Printf("%s sub(%d): %s", c.Name, Index.Capi("ncontext", 1), s.Name) log.Printf("%s sub(%d): %s", c.Name, Pulse.Capi("ncontext", 1), s.Name)
return s return s
} }
// }}} // }}}
func (c *Context) Begin(m *Message) *Context { // {{{ func (c *Context) Begin(m *Message) *Context { // {{{
for k, x := range c.Configs { for k, x := range m.Target.Configs {
if x.Hand != nil { if x.Hand != nil {
c.Conf(k, x.Value) m.Conf(k, x.Value)
} }
} }
@ -374,16 +570,16 @@ func (c *Context) Start(m *Message) bool { // {{{
c.Caches["status"] = &Cache{Name: "服务状态", Value: "stop", Help: "服务状态start:正在运行stop:未在运行"} c.Caches["status"] = &Cache{Name: "服务状态", Value: "stop", Help: "服务状态start:正在运行stop:未在运行"}
} }
if c.Cap("status") != "start" && c.Server != nil { if m.Cap("status") != "start" && c.Server != nil {
c.AssertOne(m, true, func(c *Context, m *Message) { c.AssertOne(m, true, func(c *Context, m *Message) {
c.Cap("status", "start") m.Cap("status", "start")
defer c.Cap("status", "stop") defer m.Cap("status", "stop")
log.Printf("%d start(%d): %s %s", m.Code, Index.Capi("nserver", 1), c.Name, c.Help) log.Printf("%d start(%d): %s %s", m.Code, Pulse.Capi("nserver", 1), c.Name, c.Help)
defer Index.Capi("nserver", -1) defer Pulse.Capi("nserver", -1)
defer log.Printf("%d stop(%s): %s %s", m.Code, Index.Cap("nserver"), c.Name, c.Help) defer log.Printf("%d stop(%s): %s %s", m.Code, Pulse.Cap("nserver"), c.Name, c.Help)
c.Owner = m.Owner c.Owner = m.Source.Owner
c.Requests = []*Message{m} c.Requests = []*Message{m}
c.Server.Start(m, m.Meta["detail"]...) c.Server.Start(m, m.Meta["detail"]...)
}) })
@ -407,12 +603,12 @@ func (c *Context) Spawn(m *Message, key string) *Context { // {{{
// }}} // }}}
func (c *Context) Deal(pre func(m *Message, arg ...string) bool, post func(m *Message, arg ...string) bool) (live bool) { // {{{ func (msg *Message) Deal(pre func(m *Message, arg ...string) bool, post func(m *Message, arg ...string) bool) (live bool) { // {{{
if c.Messages == nil { if msg.Target.Messages == nil {
c.Messages = make(chan *Message, c.Confi("MessageQueueSize")) msg.Target.Messages = make(chan *Message, msg.Confi("MessageQueueSize"))
} }
m := <-c.Messages m := <-msg.Target.Messages
defer m.End(true) defer m.End(true)
if len(m.Meta["detail"]) == 0 { if len(m.Meta["detail"]) == 0 {
@ -424,14 +620,15 @@ func (c *Context) Deal(pre func(m *Message, arg ...string) bool, post func(m *Me
} }
arg := m.Meta["detail"] arg := m.Meta["detail"]
c.AssertOne(m, true, func(c *Context, m *Message) { msg.Target.AssertOne(m, true, func(c *Context, m *Message) {
m.Cmd() m.Cmd()
}, func(c *Context, m *Message) { }, func(c *Context, m *Message) {
c.Cmd(m, arg[0], arg[1:]...) m.Master = c
m.Cmd()
}, func(c *Context, m *Message) { }, func(c *Context, m *Message) {
log.Printf("system command(%s->%s): %v", m.Context.Name, m.Target.Name, arg) log.Printf("system command(%s->%s): %v", m.Source.Name, m.Target.Name, arg)
cmd := exec.Command(arg[0], arg[1:]...) cmd := exec.Command(arg[0], arg[1:]...)
v, e := cmd.CombinedOutput() v, e := cmd.CombinedOutput()
if e != nil { if e != nil {
@ -455,7 +652,7 @@ func (c *Context) Exit(m *Message, arg ...string) { // {{{
if m.Target == c { if m.Target == c {
if m.Index == -1 { if m.Index == -1 {
log.Println(c.Name, c.Help, "exit: resource", m.Code, m.Context.Name, m.Context.Help) log.Println(c.Name, c.Help, "exit: resource", m.Code, m.Source.Name, m.Source.Help)
if c.Server != nil { if c.Server != nil {
c.Server.Exit(m, arg...) c.Server.Exit(m, arg...)
log.Println(c.Name, c.Help, "exit: self", m.Code) log.Println(c.Name, c.Help, "exit: self", m.Code)
@ -480,11 +677,11 @@ func (c *Context) Exit(m *Message, arg ...string) { // {{{
for _, v := range c.Requests { for _, v := range c.Requests {
if v.Index != -1 { if v.Index != -1 {
v.Index = -1 v.Index = -1
v.Context.Exit(v, arg...) v.Source.Exit(v, arg...)
log.Println(c.Name, c.Help, "exit: resource", v.Code, v.Context.Name, v.Context.Help) log.Println(c.Name, c.Help, "exit: resource", v.Code, v.Source.Name, v.Source.Help)
} }
} }
} else if m.Context == c { } else if m.Source == c {
m.Name = "" m.Name = ""
log.Println(c.Name, c.Help, "exit: session", m.Code, m.Target.Name, m.Target.Help) log.Println(c.Name, c.Help, "exit: session", m.Code, m.Target.Name, m.Target.Help)
if c.Server != nil { if c.Server != nil {
@ -680,7 +877,7 @@ func (c *Context) Check(s *Context) bool { // {{{
func (c *Context) Travel(hand func(s *Context) bool) { // {{{ func (c *Context) Travel(hand func(s *Context) bool) { // {{{
cs := []*Context{c} cs := []*Context{c}
for i := 0; i < len(cs); i++ { for i := 0; i < len(cs); i++ {
for _, v := range cs[i].Contexts { for _, v := range cs[i].contexts {
cs = append(cs, v) cs = append(cs, v)
} }
@ -716,10 +913,10 @@ func (c *Context) Search(name string) []*Context { // {{{
// }}} // }}}
func (c *Context) Find(name string) (s *Context) { // {{{ func (c *Context) Find(name string) (s *Context) { // {{{
ns := strings.Split(name, ".") ns := strings.Split(name, ".")
cs := c.Contexts cs := c.contexts
for _, v := range ns { for _, v := range ns {
if x, ok := cs[v]; ok { if x, ok := cs[v]; ok {
cs = x.Contexts cs = x.contexts
s = x s = x
} else { } else {
panic(errors.New(c.Name + " not find: " + name)) panic(errors.New(c.Name + " not find: " + name))
@ -730,168 +927,7 @@ func (c *Context) Find(name string) (s *Context) { // {{{
// }}} // }}}
func (c *Context) Cmd(m *Message, key string, arg ...string) string { // {{{ var Pulse = &Message{Code: 1, Time: time.Now(), Index: 0, Target: Index, Master: Index, Source: Index, Name: "ctx"}
if m.Meta == nil {
m.Meta = make(map[string][]string)
}
m.Meta["detail"] = nil
m.Add("detail", key, arg...)
for s := c; s != nil; s = s.Context {
if x, ok := s.Commands[key]; ok {
log.Printf("%s cmd(%s->%s): %v", c.Name, m.Context.Name, m.Target.Name, m.Meta["detail"])
if !m.Context.Check(m.Target) {
log.Printf("没有权限:")
return ""
}
for _, v := range m.Meta["option"] {
if _, ok := x.Options[v]; !ok {
panic(errors.New(fmt.Sprintf("未知参数:" + v)))
}
}
m.Meta["result"] = nil
c.AssertOne(m, true, func(c *Context, m *Message) {
ret := x.Hand(c, m, key, arg...)
if ret != "" {
m.Echo(ret)
}
})
if x.Appends != nil {
for _, v := range m.Meta["append"] {
if _, ok := x.Appends[v]; !ok {
panic(errors.New(fmt.Sprintf("未知参数:" + v)))
}
}
}
return m.Get("result")
}
}
panic(errors.New(fmt.Sprintf("未知命令:" + key)))
}
// }}}
func (c *Context) Conf(key string, arg ...string) string { // {{{
for s := c; s != nil; s = s.Context {
if x, ok := s.Configs[key]; ok {
switch len(arg) {
case 0:
if x.Hand != nil {
return x.Hand(c, x)
}
return x.Value
case 1:
log.Println(c.Name, "conf:", key, arg[0])
x.Value = arg[0]
if x.Hand != nil {
x.Hand(c, x, x.Value)
}
return x.Value
case 3:
log.Println(c.Name, "conf:", key, arg)
if s == c {
panic(errors.New(key + "配置项已存在"))
}
if c.Configs == nil {
c.Configs = make(map[string]*Config)
}
c.Configs[key] = &Config{Name: arg[0], Value: arg[1], Help: arg[2], Hand: x.Hand}
return arg[1]
default:
panic(errors.New(key + "配置项参数错误"))
}
}
}
if len(arg) == 3 {
log.Println(c.Name, "conf:", key, arg)
if c.Configs == nil {
c.Configs = make(map[string]*Config)
}
c.Configs[key] = &Config{Name: arg[0], Value: arg[1], Help: arg[2]}
return arg[1]
}
panic(errors.New(key + "配置项不存在"))
}
// }}}
func (c *Context) Confi(key string, arg ...int) int { // {{{
if len(arg) > 0 {
n, e := strconv.Atoi(c.Conf(key, fmt.Sprintf("%d", arg[0])))
c.Assert(e)
return n
}
n, e := strconv.Atoi(c.Conf(key))
c.Assert(e)
return n
}
// }}}
func (c *Context) Cap(key string, arg ...string) string { // {{{
for s := c; s != nil; s = s.Context {
if x, ok := s.Caches[key]; ok {
switch len(arg) {
case 0:
if x.Hand != nil {
x.Value = x.Hand(c, x)
}
return x.Value
case 1:
if x.Hand != nil {
x.Value = x.Hand(c, x, arg[0])
} else {
x.Value = arg[0]
}
return x.Value
case 3:
log.Println(c.Name, "cap:", key, arg)
if s == c {
panic(errors.New(key + "缓存项已存在"))
}
if c.Caches == nil {
c.Caches = make(map[string]*Cache)
}
c.Caches[key] = &Cache{arg[0], arg[1], arg[2], x.Hand}
return arg[1]
default:
panic(errors.New(key + "缓存项参数错误"))
}
}
}
if len(arg) == 3 {
log.Println(c.Name, "cap:", key, arg)
if c.Caches == nil {
c.Caches = make(map[string]*Cache)
}
c.Caches[key] = &Cache{arg[0], arg[1], arg[2], nil}
return arg[1]
}
panic(errors.New(key + "缓存项不存在"))
}
// }}}
func (c *Context) Capi(key string, arg ...int) int { // {{{
n, e := strconv.Atoi(c.Cap(key))
c.Assert(e)
if len(arg) > 0 {
n += arg[0]
c.Cap(key, strconv.Itoa(n))
}
return n
}
// }}}
var Pulse = &Message{Code: 1, Time: time.Now(), Name: "ctx", Index: 0}
var Index = &Context{Name: "ctx", Help: "根模块", var Index = &Context{Name: "ctx", Help: "根模块",
Caches: map[string]*Cache{ Caches: map[string]*Cache{
@ -902,7 +938,7 @@ var Index = &Context{Name: "ctx", Help: "根模块",
Configs: map[string]*Config{ Configs: map[string]*Config{
"start": &Config{Name: "启动模块", Value: "cli", Help: "启动时自动运行的模块"}, "start": &Config{Name: "启动模块", Value: "cli", Help: "启动时自动运行的模块"},
"init.sh": &Config{Name: "启动脚本", Value: "etc/init.sh", Help: "模块启动时自动运行的脚本"}, "init.sh": &Config{Name: "启动脚本", Value: "etc/init.sh", Help: "模块启动时自动运行的脚本"},
"bench.log": &Config{Name: "日志文件", Value: "var/bench.log", Help: "模块日志输出的文件", Hand: func(c *Context, x *Config, arg ...string) string { "bench.log": &Config{Name: "日志文件", Value: "var/bench.log", Help: "模块日志输出的文件", Hand: func(m *Message, x *Config, arg ...string) string {
if len(arg) > 0 { // {{{ if len(arg) > 0 { // {{{
if e := os.MkdirAll(path.Dir(arg[0]), os.ModePerm); e == nil { if e := os.MkdirAll(path.Dir(arg[0]), os.ModePerm); e == nil {
if l, e := os.Create(x.Value); e == nil { if l, e := os.Create(x.Value); e == nil {
@ -913,11 +949,11 @@ var Index = &Context{Name: "ctx", Help: "根模块",
return x.Value return x.Value
// }}} // }}}
}}, }},
"root": &Config{Name: "工作目录", Value: ".", Help: "所有模块的当前目录", Hand: func(c *Context, x *Config, arg ...string) string { "root": &Config{Name: "工作目录", Value: ".", Help: "所有模块的当前目录", Hand: func(m *Message, x *Config, arg ...string) string {
if len(arg) > 0 { // {{{ if len(arg) > 0 { // {{{
if !path.IsAbs(x.Value) { if !path.IsAbs(x.Value) {
wd, e := os.Getwd() wd, e := os.Getwd()
c.Assert(e) m.Assert(e)
x.Value = path.Join(wd, x.Value) x.Value = path.Join(wd, x.Value)
} }
@ -945,56 +981,56 @@ var Index = &Context{Name: "ctx", Help: "根模块",
}, },
Commands: map[string]*Command{ Commands: map[string]*Command{
"show": &Command{Name: "输出简单的信息", Help: "建立远程连接", Hand: func(c *Context, m *Message, key string, arg ...string) string { "show": &Command{Name: "输出简单的信息", Help: "建立远程连接", Hand: func(c *Context, m *Message, key string, arg ...string) string {
m.Echo("nserver: %s\n", c.Cap("nserver")) // {{{ m.Echo("nserver: %s\n", m.Cap("nserver")) // {{{
m.Echo("ncontext: %s\n", c.Cap("ncontext")) m.Echo("ncontext: %s\n", m.Cap("ncontext"))
m.Echo("nmessage: %s\n", c.Cap("nmessage")) m.Echo("nmessage: %s\n", m.Cap("nmessage"))
return "" return ""
// }}} // }}}
}}, }},
}, },
Requests: []*Message{Pulse},
Sessions: map[string]*Message{"root": Pulse},
} }
func init() { func init() {
Pulse.Root = Pulse Pulse.Root = Pulse
Pulse.Target = Index
Pulse.Context = Index
Pulse.Wait = make(chan bool, 10) Pulse.Wait = make(chan bool, 10)
Index.Requests = []*Message{Pulse}
Index.Sessions = map[string]*Message{"root": Pulse}
} }
func Start(args ...string) { func Start(args ...string) {
if len(args) > 0 { if len(args) > 0 {
Index.Conf("start", args[0]) Pulse.Conf("start", args[0])
} }
if len(args) > 1 { if len(args) > 1 {
Index.Conf("init.sh", args[1]) Pulse.Conf("init.sh", args[1])
} }
if len(args) > 2 { if len(args) > 2 {
Index.Conf("bench.log", args[2]) Pulse.Conf("bench.log", args[2])
} else { } else {
Index.Conf("bench.log", Index.Conf("bench.log")) Pulse.Conf("bench.log", Pulse.Conf("bench.log"))
} }
if len(args) > 3 { if len(args) > 3 {
Index.Conf("root", args[3]) Pulse.Conf("root", args[3])
} }
log.Println("\n\n\n") log.Println("\n\n\n")
Index.Travel(func(s *Context) bool { Index.Travel(func(s *Context) bool {
Pulse.Target = s
s.Root = Index s.Root = Index
s.Begin(nil) s.Begin(Pulse)
return true return true
}) })
Pulse.Target = Index
if n := 0; Index.Conf("start") != "" { if n := 0; Pulse.Conf("start") != "" {
for _, s := range Index.Contexts { for _, s := range Index.contexts {
if ok, _ := regexp.MatchString(Index.Conf("start"), s.Name); ok { if ok, _ := regexp.MatchString(Pulse.Conf("start"), s.Name); ok {
go s.Start(Pulse.Spawn(s, s.Name).Put("option", "io", os.Stdout)) go s.Start(Pulse.Spawn(s, s.Name).Put("option", "io", os.Stdout))
n++ n++
} }
} }
for n > 0 || Index.Capi("nserver", 0) > 0 { for n > 0 || Pulse.Capi("nserver", 0) > 0 {
<-Pulse.Wait <-Pulse.Wait
n-- n--
} }