Skip to content

Commit

Permalink
Optimize router. (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
little-cui authored and asifdxtreme committed Oct 27, 2017
1 parent 32e7948 commit 3d384e8
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 44 deletions.
30 changes: 18 additions & 12 deletions pkg/chain/callback.go
Expand Up @@ -14,6 +14,7 @@
package chain

import (
"fmt"
"github.com/ServiceComb/service-center/pkg/util"
)

Expand All @@ -23,17 +24,28 @@ type Result struct {
Args []interface{}
}

type CallbackFunc func(r Result)
func (r Result) String() string {
if r.OK {
return "OK"
}
return fmt.Sprintf("FAIL(error: %s)", r.Err)
}

type Callback struct {
Func CallbackFunc
Func func(r Result)
}

func (cb *Callback) Invoke(r Result) {
go func() {
defer util.RecoverAndReport()
cb.Func(r)
}()
go cb.syncInvoke(r)
}

func (cb *Callback) syncInvoke(r Result) {
defer util.RecoverAndReport()
if cb.Func == nil {
util.Logger().Errorf(nil, "Callback function is nil. result: %s,", r)
return
}
cb.Func(r)
}

func (cb *Callback) Fail(err error, args ...interface{}) {
Expand All @@ -50,9 +62,3 @@ func (cb *Callback) Success(args ...interface{}) {
Args: args,
})
}

func NewCallback(f CallbackFunc) Callback {
return Callback{
Func: f,
}
}
34 changes: 22 additions & 12 deletions pkg/chain/chain.go
Expand Up @@ -14,25 +14,21 @@
package chain

import (
"fmt"
errorsEx "github.com/ServiceComb/service-center/pkg/errors"
"github.com/ServiceComb/service-center/pkg/util"
"sync"
)

var handlersMap map[string][]Handler

type Chain struct {
name string
handlers []Handler
currentIndex int
mux sync.Mutex
}

func (c *Chain) Init(chainName string, hs []Handler) {
c.name = chainName
c.currentIndex = -1
if len(hs) > 0 {
c.handlers = make([]Handler, 0, len(hs))
c.handlers = make([]Handler, len(hs))
copy(c.handlers, hs)
}
}
Expand All @@ -41,17 +37,31 @@ func (c *Chain) Name() string {
return c.name
}

func (c *Chain) doNext(i *Invocation) {
defer util.RecoverAndReport()
func (c *Chain) syncNext(i *Invocation) {
defer func() {
itf := recover()
if itf == nil {
return
}
util.Logger().Errorf(nil, "recover! %v", itf)

i.Fail(errorsEx.RaiseError(itf))
}()

if c.currentIndex >= len(c.handlers) {
i.Fail(fmt.Errorf("Over end of chain '%s'", c.name))
if c.currentIndex >= len(c.handlers)-1 {
i.Success()
return
}
c.currentIndex += 1
c.handlers[c.currentIndex].Handle(i)
}

func (c *Chain) next(i *Invocation) {
go c.doNext(i)
func (c *Chain) Next(i *Invocation) {
go c.syncNext(i)
}

func NewChain(name string, handlers ...Handler) *Chain {
var ch Chain
ch.Init(name, handlers)
return &ch
}
15 changes: 15 additions & 0 deletions pkg/chain/handler.go
Expand Up @@ -13,6 +13,21 @@
//limitations under the License.
package chain

var handlersMap map[string][]Handler = make(map[string][]Handler, CAP_SIZE)

type Handler interface {
Handle(i *Invocation)
}

func RegisterHandler(catalog string, h Handler) {
handlers, ok := handlersMap[catalog]
if !ok {
handlers = make([]Handler, 0, CAP_SIZE)
}
handlers = append(handlers, h)
handlersMap[catalog] = handlers
}

func Handlers(catalog string) []Handler {
return handlersMap[catalog]
}
22 changes: 16 additions & 6 deletions pkg/chain/invocation.go
Expand Up @@ -17,7 +17,7 @@ import (
"errors"
)

const DEFAULT_MAP_SIZE = 10
const CAP_SIZE = 10

type Invocation struct {
Callback
Expand All @@ -27,8 +27,8 @@ type Invocation struct {
}

func (i *Invocation) Init(ch *Chain) {
i.handlerContext = make(map[string]interface{}, DEFAULT_MAP_SIZE)
i.context = make(map[string]interface{}, DEFAULT_MAP_SIZE)
i.handlerContext = make(map[string]interface{}, CAP_SIZE)
i.context = make(map[string]interface{}, CAP_SIZE)
i.chain = ch
}

Expand All @@ -50,11 +50,21 @@ func (i *Invocation) WithContext(key string, val interface{}) *Invocation {
return i
}

func (i *Invocation) Next(f CallbackFunc) {
i.Func = f
func (i *Invocation) Next() {
if i.chain == nil {
i.Fail(errors.New("Can not find any chain for this invocation"))
return
}
i.chain.next(i)
i.chain.Next(i)
}

func (i *Invocation) Invoke(f func(r Result)) {
i.Func = f
i.Next()
}

func NewInvocation(ch *Chain) *Invocation {
var inv Invocation
inv.Init(ch)
return &inv
}
14 changes: 14 additions & 0 deletions pkg/errors/error.go
Expand Up @@ -13,8 +13,22 @@
//limitations under the License.
package errors

import (
"fmt"
)

type InternalError string

func (e InternalError) Error() string {
return string(e)
}

func RaiseError(itf interface{}) InternalError {
if itf == nil {
return InternalError("panic: unknown")
}
if err, ok := itf.(error); ok {
return InternalError(err.Error())
}
return InternalError(fmt.Sprintf("%v", itf))
}
24 changes: 12 additions & 12 deletions pkg/rest/route.go
Expand Up @@ -18,7 +18,6 @@ import (
"fmt"
"github.com/ServiceComb/service-center/pkg/util"
"net/http"
"net/url"
"strings"
)

Expand Down Expand Up @@ -47,13 +46,13 @@ type Route struct {
// 2. redirect not supported
type ROAServerHandler struct {
handlers map[string][]*urlPatternHandler
filters []Filter
filters []Filter
}

func NewROAServerHander() *ROAServerHandler {
return &ROAServerHandler{
handlers: make(map[string][]*urlPatternHandler),
filters: make([]Filter, 0, 5),
filters: make([]Filter, 0, 5),
}
}

Expand All @@ -76,7 +75,7 @@ func (this *ROAServerHandler) ServeHTTP(w http.ResponseWriter, r *http.Request)
for _, ph := range this.handlers[r.Method] {
if params, ok := ph.try(r.URL.Path); ok {
if len(params) > 0 {
r.URL.RawQuery = url.Values(params).Encode() + "&" + r.URL.RawQuery
r.URL.RawQuery = util.UrlEncode(params) + "&" + r.URL.RawQuery
}

if err = this.doFilter(r); err != nil {
Expand Down Expand Up @@ -124,12 +123,13 @@ func (this *ROAServerHandler) doFilter(r *http.Request) error {
return nil
}

func (this *urlPatternHandler) try(path string) (p map[string][]string, _ bool) {
func (this *urlPatternHandler) try(path string) (p map[string]string, _ bool) {
var i, j int
for i < len(path) {
l, sl := len(this.Path), len(path)
for i < sl {
switch {
case j >= len(this.Path):
if this.Path != "/" && len(this.Path) > 0 && this.Path[len(this.Path)-1] == '/' {
case j >= l:
if this.Path != "/" && l > 0 && this.Path[l-1] == '/' {
return p, true
}
return nil, false
Expand All @@ -141,17 +141,17 @@ func (this *urlPatternHandler) try(path string) (p map[string][]string, _ bool)
val, _, i = match(path, matchParticial, nextc, i)

if p == nil {
p = make(map[string][]string)
p = make(map[string]string, 5)
}
p[this.Path[o:j]] = []string{val}
p[this.Path[o:j]] = val
case path[i] == this.Path[j]:
i++
j++
default:
return nil, false
}
}
if j != len(this.Path) {
if j != l {
return nil, false
}
return p, true
Expand Down Expand Up @@ -188,4 +188,4 @@ func isAlnum(ch byte) bool {
type Filter interface {
IsMatch(r *http.Request) bool
Do(r *http.Request) error
}
}
17 changes: 15 additions & 2 deletions pkg/util/util.go
Expand Up @@ -209,10 +209,11 @@ func StringJoin(args []string, sep string) string {
}
}

func RecoverAndReport() {
if r := recover(); r != nil {
func RecoverAndReport() (r interface{}) {
if r = recover(); r != nil {
Logger().Errorf(nil, "recover! %v", r)
}
return
}

func ParseEndpoint(ep string) (string, error) {
Expand Down Expand Up @@ -269,3 +270,15 @@ func BytesToInt32(bs []byte) (in int32) {
}
return
}

func UrlEncode(keys map[string]string) string {
l := len(keys)
if l == 0 {
return ""
}
arr := make([]string, 0, l)
for k, v := range keys {
arr = append(arr, url.QueryEscape(k)+"="+url.QueryEscape(v))
}
return StringJoin(arr, "&")
}

0 comments on commit 3d384e8

Please sign in to comment.