You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ti...@apache.org on 2019/09/16 09:47:34 UTC
[servicecomb-service-center] branch master updated: Bugfix: data
decreasing causes panic during paging (#587)
This is an automated email from the ASF dual-hosted git repository.
tianxiaoliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-service-center.git
The following commit(s) were added to refs/heads/master by this push:
new c655323 Bugfix: data decreasing causes panic during paging (#587)
c655323 is described below
commit c655323f1c4b10cde53fda2a862c280d3581e1f5
Author: humingcheng <hu...@163.com>
AuthorDate: Mon Sep 16 17:47:29 2019 +0800
Bugfix: data decreasing causes panic during paging (#587)
---
server/plugin/pkg/registry/etcd/etcd.go | 13 ++-
server/plugin/pkg/registry/etcd/etcd_test.go | 118 ++++++++++++++++++++++++---
2 files changed, 115 insertions(+), 16 deletions(-)
diff --git a/server/plugin/pkg/registry/etcd/etcd.go b/server/plugin/pkg/registry/etcd/etcd.go
index 2f872ca..04344ce 100644
--- a/server/plugin/pkg/registry/etcd/etcd.go
+++ b/server/plugin/pkg/registry/etcd/etcd.go
@@ -20,6 +20,11 @@ import (
"crypto/tls"
"errors"
"fmt"
+ "net/url"
+ "strconv"
+ "strings"
+ "time"
+
"github.com/apache/servicecomb-service-center/pkg/backoff"
errorsEx "github.com/apache/servicecomb-service-center/pkg/errors"
"github.com/apache/servicecomb-service-center/pkg/gopool"
@@ -28,15 +33,12 @@ import (
"github.com/apache/servicecomb-service-center/server/alarm"
mgr "github.com/apache/servicecomb-service-center/server/plugin"
"github.com/apache/servicecomb-service-center/server/plugin/pkg/registry"
+
"github.com/coreos/etcd/clientv3"
"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
"github.com/coreos/etcd/etcdserver/etcdserverpb"
"github.com/coreos/etcd/mvcc/mvccpb"
"golang.org/x/net/context"
- "net/url"
- "strconv"
- "strings"
- "time"
)
var firstEndpoint string
@@ -419,6 +421,9 @@ func (c *EtcdClient) paging(ctx context.Context, op registry.PluginOp) (*clientv
}
l := int64(len(recordResp.Kvs))
+ if l <= 0 { // no more data, data may decrease during paging
+ break
+ }
nextKey = util.BytesToStringWithNoCopy(recordResp.Kvs[l-1].Key)
if i < minPage {
// even through current page index less then the min page index,
diff --git a/server/plugin/pkg/registry/etcd/etcd_test.go b/server/plugin/pkg/registry/etcd/etcd_test.go
index aa4e69f..988c0ce 100644
--- a/server/plugin/pkg/registry/etcd/etcd_test.go
+++ b/server/plugin/pkg/registry/etcd/etcd_test.go
@@ -20,19 +20,24 @@ import _ "github.com/apache/servicecomb-service-center/server/plugin/pkg/tracing
import _ "github.com/apache/servicecomb-service-center/server/plugin/pkg/security/buildin"
import _ "github.com/apache/servicecomb-service-center/server/plugin/pkg/tls/buildin"
import (
+ context2 "context"
"fmt"
- "github.com/apache/servicecomb-service-center/server/core"
- "github.com/apache/servicecomb-service-center/server/plugin/pkg/registry"
- "github.com/apache/servicecomb-service-center/server/rpc"
- "golang.org/x/net/context"
- "google.golang.org/grpc/status"
- "net/http"
"os"
"strconv"
"strings"
"sync"
"testing"
"time"
+
+ "github.com/apache/servicecomb-service-center/server/core"
+ "github.com/apache/servicecomb-service-center/server/plugin/pkg/registry"
+ "github.com/apache/servicecomb-service-center/server/rpc"
+
+ "github.com/coreos/etcd/clientv3"
+ "github.com/coreos/etcd/etcdserver/etcdserverpb"
+ "github.com/coreos/etcd/mvcc/mvccpb"
+ "golang.org/x/net/context"
+ "google.golang.org/grpc/status"
)
const (
@@ -746,6 +751,101 @@ func TestEtcdClient_Watch(t *testing.T) {
<-ch
}
+type mockKVForPagine struct {
+ rangeCount int
+ countResp *clientv3.GetResponse
+ rangeResp1 *clientv3.GetResponse
+ rangeResp2 *clientv3.GetResponse
+}
+
+func (m *mockKVForPagine) Put(ctx context2.Context, key, val string, opts ...clientv3.OpOption) (*clientv3.PutResponse, error) {
+ return nil, nil
+}
+
+func (m *mockKVForPagine) Get(ctx context2.Context, key string, opts ...clientv3.OpOption) (*clientv3.GetResponse, error) {
+ op := &clientv3.Op{}
+ for _, o := range opts {
+ o(op)
+ }
+ if op.IsCountOnly() {
+ return m.countResp, nil
+ }
+ if m.rangeCount == 0 {
+ m.rangeCount = 1
+ return m.rangeResp1, nil
+ }
+ return m.rangeResp2, nil
+}
+
+func (m *mockKVForPagine) Delete(ctx context2.Context, key string, opts ...clientv3.OpOption) (*clientv3.DeleteResponse, error) {
+ return nil, nil
+}
+
+func (m *mockKVForPagine) Compact(ctx context2.Context, rev int64, opts ...clientv3.CompactOption) (*clientv3.CompactResponse, error) {
+ return nil, nil
+}
+
+func (m *mockKVForPagine) Do(ctx context2.Context, op clientv3.Op) (clientv3.OpResponse, error) {
+ return clientv3.OpResponse{}, nil
+}
+
+func (m *mockKVForPagine) Txn(ctx context2.Context) clientv3.Txn {
+ return nil
+}
+
+// test scenario: db data decreases during paging.
+func TestEtcdClient_paging(t *testing.T) {
+ // key range: [startKey, endKey)
+ generateGetResp := func(startKey, endKey int) *clientv3.GetResponse {
+ resp := &clientv3.GetResponse{
+ Count: int64(endKey - startKey),
+ Header: &etcdserverpb.ResponseHeader{
+ Revision: 0,
+ },
+ Kvs: make([]*mvccpb.KeyValue, 0),
+ }
+ if resp.Count <= 0 {
+ return resp
+ }
+ for i := startKey; i < endKey; i++ {
+ kvPart := &mvccpb.KeyValue{
+ Key: []byte(fmt.Sprint(i)),
+ Value: []byte(""),
+ }
+ resp.Kvs = append(resp.Kvs, kvPart)
+ }
+ return resp
+ }
+
+ mockKv := &mockKVForPagine{
+ rangeCount: 0,
+ // if count only, return 4097 kvs
+ countResp: generateGetResp(0, 4097),
+ // the first paging request, return 4096 kvs
+ rangeResp1: generateGetResp(0, 4096),
+ // the second paging request, return 0 kv
+ // meaning data decreases during paging
+ rangeResp2: generateGetResp(0, 0),
+ }
+ c := EtcdClient{
+ Client: &clientv3.Client{
+ KV: mockKv,
+ },
+ }
+
+ op := registry.PluginOp{
+ Offset: -1,
+ Limit: registry.DEFAULT_PAGE_COUNT,
+ }
+ r, err := c.paging(context2.Background(), op)
+ if err != nil {
+ t.Fatalf("TestEtcdClient_paging failed, %#v", err)
+ }
+ if len(r.Kvs) <= 0 {
+ t.Fatalf("TestEtcdClient_paging failed")
+ }
+}
+
func TestNewRegistry(t *testing.T) {
etcd := &EtcdClient{
Endpoints: []string{endpoint, "0.0.0.0:2379"},
@@ -759,12 +859,6 @@ func TestNewRegistry(t *testing.T) {
}
}
-type mockTLSHandler struct {
-}
-
-func (m *mockTLSHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
-}
-
func TestWithTLS(t *testing.T) {
sslRoot := "../../../../../examples/service_center/ssl/"
os.Setenv("SSL_ROOT", sslRoot)