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" "time"
"fmt" "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 { // {{{ func (aaa *AAA) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{ 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 { "password": &ctx.Cache{Name: "密码", Value: "", Help: "用户密码,加密存储", Hand: func(m *ctx.Message, x *ctx.Cache, arg ...string) string {
if len(arg) > 0 { // {{{ if len(arg) > 0 { // {{{
if arg[0] == "" { if arg[0] == "" {
@ -53,7 +52,7 @@ func (aaa *AAA) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server
} else { } else {
bs := md5.Sum([]byte(fmt.Sprintln("用户密码:%s", arg[0]))) bs := md5.Sum([]byte(fmt.Sprintln("用户密码:%s", arg[0])))
if x.Value != hex.EncodeToString(bs[:]) { 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("密码错误") panic("密码错误")
} }
} }
@ -92,7 +91,8 @@ var Index = &ctx.Context{Name: "aaa", Help: "认证中心",
}, },
Commands: map[string]*ctx.Command{ 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 { "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) { switch len(arg) {
case 0: case 0:
m.Travel(m.Target, func(m *ctx.Message) bool { 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 { if s, ok := aaa.sessions[arg[0]]; ok {
m.Target = s m.Target = s
m.Source.Owner = 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") return m.Cap("username")
} }
m.Target = target m.Target = target
case 2: case 2:
s := m.Target.Find(arg[0]) m.Master = aaa.Context
if s != nil { if m.Find(arg[0]) != nil {
old := m.Source
defer func() { m.Source = old }()
m.Source = s
m.Target = s
m.Cap("password", arg[1]) m.Cap("password", arg[1])
log.Println(aaa.Name, "login in:", arg[0]) m.Log("info", "%s: login", aaa.Name)
old.Owner = s
} else { } else {
m.Start(arg[0], arg...) m.Start(arg[0], arg...)
s = m.Target aaa.sessions[m.Cap("sessid")] = m.Target
m.Log("info", "%s: logup %s", aaa.Name, m.Target.Name)
aaa.sessions[m.Cap("sessid")] = s
log.Println(aaa.Name, "login up:", arg[0])
} }
m.Target.Owner = s target := m.Target
m.Source.Owner = ctx.Index.Owner
if arg[0] == m.Conf("rootname") { if arg[0] == m.Conf("rootname") {
ctx.Index.Owner = s
m.Travel(m.Target.Root, func(m *ctx.Message) bool { m.Travel(m.Target.Root, func(m *ctx.Message) bool {
if m.Target.Owner == nil { if m.Target.Owner == nil {
m.Target.Owner = s m.Target.Owner = target
} }
return true return true
}) })
} }
m.Source.Owner = s
m.Target.Owner = target
m.Source.Owner = target
m.Source.Group = m.Cap("group") m.Source.Group = m.Cap("group")
return m.Cap("sessid") return m.Cap("sessid")

View File

@ -5,7 +5,6 @@ import ( // {{{
"context" "context"
"fmt" "fmt"
"io" "io"
"log"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -48,7 +47,7 @@ func (cli *CLI) push(f io.ReadCloser) { // {{{
// }}} // }}}
func (cli *CLI) parse(m *ctx.Message) bool { // {{{ func (cli *CLI) parse(m *ctx.Message) bool { // {{{
if len(cli.ins) == 1 && cli.Owner == nil { if 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 := "" username := ""
fmt.Fprintf(cli.out, "username>") fmt.Fprintf(cli.out, "username>")
@ -58,8 +57,6 @@ func (cli *CLI) parse(m *ctx.Message) bool { // {{{
fmt.Fprintf(cli.out, "password>") fmt.Fprintf(cli.out, "password>")
fmt.Fscanln(cli.in, &password) fmt.Fscanln(cli.in, &password)
msg := m.Spawn(aaa, "username")
if msg.Cmd("login", username, password) == "" { if msg.Cmd("login", username, password) == "" {
fmt.Fprintln(cli.out, "登录失败") fmt.Fprintln(cli.out, "登录失败")
m.Cmd("exit") m.Cmd("exit")
@ -233,20 +230,21 @@ func (cli *CLI) Start(m *ctx.Message, arg ...string) bool { // {{{
cli.push(io) cli.push(io)
if m.Has("master") { if m.Has("master") {
log.Println(cli.Name, "master terminal:") m.Log("info", "%s: master terminal", cli.Name)
if cli.bufs == nil { if cli.bufs == nil {
cli.bufs = make([][]byte, 0, 10) cli.bufs = make([][]byte, 0, 10)
} }
for { for {
b := make([]byte, 128) b := make([]byte, 128)
n, e := cli.bio.Read(b) n, e := cli.bio.Read(b)
log.Println(cli.Name, "read:", n) m.Log("info", "%s: read %d", cli.Name, n)
m.Assert(e) m.Assert(e)
cli.bufs = append(cli.bufs, b) cli.bufs = append(cli.bufs, b)
} }
return true return true
} else { } 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 { if f, e := os.Open(m.Conf("init.sh")); e == nil {
cli.push(f) cli.push(f)
@ -305,7 +303,7 @@ func (cli *CLI) Exit(m *ctx.Message, arg ...string) bool { // {{{
return false return false
case m.Target: case m.Target:
log.Println(cli.Name, "release:") m.Log("exit", "%s: release", cli.Name)
} }
return true return true
@ -319,8 +317,8 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
}, },
Configs: map[string]*ctx.Config{}, Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
"context": &ctx.Command{Name: "context [root|back|home] [[find|search] name] [show|spawn|start|switch][args]", Help: "查找并操作模块,\n查找起点root:根模块、back:父模块、home:本模块,\n查找方法find:路径匹配、search:模糊匹配,\n查找对象name:支持点分和正则,\n操作类型show:显示信息、switch:切换为当前、start:启动模块、spawn:分裂子模块args:启动参数", "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, "show": 0, "switch": 0, "start": -1, "spawn": -1}, 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 { Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
cli, ok := m.Source.Server.(*CLI) // {{{ cli, ok := m.Source.Server.(*CLI) // {{{
if !ok { if !ok {
@ -330,25 +328,7 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
} }
} }
switch len(arg) { target := m.Target
case 0:
m.Travel(m.Target.Root, func(m *ctx.Message) bool {
if m.Target.Context != nil {
target := m.Target
m.Target = m.Target.Owner
if m.Target != nil && m.Check(m.Target, "caches", "username") && m.Check(m.Target, "caches", "group") {
m.Echo("%s: %s(%s) %s %s\n", target.Context.Name, target.Name, target.Help, m.Cap("username"), m.Cap("group"))
} else {
m.Echo("%s: %s(%s)\n", target.Context.Name, target.Name, target.Help)
}
m.Target = target
}
return true
})
return ""
}
target := m.Target.Root
if m.Has("home") { if m.Has("home") {
target = m.Target target = m.Target
} }
@ -359,55 +339,72 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
target = m.Target.Context target = m.Target.Context
} }
cs := []*ctx.Context{} ms := []*ctx.Message{}
switch { switch {
case m.Has("search"): case m.Has("search"):
if s := m.Search(target, m.Get("search")); len(s) > 0 { if s := m.Search(target, m.Get("search")); len(s) > 0 {
cs = append(cs, s...) ms = append(ms, s...)
} }
case m.Has("find"): case m.Has("find"):
if s := target.Find(m.Get("find")); s != nil { if msg := m.Spawn(target).Find(m.Get("find")); msg != nil {
cs = append(cs, s) ms = append(ms, msg)
} }
case m.Has("args"): case m.Has("args"):
if s := m.Search(target, m.Get("args")); len(s) > 0 { if s := m.Search(target, m.Get("args")); len(s) > 0 {
cs = append(cs, s...) ms = append(ms, s...)
arg = arg[1:]
} }
default: default:
cs = append(cs, target) ms = append(ms, m.Spawn(target))
} }
for _, v := range cs { for _, v := range ms {
// if !m.Source.Check(v) {
// continue
// }
//
switch { switch {
case m.Has("start"): case m.Has("start"):
args := m.Meta["start"] args := m.Meta["start"]
m.Message.Spawn(v, args[0]).Start(arg[0], args[1:]...) v.Start(arg[0], args[1:]...)
case m.Has("spawn"): case m.Has("spawn"):
args := m.Meta["spawn"] args := m.Meta["spawn"]
msg := m.Spawn(v) v.Target.Spawn(v, args[0]).Begin(v)
v.Spawn(msg, args[0]).Begin(msg) cli.target = v.Target
cli.target = msg.Target
case m.Has("switch"): case m.Has("switch"):
cli.target = v cli.target = v.Target
case m.Has("show"): case m.Has("show"):
m.Echo("%s: %s\n", v.Name, v.Help) m.Echo("%s(%s): %s\n", v.Target.Name, v.Target.Owner.Name, v.Target.Help)
m.Echo("模块资源:\n") if len(v.Target.Requests) > 0 {
for i, v := range v.Requests { m.Echo("模块资源:\n")
m.Echo("\t%d(%d): <- %s %s\n", i, v.Code, v.Source.Name, v.Source.Help) 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"])
}
}
} }
m.Echo("模块引用:\n") if len(v.Target.Sessions) > 0 {
for k, v := range v.Sessions { m.Echo("模块引用:\n")
m.Echo("\t%s(%d): -> %s %s\n", k, v.Code, v.Target.Name, v.Target.Help) 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") {
m.Echo("%s: %s(%s) %s %s\n", target.Context.Name, target.Name, target.Help, m.Cap("username"), m.Cap("group"))
} else {
m.Echo("%s: %s(%s)\n", target.Context.Name, target.Name, target.Help)
}
m.Target = target
}
return true
})
default: default:
cli.target = v cli.target = v.Target
return ""
} }
} }
return "" return ""
// }}} // }}}
}}, }},
@ -484,13 +481,12 @@ var Index = &ctx.Context{Name: "cli", Help: "管理终端",
return "" return ""
} }
s := c.Root.Find(m.Get("args"))
action := "dial" action := "dial"
if m.Has("listen") { if m.Has("listen") {
action = "listen" action = "listen"
} }
msg := m.Spawn(c.Root).Find(m.Get("args"))
msg := m.Spawn(s)
if m.Has("master") { if m.Has("master") {
msg.Template = msg.Spawn(msg.Source).Add("option", "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 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 return s
} }
@ -129,9 +129,9 @@ func (c *Context) Start(m *Message) bool { // {{{
m.Cap("status", "start") m.Cap("status", "start")
defer m.Cap("status", "stop") 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 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.Requests = []*Message{m}
c.Server.Start(m, m.Meta["detail"]...) 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 { // {{{ 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} s := &Context{Name: key, Help: c.Help, Owner: m.Source.Owner}
m.Log("begin", "%s: %s", key, c.Help)
m.Target = s m.Target = s
if m.Template != nil { if m.Template != nil {
m.Template.Source = s 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) { // {{{ func (c *Context) Exit(m *Message, arg ...string) { // {{{
if m.Code != 0 { m.Log("exit", "%s: %v", c.Name, arg)
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)
}
if m.Target == c { if m.Target == c {
for _, v := range c.Sessions { 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 { type Message struct {
@ -421,28 +399,73 @@ type Message struct {
Template *Message Template *Message
} }
func (m *Message) Assert(e error) bool { // {{{ func (m *Message) Log(action, str string, arg ...interface{}) { // {{{
if e != nil { color := 0
m.Set("result", "error:", fmt.Sprintln(e)) switch action {
case "check":
log.Println(m.Code, "error:", e) color = 31
if m.Conf("debug") == "on" { case "cmd":
fmt.Println(m.Code, "error:", e) color = 32
} case "conf":
color = 33
panic(e) case "find":
color = 35
case "search":
color = 35
case "spawn":
color = 35
case "begin":
color = 36
case "start":
color = 36
case "stop":
color = 36
} }
return true
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))
if m.Conf("debug") == "on" {
fmt.Println(m.Code, "error:", e)
}
panic(e)
} }
// }}} // }}}
func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message)) *Message { // {{{ func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message)) *Message { // {{{
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
log.Println(msg.Target.Name, e) if _, ok := e.(error); ok {
if msg.Conf("debug") == "on" && e != io.EOF { msg.Log("error", "error: %v", e)
fmt.Println(msg.Target.Name, "error:", e) if msg.Conf("debug") == "on" && e != io.EOF {
debug.PrintStack() fmt.Println(msg.Target.Name, "error:", e)
debug.PrintStack()
}
} }
if e == io.EOF { if e == io.EOF {
@ -453,7 +476,6 @@ func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message))
m.AssertOne(msg, safe, hand[1:]...) m.AssertOne(msg, safe, hand[1:]...)
} else { } else {
if !safe { if !safe {
log.Println(msg.Target.Name, "error:", e)
panic(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 { // {{{ func (m *Message) Spawn(c *Context, key ...string) *Message { // {{{
msg := &Message{ msg := &Message{
Code: m.Capi("nmessage", 1),
Time: time.Now(), Time: time.Now(),
Message: m, Message: m,
Root: m.Root, Root: m.Root,
Source: m.Target, Source: m.Target,
Master: c, Master: m.Target,
Target: c, Target: c,
} }
if len(key) == 0 {
return msg
}
msg.Code = m.Capi("nmessage", 1)
if m.Messages == nil { if m.Messages == nil {
m.Messages = make([]*Message, 0, 10) m.Messages = make([]*Message, 0, 10)
} }
m.Messages = append(m.Messages, msg) m.Messages = append(m.Messages, msg)
if len(key) == 0 {
return msg
}
if msg.Source.Sessions == nil { if msg.Source.Sessions == nil {
msg.Source.Sessions = make(map[string]*Message) msg.Source.Sessions = make(map[string]*Message)
} }
msg.Source.Sessions[key[0]] = msg msg.Source.Sessions[key[0]] = msg
msg.Name = key[0] msg.Name = key[0]
log.Printf("%d spawn %d: %s.%s->%s.%d", m.Code, msg.Code, msg.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 return msg
} }
@ -526,7 +547,7 @@ func (m *Message) Reply(key ...string) *Message { // {{{
msg.Source.Sessions[key[0]] = msg msg.Source.Sessions[key[0]] = msg
msg.Name = key[0] msg.Name = key[0]
log.Printf("%d spawn %d: %s.%s->%s.%d", m.Code, msg.Code, msg.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 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 { // {{{ func (m *Message) Search(c *Context, name string) []*Message { // {{{
cs := make([]*Context, 0, 3) ms := make([]*Message, 0, 3)
m.Travel(c, func(m *Message) bool { m.Travel(c, func(m *Message) bool {
if strings.Contains(m.Target.Name, name) || strings.Contains(m.Target.Help, name) { if strings.Contains(m.Target.Name, name) || strings.Contains(m.Target.Help, name) {
cs = append(cs, m.Target) ms = append(ms, m.Spawn(m.Target))
log.Println(c.Name, "search:", m.Target.Name, "[match]", name) m.Log("search", "%s: match [%s]", m.Target.Name, name)
} }
return true 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} cs := []*Context{m.Target, m.Target.Master, m.Source, m.Source.Master}
for _, c := range cs { for _, c := range cs {
if c == nil { if c == nil {
continue continue
} }
for s := c; s != nil; s = s.Context { for s := c; s != nil; s = s.Context {
if x, ok := s.Commands[arg[0]]; ok { if x, ok := s.Commands[key]; ok {
if !m.Check(s, "commands", arg[0]) {
panic(errors.New(fmt.Sprintf("没有权限:" + arg[0])))
}
m.Master = s m.Master = s
if !m.Check(s, "commands", key) {
break
}
success := false success := false
m.AssertOne(m, true, func(m *Message) { m.AssertOne(m, true, func(m *Message) {
if m.Code != 0 { m.Log("cmd", "%s: %s %v", s.Name, key, arg)
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)
}
if x.Options != nil { if x.Options != nil {
for _, v := range m.Meta["option"] { for _, v := range m.Meta["option"] {
@ -706,7 +743,7 @@ func (m *Message) Exec(arg ...string) string { // {{{
} }
if x.Formats != nil { 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]] n, ok := x.Formats[args[i]]
if !ok { if !ok {
m.Add("option", "args", arg[i]) 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]...) m.Add("option", args[i], arg[i+1:i+1+n]...)
i += n i += n
} }
arg = m.Meta["args"]
} }
m.Meta["result"] = nil m.Meta["result"] = nil
ret := x.Hand(c, m, arg[0], arg[1:]...) ret := x.Hand(c, m, key, arg...)
if ret != "" { if ret != "" {
m.Echo(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 success = true
}) })
@ -745,8 +788,8 @@ func (m *Message) Exec(arg ...string) string { // {{{
} }
m.AssertOne(m, true, func(m *Message) { m.AssertOne(m, true, func(m *Message) {
log.Printf("system command(%s->%s): %v", m.Source.Name, m.Target.Name, arg) m.Log("system", ":%v", arg)
cmd := exec.Command(arg[0], arg[1:]...) cmd := exec.Command(key, arg[1:]...)
v, e := cmd.CombinedOutput() v, e := cmd.CombinedOutput()
if e != nil { if e != nil {
m.Echo("%s\n", e) 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) { 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"]...) { if post != nil && !post(msg, msg.Meta["result"]...) {
@ -817,9 +860,9 @@ func (m *Message) Check(s *Context, arg ...string) bool { // {{{
if !ok { if !ok {
if g, ok = s.Index["void"]; !ok { if g, ok = s.Index["void"]; !ok {
if m.Master.Owner != nil { 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 { } 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 return false
@ -841,9 +884,9 @@ func (m *Message) Check(s *Context, arg ...string) bool { // {{{
if !ok { if !ok {
if m.Master.Owner != nil { 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 { } 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 return false
} }
@ -860,7 +903,7 @@ func (m *Message) Cmd(arg ...string) string { // {{{
m.Post(s) 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 return x.Value
case 1: case 1:
if m.Code != 0 { m.Log("conf", "%s: %s %v", s.Name, key, arg)
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)
}
x.Value = arg[0] x.Value = arg[0]
if x.Hand != nil { if x.Hand != nil {
@ -890,11 +929,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
} }
return x.Value return x.Value
case 3: case 3:
if m.Code != 0 { m.Log("conf", "%s: %s %v", s.Name, key, arg)
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)
}
if s == m.Target { if s == m.Target {
panic(errors.New(key + "配置项已存在")) panic(errors.New(key + "配置项已存在"))
@ -911,7 +946,7 @@ func (m *Message) Conf(key string, arg ...string) string { // {{{
} }
if len(arg) == 3 { 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 { if m.Target.Configs == nil {
m.Target.Configs = make(map[string]*Config) 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 { // {{{ 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 { for s := m.Target; s != nil; s = s.Context {
if x, ok := s.Caches[key]; ok { if x, ok := s.Caches[key]; ok {
if !m.Check(s, "caches", key) { if !m.Check(s, "caches", key) {
@ -963,7 +992,7 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
} }
return x.Value return x.Value
case 3: 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 { if s == m.Target {
panic(errors.New(key + "缓存项已存在")) panic(errors.New(key + "缓存项已存在"))
} }
@ -978,7 +1007,7 @@ func (m *Message) Cap(key string, arg ...string) string { // {{{
} }
} }
if len(arg) == 3 { 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 { if m.Target.Caches == nil {
m.Target.Caches = make(map[string]*Cache) m.Target.Caches = make(map[string]*Cache)
} }
@ -1051,7 +1080,7 @@ var Index = &Context{Name: "ctx", Help: "根模块",
"ContextSessionSize": &Config{Name: "会话队列长度", Value: "10", Help: "每个模块可以启动其它模块的数量"}, "ContextSessionSize": &Config{Name: "会话队列长度", Value: "10", Help: "每个模块可以启动其它模块的数量"},
"MessageQueueSize": &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: "证书文件"}, "cert": &Config{Name: "证书文件", Value: "etc/cert.pem", Help: "证书文件"},
"key": &Config{Name: "私钥文件", Value: "etc/key.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: "查看模块的用户信息", "userinfo": &Command{Name: "userinfo [add|del [context key name help]|[command|config|cache group name]]", Help: "查看模块的用户信息",
Formats: map[string]int{"add": -1, "del": -1}, Formats: map[string]int{"add": -1, "del": -1},
Hand: func(c *Context, m *Message, key string, arg ...string) string { Hand: func(c *Context, m *Message, key string, arg ...string) string {
log.Println(m.Meta) switch { // {{{
switch {
case m.Has("add"): case m.Has("add"):
m.Target.Add(m.Source.Group, m.Meta["add"]...) m.Target.Add(m.Source.Group, m.Meta["add"]...)
case m.Has("del"): case m.Has("del"):
@ -1093,6 +1121,7 @@ var Index = &Context{Name: "ctx", Help: "根模块",
} }
} }
return "" return ""
// }}}
}}, }},
"server": &Command{Name: "server [start|exit|switch][args]", Help: "服务启动停止切换", Hand: func(c *Context, m *Message, key string, arg ...string) string { "server": &Command{Name: "server [start|exit|switch][args]", Help: "服务启动停止切换", Hand: func(c *Context, m *Message, key string, arg ...string) string {
switch len(arg) { // {{{ switch len(arg) { // {{{
@ -1116,14 +1145,71 @@ var Index = &Context{Name: "ctx", Help: "根模块",
return "" return ""
// }}} // }}}
}}, }},
"message": &Command{Name: "message", Help: "查看消息", Hand: func(c *Context, m *Message, key string, arg ...string) string { "message": &Command{Name: "message [index|home] [order]", Help: "查看消息", Hand: func(c *Context, m *Message, key string, arg ...string) string {
ms := []*Message{m.Root} // {{{ switch len(arg) { // {{{
for i := 0; i < len(ms); i++ { case 0:
if ms[i].Code != 0 { for k, v := range m.Target.Sessions {
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"]) 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"])
}
}
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])
}
} }
ms = append(ms, ms[i].Messages...)
} }
return "" return ""
// }}} // }}}
}}, }},
@ -1163,60 +1249,52 @@ var Index = &Context{Name: "ctx", Help: "根模块",
return "" 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 { "config": &Command{Name: "config [all] [[delete|void] key [value]|[name value help]]", Help: "删除、空值、查看、修改或添加配置",
all := false // {{{ Formats: map[string]int{"all": 0, "delete": 0, "void": 0},
if len(arg) > 0 && arg[0] == "all" { Hand: func(c *Context, m *Message, key string, arg ...string) string {
arg = arg[1:] all := m.Has("all") // {{{
all = true
}
m.Target.BackTrace(func(s *Context) bool {
switch len(arg) { switch len(arg) {
case 0: case 0:
for k, v := range s.Configs { m.Target.BackTrace(func(s *Context) bool {
if m.Check(m.Target, "configs", k) { m.Echo("%s configs:\n", s.Name)
m.Echo("%s(%s): %s\n", k, v.Value, v.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)
case 1:
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: return all
if m.Check(m.Target, "configs", arg[0]) { })
m.Conf(arg[0], arg[1]) 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)
}
} }
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: case 4:
if m.Check(m.Target) { m.Conf(arg[0], arg[1:]...)
m.Conf(arg[0], arg[1:]...)
}
return false
} }
return all return ""
}) // }}}
return "" }},
// }}}
}},
"cache": &Command{Name: "cache [all] [[delete] key [value]|[name value help]]", Help: "删除、查看、修改或添加配置", Hand: func(c *Context, m *Message, key string, arg ...string) string { "cache": &Command{Name: "cache [all] [[delete] key [value]|[name value help]]", Help: "删除、查看、修改或添加配置", Hand: func(c *Context, m *Message, key string, arg ...string) string {
all := false // {{{ all := false // {{{
if len(arg) > 0 && arg[0] == "all" { if len(arg) > 0 && arg[0] == "all" {
@ -1273,6 +1351,9 @@ var Index = &Context{Name: "ctx", Help: "根模块",
}, },
Index: map[string]*Context{ Index: map[string]*Context{
"void": &Context{Name: "void", "void": &Context{Name: "void",
Caches: map[string]*Cache{
"nmessage": &Cache{},
},
Configs: map[string]*Config{ Configs: map[string]*Config{
"debug": &Config{}, "debug": &Config{},
}, },
@ -1305,7 +1386,6 @@ func Start(args ...string) {
if len(args) > 3 { if len(args) > 3 {
Pulse.Conf("root", args[3]) Pulse.Conf("root", args[3])
} }
log.Println("\n\n\n")
Pulse.Travel(Index, func(m *Message) bool { Pulse.Travel(Index, func(m *Message) bool {
m.Target.Begin(m) m.Target.Begin(m)

View File

@ -8,7 +8,6 @@ import ( // {{{
"errors" "errors"
"fmt" "fmt"
"log"
) )
// }}} // }}}
@ -19,25 +18,11 @@ type MDB struct {
} }
func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{ 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 return mdb
} }
// }}} // }}}
func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{ 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") == "" { if m.Conf("source") == "" || m.Conf("driver") == "" {
return true 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")) db, e := sql.Open(m.Conf("driver"), m.Conf("source"))
m.Assert(e) m.Assert(e)
mdb.db = db mdb.db = db
defer mdb.db.Close()
log.Println(mdb.Name, "open:", m.Conf("driver"), m.Conf("source")) m.Log("info", "%s: open %s %s", mdb.Name, m.Conf("driver"), m.Conf("source"))
defer log.Println(mdb.Name, "close:", m.Conf("driver"), m.Conf("source")) m.Capi("nsource", 1)
for _, p := range m.Meta["prepare"] {
_, e := db.Exec(p)
m.Assert(e)
}
return true 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 { // {{{ func (mdb *MDB) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{} 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 := new(MDB)
s.Context = c 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 { // {{{ 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 return true
} }
@ -81,15 +77,11 @@ var Index = &ctx.Context{Name: "mdb", Help: "内存数据库",
}, },
Configs: map[string]*ctx.Config{}, Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
"open": &ctx.Command{Name: "open [source [driver]]", Help: "打开数据库", "open": &ctx.Command{Name: "open name [source [driver]]", Help: "打开数据库", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
Options: map[string]string{ m.Start(arg[0], arg[1:]...) // {{{
"prepare": "打开数据库时自动执行的语句", return ""
}, // }}}
Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string { }},
m.Start("db"+m.Cap("nsource"), arg...) // {{{
return ""
// }}}
}},
"exec": &ctx.Command{Name: "exec sql [arg]", Help: "执行SQL语句", "exec": &ctx.Command{Name: "exec sql [arg]", Help: "执行SQL语句",
Appends: map[string]string{ Appends: map[string]string{
"LastInsertId": "最后插入元组的标识", "LastInsertId": "最后插入元组的标识",

View File

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