func (fssd *fileSystemServiceDiscovery) GetHealthyInstancesByPage(serviceName string, offset int, pageSize int,
	healthy bool) gxpage.Pager {
	return nil
}
GetHealthyInstancesByPage will return a page containing instances of ServiceInstance.
The param healthy indices that the instance should be healthy or not.
The page will start at offset
package file
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"strconv"
)
import (
	gxset "github.com/dubbogo/gost/container/set"
	gxpage "github.com/dubbogo/gost/hash/page"
	perrors "github.com/pkg/errors"
)
import (
	"dubbo.apache.org/dubbo-go/v3/common"
	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"dubbo.apache.org/dubbo-go/v3/common/extension"
	"dubbo.apache.org/dubbo-go/v3/common/logger"
	"dubbo.apache.org/dubbo-go/v3/config"
	"dubbo.apache.org/dubbo-go/v3/config_center"
	"dubbo.apache.org/dubbo-go/v3/config_center/file"
	"dubbo.apache.org/dubbo-go/v3/registry"
)
func init() {
	extension.SetServiceDiscovery(constant.FILE_KEY, newFileSystemServiceDiscovery)
}
type fileSystemServiceDiscovery struct {
	dynamicConfiguration file.FileSystemDynamicConfiguration
	rootPath             string
	fileMap              map[string]string
}
func newFileSystemServiceDiscovery() (registry.ServiceDiscovery, error) {
	if config.GetMetadataReportConfg().Protocol != constant.FILE_KEY {
		return nil, perrors.New("could not init the instance because the config is invalid")
	}
	rp, err := file.Home()
	if err != nil {
		return nil, perrors.WithStack(err)
	}
	fdcf := extension.GetConfigCenterFactory(constant.FILE_KEY)
	p := path.Join(rp, ".dubbo", constant.REGISTRY_KEY)
	url, _ := common.NewURL("")
	url.AddParamAvoidNil(file.ConfigCenterDirParamName, p)
	c, err := fdcf.GetDynamicConfiguration(url)
	if err != nil {
		return nil, perrors.WithStack(err)
	}
	sd := &fileSystemServiceDiscovery{
		dynamicConfiguration: *c.(*file.FileSystemDynamicConfiguration),
		rootPath:             p,
		fileMap:              make(map[string]string),
	}
	extension.AddCustomShutdownCallback(func() {
		if err := sd.Destroy(); err != nil {
			logger.Warnf("sd.Destroy() = error:%v", err)
		}
	})
	for _, v := range sd.GetServices().Values() {
		for _, i := range sd.GetInstances(v.(string)) {
			l := &RegistryConfigurationListener{}
			sd.dynamicConfiguration.AddListener(getServiceInstanceId(i), l, config_center.WithGroup(getServiceName(i)))
		}
	}
	return sd, nil
}
func (fssd *fileSystemServiceDiscovery) String() string {
	return fmt.Sprintf("file-system-service-discovery")
}
func (fssd *fileSystemServiceDiscovery) Destroy() error {
	fssd.dynamicConfiguration.Close()
	for _, f := range fssd.fileMap {
		fssd.releaseAndRemoveRegistrationFiles(f)
	}
	return nil
}
func (fssd *fileSystemServiceDiscovery) releaseAndRemoveRegistrationFiles(file string) {
	os.RemoveAll(file)
}
func (fssd *fileSystemServiceDiscovery) Register(instance registry.ServiceInstance) error {
	id := getServiceInstanceId(instance)
	sn := getServiceName(instance)
	c, err := toJsonString(instance)
	if err != nil {
		return perrors.WithStack(err)
	}
	err = fssd.dynamicConfiguration.PublishConfig(id, sn, c)
	if err != nil {
		return perrors.WithStack(err)
	}
	fssd.fileMap[id] = fssd.dynamicConfiguration.GetPath(id, sn)
	return nil
}
func getServiceInstanceId(si registry.ServiceInstance) string {
	if si.GetID() == "" {
		return si.GetHost() + "." + strconv.Itoa(si.GetPort())
	}
	return si.GetID()
}
func getServiceName(si registry.ServiceInstance) string {
	return si.GetServiceName()
}
func toJsonString(si registry.ServiceInstance) (string, error) {
	bytes, err := json.Marshal(si)
	if err != nil {
		return "", perrors.WithStack(err)
	}
	return string(bytes), nil
}
func (fssd *fileSystemServiceDiscovery) Update(instance registry.ServiceInstance) error {
	return fssd.Register(instance)
}
func (fssd *fileSystemServiceDiscovery) Unregister(instance registry.ServiceInstance) error {
	id := getServiceInstanceId(instance)
	sn := getServiceName(instance)
	err := fssd.dynamicConfiguration.RemoveConfig(id, sn)
	if err != nil {
		return perrors.WithStack(err)
	}
	delete(fssd.fileMap, instance.GetID())
	return nil
}
func (fssd *fileSystemServiceDiscovery) GetDefaultPageSize() int {
	return 100
}
func (fssd *fileSystemServiceDiscovery) GetServices() *gxset.HashSet {
	r := gxset.NewSet()
	fileInfo, _ := ioutil.ReadDir(fssd.dynamicConfiguration.RootPath())
	for _, file := range fileInfo {
		if file.IsDir() {
			r.Add(file.Name())
		}
	}
	return r
}
func (fssd *fileSystemServiceDiscovery) GetInstances(serviceName string) []registry.ServiceInstance {
	set, err := fssd.dynamicConfiguration.GetConfigKeysByGroup(serviceName)
	if err != nil {
		logger.Errorf("[FileServiceDiscovery] Could not query the instances for service{%s}, error = err{%v} ",
			serviceName, err)
		return make([]registry.ServiceInstance, 0)
	}
	res := make([]registry.ServiceInstance, 0, set.Size())
	for _, v := range set.Values() {
		id := v.(string)
		p, err := fssd.dynamicConfiguration.GetProperties(id, config_center.WithGroup(serviceName))
		if err != nil {
			logger.Errorf("[FileServiceDiscovery] Could not get the properties for id{%s}, service{%s}, "+
				"error = err{%v} ",
				id, serviceName, err)
			return make([]registry.ServiceInstance, 0)
		}
		dsi := &registry.DefaultServiceInstance{}
		err = json.Unmarshal([]byte(p), dsi)
		if err != nil {
			logger.Errorf("[FileServiceDiscovery] Could not unmarshal the properties for id{%s}, service{%s}, "+
				"error = err{%v} ",
				id, serviceName, err)
			return make([]registry.ServiceInstance, 0)
		}
		res = append(res, dsi)
	}
	return res
}
func (fssd *fileSystemServiceDiscovery) GetInstancesByPage(serviceName string, offset int, pageSize int) gxpage.Pager {
	return nil
}