1
0
forked from x/icebergs

add log&gdb

This commit is contained in:
shaoying 2019-12-18 23:38:01 +08:00
parent a2dfaa3b19
commit 7a2f552db5
13 changed files with 462 additions and 98 deletions

89
base.go
View File

@ -2,11 +2,15 @@ package ice
import (
"github.com/shylinux/toolkits"
"os"
"strings"
"sync"
"time"
)
type Frame struct {
code int
}
func (f *Frame) Spawn(m *Message, c *Context, arg ...string) Server {
@ -21,28 +25,15 @@ func (f *Frame) Begin(m *Message, arg ...string) Server {
list[s] = sub
}
})
m.target.wg = &sync.WaitGroup{}
return f
}
func (f *Frame) Start(m *Message, arg ...string) bool {
// 加载配置
m.Travel(func(p *Context, s *Context) {
if _, ok := s.Commands["_init"]; ok {
m.Spawns(s).Runs("_init", "_init", arg...)
}
})
// 启动服务
Index.begin.Cmd(arg)
m.Cmd("_init").Cmd("init", arg)
return true
}
func (f *Frame) Close(m *Message, arg ...string) bool {
// 保存配置
m.Travel(func(p *Context, s *Context) {
if _, ok := s.Commands["_exit"]; ok {
m.Spawns(s).Runs("_exit", "_exit", arg...)
}
})
m.target.wg.Wait()
list := map[*Context]*Message{m.target: m}
m.Travel(func(p *Context, s *Context) {
if msg, ok := list[p]; ok && msg != nil {
@ -55,29 +46,63 @@ func (f *Frame) Close(m *Message, arg ...string) bool {
}
var Index = &Context{Name: "ice", Help: "冰山模块",
Caches: map[string]*Cache{},
Caches: map[string]*Cache{
"status": {Value: "begin"},
"stream": {Value: "shy"},
},
Configs: map[string]*Config{
"table": {Name: "数据缓存", Value: map[string]interface{}{
"space": " ",
"col_sep": " ",
"row_sep": "\n",
"compact": "false",
}},
"cache": {Name: "数据缓存", Value: map[string]interface{}{
"store": "var/data",
"limit": "30",
"least": "10",
}},
"help": {Value: map[string]interface{}{
"index": []interface{}{
"^_^ 欢迎使用冰山框架 ^_^",
"^_^ Welcome to Icebergs world ^_^",
"",
"Meet: shylinuxc@gmail.com",
"More: https://shylinux.com",
"More: https://github.com/shylinux/icebergs",
"",
},
}},
},
Commands: map[string]*Command{
"_init": {Name: "_init", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
m.Travel(func(p *Context, s *Context) {
if _, ok := s.Commands["_init"]; ok && p != nil {
m.Spawns(s).Runs("_init", "_init", arg...)
}
})
}},
"init": {Name: "init", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
m.Start("log", arg...)
m.Start("gdb", arg...)
m.Start("ssh", arg...)
m.Cmd(arg)
}},
"help": {Name: "help", Help: "帮助", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
m.Echo(strings.Join(kit.Simple(m.Confv("help", "index")), "\n"))
}},
"exit": {Name: "exit", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
c.Close(m.Spawn(c), arg...)
os.Exit(kit.Int(kit.Select("0", arg, 0)))
}},
"restart": {Name: "restart", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
switch kit.Select("0", arg, 0) {
case "0":
c.Close(m.Spawn(c), arg...)
os.Exit(kit.Int(kit.Select("0", arg, 0)))
}
Code = kit.Int(kit.Select("0", arg, 0))
m.root.Cmd("_exit")
}},
"_exit": {Name: "_init", Help: "hello", Hand: func(m *Message, c *Context, cmd string, arg ...string) {
m.root.Travel(func(p *Context, s *Context) {
if _, ok := s.Commands["_exit"]; ok && p != nil {
m.TryCatch(m.Spawns(s), true, func(msg *Message) {
msg.Runs("_exit", "_exit", arg...)
})
}
})
}},
},
}
@ -94,9 +119,10 @@ var Pulse = &Message{
func init() {
Index.root = Index
Pulse.root = Pulse
Index.server = &Frame{}
}
var Code = 0
func Run(arg ...string) string {
if len(arg) == 0 {
arg = os.Args[1:]
@ -105,8 +131,13 @@ func Run(arg ...string) string {
arg = append(arg, os.Getenv("ice_serve"))
}
if Index.Begin(Pulse.Spawns(), arg...).Start(Index.begin.Spawns(), arg...) {
Index.Close(Index.start.Spawns(), arg...)
frame := &Frame{}
Index.server = frame
if frame.Begin(Pulse.Spawns(), arg...).Start(Pulse.Spawns(), arg...) {
frame.Close(Pulse.Spawns(), arg...)
}
time.Sleep(time.Second)
os.Exit(Code)
return Pulse.Result()
}

View File

@ -24,6 +24,8 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
},
Commands: map[string]*ice.Command{
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd("ctx.config", "load", "var/conf/cli.json")
m.Conf("runtime", "host.GOARCH", runtime.GOARCH)
m.Conf("runtime", "host.GOOS", runtime.GOOS)
m.Conf("runtime", "host.pid", os.Getpid())
@ -42,6 +44,9 @@ var Index = &ice.Context{Name: "cli", Help: "命令模块",
m.Conf("runtime", "node.name", m.Conf("runtime", "boot.pathname"))
m.Log("info", "runtime %v", kit.Formats(m.Confv("runtime")))
}},
"_exit": {Name: "_exit", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd("ctx.config", "save", "var/conf/cli.json", "cli.runtime")
}},
"runtime": {Name: "runtime", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
}},
"system": {Name: "system", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) {

View File

@ -5,19 +5,40 @@ import (
"github.com/shylinux/icebergs"
"github.com/shylinux/toolkits"
"os"
"sort"
)
var Index = &ice.Context{Name: "ctx", Help: "元始模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
"context": {Name: "context", Help: "模块", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
ice.Pulse.Travel(func(p *ice.Context, s *ice.Context) {
if p != nil {
m.Push("ups", p.Name)
} else {
m.Push("ups", "shy")
}
m.Push("name", s.Name)
m.Push("status", s.Cap("status"))
m.Push("stream", s.Cap("stream"))
m.Push("help", s.Help)
})
}},
"command": {Name: "command", Help: "命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if len(arg) == 0 {
ice.Pulse.Travel(func(p *ice.Context, s *ice.Context) {
for k, v := range s.Commands {
list := []string{}
for k := range s.Commands {
if k[0] == '/' || k[0] == '_' {
continue
}
list = append(list, k)
}
sort.Strings(list)
for _, k := range list {
v := s.Commands[k]
if p != nil && p != ice.Index {
m.Push("key", p.Name+"."+s.Name)
} else {
@ -39,12 +60,9 @@ var Index = &ice.Context{Name: "ctx", Help: "元始模块",
m.Push("meta", kit.Format(i.Meta))
m.Push("list", kit.Format(i.List))
} else {
switch arg[2] {
case "run":
m.Copy(m.Spawns(s).Runs(key, key, arg[3:]...))
}
}
}
})
}},
"config": {Name: "config", Help: "配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -10,7 +10,7 @@ import (
)
type Frame struct {
signal chan os.Signal
p chan os.Signal
}
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
@ -22,35 +22,37 @@ func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
f.WriteString(kit.Format(os.Getpid()))
m.Log("info", "pid %d %s", os.Getpid(), p)
}
f.signal = make(chan os.Signal, 10)
m.Confm("signal", nil, func(sig string, action string) {
m.Log("signal", "add %s: %s", sig, action)
signal.Notify(f.signal, syscall.Signal(kit.Int(sig)))
})
m.Gos(m, func(m *ice.Message) {
if s, ok := <-f.signal; ok {
m.Log("info", "signal %v", s)
m.Cmd(m.Confv("signal", kit.Format(s)))
}
})
m.Gos(m, func(m *ice.Message) {
for {
time.Sleep(100 * time.Millisecond)
now := int(time.Now().Unix())
m.Confm("timer", "hash", func(key string, value map[string]interface{}) {
if kit.Int(value["next"]) <= now {
m.Log("info", "timer %v %v", key, value["next"])
m.Cmd(value["cmd"])
value["next"] = now + int(kit.Duration(value["interval"]))/int(time.Second)
}
})
}
})
return f
}
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
f.p = make(chan os.Signal, 10)
m.Confm("signal", nil, func(sig string, action string) {
m.Log("signal", "add %s: %s", sig, action)
signal.Notify(f.p, syscall.Signal(kit.Int(sig)))
})
m.Cap("stream", m.Conf("timer", "meta.tick"))
tick := time.Tick(kit.Duration(m.Conf("timer", "meta.tick")))
for {
select {
case sig, ok := <-f.p:
if !ok {
return true
}
m.Log("info", "signal %v", sig)
m.Cmd(m.Confv("signal", kit.Format(sig)))
case now, _ := <-tick:
// m.Log("info", "ticker %v", kit.Format(now))
stamp := int(now.Unix())
m.Confm("timer", "hash", func(key string, value map[string]interface{}) {
if kit.Int(value["next"]) <= stamp {
m.Log("info", "timer %v %v", key, value["next"])
m.Cmd(value["cmd"])
value["next"] = stamp + int(kit.Duration(value["interval"]))/int(time.Second)
}
})
}
}
return true
}
func (f *Frame) Close(m *ice.Message, arg ...string) bool {
@ -62,18 +64,29 @@ var Index = &ice.Context{Name: "gdb", Help: "调试模块",
Configs: map[string]*ice.Config{
"logpid": &ice.Config{Name: "logpid", Value: "var/run/shy.pid", Help: ""},
"signal": &ice.Config{Name: "signal", Value: map[string]interface{}{
"2": []interface{}{"exit"}, "3": "QUIT", "15": "TERM",
"2": []interface{}{"exit"},
"3": []interface{}{"exit", "1"},
"15": []interface{}{"exit", "1"},
"30": []interface{}{"exit"},
"31": []interface{}{"exit", "1"},
"28": "WINCH",
"30": "restart",
"31": "upgrade",
}, Help: "信号"},
"timer": {Name: "定时器", Value: map[string]interface{}{
"meta": map[string]interface{}{},
"meta": map[string]interface{}{
"tick": "100ms",
},
"hash": map[string]interface{}{},
"list": map[string]interface{}{},
}},
},
Commands: map[string]*ice.Command{
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
}},
"_exit": {Name: "_exit", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
close(f.p)
}},
"timer": {Name: "timer", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
case "start":

View File

@ -1,17 +1,93 @@
package log
import (
"fmt"
"github.com/shylinux/icebergs"
"github.com/shylinux/toolkits"
"os"
"path"
)
type Log struct {
m *ice.Message
level string
str string
}
type Frame struct {
p chan *Log
}
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
return &Frame{}
}
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
f.p = make(chan *Log, 100)
ice.Log = func(msg *ice.Message, level string, str string) {
f.p <- &Log{m: msg, level: level, str: str}
}
return f
}
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
m.Confm("file", nil, func(key string, value map[string]interface{}) {
if f, p, e := kit.Create(kit.Format(value["path"])); m.Assert(e) {
m.Cap("stream", path.Base(p))
m.Log("info", "log %s %s", key, p)
value["file"] = f
}
})
for {
if l, ok := <-f.p; !ok {
break
} else {
file := kit.Select("bench", m.Conf("show", l.level+".file"))
f := m.Confv("file", file+".file").(*os.File)
ls := []string{l.m.Format("prefix"), " "}
ls = append(ls, m.Conf("show", l.level+".prefix"),
l.level, " ", l.str, m.Conf("show", l.level+".suffix"), "\n")
for _, v := range ls {
fmt.Fprintf(f, v)
}
}
}
return true
}
func (f *Frame) Close(m *ice.Message, arg ...string) bool {
return true
}
var Index = &ice.Context{Name: "log", Help: "日志模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Configs: map[string]*ice.Config{
"file": &ice.Config{Name: "file", Value: map[string]interface{}{
"bench": map[string]interface{}{"path": "var/log/bench.log"},
}, Help: "信号"},
"show": &ice.Config{Name: "file", Value: map[string]interface{}{
"bench": map[string]interface{}{"file": "bench"},
"cmd": map[string]interface{}{"file": "bench", "prefix": "\033[32m", "suffix": "\033[0m"},
"start": map[string]interface{}{"file": "bench", "prefix": "\033[32m", "suffix": "\033[0m"},
"serve": map[string]interface{}{"file": "bench", "prefix": "\033[32m", "suffix": "\033[0m"},
"cost": map[string]interface{}{"file": "bench", "prefix": "\033[33m", "suffix": "\033[0m"},
"warn": map[string]interface{}{"file": "bench", "prefix": "\033[31m", "suffix": "\033[0m"},
"close": map[string]interface{}{"file": "bench", "prefix": "\033[31m", "suffix": "\033[0m"},
}, Help: "信号"},
},
Commands: map[string]*ice.Command{
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
}},
"_exit": {Name: "_exit", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
ice.Log = nil
close(f.p)
}},
},
}
func init() { ice.Index.Register(Index, nil) }
func init() { ice.Index.Register(Index, &Frame{}) }

View File

@ -4,9 +4,13 @@ import (
_ "github.com/shylinux/icebergs/base/aaa"
_ "github.com/shylinux/icebergs/base/cli"
_ "github.com/shylinux/icebergs/base/ctx"
_ "github.com/shylinux/icebergs/base/web"
_ "github.com/shylinux/icebergs/base/gdb"
_ "github.com/shylinux/icebergs/base/log"
_ "github.com/shylinux/icebergs/base/mdb"
_ "github.com/shylinux/icebergs/base/nfs"
_ "github.com/shylinux/icebergs/base/web"
_ "github.com/shylinux/icebergs/base/ssh"
_ "github.com/shylinux/icebergs/base/tcp"
)

View File

@ -2,16 +2,73 @@ package ssh
import (
"github.com/shylinux/icebergs"
"github.com/shylinux/toolkits"
"bufio"
"fmt"
"io"
"os"
)
var Index = &ice.Context{Name: "ssh", Help: "远程模块",
type Frame struct {
in io.ReadCloser
out io.WriteCloser
}
func (f *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
return &Frame{}
}
func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
return f
}
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
f.in = os.Stdin
f.out = os.Stdout
m.Cap("stream", "stdio")
prompt := "%d[15:04:05]%s> "
target := m.Target()
count := 0
bio := bufio.NewScanner(f.in)
fmt.Fprintf(f.out, m.Time(prompt, count, target.Name))
for bio.Scan() {
ls := kit.Split(bio.Text())
m.Log("info", "input %v", ls)
msg := m.Spawn(target)
if msg.Cmdy(ls); !msg.Hand {
msg = msg.Cmdy("cli.system", ls)
}
res := msg.Result()
if res == "" {
msg.Table()
res = msg.Result()
}
fmt.Fprintf(f.out, res)
fmt.Fprintf(f.out, m.Time(prompt, count, target.Name))
count++
}
return true
}
func (f *Frame) Close(m *ice.Message, arg ...string) bool {
return true
}
var Index = &ice.Context{Name: "ssh", Help: "终端模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
}},
"_exit": {Name: "_exit", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
f := m.Target().Server().(*Frame)
f.in.Close()
m.Target().Done()
}},
},
}
func init() { ice.Index.Register(Index, nil) }
func init() { ice.Index.Register(Index, &Frame{}) }

View File

@ -2,14 +2,40 @@ package tcp
import (
"github.com/shylinux/icebergs"
"net"
"strings"
)
var Index = &ice.Context{Name: "tcp", Help: "网络模块",
Caches: map[string]*ice.Cache{},
Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
"hi": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
"ifconfig": {Name: "ifconfig [name]", Help: "网络配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
if ifs, e := net.Interfaces(); m.Assert(e) {
for _, v := range ifs {
if len(arg) > 0 && !strings.Contains(v.Name, arg[0]) {
continue
}
if ips, e := v.Addrs(); m.Assert(e) {
for _, x := range ips {
ip := strings.Split(x.String(), "/")
if strings.Contains(ip[0], ":") || len(ip) == 0 {
continue
}
if len(v.HardwareAddr.String()) == 0 {
continue
}
m.Push("index", v.Index)
m.Push("name", v.Name)
m.Push("ip", ip[0])
m.Push("mask", ip[1])
m.Push("hard", v.HardwareAddr.String())
}
}
}
m.Table()
}
}},
},
}

View File

@ -269,6 +269,7 @@ func (web *WEB) Start(m *ice.Message, arg ...string) bool {
})
port := kit.Select(m.Conf("spide", "self.port"), arg, 0)
m.Cap("stream", port)
web.m = m
web.Server = &http.Server{Addr: port, Handler: web}
m.Log("serve", "node %v", m.Conf("cli.runtime", "node"))
@ -311,10 +312,13 @@ var Index = &ice.Context{Name: "web", Help: "网页模块",
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Echo("hello %s world", c.Name)
}},
"_exit": {Name: "_exit", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Target().Done()
}},
"serve": {Name: "hi", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Conf("cli.runtime", "node.type", "server")
m.Conf("cli.runtime", "node.name", m.Conf("cli.runtime", "boot.hostname"))
m.Run(arg...)
m.Target().Start(m, arg...)
}},
"/space": &ice.Command{Name: "/space", Help: "", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
r := m.Optionv("request").(*http.Request)

View File

@ -18,7 +18,6 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块",
},
Commands: map[string]*ice.Command{
"_init": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd("ctx.config", "load", "var/conf/cli.json")
m.Cmd("ctx.config", "load", "var/conf/aaa.json")
m.Cmd("ctx.config", "load", "var/conf/chat.json")
}},
@ -42,7 +41,6 @@ var Index = &ice.Context{Name: "chat", Help: "聊天模块",
"_exit": {Name: "_init", Help: "hello", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Cmd("ctx.config", "save", "var/conf/chat.json", "web.chat.group")
m.Cmd("ctx.config", "save", "var/conf/aaa.json", "aaa.role", "aaa.user", "aaa.sess")
m.Cmd("ctx.config", "save", "var/conf/cli.json", "cli.runtime")
}},
"/login": {Name: "/login", Help: "登录", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {

View File

@ -2,6 +2,7 @@
export ice_app=${ice_app:="ice.app"}
export ice_err=${ice_err:="boot.log"}
export ice_conf=${ice_app:="var/conf"}
export ice_serve=${ice_serve:="web.serve"}
prepare() {
@ -38,13 +39,16 @@ build() {
start() {
[ -d usr/volcanos ] || git clone https://github.com/shylinux/volcanos usr/volcanos
while true; do
date && $ice_app $* 2>$ice_err && log "\n\nrestarting..." && sleep 1 || break
date && $ice_app $* 2>$ice_err && log "\n\nrestarting..." || break
done
}
log() { echo -e $*; }
restart() {
kill -2 `cat var/run/shy.pid`
}
shutdown() {
kill -3 `cat var/run/shy.pid`
}
help() {
echo "usage: $0 cmd arg"
}

View File

@ -1,5 +1,16 @@
# {{title "hello world"}}
init.register
ice.Begin
ice.Start
ice.Close
{{chart "table" `
ctx cli aaa web
lex yac gdb log
tcp nfs ssh mdb
`}}
{{chart "chain" `
context
volcanos

145
type.go
View File

@ -13,6 +13,7 @@ import (
"runtime"
"sort"
"strings"
"sync"
"time"
)
@ -44,11 +45,12 @@ type Context struct {
contexts map[string]*Context
context *Context
root *Context
begin *Message
start *Message
exit chan bool
server Server
wg *sync.WaitGroup
id int
}
type Server interface {
@ -62,6 +64,12 @@ func (c *Context) ID() int {
c.id++
return c.id
}
func (c *Context) Cap(key string, arg ...interface{}) string {
if len(arg) > 0 {
c.Caches[key].Value = kit.Format(arg[0])
}
return c.Caches[key].Value
}
func (c *Context) Server() Server {
return c.server
}
@ -77,18 +85,43 @@ func (c *Context) Register(s *Context, x Server) *Context {
return s
}
func (c *Context) Done() bool {
if c.context != nil && c.context.wg != nil {
c.context.wg.Done()
} else {
c.root.wg.Done()
}
return true
}
func (c *Context) Begin(m *Message, arg ...string) *Context {
c.begin = m
c.Caches["status"] = &Cache{Name: "status", Value: ""}
c.Caches["stream"] = &Cache{Name: "stream", Value: ""}
m.Log("begin", "%s", c.Name)
if c.server != nil {
if c.begin = m; c.server != nil {
m.TryCatch(m, true, func(m *Message) {
c.server.Begin(m, arg...)
})
}
return c
}
func (c *Context) Start(m *Message, arg ...string) bool {
c.start = m
if c.context != nil && c.context.wg != nil {
c.context.wg.Add(1)
} else {
c.root.wg.Add(1)
}
m.Gos(m, func(m *Message) {
m.Log("start", "%s", c.Name)
return c.server.Start(m, arg...)
c.Cap("status", "start")
c.server.Start(m, arg...)
c.Cap("status", "close")
c.Done()
})
return true
}
func (c *Context) Close(m *Message, arg ...string) bool {
m.Log("close", "%s", c.Name)
@ -347,6 +380,67 @@ func (m *Message) Table(cbs ...interface{}) *Message {
cb(i, line, m.meta["append"])
}
}
return m
}
//计算列宽
space := kit.Select(m.Conf("table", "space"), m.Option("table.space"))
depth, width := 0, map[string]int{}
for _, k := range m.meta["append"] {
if len(m.meta[k]) > depth {
depth = len(m.meta[k])
}
width[k] = kit.Width(k, len(space))
for _, v := range m.meta[k] {
if kit.Width(v, len(space)) > width[k] {
width[k] = kit.Width(v, len(space))
}
}
}
// 回调函数
rows := kit.Select(m.Conf("table", "row_sep"), m.Option("table.row_sep"))
cols := kit.Select(m.Conf("table", "col_sep"), m.Option("table.col_sep"))
compact := kit.Select(m.Conf("table", "compact"), m.Option("table.compact")) == "true"
cb := func(maps map[string]string, lists []string, line int) bool {
for i, v := range lists {
if k := m.meta["append"][i]; compact {
v = maps[k]
}
if m.Echo(v); i < len(lists)-1 {
m.Echo(cols)
}
}
m.Echo(rows)
return true
}
// 输出表头
row := map[string]string{}
wor := []string{}
for _, k := range m.meta["append"] {
row[k], wor = k, append(wor, k+strings.Repeat(space, width[k]-kit.Width(k, len(space))))
}
if !cb(row, wor, -1) {
return m
}
// 输出数据
for i := 0; i < depth; i++ {
row := map[string]string{}
wor := []string{}
for _, k := range m.meta["append"] {
data := ""
if i < len(m.meta[k]) {
data = m.meta[k][i]
}
row[k], wor = data, append(wor, data+strings.Repeat(space, width[k]-kit.Width(data, len(space))))
}
if !cb(row, wor, i) {
break
}
}
return m
}
@ -392,14 +486,19 @@ func (m *Message) Result(arg ...interface{}) string {
return strings.Join(m.Resultv(), "")
}
var Log func(*Message, string, string)
func (m *Message) Log(level string, str string, arg ...interface{}) *Message {
if Log != nil {
Log(m, level, fmt.Sprintf(str, arg...))
}
prefix, suffix := "", ""
switch level {
case "cmd":
case "cmd", "start", "serve":
prefix, suffix = "\033[32m", "\033[0m"
case "cost":
prefix, suffix = "\033[33m", "\033[0m"
case "warn":
case "warn", "close":
prefix, suffix = "\033[31m", "\033[0m"
}
fmt.Fprintf(os.Stderr, "%s %d %s->%s %s%s %s%s\n",
@ -446,8 +545,14 @@ func (m *Message) Travel(cb func(p *Context, s *Context)) *Message {
list := []*Context{m.target}
for i := 0; i < len(list); i++ {
cb(list[i].context, list[i])
for _, v := range list[i].contexts {
list = append(list, v)
ls := []string{}
for k := range list[i].contexts {
ls = append(ls, k)
}
sort.Strings(ls)
for _, k := range ls {
list = append(list, list[i].contexts[k])
}
}
return m
@ -496,6 +601,14 @@ func (m *Message) Runs(key string, cmd string, arg ...string) *Message {
}
return m
}
func (m *Message) Start(key string, arg ...string) *Message {
m.Travel(func(p *Context, s *Context) {
if s.Name == key {
s.Start(m.Spawns(s), arg...)
}
})
return m
}
func (m *Message) Call(sync bool, cb func(*Message) *Message) *Message {
if sync {
wait := make(chan bool)
@ -721,20 +834,23 @@ func (m *Message) Cmd(arg ...interface{}) *Message {
return m
}
msg := m
m.Search(list[0], func(p *Context, s *Context, key string) {
for c := s; c != nil; c = c.context {
if cmd, ok := c.Commands[key]; ok {
msg = m.Spawns(s).Log("cmd", "%s.%s %v", c.Name, key, list[1:])
m.TryCatch(m.Spawns(s), true, func(msg *Message) {
msg.Log("cmd", "%s.%s %v", c.Name, key, list[1:])
msg.meta["detail"] = list
msg.TryCatch(msg, true, func(msg *Message) {
cmd.Hand(msg, c, key, list[1:]...)
msg.Hand = true
m.Hand = true
m = msg
})
break
}
}
})
return msg
return m
}
func (m *Message) Confv(arg ...interface{}) (val interface{}) {
m.Search(arg[0], func(p *Context, s *Context, key string) {
@ -780,7 +896,8 @@ func (m *Message) Capv(arg ...interface{}) interface{} {
for _, s := range []*Context{m.target} {
for c := s; c != nil; c = c.context {
if caps, ok := c.Caches[key]; ok {
return kit.Value(caps.Value, arg[0])
caps.Value = kit.Format(arg[0])
return caps.Value
}
}
}