From 954dd13717f3c290b3b17ebb82de8a3fe553b5b1 Mon Sep 17 00:00:00 2001 From: shaoying Date: Mon, 13 Nov 2017 08:45:10 +0800 Subject: [PATCH] =?UTF-8?q?mac=20mod=20message.ccc=20=E5=B0=86=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E7=9A=84=E6=93=8D=E4=BD=9C=E6=8E=A5=E5=8F=A3=E7=A7=BB?= =?UTF-8?q?=E5=8A=A8=E6=B6=88=E6=81=AF=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- etc/init.sh | 13 +- src/context/cli/cli.go | 72 +++--- src/context/ctx.go | 524 ++++++++++++++++++++++------------------- 3 files changed, 323 insertions(+), 286 deletions(-) diff --git a/etc/init.sh b/etc/init.sh index 73f620ce..8838af3b 100644 --- a/etc/init.sh +++ b/etc/init.sh @@ -1,6 +1,7 @@ -~aaa -login root 94ca7394d007fa189cc4be0a2625d716 root -login root root - -~cli -remote slave listen :9393 tcp +# @debug on +# ~aaa +# login root 94ca7394d007fa189cc4be0a2625d716 root +# login root root +# +# ~cli +# remote slave listen :9393 tcp diff --git a/src/context/cli/cli.go b/src/context/cli/cli.go index a5e37532..0c24a16c 100644 --- a/src/context/cli/cli.go +++ b/src/context/cli/cli.go @@ -46,7 +46,7 @@ func (cli *CLI) push(f io.ReadCloser) { // {{{ // }}} 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 := "" fmt.Fprintf(cli.out, "username>") @@ -69,12 +69,12 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{ } 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" { - cli.echo(cli.Conf("PS1")) + if len(cli.ins) == 1 || m.Conf("slient") != "yes" { + cli.echo(m.Conf("PS1")) } line := "" @@ -95,10 +95,10 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{ return true } } - cli.Assert(e) + m.Assert(e) line = ls - if len(cli.ins) > 1 || cli.Conf("slient") != "yes" { + if len(cli.ins) > 1 || m.Conf("slient") != "yes" { cli.echo(line) } @@ -113,7 +113,7 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{ line = cli.next cli.next = "" - if cli.Conf("slient") != "yes" { + if m.Conf("slient") != "yes" { cli.echo(line) cli.echo("\n") } @@ -174,9 +174,9 @@ back: // }}} func (cli *CLI) echo(str string, arg ...interface{}) { // {{{ - if len(cli.ins) == 1 || cli.Conf("slient") != "yes" { - fmt.Fprintf(cli.out, str, arg...) - } + // if len(cli.ins) == 1 || m.Conf("slient") != "yes" { + 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.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)) 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 { // {{{ cli.Owner = nil - cli.Capi("nterm", 1) - defer cli.Capi("nterm", -1) + m.Capi("nterm", 1) + defer m.Capi("nterm", -1) 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 { - cli.Conf("init.sh", "启动脚本", arg[0], "模块启动时自动运行的脚本") + m.Conf("init.sh", "启动脚本", arg[0], "模块启动时自动运行的脚本") } 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.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) } @@ -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 { 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 { // {{{ if cli.Context != Index { - delete(cli.Context.Context.Contexts, cli.Name) + // delete(cli.Context.Context.Contexts, cli.Name) } 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: "模块启动时输出的信息"}, // "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 { - cli, ok := c.Server.(*CLI) // {{{ + "PS1": &ctx.Config{Name: "命令行提示符(target/detail)", Value: "target", Help: "命令行提示符,target:显示当前模块,detail:显示详细信息", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { + cli, ok := m.Target.Server.(*CLI) // {{{ if ok && cli.target != nil { // c = cli.target switch x.Value { 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": - 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{ "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 { cli, ok = c.Server.(*CLI) if !ok { @@ -321,7 +321,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", switch len(arg) { case 0: 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) } return true @@ -330,7 +330,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", } target := m.Target - switch c.Conf("default") { + switch m.Conf("default") { case "root": target = target.Root case "back": @@ -388,7 +388,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", } for _, v := range cs { - if !m.Context.Check(v) { + if !m.Source.Check(v) { continue } @@ -409,7 +409,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", } m.Echo("索引模块:\n") 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 { ms := []*ctx.Message{ctx.Pulse} // {{{ 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...) } return "" @@ -455,7 +455,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", switch len(arg) { case 1: f, e := os.Open(arg[0]) - c.Assert(e) + m.Assert(e) cli.push(f) } @@ -555,16 +555,16 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", switch arg[0] { case "void": - s.Conf(arg[1], "") + m.Conf(arg[1], "") case "delete": if _, ok := s.Configs[arg[1]]; ok { delete(s.Configs, arg[1]) } default: - s.Conf(arg[0], arg[1]) + m.Conf(arg[0], arg[1]) } case 4: - s.Conf(arg[0], arg[1:]...) + m.Conf(arg[0], arg[1:]...) return false } return all @@ -601,11 +601,11 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", } default: 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: - s.Cap(arg[0], arg[1:]...) + m.Cap(arg[0], arg[1:]...) 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 { cli, ok := m.Target.Server.(*CLI) // {{{ if !ok { - cli, ok = m.Context.Server.(*CLI) + cli, ok = m.Source.Server.(*CLI) } if ok { if !cli.exit { @@ -663,7 +663,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端", Options: map[string]string{"io": "读写流"}, Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string { // {{{ 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 { switch arg[1] { case "tcp": diff --git a/src/context/ctx.go b/src/context/ctx.go index fed8eccb..c31546bb 100644 --- a/src/context/ctx.go +++ b/src/context/ctx.go @@ -17,23 +17,21 @@ import ( // {{{ // }}} -type Cache struct { // {{{ +type Cache struct { Name string Value 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 Value 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 Help string Options map[string]string @@ -41,8 +39,6 @@ type Command struct { // {{{ Hand func(c *Context, m *Message, key string, arg ...string) string } -// }}} - type Message struct { Code int Time time.Time @@ -51,10 +47,11 @@ type Message struct { Data map[string]interface{} Wait chan bool - Name string - *Context Index int Target *Context + Master *Context + Source *Context + Name string Messages []*Message Message *Message @@ -82,10 +79,11 @@ func (m *Message) Spawn(c *Context, key ...string) *Message { // {{{ msg := &Message{ Time: time.Now(), Target: c, + Master: c, Message: m, Root: m.Root, } - msg.Context = m.Target + msg.Source = m.Target if len(key) == 0 { return msg @@ -97,13 +95,13 @@ func (m *Message) Spawn(c *Context, key ...string) *Message { // {{{ m.Messages = append(m.Messages, msg) msg.Code = m.Capi("nmessage", 1) - if msg.Sessions == nil { - msg.Sessions = make(map[string]*Message) + if msg.Source.Sessions == nil { + msg.Source.Sessions = make(map[string]*Message) } - msg.Sessions[key[0]] = msg + msg.Source.Sessions[key[0]] = msg 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 } @@ -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 { // {{{ if len(arg) > 0 { if m.Meta == nil { @@ -246,21 +276,197 @@ func (m *Message) Cmd(arg ...string) string { // {{{ } 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 Start(m *Message, arg ...string) bool Spawn(c *Context, m *Message, arg ...string) Server Exit(m *Message, arg ...string) bool } -// }}} - type Context struct { Name string Help string @@ -277,31 +483,20 @@ type Context struct { Sessions map[string]*Message Owner *Context + Group string Index map[string]*Context Groups map[string]*Context - Contexts map[string]*Context + contexts map[string]*Context Context *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 { // {{{ defer func() { if e := recover(); e != nil { 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) 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 { // {{{ - 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)) } - c.Contexts[s.Name] = s + c.contexts[s.Name] = s s.Root = c.Root s.Context = c 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 } // }}} func (c *Context) Begin(m *Message) *Context { // {{{ - for k, x := range c.Configs { + for k, x := range m.Target.Configs { 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:未在运行"} } - 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.Cap("status", "start") - defer c.Cap("status", "stop") + m.Cap("status", "start") + defer m.Cap("status", "stop") - log.Printf("%d start(%d): %s %s", m.Code, Index.Capi("nserver", 1), c.Name, c.Help) - defer Index.Capi("nserver", -1) - defer log.Printf("%d stop(%s): %s %s", m.Code, Index.Cap("nserver"), c.Name, c.Help) + log.Printf("%d start(%d): %s %s", m.Code, Pulse.Capi("nserver", 1), c.Name, c.Help) + defer Pulse.Capi("nserver", -1) + 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.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 { - c.Messages = make(chan *Message, c.Confi("MessageQueueSize")) + if msg.Target.Messages == nil { + msg.Target.Messages = make(chan *Message, msg.Confi("MessageQueueSize")) } - m := <-c.Messages + m := <-msg.Target.Messages defer m.End(true) 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"] - c.AssertOne(m, true, func(c *Context, m *Message) { + msg.Target.AssertOne(m, true, func(c *Context, m *Message) { m.Cmd() }, func(c *Context, m *Message) { - c.Cmd(m, arg[0], arg[1:]...) + m.Master = c + m.Cmd() }, 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:]...) v, e := cmd.CombinedOutput() if e != nil { @@ -455,7 +652,7 @@ func (c *Context) Exit(m *Message, arg ...string) { // {{{ if m.Target == c { 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 { c.Server.Exit(m, arg...) 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 { if v.Index != -1 { v.Index = -1 - v.Context.Exit(v, arg...) - log.Println(c.Name, c.Help, "exit: resource", v.Code, v.Context.Name, v.Context.Help) + v.Source.Exit(v, arg...) + 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 = "" log.Println(c.Name, c.Help, "exit: session", m.Code, m.Target.Name, m.Target.Help) if c.Server != nil { @@ -680,7 +877,7 @@ func (c *Context) Check(s *Context) bool { // {{{ func (c *Context) Travel(hand func(s *Context) bool) { // {{{ cs := []*Context{c} for i := 0; i < len(cs); i++ { - for _, v := range cs[i].Contexts { + for _, v := range cs[i].contexts { cs = append(cs, v) } @@ -716,10 +913,10 @@ func (c *Context) Search(name string) []*Context { // {{{ // }}} func (c *Context) Find(name string) (s *Context) { // {{{ ns := strings.Split(name, ".") - cs := c.Contexts + cs := c.contexts for _, v := range ns { if x, ok := cs[v]; ok { - cs = x.Contexts + cs = x.contexts s = x } else { 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 { // {{{ - 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 Pulse = &Message{Code: 1, Time: time.Now(), Index: 0, Target: Index, Master: Index, Source: Index, Name: "ctx"} var Index = &Context{Name: "ctx", Help: "根模块", Caches: map[string]*Cache{ @@ -902,7 +938,7 @@ var Index = &Context{Name: "ctx", Help: "根模块", Configs: map[string]*Config{ "start": &Config{Name: "启动模块", Value: "cli", 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 e := os.MkdirAll(path.Dir(arg[0]), os.ModePerm); e == nil { if l, e := os.Create(x.Value); e == nil { @@ -913,11 +949,11 @@ var Index = &Context{Name: "ctx", Help: "根模块", 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 !path.IsAbs(x.Value) { wd, e := os.Getwd() - c.Assert(e) + m.Assert(e) x.Value = path.Join(wd, x.Value) } @@ -945,56 +981,56 @@ var Index = &Context{Name: "ctx", Help: "根模块", }, Commands: map[string]*Command{ "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("ncontext: %s\n", c.Cap("ncontext")) - m.Echo("nmessage: %s\n", c.Cap("nmessage")) + m.Echo("nserver: %s\n", m.Cap("nserver")) // {{{ + m.Echo("ncontext: %s\n", m.Cap("ncontext")) + m.Echo("nmessage: %s\n", m.Cap("nmessage")) return "" // }}} }}, }, - Requests: []*Message{Pulse}, - Sessions: map[string]*Message{"root": Pulse}, } func init() { Pulse.Root = Pulse - Pulse.Target = Index - Pulse.Context = Index Pulse.Wait = make(chan bool, 10) + Index.Requests = []*Message{Pulse} + Index.Sessions = map[string]*Message{"root": Pulse} } func Start(args ...string) { if len(args) > 0 { - Index.Conf("start", args[0]) + Pulse.Conf("start", args[0]) } if len(args) > 1 { - Index.Conf("init.sh", args[1]) + Pulse.Conf("init.sh", args[1]) } if len(args) > 2 { - Index.Conf("bench.log", args[2]) + Pulse.Conf("bench.log", args[2]) } else { - Index.Conf("bench.log", Index.Conf("bench.log")) + Pulse.Conf("bench.log", Pulse.Conf("bench.log")) } if len(args) > 3 { - Index.Conf("root", args[3]) + Pulse.Conf("root", args[3]) } log.Println("\n\n\n") Index.Travel(func(s *Context) bool { + Pulse.Target = s s.Root = Index - s.Begin(nil) + s.Begin(Pulse) return true }) + Pulse.Target = Index - if n := 0; Index.Conf("start") != "" { - for _, s := range Index.Contexts { - if ok, _ := regexp.MatchString(Index.Conf("start"), s.Name); ok { + if n := 0; Pulse.Conf("start") != "" { + for _, s := range Index.contexts { + if ok, _ := regexp.MatchString(Pulse.Conf("start"), s.Name); ok { go s.Start(Pulse.Spawn(s, s.Name).Put("option", "io", os.Stdout)) n++ } } - for n > 0 || Index.Capi("nserver", 0) > 0 { + for n > 0 || Pulse.Capi("nserver", 0) > 0 { <-Pulse.Wait n-- }