diff --git a/etc/go.snippets b/etc/go.snippets index 346a084b..f987e19f 100644 --- a/etc/go.snippets +++ b/etc/go.snippets @@ -26,6 +26,7 @@ snippet c ) type `toupper(substitute(expand("%:t"), ".go", "", ""))` struct { + *ctx.Message *ctx.Context } diff --git a/etc/init.shy b/etc/init.shy index c83b64c8..ce6d67fd 100644 --- a/etc/init.shy +++ b/etc/init.shy @@ -7,10 +7,8 @@ function plus let a = $a + 1 end end -~yac check -~lex check -~log config bench.log hi.log +~log config bench.log hi.log return if 2 < 1 diff --git a/src/context/ctx.go b/src/context/ctx.go index be505ad2..fc451c2e 100644 --- a/src/context/ctx.go +++ b/src/context/ctx.go @@ -1,6 +1,7 @@ package ctx // {{{ // }}} import ( // {{{ + "crypto/md5" "encoding/hex" "errors" @@ -19,7 +20,7 @@ import ( // {{{ // }}} -func right(str string) bool { +func Right(str string) bool { return str != "" && str != "0" && str != "false" } @@ -127,13 +128,12 @@ func (c *Context) Spawn(m *Message, name string, help string) *Context { // {{{ func (c *Context) Begin(m *Message) *Context { // {{{ c.Caches["status"] = &Cache{Name: "服务状态(begin/start/close)", Value: "begin", Help: "服务状态,begin:初始完成,start:正在运行,close:未在运行"} c.Caches["stream"] = &Cache{Name: "服务数据", Value: "", Help: "服务数据"} - c.Caches["debug"] = &Cache{Name: "命令日志", Value: "true", Help: "嵌套层级"} - c.Configs["debug"] = &Config{Name: "过程日志", Value: "true", Help: "嵌套层级"} m.Index = 1 c.Pulse = m c.Requests = []*Message{m} c.Historys = []*Message{m} + c.Sessions = map[string]*Message{} c.master = m.master.master c.Owner = m.master.Owner @@ -477,6 +477,11 @@ func (m *Message) Code() int { // {{{ return m.code } +// }}} +func (m *Message) Message() *Message { // {{{ + return m.message +} + // }}} func (m *Message) Source(s ...*Context) *Context { // {{{ if len(s) > 0 { @@ -502,40 +507,31 @@ func (m *Message) Target(s ...*Context) *Context { // {{{ } // }}} +var i = 0 -func (m *Message) Log(action string, ctx *Context, str string, arg ...interface{}) { // {{{ - color := 0 - switch action { - case "error", "check": - color = 31 - case "cmd": - color = 32 - case "conf": - color = 33 - case "search", "find", "spawn": - color = 35 - case "begin", "start", "close": - color = 36 - case "debug": - if !m.Confs("debug") { - return +func (m *Message) Log(action string, ctx *Context, str string, arg ...interface{}) { + if !m.Options("log") { + return + } + + if l := m.Sess("log"); l != nil { + if i++; i > 20000 { + debug.PrintStack() + os.Exit(1) } + // l.Wait = nil + l.Options("log", false) + l.Cmd("log", action, fmt.Sprintf(str, arg...)) + } else { + log.Printf(str, arg...) + return } - - if ctx == nil { - ctx = m.target - } - - info := fmt.Sprintf("%s", ctx.Name) - name := fmt.Sprintf("%s->%s", m.source.Name, m.target.Name) - if m.Name != "" { - name = fmt.Sprintf("%s:%s->%s.%d", m.source.Name, m.Name, m.target.Name, m.Index) - } - - log.Printf("\033[%dm%d %s(%s) %s: %s\033[0m", color, m.code, action, name, info, fmt.Sprintf(str, arg...)) } -// }}} +func (m *Message) Gdb(action string) { + +} + func (m *Message) Check(s *Context, arg ...string) bool { // {{{ if s.Owner == nil { return true @@ -603,7 +599,7 @@ func (m *Message) Check(s *Context, arg ...string) bool { // {{{ } // }}} -func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{ +func (m *Message) Assert(e interface{}, msg ...string) bool { switch e := e.(type) { case error: case bool: @@ -622,6 +618,7 @@ func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{ msg = msg[2:] } case *Message: + os.Exit(1) panic(e) default: return true @@ -641,15 +638,16 @@ func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{ } m.Set("result", "error: ", fmt.Sprintln(e), "\n") + os.Exit(1) panic(e) } -// }}} func (m *Message) AssertOne(msg *Message, safe bool, hand ...func(msg *Message)) *Message { // {{{ defer func() { if e := recover(); e != nil { switch e.(type) { case *Message: + os.Exit(1) panic(e) } @@ -693,6 +691,7 @@ func (m *Message) Spawn(c *Context, key ...string) *Message { // {{{ } m.messages = append(m.messages, msg) + msg.Wait = make(chan bool) if len(key) == 0 { return msg } @@ -820,6 +819,34 @@ func (m *Message) Start(name string, help string, arg ...string) bool { // {{{ // }}} +func (m *Message) Sess(key string, arg ...string) *Message { + if len(arg) > 0 { + root := true + if len(arg) > 2 { + root = Right(arg[2]) + } + method := "find" + if len(arg) > 1 { + method = arg[1] + } + switch method { + case "find": + m.target.Sessions[key] = m.Find(arg[0], root) + case "search": + m.target.Sessions[key] = m.Search(arg[0], root)[0] + } + return m.target.Sessions[key] + } + + for msg := m; msg != nil; msg = msg.message { + if x, ok := msg.target.Sessions[key]; ok { + return m.Spawn(x.target) + } + } + + return nil +} + func (m *Message) Add(meta string, key string, value ...string) *Message { // {{{ if m.Meta == nil { m.Meta = make(map[string][]string) @@ -855,6 +882,9 @@ func (m *Message) Add(meta string, key string, value ...string) *Message { // {{ // }}} func (m *Message) Set(meta string, arg ...string) *Message { // {{{ + if m.Meta == nil { + m.Meta = make(map[string][]string) + } switch meta { case "detail", "result": delete(m.Meta, meta) @@ -937,7 +967,7 @@ func (m *Message) Geti(key string) int { // {{{ // }}} func (m *Message) Gets(key string) bool { // {{{ - return right(m.Get(key)) + return Right(m.Get(key)) } // }}} @@ -1032,7 +1062,7 @@ func (m *Message) Detaili(index int, arg ...int) int { // {{{ // }}} func (m *Message) Details(index int, arg ...bool) bool { // {{{ - return right(m.Insert("detail", index, arg)) + return Right(m.Insert("detail", index, arg)) } // }}} @@ -1049,7 +1079,7 @@ func (m *Message) Resulti(index int, arg ...int) int { // {{{ // }}} func (m *Message) Results(index int, arg ...bool) bool { // {{{ - return right(m.Insert("result", index, arg)) + return Right(m.Insert("result", index, arg)) } // }}} @@ -1092,7 +1122,7 @@ func (m *Message) Options(key string, arg ...bool) bool { // {{{ m.Option(key, meta...) } - return right(m.Option(key)) + return Right(m.Option(key)) } // }}} @@ -1134,7 +1164,7 @@ func (m *Message) Appends(key string, arg ...bool) bool { // {{{ m.Append(key, meta...) } - return right(m.Append(key)) + return Right(m.Append(key)) } // }}} @@ -1147,9 +1177,7 @@ func (m *Message) Exec(key string, arg ...string) string { // {{{ m.master = m.source if x, ok := s.Commands[key]; ok && x.Hand != nil && m.Check(c, "commands", key) { m.AssertOne(m, true, func(m *Message) { - if !m.target.Has("debug") || m.Caps("debug") { - m.Log("cmd", s, "%d %s %v %v", len(m.target.Historys), key, arg, m.Meta["option"]) - } + m.Log("cmd", s, "%d %s %v %v", len(m.target.Historys), key, arg, m.Meta["option"]) if x.Options != nil { for _, v := range m.Meta["option"] { @@ -1246,10 +1274,6 @@ func (m *Message) Post(s *Context, async ...bool) string { // {{{ } if s != nil && s.messages != nil { - if len(async) == 0 || async[0] == false { - m.Wait = make(chan bool) - } - if s.messages <- m; m.Wait != nil { <-m.Wait } @@ -1260,11 +1284,15 @@ func (m *Message) Post(s *Context, async ...bool) string { // {{{ } // }}} -func (m *Message) Cmd(arg ...interface{}) *Message { // {{{ +func (m *Message) Cmd(arg ...interface{}) *Message { if m.Hand { - msg := m.Spawn(m.target) - msg.source = m.source - m = msg + if m.message != nil { + m = m.message.Spawn(m.target) + } else { + msg := m.Spawn(m.target) + msg.source = m.source + m = msg + } } if len(arg) > 0 { @@ -1281,8 +1309,6 @@ func (m *Message) Cmd(arg ...interface{}) *Message { // {{{ return m } -// }}} - func (m *Message) Confs(key string, arg ...bool) bool { // {{{ if len(arg) > 0 { if arg[0] { @@ -1475,11 +1501,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心", if e := os.MkdirAll(x.Value, os.ModePerm); e != nil { fmt.Println(e) - os.Exit(1) } if e := os.Chdir(x.Value); e != nil { fmt.Println(e) - os.Exit(1) } return arg[0] } @@ -2007,6 +2031,8 @@ func Start(args ...string) { Pulse.Conf("root", args[3]) } + Pulse.Options("log", true) + log.Println("\n\n") Index.Group = "root" Index.Owner = Index.contexts["aaa"] @@ -2016,6 +2042,7 @@ func Start(args ...string) { m.target.Begin(m) } log.Println() + Pulse.Sess("log", "log").Conf("bench.log", "hi.log") for _, m := range Pulse.Search(Pulse.Conf("start")) { m.Set("detail", Pulse.Conf("init.shy")).Set("option", "stdio").target.Start(m) diff --git a/src/context/lex/lex.go b/src/context/lex/lex.go index e06c7e96..2756a036 100644 --- a/src/context/lex/lex.go +++ b/src/context/lex/lex.go @@ -297,8 +297,6 @@ func (lex *LEX) Begin(m *ctx.Message, arg ...string) ctx.Server { lex.Caches["compact"] = &ctx.Cache{Name: "紧凑模式", Value: "true", Help: "实点数量"} - lex.Caps("debug", false) - lex.Confs("debug", false) return lex } diff --git a/src/context/log/log.go b/src/context/log/log.go new file mode 100644 index 00000000..74caba8b --- /dev/null +++ b/src/context/log/log.go @@ -0,0 +1,199 @@ +package log + +import ( + "context" + "fmt" + Log "log" + "strconv" + "strings" + "time" +) + +type LOG struct { + module map[string]map[string]bool + slient map[string]bool + color map[string]int + *Log.Logger + + *ctx.Message + *ctx.Context +} + +func (log *LOG) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { + c.Caches = map[string]*ctx.Cache{} + c.Configs = map[string]*ctx.Config{} + + s := new(LOG) + s.Context = c + return s +} + +func (log *LOG) Begin(m *ctx.Message, arg ...string) ctx.Server { + if log.Context == Index { + Pulse = m + } + log.Context.Master(nil) + log.Message = m + + log.Configs["flag_date"] = &ctx.Config{Name: "输出日期", Value: "true", Help: "模块日志输出消息日期"} + log.Configs["flag_time"] = &ctx.Config{Name: "输出时间", Value: "true", Help: "模块日志输出消息时间"} + log.Configs["flag_color"] = &ctx.Config{Name: "输出颜色", Value: "true", Help: "模块日志输出颜色"} + log.Configs["flag_code"] = &ctx.Config{Name: "输出序号", Value: "true", Help: "模块日志输出消息的编号"} + log.Configs["flag_action"] = &ctx.Config{Name: "输出类型", Value: "true", Help: "模块日志类型"} + log.Configs["flag_name"] = &ctx.Config{Name: "输出名称", Value: "true", Help: "模块日志输出消息源模块与消息目的模块"} + + log.Configs["bench.log"] = &ctx.Config{Name: "日志文件", Value: "var/bench.log", Help: "模块日志输出的文件", Hand: func(m *ctx.Message, x *ctx.Config, arg ...string) string { + if len(arg) > 0 { + if m.Sess("nfs") == nil { + m.Sess("nfs", "nfs").Cmd("open", arg[0]) + } + return arg[0] + } + return x.Value + }} + + return log +} + +func (log *LOG) Start(m *ctx.Message, arg ...string) bool { + log.Message = m + return false +} + +func (log *LOG) Close(m *ctx.Message, arg ...string) bool { + switch log.Context { + case m.Target(): + case m.Source(): + } + return true +} + +var Pulse *ctx.Message +var Index = &ctx.Context{Name: "log", Help: "日志中心", + Caches: map[string]*ctx.Cache{}, + Configs: map[string]*ctx.Config{}, + Commands: map[string]*ctx.Command{ + "slient": &ctx.Command{Name: "slient [[module] level state]", Help: "查看或设置日志开关, module: 模块名, level: 日志类型, state(true/false): 是否打印日志", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if log, ok := m.Target().Server.(*LOG); m.Assert(ok) { + switch len(arg) { + case 2: + if len(arg) > 1 { + log.slient[arg[0]] = ctx.Right(arg[1]) + } + case 3: + if log.module[arg[0]] == nil { + log.module[arg[0]] = map[string]bool{} + } + log.module[arg[0]][arg[1]] = ctx.Right(arg[2]) + } + + for k, v := range log.slient { + m.Echo("%s: %t\n", k, v) + } + for k, v := range log.module { + for i, x := range v { + m.Echo("%s(%s): %t\n", k, i, x) + } + } + } + }}, + "color": &ctx.Command{Name: "color [level color]", Help: "查看或设置日志颜色, level: 日志类型, color: 文字颜色", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if log, ok := m.Target().Server.(*LOG); m.Assert(ok) { + if len(arg) > 1 { + c, e := strconv.Atoi(arg[1]) + m.Assert(e) + log.color[arg[0]] = c + } + + for k, v := range log.color { + m.Echo("\033[%dm%s: %d\033[0m\n", v, k, v) + } + } + }}, + "log": &ctx.Command{Name: "log level string...", Help: "输出日志, level: 日志类型, string: 日志内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { + if log, ok := m.Target().Server.(*LOG); m.Assert(ok) { + if s, ok := log.slient[arg[0]]; ok && s == true { + return + } + + msg := m.Message() + if x, ok := m.Data["msg"]; ok { + if msg, ok = x.(*ctx.Message); !ok { + msg = m.Message() + } + } + if s, ok := log.module[msg.Target().Name]; ok { + if x, ok := s[arg[0]]; ok && x { + return + } + } + + date := "" + if m.Confs("flag_date") { + date += time.Now().Format("2006/01/02 ") + } + if m.Confs("flag_time") { + date += time.Now().Format("15:04:05 ") + } + + color := 0 + if m.Confs("flag_color") { + if c, ok := log.color[arg[0]]; ok { + color = c + } + } + + code := "" + if m.Confs("flag_code") { + code = fmt.Sprintf("%d ", msg.Code()) + } + + action := "" + if m.Confs("flag_action") { + action = fmt.Sprintf("%s", arg[0]) + + if m.Confs("flag_name") { + action = fmt.Sprintf("%s(%s->%s)", action, msg.Source().Name, msg.Target().Name) + if msg.Name != "" { + action = fmt.Sprintf("%s(%s:%s->%s.%d)", action, msg.Source().Name, msg.Name, msg.Target().Name, m.Index) + } + } + } + + if nfs := m.Sess("nfs"); nfs != nil { + if nfs.Options("log", false); color > 0 { + nfs.Cmd("write", fmt.Sprintf("%s\033[%dm%s%s %s\033[0m\n", date, color, code, action, strings.Join(arg[1:], ""))) + } else { + nfs.Cmd("write", fmt.Sprintf("%s%s%s %s\n", date, code, action, strings.Join(arg[1:], ""))) + } + } + } + }}, + }, +} + +func init() { + log := &LOG{} + log.Context = Index + ctx.Index.Register(Index, log) + + log.color = map[string]int{ + "error": 31, + "check": 31, + "cmd": 32, + "conf": 33, + "search": 35, + "find": 35, + "spawn": 35, + "begin": 36, + "start": 36, + "close": 36, + "debug": 0, + } + log.slient = map[string]bool{} + log.module = map[string]map[string]bool{ + "log": {"cmd": true}, + "lex": {"cmd": true, "debug": true}, + "yac": {"cmd": true, "debug": true}, + } +} diff --git a/src/context/nfs/nfs.go b/src/context/nfs/nfs.go index 4ac48cd7..bfb34f2f 100644 --- a/src/context/nfs/nfs.go +++ b/src/context/nfs/nfs.go @@ -234,6 +234,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", }}, "write": &ctx.Command{Name: "write string [pos]", Help: "写入文件, string: 写入内容, pos: 写入位置", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) { if nfs, ok := m.Target().Server.(*NFS); m.Assert(ok) && nfs.out != nil { // {{{ + if len(arg) > 1 { m.Cap("pos", arg[1]) } @@ -247,6 +248,7 @@ var Index = &ctx.Context{Name: "nfs", Help: "存储中心", if m.Assert(e) && m.Capi("pos", n) > m.Capi("size") { m.Cap("size", m.Cap("pos")) } + nfs.out.Sync() } m.Echo(m.Cap("pos")) diff --git a/src/context/yac/yac.go b/src/context/yac/yac.go index 829df12f..8d067ab6 100644 --- a/src/context/yac/yac.go +++ b/src/context/yac/yac.go @@ -32,7 +32,6 @@ type YAC struct { state map[State]*State mat []map[byte]*State - lex *ctx.Message *ctx.Message *ctx.Context } @@ -45,15 +44,15 @@ func (yac *YAC) name(page int) string { return name } -func (yac *YAC) train(page, hash int, word []string) (int, []*Point, []*Point) { +func (yac *YAC) train(m *ctx.Message, page, hash int, word []string) (int, []*Point, []*Point) { sn := make([]bool, yac.Capi("nline")) ss := []int{page} points := []*Point{} ends := []*Point{} - for i, n, m := 0, 1, false; i < len(word); i += n { - if !m { + for i, n, mul := 0, 1, false; i < len(word); i += n { + if !mul { if hash <= 0 && word[i] == "}" { return i + 2, points, ends } @@ -64,7 +63,7 @@ func (yac *YAC) train(page, hash int, word []string) (int, []*Point, []*Point) { switch word[i] { case "opt{", "rep{": sn[s] = true - num, point, end := yac.train(s, 0, word[i+1:]) + num, point, end := yac.train(m, s, 0, word[i+1:]) n, points = num, append(points, point...) for _, x := range end { state := &State{} @@ -82,11 +81,11 @@ func (yac *YAC) train(page, hash int, word []string) (int, []*Point, []*Point) { } } case "mul{": - m, n = true, 1 + mul, n = true, 1 goto next case "}": - if m { - m = false + if mul { + mul = false goto next } fallthrough @@ -94,12 +93,12 @@ func (yac *YAC) train(page, hash int, word []string) (int, []*Point, []*Point) { x, ok := yac.page[word[i]] if !ok { - lex := yac.lex.Cmd("parse", word[i], yac.name(s)) + lex := yac.Sess("lex").Cmd("parse", word[i], yac.name(s)) if lex.Gets("result") { x = lex.Geti("result") } else { x = len(yac.mat[s]) - yac.lex.Cmd("train", word[i], x, yac.name(s)) + lex.Cmd("train", word[i], x, yac.name(s)) } } @@ -130,7 +129,7 @@ func (yac *YAC) train(page, hash int, word []string) (int, []*Point, []*Point) { } next: - if !m { + if !mul { ss = ss[:0] for s, b := range sn { if sn[s] = false; b { @@ -190,18 +189,18 @@ func (yac *YAC) train(page, hash int, word []string) (int, []*Point, []*Point) { func (yac *YAC) parse(m *ctx.Message, cli *ctx.Context, page, void int, line string) (*ctx.Context, string, []string) { level := m.Capi("level", 1) - m.Log("debug", nil, "%s\\%d %s(%d):", m.Cap("label")[0:level], level, yac.word[page], page) + m.Sess("log").Cmd("log", "debug", fmt.Sprintf("%s\\%d %s(%d):", m.Cap("label")[0:level], level, yac.word[page], page)) hash, word := 0, []string{} for star, s := 0, page; s != 0 && len(line) > 0; { - line = yac.lex.Cmd("parse", line, yac.name(void)).Result(2) - lex := yac.lex.Cmd("parse", line, yac.name(s)) + line = yac.Sess("lex").Cmd("parse", line, yac.name(void)).Result(2) + lex := yac.Sess("lex").Cmd("parse", line, yac.name(s)) c := byte(lex.Resulti(0)) state := yac.mat[s][c] if state != nil { - if key := yac.lex.Cmd("parse", line, "key"); key.Resulti(0) == 0 || len(key.Result(1)) <= len(lex.Result(1)) { + if key := yac.Sess("lex").Cmd("parse", line, "key"); key.Resulti(0) == 0 || len(key.Result(1)) <= len(lex.Result(1)) { m.Log("debug", nil, "%s|%d get(%d,%d): %v \033[31m(%s)\033[0m", m.Cap("label")[0:level], level, s, c, state, lex.Result(1)) line, word = lex.Result(2), append(word, lex.Result(1)) } else { @@ -285,9 +284,6 @@ func (yac *YAC) Begin(m *ctx.Message, arg ...string) ctx.Server { yac.Caches["level"] = &ctx.Cache{Name: "嵌套层级", Value: "0", Help: "语法解析嵌套层级"} yac.Caches["label"] = &ctx.Cache{Name: "嵌套标记", Value: "####################", Help: "嵌套层级日志的标记"} - yac.Caps("debug", true) - yac.Confs("debug", false) - yac.page = map[string]int{"nil": 0} yac.word = map[int]string{0: "nil"} yac.hash = map[string]int{"nil": 0} @@ -339,17 +335,16 @@ var Index = &ctx.Context{Name: "yac", Help: "语法中心", yac.hand[hash] = arg[1] } - if yac.lex == nil { - lex := m.Find("lex", true) + if m.Sess("lex") == nil { + lex := m.Sess("lex", "lex") if lex.Cap("status") == "start" { lex.Start(yac.Context.Name+"lex", "语法词法") } else { lex.Target().Start(lex) } - yac.lex = lex } - yac.train(page, hash, arg[2:]) + yac.train(m, page, hash, arg[2:]) yac.seed = append(yac.seed, &Seed{page, hash, arg[2:]}) yac.Cap("stream", fmt.Sprintf("%d,%s,%s", yac.Capi("nseed", 1), yac.Cap("npage"), yac.Cap("nhash"))) } diff --git a/src/example/bench.go b/src/example/bench.go index 9137ac0b..2abae23b 100644 --- a/src/example/bench.go +++ b/src/example/bench.go @@ -11,6 +11,7 @@ import ( _ "context/tcp" _ "context/web" + _ "context/gdb" _ "context/lex" _ "context/log" _ "context/yac"