From c8e919af3330af3f8c53ce17da5f4b48a6ff84be Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Tue, 11 Sep 2018 23:57:19 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=EF=BC=9Aradix=20match=20?= =?UTF-8?q?params=E5=8F=AA=E5=8C=85=E5=90=AB=E5=8C=B9=E9=85=8D=E7=9A=84?= =?UTF-8?q?=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/appsrv/radix.go | 95 +++++++++++++++++++++++++++------------- pkg/appsrv/radix_test.go | 12 +++-- 2 files changed, 73 insertions(+), 34 deletions(-) diff --git a/pkg/appsrv/radix.go b/pkg/appsrv/radix.go index 380bee48c1..67ddd20a95 100644 --- a/pkg/appsrv/radix.go +++ b/pkg/appsrv/radix.go @@ -3,24 +3,26 @@ package appsrv import ( "fmt" "strings" + ) type RadixNode struct { data interface{} + fullPath []string next []*RadixNode parent *RadixNode matchNext *RadixNode - matchTable []string + // matchTable []string segment string } func NewRadix() *RadixNode { return &RadixNode{data: nil, - next: make([]*RadixNode, 0), - matchNext: nil, - matchTable: nil, - parent: nil, - segment: ""} + fullPath: nil, + next: make([]*RadixNode, 0), + matchNext: nil, + parent: nil, + segment: ""} } func (r *RadixNode) String() string { @@ -50,11 +52,21 @@ func isMatchSegment(seg string) bool { } func (r *RadixNode) Add(segments []string, data interface{}) error { + return r.add(segments, segments, data) +} + +func (r *RadixNode) add(path []string, segments []string, data interface{}) error { + // log.Debugf("add %#v %#v", path, segments) + if len(segments) == 0 { if r.data != nil { return fmt.Errorf("Duplicate data for node %s", r.String()) } else { r.data = data + r.fullPath = make([]string, len(path)) + for i := 0; i < len(path); i += 1 { + r.fullPath[i] = path[i] + } return nil } } @@ -65,18 +77,18 @@ func (r *RadixNode) Add(segments []string, data interface{}) error { return fmt.Errorf("%s has been registered, %s conflict with %s", r.matchNext.String(), r.matchNext.segment, segments[0]) } */ nextNode = r.matchNext - nextNode.matchTable = append(nextNode.matchTable, segments[0]) + // nextNode.matchTable = append(nextNode.matchTable, segments[0]) } else { nextNode = NewRadix() nextNode.segment = "<*>" nextNode.parent = r - nextNode.matchTable = []string{segments[0]} + // nextNode.matchTable = []string{segments[0]} r.matchNext = nextNode } } else { - for _, node := range r.next { - if node.segment == segments[0] { - nextNode = node + for i := 0; i < len(r.next); i += 1 { + if r.next[i].segment == segments[0] { + nextNode = r.next[i] break } } @@ -87,42 +99,46 @@ func (r *RadixNode) Add(segments []string, data interface{}) error { r.next = append(r.next, nextNode) } } - return nextNode.Add(segments[1:], data) + return nextNode.add(path, segments[1:], data) } func (r *RadixNode) Match(segments []string, params map[string]string) interface{} { + data, allPaths := r.match(segments) + // log.Debugf("%#v", allPaths) + for i := 0; i < len(segments); i += 1 { + for j := 0; j < len(allPaths); j += 1 { + if i < len(allPaths[j]) && isMatchSegment(allPaths[j][i]) { + params[allPaths[j][i]] = segments[i] + } + } + } + return data +} + +func (r *RadixNode) match(segments []string) (interface{}, [][]string) { if len(segments) == 0 { - return r.data + return r.data, r.getAllFullPaths() } else { - var ret interface{} = nil + var retData interface{} = nil + var retPath [][]string = nil exactMatch := false for _, node := range r.next { if node.segment == segments[0] { - ret = node.Match(segments[1:], params) - if ret != nil { - // log.Debugf("Match %s ret %#v", node.segment, ret) + retData, retPath = node.match(segments[1:]) + if retData != nil { exactMatch = true - } else { - // log.Debugf("No match %s ret %#v", node.segment, ret) } break } } - if ret != nil { - return ret + if retData != nil { + return retData, retPath } else { if !exactMatch && r.matchNext != nil { - ret = r.matchNext.Match(segments[1:], params) - if ret != nil { - for _, segname := range r.matchNext.matchTable { - if _, ok := params[segname]; !ok { - params[segname] = segments[0] - } - } - } - return ret + retData, retPath = r.matchNext.match(segments[1:]) + return retData, retPath } else { - return r.data + return r.data, r.getAllFullPaths() } } } @@ -139,3 +155,20 @@ func (r *RadixNode) Walk(f func(path string, data interface{})) { r.matchNext.Walk(f) } } + +func (r *RadixNode) getAllFullPaths() [][]string { + if r.fullPath != nil { + return [][]string{r.fullPath} + }else { + ret := make([][]string, 0) + for _, node := range r.next { + fp := node.getAllFullPaths() + ret = append(ret, fp...) + } + if r.matchNext != nil { + fp := r.matchNext.getAllFullPaths() + ret = append(ret, fp...) + } + return ret + } +} diff --git a/pkg/appsrv/radix_test.go b/pkg/appsrv/radix_test.go index fe978ceec3..ef87a46398 100644 --- a/pkg/appsrv/radix_test.go +++ b/pkg/appsrv/radix_test.go @@ -61,10 +61,16 @@ func TestRadixNode(t *testing.T) { func TestParams(t *testing.T) { r := NewRadix() - r.Add([]string{"POST", "clouds", ""}, "classAction") - r.Add([]string{"POST", "clouds", "", ""}, "objectAction") + r.Add([]string{"POST", "clouds", ""}, "classAction") + r.Add([]string{"POST", "clouds", "", "sync"}, "objectSyncAction") + r.Add([]string{"POST", "clouds", "", ""}, "objectAction") params := make(map[string]string) - ret := r.Match([]string{"POST", "clouds", "id", "sync"}, params) + ret := r.Match([]string{"POST", "clouds", "myid", "sync"}, params) + t.Logf("match: %s", ret) + t.Logf("params: %s", params) + + params = make(map[string]string) + ret = r.Match([]string{"POST", "clouds", "myid", "start"}, params) t.Logf("match: %s", ret) t.Logf("params: %s", params) From 1a30516b0f82d34401c0f78ff69317a343c0aafa Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Wed, 12 Sep 2018 01:14:33 +0800 Subject: [PATCH 2/2] minor fixes --- pkg/cloudcommon/db/fetch.go | 6 +++--- pkg/cloudcommon/db/interface.go | 2 +- pkg/cloudcommon/db/modelbase.go | 2 +- pkg/cloudcommon/db/namevalidator.go | 4 ++-- pkg/cloudcommon/db/opslog.go | 6 +++--- pkg/cloudcommon/db/sharablevirtual.go | 4 ++-- pkg/cloudcommon/db/taskman/tasks.go | 2 +- pkg/cloudcommon/db/virtualresource.go | 4 ++-- pkg/compute/models/keypairs.go | 4 ++-- 9 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pkg/cloudcommon/db/fetch.go b/pkg/cloudcommon/db/fetch.go index 05f8f49f13..0297e57216 100644 --- a/pkg/cloudcommon/db/fetch.go +++ b/pkg/cloudcommon/db/fetch.go @@ -31,10 +31,10 @@ func fetchById(manager IModelManager, idStr string) (IModel, error) { } } -func fetchByName(manager IModelManager, ownerProjId string, idStr string) (IModel, error) { +func fetchByName(manager IModelManager, owner string, idStr string) (IModel, error) { q := manager.Query() q = manager.FilterByName(q, idStr) - q = manager.FilterByOwner(q, ownerProjId) + q = manager.FilterByOwner(q, owner) count := q.Count() if count == 1 { obj, err := NewModelObject(manager) @@ -101,7 +101,7 @@ func fetchItemByName(manager IModelManager, ctx context.Context, userCred mcclie } } q = manager.FilterByName(q, idStr) - q = manager.FilterByOwner(q, userCred.GetProjectId()) + q = manager.FilterByOwner(q, manager.GetOwnerId(userCred)) count := q.Count() if count == 1 { item, err := NewModelObject(manager) diff --git a/pkg/cloudcommon/db/interface.go b/pkg/cloudcommon/db/interface.go index 71097f4614..bcc4c00779 100644 --- a/pkg/cloudcommon/db/interface.go +++ b/pkg/cloudcommon/db/interface.go @@ -37,7 +37,7 @@ type IModelManager interface { FilterById(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery FilterByNotId(q *sqlchemy.SQuery, idStr string) *sqlchemy.SQuery FilterByName(q *sqlchemy.SQuery, name string) *sqlchemy.SQuery - FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery + FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery GetOwnerId(userCred mcclient.TokenCredential) string diff --git a/pkg/cloudcommon/db/modelbase.go b/pkg/cloudcommon/db/modelbase.go index 6b5f48f0aa..4e17ff01e9 100644 --- a/pkg/cloudcommon/db/modelbase.go +++ b/pkg/cloudcommon/db/modelbase.go @@ -104,7 +104,7 @@ func (manager *SModelBaseManager) FilterByName(q *sqlchemy.SQuery, name string) return q } -func (manager *SModelBaseManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery { +func (manager *SModelBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery { return q } diff --git a/pkg/cloudcommon/db/namevalidator.go b/pkg/cloudcommon/db/namevalidator.go index aef4032450..71e9703e9b 100644 --- a/pkg/cloudcommon/db/namevalidator.go +++ b/pkg/cloudcommon/db/namevalidator.go @@ -7,11 +7,11 @@ import ( "yunion.io/x/pkg/util/stringutils" ) -func isNameUnique(manager IModelManager, ownerProjId string, name string) bool { +func isNameUnique(manager IModelManager, owner string, name string) bool { q := manager.Query() q = manager.FilterByName(q, name) if !globalVirtualResourceNamespace { - q = manager.FilterByOwner(q, ownerProjId) + q = manager.FilterByOwner(q, owner) } return q.Count() == 0 } diff --git a/pkg/cloudcommon/db/opslog.go b/pkg/cloudcommon/db/opslog.go index 457908e27f..97c5f3b3ce 100644 --- a/pkg/cloudcommon/db/opslog.go +++ b/pkg/cloudcommon/db/opslog.go @@ -349,9 +349,9 @@ func (self *SOpsLogManager) FilterByName(q *sqlchemy.SQuery, name string) *sqlch return q } -func (self *SOpsLogManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery { - if len(ownerProjId) > 0 { - return q.Equals("owner_project_id", ownerProjId) +func (self *SOpsLogManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery { + if len(owner) > 0 { + return q.Equals("owner_project_id", owner) } else { return q } diff --git a/pkg/cloudcommon/db/sharablevirtual.go b/pkg/cloudcommon/db/sharablevirtual.go index 33e8170198..62c38c442d 100644 --- a/pkg/cloudcommon/db/sharablevirtual.go +++ b/pkg/cloudcommon/db/sharablevirtual.go @@ -22,8 +22,8 @@ func NewSharableVirtualResourceBaseManager(dt interface{}, tableName string, key return SSharableVirtualResourceBaseManager{SVirtualResourceBaseManager: NewVirtualResourceBaseManager(dt, tableName, keyword, keywordPlural)} } -func (manager *SSharableVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery { - q = q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("tenant_id"), ownerProjId), sqlchemy.IsTrue(q.Field("is_public")))) +func (manager *SSharableVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery { + q = q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("tenant_id"), owner), sqlchemy.IsTrue(q.Field("is_public")))) q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("pending_deleted")), sqlchemy.IsFalse(q.Field("pending_deleted")))) q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("is_system")), sqlchemy.IsFalse(q.Field("is_system")))) return q diff --git a/pkg/cloudcommon/db/taskman/tasks.go b/pkg/cloudcommon/db/taskman/tasks.go index f221ae6f11..26df5fb08f 100644 --- a/pkg/cloudcommon/db/taskman/tasks.go +++ b/pkg/cloudcommon/db/taskman/tasks.go @@ -87,7 +87,7 @@ func (manager *STaskManager) FilterByName(q *sqlchemy.SQuery, name string) *sqlc return q } -func (manager *STaskManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery { +func (manager *STaskManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery { return q } diff --git a/pkg/cloudcommon/db/virtualresource.go b/pkg/cloudcommon/db/virtualresource.go index 8220398d3c..4b90d64b2a 100644 --- a/pkg/cloudcommon/db/virtualresource.go +++ b/pkg/cloudcommon/db/virtualresource.go @@ -49,8 +49,8 @@ func (model *SVirtualResourceBase) GetOwnerProjectId() string { return model.ProjectId } -func (manager *SVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, ownerProjId string) *sqlchemy.SQuery { - q = q.Equals("tenant_id", ownerProjId) +func (manager *SVirtualResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery { + q = q.Equals("tenant_id", owner) q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("pending_deleted")), sqlchemy.IsFalse(q.Field("pending_deleted")))) q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("is_system")), sqlchemy.IsFalse(q.Field("is_system")))) return q diff --git a/pkg/compute/models/keypairs.go b/pkg/compute/models/keypairs.go index 4563ff639f..84cb4f5b28 100644 --- a/pkg/compute/models/keypairs.go +++ b/pkg/compute/models/keypairs.go @@ -116,8 +116,8 @@ func totalKeypairCount(userId string) int { return q.Count() } -func (manager *SKeypairManager) FilterByOwner(q *sqlchemy.SQuery, ownerId string) *sqlchemy.SQuery { - return q.Equals("owner_id", ownerId) +func (manager *SKeypairManager) FilterByOwner(q *sqlchemy.SQuery, owner string) *sqlchemy.SQuery { + return q.Equals("owner_id", owner) } func (self *SKeypair) GetOwnerProjectId() string {