From e8f60a7722033eec07a292f720ea63fd8315b07f Mon Sep 17 00:00:00 2001 From: qydysky <32743305+qydysky@users.noreply.github.com> Date: Sat, 11 Feb 2023 20:02:05 +0800 Subject: [PATCH] Improve --- web/Web.go | 126 ++++++++++++++++++------------------------------ web/Web_test.go | 76 ++++++++++++++++++++++++----- 2 files changed, 110 insertions(+), 92 deletions(-) diff --git a/web/Web.go b/web/Web.go index 7bc30f9..8cc84ac 100644 --- a/web/Web.go +++ b/web/Web.go @@ -26,109 +26,75 @@ type WebPath struct { f func(w http.ResponseWriter, r *http.Request) sameP *WebPath next *WebPath - l sync.RWMutex + sync.RWMutex } func (t *WebPath) Load(path string) (func(w http.ResponseWriter, r *http.Request), bool) { - t.l.RLock() - if t.path == "" { - t.l.RUnlock() - return nil, false - } else if t.path == path { - t.l.RUnlock() + t.RLock() + defer t.RUnlock() + if t.path == path || t.f == nil { + // 操作本节点 return t.f, true - } else if len(path) > len(t.path) && path[:len(t.path)] == t.path { - if t.path == "/" || path[len(t.path)] == '/' { - if t.sameP != nil { - if f, ok := t.sameP.Load(path); ok { - t.l.RUnlock() - return f, true - } else { - t.l.RUnlock() - return t.f, true - } - } else { - t.l.RUnlock() - return t.f, true + } else if lp, ltp := len(path), len(t.path); lp > ltp && path[:ltp] == t.path && (path[ltp] == '/' || t.path[ltp-1] == '/') { + // 操作sameP节点 + if t.sameP != nil { + if f, ok := t.sameP.Load(path); ok { + return f, true } + } + if t.path[ltp-1] == '/' { + return t.f, true } else { - if t.next != nil { - t.l.RUnlock() - return t.next.Load(path) - } else { - t.l.RUnlock() - return nil, false - } + return nil, false } - } else if t.next != nil { - t.l.RUnlock() - return t.next.Load(path) + } else if lp < ltp && t.path[:lp] == path && (path[lp-1] == '/' || t.path[lp] == '/') { + // 操作sameP节点 + return nil, false } else { - t.l.RUnlock() + // 操作next节点 + if t.next != nil { + if f, ok := t.next.Load(path); ok { + return f, true + } + } return nil, false } } func (t *WebPath) Store(path string, f func(w http.ResponseWriter, r *http.Request)) { - t.l.RLock() - if t.path == path || t.path == "" { - t.l.RUnlock() - t.l.Lock() + t.Lock() + defer t.Unlock() + if t.path == path || t.f == nil { + // 操作本节点 t.path = path t.f = f - t.l.Unlock() - } else if len(path) > len(t.path) && path[:len(t.path)] == t.path { - if t.path == "/" || path[len(t.path)] == '/' { - if t.sameP != nil { - t.l.RUnlock() - t.sameP.Store(path, f) - } else { - t.l.RUnlock() - t.l.Lock() - t.sameP = &WebPath{ - path: path, - f: f, - } - t.l.Unlock() - } + } else if len(path) > len(t.path) && path[:len(t.path)] == t.path && (path[len(t.path)-1] == '/' || t.path[len(t.path)-1] == '/') { + // 操作sameP节点 + if t.sameP != nil { + t.sameP.Store(path, f) } else { - if t.next != nil { - t.l.RUnlock() - t.l.Lock() - tmp := WebPath{path: t.path, f: t.f, sameP: t.sameP, next: t.next} - t.path = path - t.f = f - t.next = &tmp - t.l.Unlock() - } else { - t.l.RUnlock() - t.l.Lock() - t.next = &WebPath{ - path: path, - f: f, - } - t.l.Unlock() + t.sameP = &WebPath{ + path: path, + f: f, } } - } else if len(path) < len(t.path) && t.path[:len(path)] == path { - t.l.RUnlock() - t.l.Lock() + } else if len(path) < len(t.path) && t.path[:len(path)] == path && (path[len(path)-1] == '/' || t.path[len(path)-1] == '/') { + // 操作sameP节点 tmp := WebPath{path: t.path, f: t.f, sameP: t.sameP, next: t.next} t.path = path t.f = f t.sameP = &tmp - t.l.Unlock() - } else if t.next != nil { - t.l.RUnlock() - t.next.Store(path, f) + t.next = nil } else { - t.l.RUnlock() - t.l.Lock() - t.next = &WebPath{ - path: path, - f: f, + // 操作next节点 + if t.next != nil { + t.next.Store(path, f) + } else { + t.next = &WebPath{ + path: path, + f: f, + } } - t.l.Unlock() } } @@ -190,7 +156,7 @@ func Easy_boot() *Web { } http.ServeFile(w, r, path) }, - `/exit`: func(w http.ResponseWriter, r *http.Request) { + `/exit`: func(_ http.ResponseWriter, _ *http.Request) { s.Server.Shutdown(context.Background()) }, }) diff --git a/web/Web_test.go b/web/Web_test.go index cdb00d8..c437abf 100644 --- a/web/Web_test.go +++ b/web/Web_test.go @@ -6,6 +6,8 @@ import ( "strconv" "testing" "time" + + reqf "github.com/qydysky/part/reqf" ) func Test_Server(t *testing.T) { @@ -16,7 +18,7 @@ func Test_Server(t *testing.T) { func Test_ServerSyncMap(t *testing.T) { var m WebPath - m.Store("/", func(w http.ResponseWriter, r *http.Request) { + m.Store("/", func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte("1")) }) NewSyncMap(&http.Server{ @@ -24,7 +26,7 @@ func Test_ServerSyncMap(t *testing.T) { }, &m) for i := 0; i < 20; i++ { time.Sleep(time.Second) - m.Store("/1", func(w http.ResponseWriter, r *http.Request) { + m.Store("/1", func(w http.ResponseWriter, _ *http.Request) { type d struct { A string `json:"a"` @@ -46,7 +48,7 @@ func BenchmarkXxx(b *testing.B) { } b.ResetTimer() for i := 0; i < b.N; i++ { - m.Store("/", func(w http.ResponseWriter, r *http.Request) { + m.Store("/", func(w http.ResponseWriter, _ *http.Request) { ResStruct{0, "ok", d{"/"}}.Write(w) }) } @@ -61,20 +63,70 @@ func Test_ServerSyncMapP(t *testing.T) { NewSyncMap(&http.Server{ Addr: "127.0.0.1:9090", }, &m) - m.Store("/", func(w http.ResponseWriter, r *http.Request) { - ResStruct{0, "ok", d{"/"}}.Write(w) - }) - m.Store("/1/2", func(w http.ResponseWriter, r *http.Request) { + m.Store("/1/2", func(w http.ResponseWriter, _ *http.Request) { ResStruct{0, "ok", d{"/1/2"}}.Write(w) }) - m.Store("/1", func(w http.ResponseWriter, r *http.Request) { - ResStruct{0, "ok", d{"/1"}}.Write(w) + m.Store("/1/", func(w http.ResponseWriter, _ *http.Request) { + ResStruct{0, "ok", d{"/1/"}}.Write(w) }) - m.Store("/2", func(w http.ResponseWriter, r *http.Request) { - ResStruct{0, "ok", d{"/2"}}.Write(w) + m.Store("/2/", func(w http.ResponseWriter, _ *http.Request) { + ResStruct{0, "ok", d{"/2/"}}.Write(w) + }) + m.Store("/", func(w http.ResponseWriter, _ *http.Request) { + ResStruct{0, "ok", d{"/"}}.Write(w) }) - time.Sleep(time.Second * time.Duration(23)) + r := reqf.New() + res := ResStruct{} + r.Reqf(reqf.Rval{ + Url: "http://127.0.0.1:9090/", + }) + json.Unmarshal(r.Respon, &res) + if data, ok := res.Data.(map[string]any); !ok || data["path"].(string) != "/" { + t.Fatal("") + } + r.Reqf(reqf.Rval{ + Url: "http://127.0.0.1:9090/1", + }) + json.Unmarshal(r.Respon, &res) + if data, ok := res.Data.(map[string]any); !ok || data["path"].(string) != "/" { + t.Fatal("") + } + r.Reqf(reqf.Rval{ + Url: "http://127.0.0.1:9090/1/", + }) + json.Unmarshal(r.Respon, &res) + if data, ok := res.Data.(map[string]any); !ok || data["path"].(string) != "/1/" { + t.Fatal("") + } + r.Reqf(reqf.Rval{ + Url: "http://127.0.0.1:9090/2", + }) + json.Unmarshal(r.Respon, &res) + if data, ok := res.Data.(map[string]any); !ok || data["path"].(string) != "/" { + t.Fatal("") + } + r.Reqf(reqf.Rval{ + Url: "http://127.0.0.1:9090/1/23", + }) + json.Unmarshal(r.Respon, &res) + if data, ok := res.Data.(map[string]any); !ok || data["path"].(string) != "/1/" { + t.Fatal("") + } + r.Reqf(reqf.Rval{ + Url: "http://127.0.0.1:9090/1/2/3", + }) + json.Unmarshal(r.Respon, &res) + if data, ok := res.Data.(map[string]any); !ok || data["path"].(string) != "/1/" { + t.Fatal("") + } + r.Reqf(reqf.Rval{ + Url: "http://127.0.0.1:9090/1/2", + }) + json.Unmarshal(r.Respon, &res) + if data, ok := res.Data.(map[string]any); !ok || data["path"].(string) != "/1/2" { + t.Fatal("") + } } type ResStruct struct { -- 2.39.2