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
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

View File

@ -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" {
// 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":

View File

@ -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--
}