diff --git a/base/aaa/role.go b/base/aaa/role.go index 73ca4481..57aeba20 100644 --- a/base/aaa/role.go +++ b/base/aaa/role.go @@ -104,18 +104,6 @@ func init() { }, Commands: map[string]*ice.Command{ ROLE: {Name: "role role auto create", Help: "角色", Action: map[string]*ice.Action{ - BLACK: {Name: "black role chain...", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) { - _role_black(m, arg[0], strings.ReplaceAll(kit.Keys(arg[1:]), "/", "."), true) - }}, - WHITE: {Name: "white role chain...", Help: "白名单", Hand: func(m *ice.Message, arg ...string) { - _role_white(m, arg[0], strings.ReplaceAll(kit.Keys(arg[1:]), "/", "."), true) - }}, - RIGHT: {Name: "right role chain...", Help: "查看权限", Hand: func(m *ice.Message, arg ...string) { - if _role_right(m, arg[0], kit.Split(strings.ReplaceAll(kit.Keys(arg[1:]), "/", "."), ".")...) { - m.Echo(ice.OK) - } - }}, - mdb.CREATE: {Name: "create role=void,tech zone=white,black key=", Help: "添加", Hand: func(m *ice.Message, arg ...string) { m.Richs(ROLE, nil, m.Option(ROLE), func(key string, value map[string]interface{}) { list := value[m.Option(kit.MDB_ZONE)].(map[string]interface{}) @@ -130,6 +118,18 @@ func init() { delete(list, m.Option(kit.MDB_KEY)) }) }}, + + BLACK: {Name: "black role chain...", Help: "黑名单", Hand: func(m *ice.Message, arg ...string) { + _role_black(m, arg[0], strings.ReplaceAll(kit.Keys(arg[1:]), "/", "."), true) + }}, + WHITE: {Name: "white role chain...", Help: "白名单", Hand: func(m *ice.Message, arg ...string) { + _role_white(m, arg[0], strings.ReplaceAll(kit.Keys(arg[1:]), "/", "."), true) + }}, + RIGHT: {Name: "right role chain...", Help: "查看权限", Hand: func(m *ice.Message, arg ...string) { + if _role_right(m, arg[0], kit.Split(strings.ReplaceAll(kit.Keys(arg[1:]), "/", "."), ".")...) { + m.Echo(ice.OK) + } + }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) < 2 { // 角色列表 _role_list(m, kit.Select("", arg, 0)) diff --git a/base/aaa/sess.go b/base/aaa/sess.go index 63e22df7..3f0ddbb9 100644 --- a/base/aaa/sess.go +++ b/base/aaa/sess.go @@ -41,6 +41,9 @@ func SessCheck(m *ice.Message, sessid string) { _sess_check(m, sessid) } func SessCreate(m *ice.Message, username string) string { + if username == "" { + return "" + } return m.Option(ice.MSG_SESSID, _sess_create(m, username)) } func SessIsCli(m *ice.Message) bool { @@ -68,23 +71,21 @@ func init() { Commands: map[string]*ice.Command{ SESS: {Name: "sess hash auto prunes", Help: "会话", Action: map[string]*ice.Action{ mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { - m.Option(mdb.FIELDS, "time,username,userrole,ip,ua") + m.Option(mdb.FIELDS, "time,hash,username,userrole,ip,ua") m.Cmdy(mdb.DELETE, SESS, "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)) }}, mdb.PRUNES: {Name: "prunes before@date", Help: "清理", Hand: func(m *ice.Message, arg ...string) { - list := []string{} - m.Richs(SESS, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) { + m.Option(mdb.FIELDS, "time,hash,username,userrole,ip,ua") + m.Cmd(mdb.PRUNES, SESS, "", mdb.HASH, func(key string, value map[string]interface{}) bool { if value = kit.GetMeta(value); kit.Time(kit.Format(value[kit.MDB_TIME])) < kit.Time(m.Option("before")) { - list = append(list, key) + m.Push(key, value, kit.Split(m.Option(mdb.FIELDS))) + return true } + return false }) - m.Option(mdb.FIELDS, "time,username,userrole,ip,ua") - for _, v := range list { - m.Cmdy(mdb.DELETE, SESS, "", mdb.HASH, kit.MDB_HASH, v) - } }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Fields(len(arg) == 0, "time,hash,username,userrole") + m.Fields(len(arg) == 0, "time,hash,username,userrole,ip") m.Cmdy(mdb.SELECT, SESS, "", mdb.HASH, kit.MDB_HASH, arg) m.PushAction(mdb.REMOVE) }}, diff --git a/base/aaa/totp.go b/base/aaa/totp.go index f3d45f01..8c7c9d1c 100644 --- a/base/aaa/totp.go +++ b/base/aaa/totp.go @@ -69,7 +69,7 @@ func init() { m.Cmd(mdb.INSERT, TOTP, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME), SECRET, m.Option(SECRET), PERIOD, m.Option(PERIOD), NUMBER, m.Option(NUMBER), ) - m.ProcessRefresh("1ms") + m.ProcessRefresh("30ms") }}, mdb.REMOVE: {Name: "remove", Help: "删除", Hand: func(m *ice.Message, arg ...string) { m.Cmdy(mdb.DELETE, TOTP, "", mdb.HASH, kit.MDB_NAME, m.Option(kit.MDB_NAME)) diff --git a/base/cli/cli.go b/base/cli/cli.go index 7240147c..e36e5660 100644 --- a/base/cli/cli.go +++ b/base/cli/cli.go @@ -11,6 +11,60 @@ import ( kit "github.com/shylinux/toolkits" ) +func _cli_init(m *ice.Message) { + + // 启动配置 + for _, k := range []string{CTX_SELF, CTX_DEV, CTX_SHY, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER} { + m.Conf(RUNTIME, kit.Keys(CONF, k), os.Getenv(k)) + } + + // 主机信息 + m.Conf(RUNTIME, kit.Keys(HOST, "GOARCH"), runtime.GOARCH) + m.Conf(RUNTIME, kit.Keys(HOST, "GOOS"), runtime.GOOS) + m.Conf(RUNTIME, kit.Keys(HOST, "pid"), os.Getpid()) + + // 启动信息 + if name, e := os.Hostname(); e == nil { + m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Select(name, os.Getenv("HOSTNAME"))) + } + if name, e := os.Getwd(); e == nil { + name = path.Base(kit.Select(name, os.Getenv("PWD"))) + ls := strings.Split(name, "/") + name = ls[len(ls)-1] + ls = strings.Split(name, "\\") + name = ls[len(ls)-1] + m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), name) + } + if m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(os.Getenv(USER), os.Getenv(CTX_USER))) == "" { + if user, e := user.Current(); e == nil && user.Name != "" { + m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(user.Name, os.Getenv(CTX_USER))) + } + } + ice.Info.HostName = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME)) + ice.Info.PathName = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)) + ice.Info.UserName = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME)) + + ice.Info.CtxShare = m.Conf(RUNTIME, kit.Keys(CONF, CTX_SHARE)) + ice.Info.CtxRiver = m.Conf(RUNTIME, kit.Keys(CONF, CTX_RIVER)) + + // 启动次数 + count := kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, kit.MDB_COUNT))) + 1 + m.Conf(RUNTIME, kit.Keys(BOOT, kit.MDB_COUNT), count) + + // 节点信息 + m.Conf(RUNTIME, kit.Keys(NODE, kit.MDB_TIME), m.Time()) + NodeInfo(m, "worker", m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME))) + m.Info("runtime %v", kit.Formats(m.Confv(RUNTIME))) + + n := kit.Int(kit.Select("1", m.Conf(RUNTIME, kit.Keys(HOST, "GOMAXPROCS")))) + m.Logs(HOST, "GOMAXPROCS", n) + runtime.GOMAXPROCS(n) + + // 版本信息 + kit.Fetch(kit.UnMarshal(kit.Format(ice.Info.Build)), func(key string, value interface{}) { + m.Conf(RUNTIME, kit.Keys(MAKE, strings.ToLower(key)), value) + }) +} func NodeInfo(m *ice.Message, kind, name string) { name = strings.ReplaceAll(name, ".", "_") m.Conf(RUNTIME, kit.Keys(NODE, kit.MDB_TYPE), kind) @@ -46,58 +100,7 @@ var Index = &ice.Context{Name: CLI, Help: "命令模块", Commands: map[string]*ice.Command{ ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Load() - - // 启动配置 - for _, k := range []string{CTX_SELF, CTX_DEV, CTX_SHY, CTX_PID, CTX_USER, CTX_SHARE, CTX_RIVER} { - m.Conf(RUNTIME, kit.Keys(CONF, k), os.Getenv(k)) - } - - // 主机信息 - m.Conf(RUNTIME, kit.Keys(HOST, "GOARCH"), runtime.GOARCH) - m.Conf(RUNTIME, kit.Keys(HOST, "GOOS"), runtime.GOOS) - m.Conf(RUNTIME, kit.Keys(HOST, "pid"), os.Getpid()) - - // 启动信息 - if name, e := os.Hostname(); e == nil { - m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME), kit.Select(name, os.Getenv("HOSTNAME"))) - } - if name, e := os.Getwd(); e == nil { - name = path.Base(kit.Select(name, os.Getenv("PWD"))) - ls := strings.Split(name, "/") - name = ls[len(ls)-1] - ls = strings.Split(name, "\\") - name = ls[len(ls)-1] - m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME), name) - } - if m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(os.Getenv(USER), os.Getenv(CTX_USER))) == "" { - if user, e := user.Current(); e == nil && user.Name != "" { - m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME), kit.Select(user.Name, os.Getenv(CTX_USER))) - } - } - ice.Info.HostName = m.Conf(RUNTIME, kit.Keys(BOOT, HOSTNAME)) - ice.Info.PathName = m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME)) - ice.Info.UserName = m.Conf(RUNTIME, kit.Keys(BOOT, USERNAME)) - - ice.Info.CtxShare = m.Conf(RUNTIME, kit.Keys(CONF, CTX_SHARE)) - ice.Info.CtxRiver = m.Conf(RUNTIME, kit.Keys(CONF, CTX_RIVER)) - - // 启动次数 - count := kit.Int(m.Conf(RUNTIME, kit.Keys(BOOT, kit.MDB_COUNT))) + 1 - m.Conf(RUNTIME, kit.Keys(BOOT, kit.MDB_COUNT), count) - - // 节点信息 - m.Conf(RUNTIME, kit.Keys(NODE, kit.MDB_TIME), m.Time()) - NodeInfo(m, "worker", m.Conf(RUNTIME, kit.Keys(BOOT, PATHNAME))) - m.Info("runtime %v", kit.Formats(m.Confv(RUNTIME))) - - n := kit.Int(kit.Select("1", m.Conf(RUNTIME, kit.Keys(HOST, "GOMAXPROCS")))) - m.Logs(HOST, "GOMAXPROCS", n) - runtime.GOMAXPROCS(n) - - // 版本信息 - kit.Fetch(kit.UnMarshal(kit.Format(ice.Info.Build)), func(key string, value interface{}) { - m.Conf(RUNTIME, kit.Keys(MAKE, strings.ToLower(key)), value) - }) + _cli_init(m) }}, ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { m.Save() diff --git a/base/cli/daemon.go b/base/cli/daemon.go index 969a0820..8d8cff5d 100644 --- a/base/cli/daemon.go +++ b/base/cli/daemon.go @@ -86,18 +86,9 @@ func init() { DAEMON: {Name: DAEMON, Help: "守护进程", Value: kit.Data(kit.MDB_PATH, path.Join(ice.USR_LOCAL, DAEMON))}, }, Commands: map[string]*ice.Command{ - ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - }}, + ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {}}, ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - list := []string{} - m.Richs(DAEMON, "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) { - if value = kit.GetMeta(value); kit.Value(value, mdb.CACHE_CLEAR_ON_EXIT) == ice.TRUE { - list = append(list, key) - } - }) - for _, k := range list { - m.Conf(DAEMON, kit.Keys(kit.MDB_HASH, k), "") - } + m.Cmd(mdb.PRUNES, DAEMON, "", mdb.HASH, mdb.CACHE_CLEAR_ON_EXIT, ice.TRUE) }}, DAEMON: {Name: "daemon hash auto start prunes", Help: "守护进程", Action: map[string]*ice.Action{ @@ -107,10 +98,9 @@ func init() { m.Cmdy(DAEMON, START) }}, START: {Name: "start cmd env dir", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - m.Option(CMD_TYPE, DAEMON) m.Option(CMD_DIR, m.Option(DIR)) m.Option(CMD_ENV, kit.Split(m.Option(ENV), " =")) - m.Cmdy(SYSTEM, kit.Split(m.Option(CMD))) + m.Cmdy(DAEMON, kit.Split(m.Option(CMD))) }}, STOP: {Name: "stop", Help: "停止", Hand: func(m *ice.Message, arg ...string) { m.Option(mdb.FIELDS, "time,hash,status,pid,cmd,dir,env") @@ -130,8 +120,7 @@ func init() { }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { // 进程列表 m.Fields(len(arg) == 0, "time,hash,status,pid,cmd,dir,env") - m.Cmdy(mdb.SELECT, DAEMON, "", mdb.HASH) - m.Table(func(index int, value map[string]string, head []string) { + m.Cmdy(mdb.SELECT, DAEMON, "", mdb.HASH).Table(func(index int, value map[string]string, head []string) { switch value[kit.MDB_STATUS] { case START: m.PushButton(RESTART, STOP) diff --git a/base/cli/qrcode.go b/base/cli/qrcode.go index 4c513057..29ca1897 100644 --- a/base/cli/qrcode.go +++ b/base/cli/qrcode.go @@ -7,11 +7,10 @@ import ( "strconv" "strings" - "github.com/skip2/go-qrcode" - ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/aaa" kit "github.com/shylinux/toolkits" + "github.com/skip2/go-qrcode" ) var _trans_web = map[string]color.Color{ @@ -126,7 +125,7 @@ func init() { m.Option(FG, kit.Select(BLUE, arg, 1)) if aaa.SessIsCli(m) { - _qrcode_cli(m, kit.Select(m.Conf("web.share", kit.Keym(kit.MDB_DOMAIN)), arg)) + _qrcode_cli(m, kit.Select(m.Conf("web.share", kit.Keym(kit.MDB_DOMAIN)), arg, 0)) } else { _qrcode_web(m, kit.Select(m.Option(ice.MSG_USERWEB), arg, 0)) } diff --git a/base/gdb/event.go b/base/gdb/event.go index fcd6abed..43c9795c 100644 --- a/base/gdb/event.go +++ b/base/gdb/event.go @@ -37,7 +37,7 @@ func init() { }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { // 事件列表 - m.Option(mdb.FIELDS, "time,event,count") + m.Fields(len(arg) == 0, "time,event,count") m.Cmdy(mdb.SELECT, EVENT, "", mdb.HASH) m.PushAction(ACTION, mdb.REMOVE) return diff --git a/base/gdb/gdb.go b/base/gdb/gdb.go index d4d79006..ada7fa40 100644 --- a/base/gdb/gdb.go +++ b/base/gdb/gdb.go @@ -48,6 +48,7 @@ const ( BUILD = "build" SPAWN = "spawn" START = "start" + ERROR = "error" STOP = "stop" STATUS = "status" diff --git a/base/gdb/gdb.shy b/base/gdb/gdb.shy index 93a014a8..c9435131 100644 --- a/base/gdb/gdb.shy +++ b/base/gdb/gdb.shy @@ -3,5 +3,4 @@ chapter "gdb" field "协程池" routine field "信号量" signal field "事件流" event - field "定时器" timer diff --git a/base/gdb/routine.go b/base/gdb/routine.go index f601791a..e11e5f00 100644 --- a/base/gdb/routine.go +++ b/base/gdb/routine.go @@ -1,9 +1,10 @@ package gdb import ( - "strings" + "path" ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/ctx" "github.com/shylinux/icebergs/base/mdb" kit "github.com/shylinux/toolkits" ) @@ -34,6 +35,7 @@ func init() { }}, mdb.PRUNES: {Name: "prunes", Help: "清理", Hand: func(m *ice.Message, arg ...string) { m.Option(mdb.FIELDS, "time,hash,status,fileline") + m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, kit.MDB_STATUS, ERROR) m.Cmdy(mdb.PRUNES, ROUTINE, "", mdb.HASH, kit.MDB_STATUS, STOP) }}, @@ -43,15 +45,9 @@ func init() { m.Cmdy(INNER, arg[1:]) default: ls := kit.Split(m.Option("fileline"), ":") - switch kit.Split(ls[0], "/")[0] { - case "usr": - ls[0] = strings.TrimPrefix(ls[0], "usr/icebergs/") - case "icebergs": - ls[0] = strings.TrimPrefix(ls[0], "icebergs/") - } - - m.ShowPlugin("", INNER, kit.SSH_RUN) - m.Push("args", kit.Format([]string{"usr/icebergs/", ls[0], ls[1]})) + m.ProcessField(INNER, kit.SSH_RUN) + m.Option(kit.SSH_ARG, kit.Format([]string{path.Dir(ls[0]), path.Base(ls[0]), ls[1]})) + m.Cmdy(ctx.COMMAND, INNER) } }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { diff --git a/base/gdb/timer.go b/base/gdb/timer.go index c564050f..d15b004f 100644 --- a/base/gdb/timer.go +++ b/base/gdb/timer.go @@ -25,7 +25,7 @@ func _timer_action(m *ice.Message, arg ...string) { m.Logs(TIMER, kit.MDB_KEY, key, ORDER, order) msg := m.Cmd(value[kit.SSH_CMD]) - m.Grow(TIMER, kit.Keys(kit.MDB_HASH, key), kit.Dict("res", msg.Result())) + m.Grow(TIMER, kit.Keys(kit.MDB_HASH, key), kit.Dict(kit.SSH_RES, msg.Result())) if value[ORDER] = kit.Format(order - 1); order > 1 { value[NEXT] = msg.Time(value[INTERVAL]) } diff --git a/base/lex/lex.go b/base/lex/lex.go index a3f83b1f..e66da884 100644 --- a/base/lex/lex.go +++ b/base/lex/lex.go @@ -1,15 +1,460 @@ package lex import ( + "sort" + "strconv" + ice "github.com/shylinux/icebergs" + "github.com/shylinux/icebergs/base/mdb" + kit "github.com/shylinux/toolkits" ) +type Seed struct { + page int + hash int + word string +} +type Point struct { + s int + c byte +} +type State struct { + star bool + next int + hash int +} +type Matrix struct { + nlang int + ncell int + + seed []*Seed + page map[string]int + hand map[int]string + hash map[string]int + word map[int]string + + trans map[byte][]byte + state map[State]*State + mat []map[byte]*State + + *ice.Context + + nseed int + npage int + nhash int + nline int + nnode int + nreal int +} + +func NewMatrix(m *ice.Message, nlang, ncell int) *Matrix { + mat := &Matrix{} + mat.nlang = nlang + mat.ncell = ncell + + mat.page = map[string]int{"nil": 0} + mat.hand = map[int]string{0: "nil"} + mat.hash = map[string]int{"nil": 0} + mat.word = map[int]string{0: "nil"} + + mat.trans = map[byte][]byte{} + for k, v := range map[byte]string{ + 't': "\t", 'n': "\n", 'b': "\t ", 's': "\t \n", + 'd': "0123456789", 'x': "0123456789ABCDEFabcdef", + } { + mat.trans[k] = []byte(v) + } + + mat.state = make(map[State]*State) + mat.mat = make([]map[byte]*State, nlang) + + mat.nline = nlang + return mat +} +func (mat *Matrix) char(c byte) []byte { + if cs, ok := mat.trans[c]; ok { + return cs + } + return []byte{c} +} +func (mat *Matrix) index(m *ice.Message, hash string, h string) int { + which, names := mat.hash, mat.word + if hash == NPAGE { + which, names = mat.page, mat.hand + } + + if x, e := strconv.Atoi(h); e == nil { + if hash == NPAGE { + m.Assert(x <= mat.npage) + } else { + mat.hash[h] = x + } + return x + } + + if x, ok := which[h]; ok { + return x + } + + if hash == NPAGE { + mat.npage++ + which[h] = mat.npage + } else { + mat.nhash++ + which[h] = mat.nhash + } + + names[which[h]] = h + m.Assert(hash != NPAGE || mat.npage < mat.nlang) + return which[h] +} +func (mat *Matrix) train(m *ice.Message, page int, hash int, seed []byte) int { + m.Debug("%s %s page: %v hash: %v seed: %v", "train", "lex", page, hash, string(seed)) + + ss := []int{page} + cn := make([]bool, mat.ncell) + cc := make([]byte, 0, mat.ncell) + sn := make([]bool, mat.nline) + + points := []*Point{} + + for p := 0; p < len(seed); p++ { + + switch seed[p] { + case '[': + set := true + if p++; seed[p] == '^' { + set, p = false, p+1 + } + + for ; seed[p] != ']'; p++ { + if seed[p] == '\\' { + p++ + for _, c := range mat.char(seed[p]) { + cn[c] = true + } + continue + } + + if seed[p+1] == '-' { + begin, end := seed[p], seed[p+2] + if begin > end { + begin, end = end, begin + } + for c := begin; c <= end; c++ { + cn[c] = true + } + p += 2 + continue + } + + cn[seed[p]] = true + } + + for c := 0; c < len(cn); c++ { + if (set && cn[c]) || (!set && !cn[c]) { + cc = append(cc, byte(c)) + } + cn[c] = false + } + + case '.': + for c := 0; c < len(cn); c++ { + cc = append(cc, byte(c)) + } + + case '\\': + p++ + for _, c := range mat.char(seed[p]) { + cc = append(cc, c) + } + default: + cc = append(cc, seed[p]) + } + + m.Debug("page: \033[31m%d %v\033[0m", len(ss), ss) + m.Debug("cell: \033[32m%d %v\033[0m", len(cc), cc) + + flag := '\000' + if p+1 < len(seed) { + switch flag = rune(seed[p+1]); flag { + case '?', '+', '*': + p++ + } + } + + for _, s := range ss { + for _, c := range cc { + + state := &State{} + if mat.mat[s][c] != nil { + *state = *mat.mat[s][c] + } else { + mat.nnode++ + } + m.Debug("GET(%d,%d): %v", s, c, state) + + switch flag { + case '+': + state.star = true + case '*': + state.star = true + sn[s] = true + case '?': + sn[s] = true + } + + if state.next == 0 { + mat.mat = append(mat.mat, make(map[byte]*State)) + sn = append(sn, false) + state.next = mat.nline + mat.nline++ + } + sn[state.next] = true + + mat.mat[s][c] = state + points = append(points, &Point{s, c}) + m.Debug("SET(%d,%d): %v(%d,%d)", s, c, state, mat.nnode, mat.nreal) + } + } + + cc, ss = cc[:0], ss[:0] + for s, b := range sn { + if sn[s] = false; b && s > 0 { + ss = append(ss, s) + } + } + } + + for _, s := range ss { + if s < mat.nlang || s >= len(mat.mat) { + continue + } + + if len(mat.mat[s]) == 0 { + last := mat.nline - 1 + mat.mat, mat.nline = mat.mat[:s], s + m.Debug("DEL: %d-%d", last, mat.nline) + } + } + + for _, s := range ss { + for _, p := range points { + state := &State{} + *state = *mat.mat[p.s][p.c] + + if state.next == s { + m.Debug("GET(%d, %d): %v", p.s, p.c, state) + if state.hash = hash; state.next >= len(mat.mat) { + state.next = 0 + } + mat.mat[p.s][p.c] = state + m.Debug("SET(%d, %d): %v", p.s, p.c, state) + } + + if x, ok := mat.state[*state]; !ok { + mat.state[*state] = mat.mat[p.s][p.c] + mat.nreal++ + } else { + mat.mat[p.s][p.c] = x + } + } + } + + m.Debug("%s %s npage: %v nhash: %v nseed: %v", "train", "lex", mat.npage, mat.nhash, len(mat.seed)) + return hash +} +func (mat *Matrix) parse(m *ice.Message, page int, line []byte) (hash int, rest []byte, word []byte) { + m.Debug("%s %s page: %v line: %v", "parse", "lex", page, line) + + pos := 0 + for star, s := 0, page; s != 0 && pos < len(line); pos++ { + + c := line[pos] + if c == '\\' && pos < len(line)-1 { //跳过转义 + pos++ + c = mat.char(line[pos])[0] + } + if c > 127 { //跳过中文 + word = append(word, c) + continue + } + + state := mat.mat[s][c] + if state == nil { + s, star, pos = star, 0, pos-1 + continue + } + m.Debug("GET (%d,%d): %v", s, c, state) + + word = append(word, c) + + if state.star { + star = s + } else if x, ok := mat.mat[star][c]; !ok || !x.star { + star = 0 + } + + if s, hash = state.next, state.hash; s == 0 { + s, star = star, 0 + } + } + + if pos == len(line) { + // hash, pos, word = -1, 0, word[:0] + } else if hash == 0 { + pos, word = 0, word[:0] + } + rest = line[pos:] + + m.Debug("%s %s hash: %v word: %v rest: %v", "parse", "lex", hash, word, rest) + return +} +func (mat *Matrix) show(m *ice.Message, page string) { + rows := map[int]bool{} + cols := map[int]bool{} + + nrow := []int{mat.page[page]} + for i := 0; i < len(nrow); i++ { + line := nrow[i] + rows[line] = true + + for i := 1; i < mat.ncell; i++ { + if node := mat.mat[line][byte(i)]; node != nil { + if cols[i] = true; node.next != 0 { + nrow = append(nrow, node.next) + } + } + } + } + + nrow = nrow[:0] + ncol := []int{} + for k := range rows { + nrow = append(nrow, k) + } + for k := range cols { + ncol = append(ncol, k) + } + sort.Ints(nrow) + sort.Ints(ncol) + + for _, i := range nrow { + m.Push("0", kit.Select(kit.Format(i), mat.hand[i])) + for _, j := range ncol { + node := mat.mat[i][byte(j)] + if node != nil { + m.Push(kit.Format("%c", j), kit.Format("%v", node.next)) + } else { + m.Push(kit.Format("%c", j), "") + } + } + } +} + +const ( + NLANG = "nlang" + NCELL = "ncell" + + NSEED = "nseed" + NPAGE = "npage" + NHASH = "nhash" +) +const ( + TRAIN = "train" + PARSE = "parse" +) +const MATRIX = "matrix" + const LEX = "lex" var Index = &ice.Context{Name: LEX, Help: "词法模块", + Configs: map[string]*ice.Config{ + MATRIX: {Name: MATRIX, Help: "魔方矩阵", Value: kit.Data()}, + }, 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) + ice.CTX_INIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + m.Load() + m.Richs(m.Prefix(MATRIX), "", kit.MDB_FOREACH, func(key string, value map[string]interface{}) { + value = kit.GetMeta(value) + + mat := NewMatrix(m, kit.Int(kit.Select("32", value[NLANG])), kit.Int(kit.Select("256", value[NCELL]))) + m.Grows(m.Prefix(MATRIX), kit.Keys(kit.MDB_HASH, key), "", "", func(index int, value map[string]interface{}) { + page := mat.index(m, NPAGE, kit.Format(value[NPAGE])) + hash := mat.index(m, NHASH, kit.Format(value[NHASH])) + if mat.mat[page] == nil { + mat.mat[page] = map[byte]*State{} + } + mat.seed = append(mat.seed, &Seed{page, hash, kit.Format(value[kit.MDB_TEXT])}) + mat.train(m, page, hash, []byte(kit.Format(value[kit.MDB_TEXT]))) + }) + value[MATRIX] = mat + }) + }}, + ice.CTX_EXIT: {Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + m.Save() + }}, + MATRIX: {Name: "matrix hash npage text auto", Help: "魔方矩阵", Action: map[string]*ice.Action{ + mdb.CREATE: {Name: "create nlang=32 ncell=256", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + mat := NewMatrix(m, kit.Int(kit.Select("32", m.Option(NLANG))), kit.Int(kit.Select("256", m.Option(NCELL)))) + m.Rich(m.Prefix(MATRIX), "", kit.Data(kit.MDB_TIME, m.Time(), MATRIX, mat, NLANG, mat.nlang, NCELL, mat.ncell)) + }}, + mdb.INSERT: {Name: "insert npage=num nhash=num text=123", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + m.Richs(m.Prefix(MATRIX), "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) { + value = kit.GetMeta(value) + + mat, _ := value[MATRIX].(*Matrix) + page := mat.index(m, NPAGE, m.Option(NPAGE)) + hash := mat.index(m, NHASH, m.Option(NHASH)) + if mat.mat[page] == nil { + mat.mat[page] = map[byte]*State{} + } + + mat.seed = append(mat.seed, &Seed{page, hash, m.Option(kit.MDB_TEXT)}) + m.Grow(m.Prefix(MATRIX), kit.Keys(kit.MDB_HASH, key), kit.Dict( + kit.MDB_TIME, m.Time(), NPAGE, m.Option(NPAGE), NHASH, m.Option(NHASH), kit.MDB_TEXT, m.Option(kit.MDB_TEXT), + )) + + mat.train(m, page, hash, []byte(m.Option(kit.MDB_TEXT))) + + value[NSEED] = len(mat.seed) + value[NPAGE] = len(mat.page) - 1 + value[NHASH] = len(mat.hash) - 1 + }) + }}, + mdb.REMOVE: {Name: "create", Help: "删除", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.DELETE, m.Prefix(MATRIX), "", mdb.HASH, kit.MDB_HASH, m.Option(kit.MDB_HASH)) + }}, + }, Hand: func(m *ice.Message, c *ice.Context, key string, arg ...string) { + if m.Action(mdb.CREATE); len(arg) == 0 { // 矩阵列表 + m.Fields(len(arg) == 0, "time,hash,npage,nhash") + m.Cmdy(mdb.SELECT, m.Prefix(MATRIX), "", mdb.HASH) + m.PushAction(mdb.INSERT, mdb.REMOVE) + return + } + + if m.Action(mdb.INSERT); len(arg) == 1 { // 词法列表 + m.Fields(len(arg) == 1, "time,npage,nhash,text") + m.Cmdy(mdb.SELECT, m.Prefix(MATRIX), kit.Keys(kit.MDB_HASH, arg[0]), mdb.LIST) + return + } + + m.Richs(m.Prefix(MATRIX), "", arg[0], func(key string, value map[string]interface{}) { + value = kit.GetMeta(value) + mat, _ := value[MATRIX].(*Matrix) + m.Debug("what %#v", mat) + + if len(arg) == 2 { // 词法矩阵 + mat.show(m, arg[1]) + return + } + + hash, rest, word := mat.parse(m, mat.index(m, NPAGE, arg[1]), []byte(arg[2])) + m.Push("time", m.Time()) + m.Push("hash", mat.word[hash]) + m.Push("word", string(word)) + m.Push("rest", string(rest)) + }) }}, }, } diff --git a/base/log/log.go b/base/log/log.go index 1f7213f2..1997c78f 100644 --- a/base/log/log.go +++ b/base/log/log.go @@ -21,7 +21,7 @@ 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, 4096) + f.p = make(chan *Log, ice.MOD_BUFS) ice.Log = func(msg *ice.Message, p, l, s string) { f.p <- &Log{m: msg, p: p, l: l, s: s} } @@ -40,17 +40,17 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { bio := m.Confv(FILE, kit.Keys(file, FILE)).(*bufio.Writer) bio.WriteString(l.p) - bio.WriteString(" ") + bio.WriteString(ice.MOD_SP) if p, ok := view[PREFIX].(string); ok { bio.WriteString(p) } bio.WriteString(l.l) - bio.WriteString(" ") + bio.WriteString(ice.MOD_SP) bio.WriteString(l.s) if p, ok := view[SUFFIX].(string); ok { bio.WriteString(p) } - bio.WriteString("\n") + bio.WriteString(ice.MOD_NL) bio.Flush() } } diff --git a/base/mdb/mdb.go b/base/mdb/mdb.go index e38e2d1c..05d23072 100644 --- a/base/mdb/mdb.go +++ b/base/mdb/mdb.go @@ -114,10 +114,17 @@ func _hash_prunes(m *ice.Message, prefix, chain string, arg ...string) { if val[kit.MDB_META] != nil { val = val[kit.MDB_META].(map[string]interface{}) } - for i := 0; i < len(arg)-1; i += 2 { - if val[arg[i]] != arg[i+1] { + switch cb := m.Optionv(kit.Keycb(PRUNES)).(type) { + case func(string, map[string]interface{}) bool: + if !cb(key, val) { return } + default: + for i := 0; i < len(arg)-1; i += 2 { + if val[arg[i]] != arg[i+1] { + return + } + } } m.Push(key, val, fields) }) @@ -170,9 +177,6 @@ func _list_select(m *ice.Message, prefix, chain, field, value string) { } } }) - // if m.Option(FIELDS) != DETAIL { - // m.SortIntR(kit.MDB_ID) - // } } func _list_modify(m *ice.Message, prefix, chain string, field, value string, arg ...string) { m.Grows(prefix, chain, field, value, func(index int, val map[string]interface{}) { diff --git a/base/nfs/tail.go b/base/nfs/tail.go index b967fcbc..7f201de6 100644 --- a/base/nfs/tail.go +++ b/base/nfs/tail.go @@ -66,9 +66,9 @@ func init() { m.ProcessRewrite("offend", offend) }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { - m.Option(mdb.FIELDS, kit.Select("time,hash,count,name,file", kit.Select("time,id,file,text", mdb.DETAIL, len(arg) > 1 && arg[1] != ""), len(arg) > 0)) + m.Fields(true, kit.Select("time,hash,count,name,file", "time,id,file,text", len(arg) > 1 && arg[1] != "")) + m.Option(mdb.CACHE_OFFEND, kit.Select("0", arg, 3)) m.Option(mdb.CACHE_LIMIT, kit.Select("10", arg, 2)) - m.Option("cache.offend", kit.Select("0", arg, 3)) if m.Cmdy(mdb.SELECT, TAIL, "", mdb.ZONE, arg); len(arg) == 0 { m.PushAction(mdb.REMOVE) diff --git a/base/nfs/trash.go b/base/nfs/trash.go index ebc9fbbf..6c2db297 100644 --- a/base/nfs/trash.go +++ b/base/nfs/trash.go @@ -57,7 +57,7 @@ func init() { }}, }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { if len(arg) == 0 { - m.Option(mdb.FIELDS, "time,hash,file,from") + m.Fields(len(arg) == 0, "time,hash,file,from") m.Cmdy(mdb.SELECT, TRASH, "", mdb.HASH) m.PushAction(mdb.REVERT, mdb.REMOVE) return diff --git a/base/ssh/scripts.go b/base/ssh/scripts.go index b56a5e93..1120c9d7 100644 --- a/base/ssh/scripts.go +++ b/base/ssh/scripts.go @@ -12,6 +12,7 @@ import ( ice "github.com/shylinux/icebergs" "github.com/shylinux/icebergs/base/aaa" + "github.com/shylinux/icebergs/base/ctx" "github.com/shylinux/icebergs/base/mdb" "github.com/shylinux/icebergs/base/nfs" kit "github.com/shylinux/toolkits" @@ -28,8 +29,8 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) string { res := msg.Result() // 输出结果 - if fmt.Fprint(msg.O, res); !strings.HasSuffix(res, "\n") { - fmt.Fprint(msg.O, "\n") + if fmt.Fprint(msg.O, res); !strings.HasSuffix(res, ice.MOD_NL) { + fmt.Fprint(msg.O, ice.MOD_NL) } return res @@ -41,8 +42,8 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) string { } // 输出结果 - if fmt.Fprint(msg.O, res); !strings.HasSuffix(res, "\n") { - fmt.Fprint(msg.O, "\n") + if fmt.Fprint(msg.O, res); !strings.HasSuffix(res, ice.MOD_NL) { + fmt.Fprint(msg.O, ice.MOD_NL) } return res } @@ -167,7 +168,7 @@ func (f *Frame) option(m *ice.Message, ls []string) []string { } func (f *Frame) change(m *ice.Message, ls []string) []string { if len(ls) == 1 && ls[0] == "~" { // 模块列表 - ls = []string{"context"} + ls = []string{ctx.CONTEXT} } else if len(ls) > 0 && strings.HasPrefix(ls[0], "~") { // 切换模块 target := ls[0][1:] @@ -282,11 +283,9 @@ func (f *Frame) scan(m *ice.Message, h, line string) *Frame { return f } func (f *Frame) close() { - fmt.Printf("what %v\n", 123) if stdin, ok := f.stdin.(io.Closer); ok { stdin.Close() f.stdin = nil - fmt.Printf("what %v\n", 123) } } @@ -406,18 +405,15 @@ func init() { f := m.Target().Server().(*Frame) m.Search(arg[0]+".", func(p *ice.Context, s *ice.Context, key string) { f.target = s }) f.prompt(m) - m.Echo(arg[0]) }}, PROMPT: {Name: "prompt arg 执行:button", Help: "命令提示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { f := m.Target().Server().(*Frame) f.ps1 = arg f.prompt(m) - m.Echo(arg[0]) }}, PRINTF: {Name: "printf 执行:button text:textarea", Help: "输出显示", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { f := m.Target().Server().(*Frame) f.printf(m, arg[0]) - m.Echo(arg[0]) }}, SCREEN: {Name: "screen 执行:button text:textarea", Help: "输出命令", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) { f := m.Target().Server().(*Frame) diff --git a/base/ssh/session.go b/base/ssh/session.go index d5a99400..d09fbe1a 100644 --- a/base/ssh/session.go +++ b/base/ssh/session.go @@ -75,7 +75,7 @@ func init() { m.Richs(SESSION, "", m.Option(kit.MDB_HASH), func(key string, value map[string]interface{}) { if w, ok := kit.Value(value, kit.Keym(INPUT)).(io.Writer); ok { m.Grow(SESSION, kit.Keys(kit.MDB_HASH, key), kit.Dict(kit.MDB_TYPE, CMD, kit.MDB_TEXT, m.Option(CMD))) - w.Write([]byte(m.Option(CMD) + "\n")) + w.Write([]byte(m.Option(CMD) + ice.MOD_NL)) } }) m.ProcessRefresh("300ms") diff --git a/base/tcp/client.go b/base/tcp/client.go index 8c457418..6f696344 100644 --- a/base/tcp/client.go +++ b/base/tcp/client.go @@ -73,7 +73,7 @@ func init() { m.Assert(e) cb(c) case func(net.Conn, []byte, error): - b := make([]byte, 4096) + b := make([]byte, ice.MOD_BUFS) for { n, e := c.Read(b) if cb(c, b[:n], e); e != nil { diff --git a/base/tcp/server.go b/base/tcp/server.go index 65262825..127d52c8 100644 --- a/base/tcp/server.go +++ b/base/tcp/server.go @@ -77,7 +77,7 @@ func init() { break } - b := make([]byte, 4096) + b := make([]byte, ice.MOD_BUFS) if n, e := c.Read(b); e == nil { m.Info("nonce", string(b[:n])) c.Write(b[:n]) diff --git a/base/web/space.go b/base/web/space.go index 2bfc347e..1e30dcb1 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -229,7 +229,7 @@ func init() { Index.Merge(&ice.Context{ Configs: map[string]*ice.Config{ SPACE: {Name: SPACE, Help: "空间站", Value: kit.Data(kit.MDB_SHORT, kit.MDB_NAME, - "redial", kit.Dict("a", 3000, "b", 1000, "c", 1000, "r", 4096, "w", 4096), + "redial", kit.Dict("a", 3000, "b", 1000, "c", 1000, "r", ice.MOD_BUFS, "w", ice.MOD_BUFS), "timeout", kit.Dict("c", "180s"), )}, }, diff --git a/base/yac/yac.go b/base/yac/yac.go index 8f4c2142..a0293c07 100644 --- a/base/yac/yac.go +++ b/base/yac/yac.go @@ -1,7 +1,7 @@ package yac import ( - "github.com/shylinux/icebergs" + ice "github.com/shylinux/icebergs" ) const YAC = "yac" diff --git a/conf.go b/conf.go index 40ef7e9b..81c16d44 100644 --- a/conf.go +++ b/conf.go @@ -1,6 +1,8 @@ package ice const ( // MOD + MOD_SP = " " + MOD_NL = "\n" MOD_DIR = 0750 MOD_FILE = 0640 diff --git a/misc.go b/misc.go index e56c5b28..9590c357 100644 --- a/misc.go +++ b/misc.go @@ -361,3 +361,13 @@ func (m *Message) OptionLoad(file string) *Message { } return m } + +func (m *Message) Confi(key string, sub string) int { + return kit.Int(m.Conf(key, sub)) +} +func (m *Message) Capi(key string, val ...interface{}) int { + if len(val) > 0 { + m.Cap(key, kit.Int(m.Cap(key))+kit.Int(val[0])) + } + return kit.Int(m.Cap(key)) +}