Skip to content

Commit

Permalink
Merge 70418c7 into fa2904b
Browse files Browse the repository at this point in the history
  • Loading branch information
little-cui committed Oct 18, 2017
2 parents fa2904b + 70418c7 commit 0aed888
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 15 deletions.
13 changes: 13 additions & 0 deletions pkg/util/sys.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ package util
import (
"net"
"os"
"unsafe"
)

const INT_SIZE int = int(unsafe.Sizeof(0))

func GetLocalHostname() string {
hostName, _ := os.Hostname()
return hostName
Expand All @@ -38,3 +41,13 @@ func GetLocalIP() string {
}
return ""
}

func IsBigEndian() bool {
return !IsLittleEndian()
}

func IsLittleEndian() bool {
i := 0x1
bs := (*[INT_SIZE]byte)(unsafe.Pointer(&i))
return bs[0] == 0
}
20 changes: 20 additions & 0 deletions pkg/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,23 @@ func GetStartTimeFromContext(ctx context.Context) time.Time {
}
return v
}

func BytesToInt32(bs []byte) (in int32) {
l := len(bs)
if l > 4 || l == 0 {
return 0
}

pi := (*[4]byte)(unsafe.Pointer(&in))
if IsBigEndian() {
for i := range bs {
pi[i] = bs[l-i-1]
}
return
}

for i := range bs {
pi[3-i] = bs[l-i-1]
}
return
}
50 changes: 50 additions & 0 deletions pkg/util/util_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//Copyright 2017 Huawei Technologies Co., Ltd
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
package util

import (
"testing"
)

func TestBytesToInt32(t *testing.T) {
bs := []byte{0, 0, 0, 1}
i := BytesToInt32(bs)
if i != 1 {
t.FailNow()
}

bs = []byte{1, 0, 0, 0}
i = BytesToInt32(bs)
if i != 1<<(3*8) {
t.FailNow()
}

bs = []byte{0, 0, 0, 0, 1}
i = BytesToInt32(bs)
if i != 0 {
t.FailNow()
}

bs = []byte{1}
i = BytesToInt32(bs)
if i != 1 {
t.FailNow()
}

bs = []byte{1, 0}
i = BytesToInt32(bs)
if i != 1<<8 {
t.FailNow()
}
}
34 changes: 19 additions & 15 deletions server/service/util/versionrule.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
package util

import (
"bytes"
"github.com/ServiceComb/service-center/pkg/util"
"github.com/coreos/etcd/mvcc/mvccpb"
"sort"
Expand All @@ -27,13 +26,14 @@ type VersionRule func(sorted []string, kvs map[string]string, start, end string)
func (vr VersionRule) Match(kvs []*mvccpb.KeyValue, ops ...string) []string {
sorter := &serviceKeySorter{
sortArr: make([]string, len(kvs)),
kvs: make(map[string]string),
kvs: make(map[string]string, len(kvs)),
cmp: Larger,
}
for i, kv := range kvs {
key := util.BytesToStringWithNoCopy(kv.Key)
sorter.sortArr[i] = key[strings.LastIndex(key, "/")+1:]
sorter.kvs[sorter.sortArr[i]] = util.BytesToStringWithNoCopy(kv.Value)
ver := key[strings.LastIndex(key, "/")+1:]
sorter.sortArr[i] = ver
sorter.kvs[ver] = util.BytesToStringWithNoCopy(kv.Value)
}
sort.Sort(sorter)

Expand Down Expand Up @@ -66,23 +66,27 @@ func (sks *serviceKeySorter) Less(i, j int) bool {
return sks.cmp(sks.sortArr[i], sks.sortArr[j])
}

func stringToBytesVersion(versionStr string) []byte {
verSet := strings.Split(versionStr, ".")
verBytes := make([]byte, len(verSet))
for i, v := range verSet {
integer, err := strconv.ParseInt(v, 10, 8)
if err != nil {
return []byte{}
func versionToInt(versionStr string) (ret int32) {
verBytes := [4]byte{}
idx := 0
for i := 0; i < 4 && idx < len(versionStr); i++ {
f := strings.IndexRune(versionStr[idx:], '.')
if f < 0 {
f = len(versionStr) - idx
}
integer, err := strconv.ParseInt(versionStr[idx:idx+f], 10, 8)
if err != nil || integer < 0 {
return 0
}
verBytes[i] = byte(integer)
idx += f + 1
}
return verBytes[:]
ret = util.BytesToInt32(verBytes[:])
return
}

func Larger(start, end string) bool {
startVerBytes := stringToBytesVersion(start)
endVerBytes := stringToBytesVersion(end)
return bytes.Compare(startVerBytes, endVerBytes) > 0
return versionToInt(start) > versionToInt(end)
}

func Latest(sorted []string, kvs map[string]string, start, end string) []string {
Expand Down
22 changes: 22 additions & 0 deletions server/service/util/versionrule_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import (
"github.com/coreos/etcd/mvcc/mvccpb"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"math"
"math/rand"
"sort"
"testing"
)

var _ = Describe("Version Rule sorter", func() {
Expand Down Expand Up @@ -220,3 +223,22 @@ var _ = Describe("Version Rule sorter", func() {
})
})
})

func BenchmarkVersionRule_Match(b *testing.B) {
var kvs = []*mvccpb.KeyValue{}
for i := 1; i <= b.N; i++ {
x := rand.Intn(math.MaxInt8)
y := rand.Intn(math.MaxInt8)
z := rand.Intn(math.MaxInt8)
kvs = append(kvs, &mvccpb.KeyValue{
Key: []byte(fmt.Sprintf("/service/ver/%d.%d.%d", x, y, z)),
Value: []byte(fmt.Sprintf("%d.%d.%d", x, y, z)),
})
}

b.ResetTimer()
for i := 0; i < b.N; i++ {
VersionRule(Latest).Match(kvs)
}
b.ReportAllocs()
}

0 comments on commit 0aed888

Please sign in to comment.