zouyx commented on a change in pull request #471:
URL: https://github.com/apache/dubbo-go/pull/471#discussion_r412023225



##########
File path: metadata/definition/definition.go
##########
@@ -39,3 +51,39 @@ type TypeDefinition struct {
        Properties      map[string]TypeDefinition
        TypeBuilderName string
 }
+
+// BuildServiceDefinition can build service definition which will be used to 
describe a service
+func BuildServiceDefinition(service common.Service, url common.URL) 
ServiceDefinition {
+       sd := ServiceDefinition{}
+       sd.CanonicalName = url.Service()
+
+       for k, m := range service.Method() {
+               var paramTypes []string
+               for _, t := range m.ArgsType() {
+                       paramTypes = append(paramTypes, t.Kind().String())
+               }
+               methodD := MethodDefinition{
+                       Name:           k,
+                       ParameterTypes: paramTypes,
+                       ReturnType:     m.ReplyType().Kind().String(),
+               }
+               sd.Methods = append(sd.Methods, methodD)
+       }
+
+       return sd
+}
+
+// ServiceDescriperBuild: build the service key, format is 
`group/serviceName:version` which be same as URL's service key
+func ServiceDescriperBuild(serviceName string, group string, version string) 
string {
+       buf := &bytes.Buffer{}
+       if group != "" {
+               buf.WriteString(group)
+               buf.WriteString(constant.PATH_SEPARATOR)
+       }
+       buf.WriteString(serviceName)
+       if version != "" && version != "0.0.0" {

Review comment:
       i dont suggest use "0.0.0" .
   
   what about split by `.` and convert to int, finally compare to `0` ?

##########
File path: config/config_loader_test.go
##########
@@ -18,6 +18,7 @@
 package config
 
 import (
+       "go.uber.org/atomic"

Review comment:
       split

##########
File path: config/service_config.go
##########
@@ -160,22 +179,42 @@ func (c *ServiceConfig) Export() error {
                                c.cacheMutex.Unlock()
 
                                invoker := 
extension.GetProxyFactory(providerConfig.ProxyFactory).GetInvoker(*regUrl)
-                               exporter := c.cacheProtocol.Export(invoker)
+                               exporter = c.cacheProtocol.Export(invoker)
                                if exporter == nil {
                                        panic(perrors.New(fmt.Sprintf("Registry 
protocol new exporter error,registry is {%v},url is {%v}", regUrl, ivkURL)))
                                }
                        }
                } else {
                        invoker := 
extension.GetProxyFactory(providerConfig.ProxyFactory).GetInvoker(*ivkURL)
-                       exporter := 
extension.GetProtocol(protocolwrapper.FILTER).Export(invoker)
+                       exporter = 
extension.GetProtocol(protocolwrapper.FILTER).Export(invoker)
                        if exporter == nil {
                                panic(perrors.New(fmt.Sprintf("Filter protocol 
without registry new exporter error,url is {%v}", ivkURL)))
                        }
                }
+               c.exporters = append(c.exporters, exporter)
        }
+       c.exported.Store(true)
        return nil
 }
 
+// Unexport will call unexport of all exporters service config exported
+func (c *ServiceConfig) Unexport() {
+       if !c.exported.Load() {
+               return
+       }
+       if c.unexported.Load() {
+               return
+       }
+       c.exportersLock.Lock()
+       defer c.exportersLock.Unlock()
+       for _, exporter := range c.exporters {
+               exporter.Unexport()
+       }
+       c.exporters = nil

Review comment:
       just lock this block ,no need to  defer?

##########
File path: metadata/service/inmemory/service.go
##########
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 inmemory
+
+import (
+       "encoding/json"
+       "sync"
+)
+
+import (
+       cm "github.com/Workiva/go-datastructures/common"
+       "github.com/Workiva/go-datastructures/slice/skip"
+)
+
+import (
+       "github.com/apache/dubbo-go/common"
+       "github.com/apache/dubbo-go/common/constant"
+       "github.com/apache/dubbo-go/common/logger"
+       "github.com/apache/dubbo-go/metadata/definition"
+       "github.com/apache/dubbo-go/metadata/service"
+)
+
+// MetadataService is store and query the metadata info in memory when each 
service registry
+type MetadataService struct {
+       service.BaseMetadataService
+       exportedServiceURLs   *sync.Map
+       subscribedServiceURLs *sync.Map
+       serviceDefinitions    *sync.Map
+       lock                  *sync.RWMutex
+}
+
+// NewMetadataService: initiate a metadata service
+func NewMetadataService() *MetadataService {
+       return &MetadataService{
+               exportedServiceURLs:   &sync.Map{},
+               subscribedServiceURLs: &sync.Map{},
+               serviceDefinitions:    &sync.Map{},
+               lock:                  &sync.RWMutex{},
+       }
+}
+
+// comparator is defined as Comparator for skip list to compare the URL
+type comparator common.URL
+
+// Compare is defined as Comparator for skip list to compare the URL
+func (c comparator) Compare(comp cm.Comparator) int {
+       a := common.URL(c).String()
+       b := common.URL(comp.(comparator)).String()
+       switch {
+       case a > b:
+               return 1
+       case a < b:
+               return -1
+       default:
+               return 0
+       }
+}
+
+// addURL will add URL in memory
+func (mts *MetadataService) addURL(targetMap *sync.Map, url *common.URL) bool {
+       var (
+               urlSet interface{}
+               loaded bool
+       )
+       logger.Debug(url.ServiceKey())
+       if urlSet, loaded = targetMap.LoadOrStore(url.ServiceKey(), 
skip.New(uint64(0))); loaded {
+               mts.lock.RLock()
+               wantedUrl := urlSet.(*skip.SkipList).Get(comparator(*url))
+               if len(wantedUrl) > 0 && wantedUrl[0] != nil {
+                       mts.lock.RUnlock()
+                       return false
+               }
+               mts.lock.RUnlock()
+       }
+       mts.lock.Lock()
+       //double chk
+       wantedUrl := urlSet.(*skip.SkipList).Get(comparator(*url))
+       if len(wantedUrl) > 0 && wantedUrl[0] != nil {
+               mts.lock.Unlock()
+               return false
+       }
+       urlSet.(*skip.SkipList).Insert(comparator(*url))
+       mts.lock.Unlock()
+       return true
+}
+
+// removeURL is used to remove specified url
+func (mts *MetadataService) removeURL(targetMap *sync.Map, url *common.URL) {
+       if value, loaded := targetMap.Load(url.ServiceKey()); loaded {
+               mts.lock.Lock()
+               value.(*skip.SkipList).Delete(comparator(*url))
+               mts.lock.Unlock()
+               mts.lock.RLock()
+               defer mts.lock.RUnlock()
+               if value.(*skip.SkipList).Len() == 0 {
+                       targetMap.Delete(url.ServiceKey())
+               }
+       }
+}
+
+// getAllService can return all the exportedUrlString except for 
metadataService
+func (mts *MetadataService) getAllService(services *sync.Map) *skip.SkipList {
+       skipList := skip.New(uint64(0))

Review comment:
       as above

##########
File path: metadata/service/exporter/configurable/exporter.go
##########
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 configurable
+
+import (
+       "context"
+       "sync"
+)
+
+import (
+       "github.com/apache/dubbo-go/common"
+       "github.com/apache/dubbo-go/common/constant"
+       "github.com/apache/dubbo-go/common/logger"
+       "github.com/apache/dubbo-go/config"
+       "github.com/apache/dubbo-go/metadata/service"
+       "github.com/apache/dubbo-go/metadata/service/exporter"
+)
+
+// MetadataServiceExporter is the ConfigurableMetadataServiceExporter which 
implement MetadataServiceExporter interface
+type MetadataServiceExporter struct {
+       serviceConfig   *config.ServiceConfig
+       lock            sync.RWMutex
+       metadataService service.MetadataService
+}
+
+// NewMetadataServiceExporter will return a 
service_exporter.MetadataServiceExporter with the specified  metadata service
+func NewMetadataServiceExporter(metadataService service.MetadataService) 
exporter.MetadataServiceExporter {
+       return &MetadataServiceExporter{
+               metadataService: metadataService,
+       }
+}
+
+// Export will export the metadataService
+func (exporter *MetadataServiceExporter) Export() error {
+       if !exporter.IsExported() {
+               exporter.lock.Lock()
+               defer exporter.lock.Unlock()
+               exporter.serviceConfig = 
config.NewServiceConfig("MetadataService", context.Background())
+               exporter.serviceConfig.Protocol = constant.DEFAULT_PROTOCOL
+               exporter.serviceConfig.Protocols = 
map[string]*config.ProtocolConfig{
+                       constant.DEFAULT_PROTOCOL: generateMetadataProtocol(),
+               }
+               exporter.serviceConfig.InterfaceName = 
constant.METADATA_SERVICE_NAME
+               exporter.serviceConfig.Group = 
config.GetApplicationConfig().Name
+               exporter.serviceConfig.Version = 
exporter.metadataService.Version()
+               exporter.serviceConfig.Implement(exporter.metadataService)
+               err := exporter.serviceConfig.Export()

Review comment:
       ```suggestion
                serviceConfig :=&config.ServiceConfig{}
                serviceConfig = config.NewServiceConfig("MetadataService", 
context.Background())
                serviceConfig.Protocol = constant.DEFAULT_PROTOCOL
                serviceConfig.Protocols = map[string]*config.ProtocolConfig{
                        constant.DEFAULT_PROTOCOL: generateMetadataProtocol(),
                }
                serviceConfig.InterfaceName = constant.METADATA_SERVICE_NAME
                serviceConfig.Group = config.GetApplicationConfig().Name
                exporter.serviceConfig.Version = 
exporter.metadataService.Version()
                exporter.lock.Lock()
                exporter.serviceConfig=serviceConfig
                exporter.serviceConfig.Implement(exporter.metadataService)
                err := exporter.serviceConfig.Export()
                exporter.lock.Unlock()
   ```

##########
File path: metadata/service/inmemory/service.go
##########
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 inmemory
+
+import (
+       "encoding/json"
+       "sync"
+)
+
+import (
+       cm "github.com/Workiva/go-datastructures/common"
+       "github.com/Workiva/go-datastructures/slice/skip"
+)
+
+import (
+       "github.com/apache/dubbo-go/common"
+       "github.com/apache/dubbo-go/common/constant"
+       "github.com/apache/dubbo-go/common/logger"
+       "github.com/apache/dubbo-go/metadata/definition"
+       "github.com/apache/dubbo-go/metadata/service"
+)
+
+// MetadataService is store and query the metadata info in memory when each 
service registry
+type MetadataService struct {
+       service.BaseMetadataService
+       exportedServiceURLs   *sync.Map
+       subscribedServiceURLs *sync.Map
+       serviceDefinitions    *sync.Map
+       lock                  *sync.RWMutex
+}
+
+// NewMetadataService: initiate a metadata service
+func NewMetadataService() *MetadataService {
+       return &MetadataService{
+               exportedServiceURLs:   &sync.Map{},
+               subscribedServiceURLs: &sync.Map{},
+               serviceDefinitions:    &sync.Map{},
+               lock:                  &sync.RWMutex{},
+       }
+}
+
+// comparator is defined as Comparator for skip list to compare the URL
+type comparator common.URL
+
+// Compare is defined as Comparator for skip list to compare the URL
+func (c comparator) Compare(comp cm.Comparator) int {
+       a := common.URL(c).String()
+       b := common.URL(comp.(comparator)).String()
+       switch {
+       case a > b:
+               return 1
+       case a < b:
+               return -1
+       default:
+               return 0
+       }
+}
+
+// addURL will add URL in memory
+func (mts *MetadataService) addURL(targetMap *sync.Map, url *common.URL) bool {
+       var (
+               urlSet interface{}
+               loaded bool
+       )
+       logger.Debug(url.ServiceKey())
+       if urlSet, loaded = targetMap.LoadOrStore(url.ServiceKey(), 
skip.New(uint64(0))); loaded {
+               mts.lock.RLock()
+               wantedUrl := urlSet.(*skip.SkipList).Get(comparator(*url))
+               if len(wantedUrl) > 0 && wantedUrl[0] != nil {
+                       mts.lock.RUnlock()
+                       return false
+               }
+               mts.lock.RUnlock()
+       }
+       mts.lock.Lock()
+       //double chk
+       wantedUrl := urlSet.(*skip.SkipList).Get(comparator(*url))
+       if len(wantedUrl) > 0 && wantedUrl[0] != nil {
+               mts.lock.Unlock()
+               return false
+       }
+       urlSet.(*skip.SkipList).Insert(comparator(*url))
+       mts.lock.Unlock()
+       return true
+}
+
+// removeURL is used to remove specified url
+func (mts *MetadataService) removeURL(targetMap *sync.Map, url *common.URL) {
+       if value, loaded := targetMap.Load(url.ServiceKey()); loaded {
+               mts.lock.Lock()
+               value.(*skip.SkipList).Delete(comparator(*url))
+               mts.lock.Unlock()
+               mts.lock.RLock()
+               defer mts.lock.RUnlock()
+               if value.(*skip.SkipList).Len() == 0 {
+                       targetMap.Delete(url.ServiceKey())
+               }
+       }
+}
+
+// getAllService can return all the exportedUrlString except for 
metadataService
+func (mts *MetadataService) getAllService(services *sync.Map) *skip.SkipList {
+       skipList := skip.New(uint64(0))
+       services.Range(func(key, value interface{}) bool {
+               urls := value.(*skip.SkipList)
+               for i := uint64(0); i < urls.Len(); i++ {
+                       url := common.URL(urls.ByPosition(i).(comparator))
+                       if url.GetParam(constant.INTERFACE_KEY, url.Path) != 
"MetadataService" {
+                               skipList.Insert(comparator(url))
+                       }
+               }
+               return true
+       })
+       return skipList
+}
+
+// getSpecifiedService can return specified service url by serviceKey
+func (mts *MetadataService) getSpecifiedService(services *sync.Map, serviceKey 
string, protocol string) *skip.SkipList {
+       skipList := skip.New(uint64(0))

Review comment:
       as above

##########
File path: metadata/service/inmemory/service.go
##########
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 inmemory
+
+import (
+       "encoding/json"
+       "sync"
+)
+
+import (
+       cm "github.com/Workiva/go-datastructures/common"
+       "github.com/Workiva/go-datastructures/slice/skip"
+)
+
+import (
+       "github.com/apache/dubbo-go/common"
+       "github.com/apache/dubbo-go/common/constant"
+       "github.com/apache/dubbo-go/common/logger"
+       "github.com/apache/dubbo-go/metadata/definition"
+       "github.com/apache/dubbo-go/metadata/service"
+)
+
+// MetadataService is store and query the metadata info in memory when each 
service registry
+type MetadataService struct {
+       service.BaseMetadataService
+       exportedServiceURLs   *sync.Map
+       subscribedServiceURLs *sync.Map
+       serviceDefinitions    *sync.Map
+       lock                  *sync.RWMutex
+}
+
+// NewMetadataService: initiate a metadata service
+func NewMetadataService() *MetadataService {
+       return &MetadataService{
+               exportedServiceURLs:   &sync.Map{},
+               subscribedServiceURLs: &sync.Map{},
+               serviceDefinitions:    &sync.Map{},
+               lock:                  &sync.RWMutex{},
+       }
+}
+
+// comparator is defined as Comparator for skip list to compare the URL
+type comparator common.URL
+
+// Compare is defined as Comparator for skip list to compare the URL
+func (c comparator) Compare(comp cm.Comparator) int {
+       a := common.URL(c).String()
+       b := common.URL(comp.(comparator)).String()
+       switch {
+       case a > b:
+               return 1
+       case a < b:
+               return -1
+       default:
+               return 0
+       }
+}
+
+// addURL will add URL in memory
+func (mts *MetadataService) addURL(targetMap *sync.Map, url *common.URL) bool {
+       var (
+               urlSet interface{}
+               loaded bool
+       )
+       logger.Debug(url.ServiceKey())
+       if urlSet, loaded = targetMap.LoadOrStore(url.ServiceKey(), 
skip.New(uint64(0))); loaded {

Review comment:
       why ```New(uint64(0))```? Should it change to a default value, like  `8` 
?

##########
File path: metadata/service/service.go
##########
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 service
+
+import (
+       "github.com/Workiva/go-datastructures/slice/skip"
+)
+
+import (
+       "github.com/apache/dubbo-go/common"
+       "github.com/apache/dubbo-go/config"
+)
+
+// Metadataservice is used to define meta data related behaviors
+type MetadataService interface {
+       // ServiceName will get the service's name in meta service , which is 
application name
+       ServiceName() (string, error)
+       // ExportURL will store the exported url in metadata
+       ExportURL(url common.URL) (bool, error)
+       // UnexportURL will delete the exported url in metadata
+       UnexportURL(url common.URL) error
+       // SubscribeURL will store the subscribed url in metadata
+       SubscribeURL(url common.URL) (bool, error)
+       // UnsubscribeURL will delete the subscribed url in metadata
+       UnsubscribeURL(url common.URL) error
+       // PublishServiceDefinition will generate the target url's code info
+       PublishServiceDefinition(url common.URL) error
+       // GetExportedURLs will get the target exported url in metadata
+       GetExportedURLs(serviceInterface string, group string, version string, 
protocol string) (*skip.SkipList, error)
+       // GetExportedURLs will get the target subscribed url in metadata
+       GetSubscribedURLs() (*skip.SkipList, error)
+       // GetServiceDefinition will get the target service info store in 
metadata
+       GetServiceDefinition(interfaceName string, group string, version 
string) (string, error)
+       // GetServiceDefinition will get the target service info store in 
metadata by service key
+       GetServiceDefinitionByServiceKey(serviceKey string) (string, error)
+       // Version will return the metadata service version
+       Version() string
+       common.RPCService

Review comment:
       what about put it to the front of all methods?




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to