forked from x/ContextOS
mac mod message.ccc 将模块的操作接口移动消息上
This commit is contained in:
parent
c293a1bd95
commit
954dd13717
13
etc/init.sh
13
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
|
||||
|
@ -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":
|
||||
|
@ -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--
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user