1
0
forked from x/ContextOS

Merge branch '0.3.0'

This commit is contained in:
shaoying 2017-11-25 16:28:10 +08:00
commit 72a361c4b7
5 changed files with 329 additions and 266 deletions

View File

@ -10,7 +10,6 @@ import ( // {{{
"time"
"fmt"
"log"
)
// }}}
@ -40,7 +39,7 @@ func (aaa *AAA) Start(m *ctx.Message, arg ...string) bool { // {{{
// }}}
func (aaa *AAA) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{
"username": &ctx.Cache{Name: "用户名", Value: arg[0], Help: "显示已经启动运行模块的数量"},
"username": &ctx.Cache{Name: "用户名", Value: arg[0], Help: "用户名"},
"password": &ctx.Cache{Name: "密码", Value: "", Help: "用户密码,加密存储", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string {
if len(arg) > 0 { // {{{
if arg[0] == "" {
@ -53,7 +52,7 @@ func (aaa *AAA) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server
} else {
bs := md5.Sum([]byte(fmt.Sprintln("用户密码:%s", arg[0])))
if x.Value != hex.EncodeToString(bs[:]) {
log.Println(m.Target.Name, "login in:", arg[0], "密码错误")
m.Log("info", "%s: login error", m.Target.Name)
panic("密码错误")
}
}
@ -92,7 +91,8 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
},
Commands: map[string]*ctx.Command{
"login": &ctx.Command{Name: "login [sessid]|[username password [group]]]", Help: "", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
aaa := c.Server.(*AAA) // {{{
m.Target = m.Master
aaa := m.Target.Server.(*AAA) // {{{
switch len(arg) {
case 0:
m.Travel(m.Target, func(m *ctx.Message) bool {
@ -107,44 +107,33 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
if s, ok := aaa.sessions[arg[0]]; ok {
m.Target = s
m.Source.Owner = s
log.Println(aaa.Name, "login on:", aaa.sessions)
m.Log("info", "%s: logon %s", aaa.Name, m.Cap("username"))
return m.Cap("username")
}
m.Target = target
case 2:
s := m.Target.Find(arg[0])
if s != nil {
old := m.Source
defer func() { m.Source = old }()
m.Source = s
m.Target = s
m.Master = aaa.Context
if m.Find(arg[0]) != nil {
m.Cap("password", arg[1])
log.Println(aaa.Name, "login in:", arg[0])
old.Owner = s
m.Log("info", "%s: login", aaa.Name)
} else {
m.Start(arg[0], arg...)
s = m.Target
aaa.sessions[m.Cap("sessid")] = s
log.Println(aaa.Name, "login up:", arg[0])
aaa.sessions[m.Cap("sessid")] = m.Target
m.Log("info", "%s: logup %s", aaa.Name, m.Target.Name)
}
m.Target.Owner = s
m.Source.Owner = ctx.Index.Owner
target := m.Target
if arg[0] == m.Conf("rootname") {
ctx.Index.Owner = s
m.Travel(m.Target.Root, func(m *ctx.Message) bool {
if m.Target.Owner == nil {
m.Target.Owner = s
m.Target.Owner = target
}
return true
})
}
m.Source.Owner = s
m.Target.Owner = target
m.Source.Owner = target
m.Source.Group = m.Cap("group")
return m.Cap("sessid")

View File

@ -5,7 +5,6 @@ import ( // {{{
"context"
"fmt"
"io"
"log"
"os"
"strconv"
"strings"
@ -48,7 +47,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 aaa := cli.Root.Find("aaa"); aaa != nil {
if msg := m.Spawn(cli.Root).Find("aaa"); msg != nil {
username := ""
fmt.Fprintf(cli.out, "username>")
@ -58,8 +57,6 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{
fmt.Fprintf(cli.out, "password>")
fmt.Fscanln(cli.in, &password)
msg := m.Spawn(aaa, "username")
if msg.Cmd("login", username, password) == "" {
fmt.Fprintln(cli.out, "登录失败")
m.Cmd("exit")
@ -233,20 +230,21 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
cli.push(io)
if m.Has("master") {
log.Println(cli.Name, "master terminal:")
m.Log("info", "%s: master terminal", cli.Name)
if cli.bufs == nil {
cli.bufs = make([][]byte, 0, 10)
}
for {
b := make([]byte, 128)
n, e := cli.bio.Read(b)
log.Println(cli.Name, "read:", n)
m.Log("info", "%s: read %d", cli.Name, n)
m.Assert(e)
cli.bufs = append(cli.bufs, b)
}
return true
} else {
log.Println(cli.Name, "slaver terminal:")
m.Log("info", "%s: slaver terminal", cli.Name)
m.Log("info", "%s: open %s", cli.Name, m.Conf("init.sh"))
if f, e := os.Open(m.Conf("init.sh")); e == nil {
cli.push(f)
@ -305,7 +303,7 @@ func (cli *CLI) Exit(m *ctx.Message, arg ...string) bool { // {{{
return false
case m.Target:
log.Println(cli.Name, "release:")
m.Log("exit", "%s: release", cli.Name)
}
return true
@ -319,8 +317,8 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
},
Configs: map[string]*ctx.Config{},
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:启动参数",
Formats: map[string]int{"root": 0, "back": 0, "home": 0, "find": 1, "search": 1, "show": 0, "switch": 0, "start": -1, "spawn": -1},
"context": &ctx.Command{Name: "context [root|back|home] [[find|search] name] [list|show|spawn|start|switch][args]", Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块args:启动参数",
Formats: map[string]int{"root": 0, "back": 0, "home": 0, "find": 1, "search": 1, "list": 0, "show": 0, "switch": 0, "start": 0, "spawn": 0},
Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
cli, ok := m.Source.Server.(*CLI) // {{{
if !ok {
@ -330,10 +328,67 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
}
}
switch len(arg) {
case 0:
m.Travel(m.Target.Root, func(m *ctx.Message) bool {
if m.Target.Context != nil {
target := m.Target
if m.Has("home") {
target = m.Target
}
if m.Has("root") {
target = m.Target.Root
}
if m.Has("back") && target.Context != nil {
target = m.Target.Context
}
ms := []*ctx.Message{}
switch {
case m.Has("search"):
if s := m.Search(target, m.Get("search")); len(s) > 0 {
ms = append(ms, s...)
}
case m.Has("find"):
if msg := m.Spawn(target).Find(m.Get("find")); msg != nil {
ms = append(ms, msg)
}
case m.Has("args"):
if s := m.Search(target, m.Get("args")); len(s) > 0 {
ms = append(ms, s...)
arg = arg[1:]
}
default:
ms = append(ms, m.Spawn(target))
}
for _, v := range ms {
switch {
case m.Has("start"):
args := m.Meta["start"]
v.Start(arg[0], args[1:]...)
case m.Has("spawn"):
args := m.Meta["spawn"]
v.Target.Spawn(v, args[0]).Begin(v)
cli.target = v.Target
case m.Has("switch"):
cli.target = v.Target
case m.Has("show"):
m.Echo("%s(%s): %s\n", v.Target.Name, v.Target.Owner.Name, v.Target.Help)
if len(v.Target.Requests) > 0 {
m.Echo("模块资源:\n")
for i, v := range v.Target.Requests {
m.Echo(" %d(%d): <- %s %s\n", i, v.Code, v.Source.Name, v.Meta["detail"])
for i, v := range v.Messages {
m.Echo(" %d(%d): -> %s %s\n", i, v.Code, v.Source.Name, v.Meta["detail"])
}
}
}
if len(v.Target.Sessions) > 0 {
m.Echo("模块引用:\n")
for k, v := range v.Target.Sessions {
m.Echo(" %s(%d): -> %s %v\n", k, v.Code, v.Target.Name, v.Meta["detail"])
}
}
case m.Has("list") || cli.target == v.Target:
m.Travel(v.Target, func(m *ctx.Message) bool {
if m.Target.Context != nil && m.Target != v.Target {
target := m.Target
m.Target = m.Target.Owner
if m.Target != nil && m.Check(m.Target, "caches", "username") && m.Check(m.Target, "caches", "group") {
@ -345,69 +400,11 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
}
return true
})
default:
cli.target = v.Target
return ""
}
target := m.Target.Root
if m.Has("home") {
target = m.Target
}
if m.Has("root") {
target = m.Target.Root
}
if m.Has("back") && target.Context != nil {
target = m.Target.Context
}
cs := []*ctx.Context{}
switch {
case m.Has("search"):
if s := m.Search(target, m.Get("search")); len(s) > 0 {
cs = append(cs, s...)
}
case m.Has("find"):
if s := target.Find(m.Get("find")); s != nil {
cs = append(cs, s)
}
case m.Has("args"):
if s := m.Search(target, m.Get("args")); len(s) > 0 {
cs = append(cs, s...)
}
default:
cs = append(cs, target)
}
for _, v := range cs {
// if !m.Source.Check(v) {
// continue
// }
//
switch {
case m.Has("start"):
args := m.Meta["start"]
m.Message.Spawn(v, args[0]).Start(arg[0], args[1:]...)
case m.Has("spawn"):
args := m.Meta["spawn"]
msg := m.Spawn(v)
v.Spawn(msg, args[0]).Begin(msg)
cli.target = msg.Target
case m.Has("switch"):
cli.target = v
case m.Has("show"):
m.Echo("%s: %s\n", v.Name, v.Help)
m.Echo("模块资源:\n")
for i, v := range v.Requests {
m.Echo("\t%d(%d): <- %s %s\n", i, v.Code, v.Source.Name, v.Source.Help)
}
m.Echo("模块引用:\n")
for k, v := range v.Sessions {
m.Echo("\t%s(%d): -> %s %s\n", k, v.Code, v.Target.Name, v.Target.Help)
}
default:
cli.target = v
}
}
return ""
// }}}
}},
@ -484,13 +481,12 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
return ""
}
s := c.Root.Find(m.Get("args"))
action := "dial"
if m.Has("listen") {
action = "listen"
}
msg := m.Spawn(c.Root).Find(m.Get("args"))
msg := m.Spawn(s)
if m.Has("master") {
msg.Template = msg.Spawn(msg.Source).Add("option", "master")
}

View File

@ -98,7 +98,7 @@ func (c *Context) Register(s *Context, x Server) *Context { // {{{
s.Root = Index
}
log.Printf("%s sub(%d): %s", c.Name, Pulse.Capi("ncontext", 1), s.Name)
// log.Printf("%s sub(%d): %s", c.Name, Pulse.Capi("ncontext", 1), s.Name)
return s
}
@ -129,9 +129,9 @@ func (c *Context) Start(m *Message) bool { // {{{
m.Cap("status", "start")
defer m.Cap("status", "stop")
log.Printf("%d start(%d): %s %s %v", m.Code, m.Root.Capi("nserver", 1), c.Name, c.Help, m.Meta["detail"])
m.Log("start", "%s: %d %v", c.Name, m.Root.Capi("nserver", 1), m.Meta["detail"])
defer m.Root.Capi("nserver", -1)
defer log.Printf("%d stop(%s): %s %s", m.Code, m.Root.Cap("nserver"), c.Name, c.Help)
defer m.Log("stop", "%s: %d %v", c.Name, m.Root.Capi("nserver"), m.Meta["detail"])
c.Requests = []*Message{m}
c.Server.Start(m, m.Meta["detail"]...)
@ -144,8 +144,8 @@ func (c *Context) Start(m *Message) bool { // {{{
// }}}
func (c *Context) Spawn(m *Message, key string) *Context { // {{{
// s := &Context{Name: key, Help: c.Help}
s := &Context{Name: key, Help: c.Help, Owner: m.Source.Owner}
m.Log("begin", "%s: %s", key, c.Help)
m.Target = s
if m.Template != nil {
m.Template.Source = s
@ -161,11 +161,7 @@ func (c *Context) Spawn(m *Message, key string) *Context { // {{{
// }}}
func (c *Context) Exit(m *Message, arg ...string) { // {{{
if m.Code != 0 {
log.Printf("%d exit(%s:%s->%s.%d): %s %v", m.Code, m.Source.Name, m.Name, m.Target.Name, m.Index, c.Name, arg)
} else {
log.Printf("%d exit(%s->%s): %s %v", m.Code, m.Source.Name, m.Target.Name, c.Name, arg)
}
m.Log("exit", "%s: %v", c.Name, arg)
if m.Target == c {
for _, v := range c.Sessions {
@ -380,24 +376,6 @@ func (c *Context) BackTrace(hand func(s *Context) bool) { // {{{
}
}
// }}}
func (c *Context) Find(name string) (s *Context) { // {{{
ns := strings.Split(name, ".")
cs := c.contexts
for _, v := range ns {
if x, ok := cs[v]; ok {
cs = x.contexts
s = x
} else {
log.Println(c.Name, "not find:", name)
return nil
panic(errors.New(c.Name + " not find: " + name))
}
}
log.Println(c.Name, "find:", name)
return s
}
// }}}
type Message struct {
@ -421,29 +399,74 @@ type Message struct {
Template *Message
}
func (m *Message) Assert(e error) bool { // {{{
if e != nil {
func (m *Message) Log(action, str string, arg ...interface{}) { // {{{
color := 0
switch action {
case "check":
color = 31
case "cmd":
color = 32
case "conf":
color = 33
case "find":
color = 35
case "search":
color = 35
case "spawn":
color = 35
case "begin":
color = 36
case "start":
color = 36
case "stop":
color = 36
}
if m.Name != "" {
log.Printf("\033[%dm%d %s(%s:%s->%s.%d) %s\033[0m", color, m.Code, action, m.Source.Name, m.Name, m.Target.Name, m.Index, fmt.Sprintf(str, arg...))
} else {
log.Printf("\033[%dm%d %s(%s->%s) %s\033[0m", color, m.Code, action, m.Source.Name, m.Target.Name, fmt.Sprintf(str, arg...))
}
}
// }}}
func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{
switch e := e.(type) {
case error:
case string:
if e == "error:" {
if len(msg) > 0 {
panic(errors.New(msg[0]))
}
panic(errors.New("error"))
}
return true
default:
return true
}
m.Log("error", "error: %v", e)
m.Set("result", "error:", fmt.Sprintln(e))
log.Println(m.Code, "error:", e)
if m.Conf("debug") == "on" {
fmt.Println(m.Code, "error:", e)
}
panic(e)
}
return true
}
// }}}
func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message)) *Message { // {{{
defer func() {
if e := recover(); e != nil {
log.Println(msg.Target.Name, e)
if _, ok := e.(error); ok {
msg.Log("error", "error: %v", e)
if msg.Conf("debug") == "on" && e != io.EOF {
fmt.Println(msg.Target.Name, "error:", e)
debug.PrintStack()
}
}
if e == io.EOF {
return
@ -453,7 +476,6 @@ func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message))
m.AssertOne(msg, safe, hand[1:]...)
} else {
if !safe {
log.Println(msg.Target.Name, "error:", e)
panic(e)
}
}
@ -472,32 +494,31 @@ func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message))
func (m *Message) Spawn(c *Context, key ...string) *Message { // {{{
msg := &Message{
Code: m.Capi("nmessage", 1),
Time: time.Now(),
Message: m,
Root: m.Root,
Source: m.Target,
Master: c,
Master: m.Target,
Target: c,
}
if len(key) == 0 {
return msg
}
msg.Code = m.Capi("nmessage", 1)
if m.Messages == nil {
m.Messages = make([]*Message, 0, 10)
}
m.Messages = append(m.Messages, msg)
if len(key) == 0 {
return msg
}
if msg.Source.Sessions == nil {
msg.Source.Sessions = make(map[string]*Message)
}
msg.Source.Sessions[key[0]] = msg
msg.Name = key[0]
log.Printf("%d spawn %d: %s.%s->%s.%d", m.Code, msg.Code, msg.Source.Name, msg.Name, msg.Target.Name, msg.Index)
m.Log("spawn", "%d: %s.%s->%s.%d", msg.Code, msg.Source.Name, msg.Name, msg.Target.Name, msg.Index)
return msg
}
@ -526,7 +547,7 @@ func (m *Message) Reply(key ...string) *Message { // {{{
msg.Source.Sessions[key[0]] = msg
msg.Name = key[0]
log.Printf("%d spawn %d: %s.%s->%s.%d", m.Code, msg.Code, msg.Source.Name, msg.Name, msg.Target.Name, msg.Index)
m.Log("spawn", "%d: %s.%s->%s.%d", msg.Code, msg.Source.Name, msg.Name, msg.Target.Name, msg.Index)
return msg
}
@ -654,17 +675,37 @@ func (m *Message) Travel(c *Context, hand func(m *Message) bool) { // {{{
}
// }}}
func (m *Message) Search(c *Context, name string) []*Context { // {{{
cs := make([]*Context, 0, 3)
func (m *Message) Search(c *Context, name string) []*Message { // {{{
ms := make([]*Message, 0, 3)
m.Travel(c, func(m *Message) bool {
if strings.Contains(m.Target.Name, name) || strings.Contains(m.Target.Help, name) {
cs = append(cs, m.Target)
log.Println(c.Name, "search:", m.Target.Name, "[match]", name)
ms = append(ms, m.Spawn(m.Target))
m.Log("search", "%s: match [%s]", m.Target.Name, name)
}
return true
})
return cs
return ms
}
// }}}
func (m *Message) Find(name string) *Message { // {{{
ns := strings.Split(name, ".")
cs := m.Target.contexts
old := m.Target.Name
for _, v := range ns {
if x, ok := cs[v]; ok {
cs = x.contexts
m.Target = x
} else {
m.Log("find", "%s: not find %s", m.Target.Name, v)
return nil
panic(errors.New(m.Target.Name + " not find: " + v))
}
}
m.Log("find", "%s: find %s", old, name)
return m
}
// }}}
@ -676,26 +717,22 @@ func (m *Message) Start(key string, arg ...string) bool { // {{{
}
// }}}
func (m *Message) Exec(arg ...string) string { // {{{
func (m *Message) Exec(key string, arg ...string) string { // {{{
cs := []*Context{m.Target, m.Target.Master, m.Source, m.Source.Master}
for _, c := range cs {
if c == nil {
continue
}
for s := c; s != nil; s = s.Context {
if x, ok := s.Commands[arg[0]]; ok {
if !m.Check(s, "commands", arg[0]) {
panic(errors.New(fmt.Sprintf("没有权限:" + arg[0])))
}
if x, ok := s.Commands[key]; ok {
m.Master = s
if !m.Check(s, "commands", key) {
break
}
success := false
m.AssertOne(m, true, func(m *Message) {
if m.Code != 0 {
log.Printf("%d cmd(%s:%s->%s.%d): %s %v", m.Code, m.Source.Name, m.Name, m.Target.Name, m.Index, c.Name, arg)
} else {
log.Printf("%d cmd(%s->%s): %s %v", m.Code, m.Source.Name, m.Target.Name, c.Name, arg)
}
m.Log("cmd", "%s: %s %v", s.Name, key, arg)
if x.Options != nil {
for _, v := range m.Meta["option"] {
@ -706,7 +743,7 @@ func (m *Message) Exec(arg ...string) string { // {{{
}
if x.Formats != nil {
for i, args := 1, m.Meta["detail"]; i < len(args); i++ {
for i, args := 0, arg; i < len(args); i++ {
n, ok := x.Formats[args[i]]
if !ok {
m.Add("option", "args", arg[i])
@ -720,10 +757,11 @@ func (m *Message) Exec(arg ...string) string { // {{{
m.Add("option", args[i], arg[i+1:i+1+n]...)
i += n
}
arg = m.Meta["args"]
}
m.Meta["result"] = nil
ret := x.Hand(c, m, arg[0], arg[1:]...)
ret := x.Hand(c, m, key, arg...)
if ret != "" {
m.Echo(ret)
}
@ -736,6 +774,11 @@ func (m *Message) Exec(arg ...string) string { // {{{
}
}
if c.Requests == nil {
c.Requests = make([]*Message, 0, 10)
}
c.Requests = append(c.Requests, m)
success = true
})
@ -745,8 +788,8 @@ func (m *Message) Exec(arg ...string) string { // {{{
}
m.AssertOne(m, true, func(m *Message) {
log.Printf("system command(%s->%s): %v", m.Source.Name, m.Target.Name, arg)
cmd := exec.Command(arg[0], arg[1:]...)
m.Log("system", ":%v", arg)
cmd := exec.Command(key, arg[1:]...)
v, e := cmd.CombinedOutput()
if e != nil {
m.Echo("%s\n", e)
@ -775,7 +818,7 @@ func (m *Message) Deal(pre func(msg *Message, arg ...string) bool, post func(msg
}
m.AssertOne(msg, true, func(msg *Message) {
msg.Exec(msg.Meta["detail"]...)
msg.Exec(msg.Meta["detail"][0], msg.Meta["detail"][1:]...)
})
if post != nil && !post(msg, msg.Meta["result"]...) {
@ -817,9 +860,9 @@ func (m *Message) Check(s *Context, arg ...string) bool { // {{{
if !ok {
if g, ok = s.Index["void"]; !ok {
if m.Master.Owner != nil {
log.Printf("%s(%s:%s) not auth: %s(%s)", m.Master.Name, m.Master.Owner.Name, m.Master.Group, s.Name, s.Owner.Name)
m.Log("check", "%s(%s:%s) not auth: %s(%s)", m.Master.Name, m.Master.Owner.Name, m.Master.Group, s.Name, s.Owner.Name)
} else {
log.Printf("%s() not auth: %s(%s)", m.Master.Name, s.Name, s.Owner.Name)
m.Log("check", "%s() not auth: %s(%s)", m.Master.Name, s.Name, s.Owner.Name)
}
return false
@ -841,9 +884,9 @@ func (m *Message) Check(s *Context, arg ...string) bool { // {{{
if !ok {
if m.Master.Owner != nil {
log.Printf("%s(%s:%s) not auth: %s(%s) %s %s", m.Master.Name, m.Master.Owner.Name, m.Master.Group, s.Name, s.Owner.Name, g.Name, arg[1])
m.Log("check", "%s(%s:%s) not auth: %s(%s) %s %s", m.Master.Name, m.Master.Owner.Name, m.Master.Group, s.Name, s.Owner.Name, g.Name, arg[1])
} else {
log.Printf("%s() not auth: %s(%s) %s %s", m.Master.Name, s.Name, s.Owner.Name, g.Name, arg[1])
m.Log("check", "%s() not auth: %s(%s) %s %s", m.Master.Name, s.Name, s.Owner.Name, g.Name, arg[1])
}
return false
}
@ -860,7 +903,7 @@ func (m *Message) Cmd(arg ...string) string { // {{{
m.Post(s)
}
return m.Exec(m.Meta["detail"]...)
return m.Exec(m.Meta["detail"][0], m.Meta["detail"][1:]...)
}
// }}}
@ -878,11 +921,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
}
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.Target.Name, m.Index, key, arg)
} else {
log.Printf("%d conf(%s->%s): %s %v", m.Code, m.Source.Name, m.Target.Name, key, arg)
}
m.Log("conf", "%s: %s %v", s.Name, key, arg)
x.Value = arg[0]
if x.Hand != nil {
@ -890,11 +929,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
}
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.Target.Name, m.Index, key, arg)
} else {
log.Printf("%d conf(%s->%s): %s %v", m.Code, m.Source.Name, m.Target.Name, key, arg)
}
m.Log("conf", "%s: %s %v", s.Name, key, arg)
if s == m.Target {
panic(errors.New(key + "配置项已存在"))
@ -911,7 +946,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
}
if len(arg) == 3 {
log.Println(m.Target.Name, "conf:", key, arg)
m.Log("conf", "%s: %s %v", m.Target.Name, key, arg)
if m.Target.Configs == nil {
m.Target.Configs = make(map[string]*Config)
}
@ -937,12 +972,6 @@ func (m *Message) Confi(key string, arg ...int) int { // {{{
// }}}
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 x, ok := s.Caches[key]; ok {
if !m.Check(s, "caches", key) {
@ -963,7 +992,7 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
}
return x.Value
case 3:
log.Println(m.Target.Name, "cap:", key, arg)
m.Log("cap", "%s: %s %v", m.Target.Name, key, arg)
if s == m.Target {
panic(errors.New(key + "缓存项已存在"))
}
@ -978,7 +1007,7 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
}
}
if len(arg) == 3 {
log.Println(m.Target.Name, "cap:", key, arg)
m.Log("cap", "%s: %s %v", m.Target.Name, key, arg)
if m.Target.Caches == nil {
m.Target.Caches = make(map[string]*Cache)
}
@ -1051,7 +1080,7 @@ var Index = &Context{Name: "ctx", Help: "根模块",
"ContextSessionSize": &Config{Name: "会话队列长度", Value: "10", Help: "每个模块可以启动其它模块的数量"},
"MessageQueueSize": &Config{Name: "消息队列长度", Value: "10", Help: "每个模块接收消息的队列长度"},
"debug": &Config{Name: "调试模式(off/on)", Value: "on", Help: "是否打印错误信息off:不打印on:打印)"},
"debug": &Config{Name: "调试模式(off/on)", Value: "off", Help: "是否打印错误信息off:不打印on:打印)"},
"cert": &Config{Name: "证书文件", Value: "etc/cert.pem", Help: "证书文件"},
"key": &Config{Name: "私钥文件", Value: "etc/key.pem", Help: "私钥文件"},
},
@ -1059,8 +1088,7 @@ var Index = &Context{Name: "ctx", Help: "根模块",
"userinfo": &Command{Name: "userinfo [add|del [context key name help]|[command|config|cache group name]]", Help: "查看模块的用户信息",
Formats: map[string]int{"add": -1, "del": -1},
Hand: func(c *Context, m *Message, key string, arg ...string) string {
log.Println(m.Meta)
switch {
switch { // {{{
case m.Has("add"):
m.Target.Add(m.Source.Group, m.Meta["add"]...)
case m.Has("del"):
@ -1093,6 +1121,7 @@ var Index = &Context{Name: "ctx", Help: "根模块",
}
}
return ""
// }}}
}},
"server": &Command{Name: "server [start|exit|switch][args]", Help: "服务启动停止切换", Hand: func(c *Context, m *Message, key string, arg ...string) string {
switch len(arg) { // {{{
@ -1116,14 +1145,71 @@ var Index = &Context{Name: "ctx", Help: "根模块",
return ""
// }}}
}},
"message": &Command{Name: "message", Help: "查看消息", Hand: func(c *Context, m *Message, key string, arg ...string) string {
ms := []*Message{m.Root} // {{{
for i := 0; i < len(ms); i++ {
if ms[i].Code != 0 {
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"])
"message": &Command{Name: "message [index|home] [order]", Help: "查看消息", Hand: func(c *Context, m *Message, key string, arg ...string) string {
switch len(arg) { // {{{
case 0:
for k, v := range m.Target.Sessions {
if v.Name != "" {
m.Echo("%s %s.%s -> %s.%d: %s %v\n", k, v.Source.Name, v.Name, v.Target.Name, v.Index, v.Time.Format("15:04:05"), v.Meta["detail"])
} else {
m.Echo("%s %s -> %s: %s %v\n", k, v.Source.Name, v.Target.Name, v.Time.Format("15:04:05"), v.Meta["detail"])
}
ms = append(ms, ms[i].Messages...)
}
for i, v := range m.Target.Requests {
if v.Name != "" {
m.Echo("%d %s.%s -> %s.%d: %s %v\n", i, v.Source.Name, v.Name, v.Target.Name, v.Index, v.Time.Format("15:04:05"), v.Meta["detail"])
} else {
m.Echo("%d %s -> %s: %s %v\n", i, v.Source.Name, v.Target.Name, v.Time.Format("15:04:05"), v.Meta["detail"])
}
for i, v := range v.Messages {
if v.Name != "" {
m.Echo(" %d %s.%s -> %s.%d: %s %v\n", i, v.Source.Name, v.Name, v.Target.Name, v.Index, v.Time.Format("15:04:05"), v.Meta["detail"])
} else {
m.Echo(" %d %s -> %s: %s %v\n", i, v.Source.Name, v.Target.Name, v.Time.Format("15:04:05"), v.Meta["detail"])
}
}
}
case 1, 2:
n, e := strconv.Atoi(arg[0])
v := m
if e == nil && 0 <= n && n < len(m.Target.Requests) {
v = m.Target.Requests[n]
} else {
v = m.Target.Sessions[arg[0]]
}
if v != nil {
if len(arg) > 1 {
if n, e = strconv.Atoi(arg[1]); e == nil && 0 <= n && n < len(v.Messages) {
v = v.Messages[n]
}
}
if v.Name != "" {
m.Echo("%s.%s -> %s.%d: %s %v\n", v.Source.Name, v.Name, v.Target.Name, v.Index, v.Time.Format("15:04:05"), v.Meta["detail"])
} else {
m.Echo("%s -> %s: %s %v\n", v.Source.Name, v.Target.Name, v.Time.Format("15:04:05"), v.Meta["detail"])
}
if len(v.Meta["option"]) > 0 {
m.Echo("option:\n")
}
for _, k := range v.Meta["option"] {
m.Echo(" %s: %v\n", k, v.Meta[k])
}
if len(v.Meta["result"]) > 0 {
m.Echo("result: %v\n", v.Meta["result"])
}
if len(v.Meta["append"]) > 0 {
m.Echo("append:\n")
}
for _, k := range v.Meta["append"] {
m.Echo(" %s: %v\n", k, v.Meta[k])
}
}
}
return ""
// }}}
}},
@ -1163,57 +1249,49 @@ var Index = &Context{Name: "ctx", Help: "根模块",
return ""
// }}}
}},
"config": &Command{Name: "config [all] [[delete|void] key [value]|[name value help]]", Help: "删除、空值、查看、修改或添加配置", Hand: func(c *Context, m *Message, key string, arg ...string) string {
all := false // {{{
if len(arg) > 0 && arg[0] == "all" {
arg = arg[1:]
all = true
}
"config": &Command{Name: "config [all] [[delete|void] key [value]|[name value help]]", Help: "删除、空值、查看、修改或添加配置",
Formats: map[string]int{"all": 0, "delete": 0, "void": 0},
Hand: func(c *Context, m *Message, key string, arg ...string) string {
all := m.Has("all") // {{{
m.Target.BackTrace(func(s *Context) bool {
switch len(arg) {
case 0:
m.Target.BackTrace(func(s *Context) bool {
m.Echo("%s configs:\n", s.Name)
for k, v := range s.Configs {
if m.Check(m.Target, "configs", k) {
m.Echo(" %s(%s): %s\n", k, v.Value, v.Name)
}
}
return all
})
case 1:
m.Target.BackTrace(func(s *Context) bool {
m.Echo("%s config:\n", s.Name)
if v, ok := s.Configs[arg[0]]; ok {
if m.Check(m.Target, "configs", arg[0]) {
m.Echo(" %s: %s\n", v.Name, v.Help)
}
}
case 2:
if s != m.Target {
m.Echo("请到%s模块上下文中操作配置%v", s.Name, arg)
return false
}
switch arg[0] {
case "void":
if m.Check(m.Target, "configs", arg[1]) {
m.Conf(arg[1], "")
}
case "delete":
if _, ok := s.Configs[arg[1]]; ok {
if m.Check(m.Target, "configs", arg[1]) {
delete(s.Configs, arg[1])
}
}
default:
if m.Check(m.Target, "configs", arg[0]) {
m.Conf(arg[0], arg[1])
}
}
case 4:
if m.Check(m.Target) {
m.Conf(arg[0], arg[1:]...)
}
return false
}
return all
})
case 2:
switch arg[0] {
case "delete":
if _, ok := m.Target.Configs[arg[1]]; ok {
if m.Check(m.Target, "configs", arg[1]) {
delete(m.Target.Configs, arg[1])
}
}
case "void":
m.Conf(arg[1], "")
default:
m.Conf(arg[0], arg[1])
}
case 4:
m.Conf(arg[0], arg[1:]...)
}
return ""
// }}}
}},
@ -1273,6 +1351,9 @@ var Index = &Context{Name: "ctx", Help: "根模块",
},
Index: map[string]*Context{
"void": &Context{Name: "void",
Caches: map[string]*Cache{
"nmessage": &Cache{},
},
Configs: map[string]*Config{
"debug": &Config{},
},
@ -1305,7 +1386,6 @@ func Start(args ...string) {
if len(args) > 3 {
Pulse.Conf("root", args[3])
}
log.Println("\n\n\n")
Pulse.Travel(Index, func(m *Message) bool {
m.Target.Begin(m)

View File

@ -8,7 +8,6 @@ import ( // {{{
"errors"
"fmt"
"log"
)
// }}}
@ -19,25 +18,11 @@ type MDB struct {
}
func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
mdb.Configs["source"] = &ctx.Config{Name: "source", Value: "", Help: "数据库参数"}
mdb.Configs["driver"] = &ctx.Config{Name: "driver", Value: "", Help: "数据库驱动"}
return mdb
}
// }}}
func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{
m.Capi("nsource", 1)
defer m.Capi("nsource", -1)
if len(arg) > 0 {
m.Conf("source", arg[0])
if len(arg) > 1 {
m.Conf("driver", arg[1])
}
}
if m.Conf("source") == "" || m.Conf("driver") == "" {
return true
}
@ -45,15 +30,9 @@ func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{
db, e := sql.Open(m.Conf("driver"), m.Conf("source"))
m.Assert(e)
mdb.db = db
defer mdb.db.Close()
log.Println(mdb.Name, "open:", m.Conf("driver"), m.Conf("source"))
defer log.Println(mdb.Name, "close:", m.Conf("driver"), m.Conf("source"))
for _, p := range m.Meta["prepare"] {
_, e := db.Exec(p)
m.Assert(e)
}
m.Log("info", "%s: open %s %s", mdb.Name, m.Conf("driver"), m.Conf("source"))
m.Capi("nsource", 1)
return true
}
@ -61,7 +40,17 @@ func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{
// }}}
func (mdb *MDB) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{}
c.Configs = map[string]*ctx.Config{}
c.Configs = map[string]*ctx.Config{
"source": &ctx.Config{Name: "source", Value: "", Help: "数据库参数"},
"driver": &ctx.Config{Name: "driver", Value: "", Help: "数据库驱动"},
}
if len(arg) > 0 {
m.Conf("source", arg[0])
if len(arg) > 1 {
m.Conf("driver", arg[1])
}
}
s := new(MDB)
s.Context = c
@ -70,6 +59,13 @@ func (mdb *MDB) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server
// }}}
func (mdb *MDB) Exit(m *ctx.Message, arg ...string) bool { // {{{
if mdb.db != nil && m.Target == mdb.Context {
m.Log("info", "%s: close %s %s", mdb.Name, m.Conf("driver"), m.Conf("source"))
m.Capi("nsource", -1)
mdb.db.Close()
mdb.db = nil
}
return true
}
@ -81,12 +77,8 @@ var Index = &ctx.Context{Name: "mdb", Help: "内存数据库",
},
Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{
"open": &ctx.Command{Name: "open [source [driver]]", Help: "打开数据库",
Options: map[string]string{
"prepare": "打开数据库时自动执行的语句",
},
Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
m.Start("db"+m.Cap("nsource"), arg...) // {{{
"open": &ctx.Command{Name: "open name [source [driver]]", Help: "打开数据库", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
m.Start(arg[0], arg[1:]...) // {{{
return ""
// }}}
}},

View File

@ -3,8 +3,14 @@ package main
import (
"context"
_ "context/cli"
_ "context/mdb"
_ "context/tcp"
_ "context/aaa"
_ "context/ssh"
_ "context/web"
"os"
)