diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..029641b2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +.git +.github +docs +default.etcd +*.gz +*.tar.gz +*.bzip2 +*.zip +/dn-data +/dp-data +/store-data \ No newline at end of file diff --git a/.gitignore b/.gitignore index f31e3453..b2cde7bb 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ /dagpool /datanode /objectstore -/dp-data /dn-data -/store-data \ No newline at end of file +/dp-data +/store-data +/iam-tools \ No newline at end of file diff --git a/Dockerfile.dagpool b/Dockerfile.dagpool new file mode 100644 index 00000000..221c577e --- /dev/null +++ b/Dockerfile.dagpool @@ -0,0 +1,27 @@ +FROM golang:1.19.3-alpine AS builder + +LABEL stage=gobuilder + +ENV CGO_ENABLED 0 +ENV GOOS linux +ENV GOPROXY https://goproxy.cn,direct + +WORKDIR /build +COPY . . +RUN go mod download + +# Builds your app with optional configuration +RUN go build -ldflags "-s -w" -o dagpool ./cmd/dagpool + +FROM scratch + +WORKDIR /app +COPY --from=builder /build/dagpool /app/dagpool + +# Tells Docker which network port your container listens on +EXPOSE 50001 + +ENTRYPOINT ["/app/dagpool"] + +# Specifies the executable command that runs when the container starts +CMD ["daemon", "--datadir=/data"] \ No newline at end of file diff --git a/Dockerfile.datanode b/Dockerfile.datanode new file mode 100644 index 00000000..ddca83a4 --- /dev/null +++ b/Dockerfile.datanode @@ -0,0 +1,27 @@ +FROM golang:1.19.3-alpine AS builder + +LABEL stage=gobuilder + +ENV CGO_ENABLED 0 +ENV GOOS linux +ENV GOPROXY https://goproxy.cn,direct + +WORKDIR /build +COPY . . +RUN go mod download + +# Builds your app with optional configuration +RUN go build -ldflags "-s -w" -o datanode ./cmd/datanode + +FROM scratch + +WORKDIR /app +COPY --from=builder /build/datanode /app/datanode + +# Tells Docker which network port your container listens on +EXPOSE 9010 + +ENTRYPOINT ["/app/datanode"] + +# Specifies the executable command that runs when the container starts +CMD ["daemon", "--datadir=/data"] \ No newline at end of file diff --git a/Dockerfile.objectstore b/Dockerfile.objectstore new file mode 100644 index 00000000..5d57f0a2 --- /dev/null +++ b/Dockerfile.objectstore @@ -0,0 +1,27 @@ +FROM golang:1.19.3-alpine AS builder + +LABEL stage=gobuilder + +ENV CGO_ENABLED 0 +ENV GOOS linux +ENV GOPROXY https://goproxy.cn,direct + +WORKDIR /build +COPY . . +RUN go mod download + +# Builds your app with optional configuration +RUN go build -ldflags "-s -w" -o objectstore ./cmd/objectstore + +FROM scratch + +WORKDIR /app +COPY --from=builder /build/objectstore /app/objectstore + +# Tells Docker which network port your container listens on +EXPOSE 9985 + +ENTRYPOINT ["/app/objectstore"] + +# Specifies the executable command that runs when the container starts +CMD ["daemon", "--datadir=/data"] \ No newline at end of file diff --git a/Makefile b/Makefile index 74bf1150..30da16e1 100644 --- a/Makefile +++ b/Makefile @@ -5,6 +5,12 @@ DATANODE_TARGET=./datanode OBJECTSTORE_TARGET=./objectstore IAMTOOLS_TARGET=./iam-tools +#VERSION ?= $(shell git describe --tags) +#TAG_DATANODE ?= "filedag/datanode:$(VERSION)" +TAG_DATANODE ?= "filedag/datanode:latest" +TAG_DAGPOOL ?= "filedag/dagpool:latest" +TAG_OBJECTSTORE ?= "filedag/objectstore:latest" + build: clean dagpool datanode objectstore iamtools dagpool: @@ -19,6 +25,18 @@ objectstore: iamtools: go build -ldflags "-s -w" -o ${IAMTOOLS_TARGET} ./cmd/tools/iam-tools +docker-datanode: + docker build -q --no-cache -t $(TAG_DATANODE) . -f Dockerfile.datanode + +docker-dagpool: + docker build -q --no-cache -t $(TAG_DAGPOOL) . -f Dockerfile.dagpool + +docker-objectstore: + docker build -q --no-cache -t $(TAG_OBJECTSTORE) . -f Dockerfile.objectstore + +docker: docker-datanode docker-dagpool docker-objectstore + docker buildx prune -f + .PHONY: clean clean: -rm -f ${DAGPOOL_TARGET} diff --git a/README-cn.md b/README-cn.md index 7cfda1e7..21145c72 100644 --- a/README-cn.md +++ b/README-cn.md @@ -1,7 +1,7 @@ # FileDAG Storage [![LICENSE](https://img.shields.io/github/license/filedag-project/filedag-storage)](./LICENSE "LICENSE") -[![Build Status](https://img.shields.io/github/workflow/status/filedag-project/filedag-storage/Go)]() +[![Build Status](https://img.shields.io/github/actions/workflow/status/filedag-project/filedag-storage/go.yml)]() Language: [English](./README.md) @@ -78,12 +78,12 @@ FileDAG Storage 的开发将为上述问题提供一种解决方案 #### Description: - DAG Node: - - 基于Reed-Solomon Erasure Code开发数据容错技术 + - [x] 基于Reed-Solomon Erasure Code开发数据容错技术 - DAG Pool: - - 基于libp2p和Redis Hash Slots,组织多个DAG Node构建存储集群 - - 提供存储节点的运行状况报告和全局一致性状态 - - 支持存储节点动态扩容 - - 支持存储节点动态扩展 + - [x] 基于Redis Hash Slots,组织多个DAG Node构建存储集群 + - [x] 提供存储节点的运行状况报告和全局一致性状态 + - [x] 支持存储节点动态扩容 + - [x] 支持存储节点动态扩展 ### Milestone 4 @@ -127,7 +127,12 @@ make ./datanode daemon --listen=127.0.0.1:9013 --datadir=/tmp/dn-data3 -./dagpool daemon --datadir=/tmp/dagpool-db --config=conf/node_config.json +./dagpool daemon --datadir=/tmp/dagpool-db + +# add a dagnode +./dagpool cluster add conf/node_config.json +# allocate slots +./dagpool cluster balance ./objectstore daemon --pool-addr=127.0.0.1:50001 --pool-user=dagpool --pool-password=dagpool ``` diff --git a/README.md b/README.md index 0af39a53..a22a718b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # FileDAG Storage [![LICENSE](https://img.shields.io/github/license/filedag-project/filedag-storage)](./LICENSE "LICENSE") -[![Build Status](https://img.shields.io/github/workflow/status/filedag-project/filedag-storage/Go)]() +[![Build Status](https://img.shields.io/github/actions/workflow/status/filedag-project/filedag-storage/go.yml)]() Language: [Chinese](./README-cn.md) @@ -77,12 +77,12 @@ Realize clustered DAG Node and development of data fault tolerance. #### Description: - DAG Node: - - develops data fault tolerance based on Reed-Solomon Erasure Code + - [x] develops data fault tolerance based on Reed-Solomon Erasure Code - DAG Pool: - - organizes multiple DAG Nodes to build a storage cluster based on libp2p and Redis Hash Slots - - provides health report of storage nodes and status of global consistency - - supports dynamic expansion of storage nodes - - supports dynamic scaling of storage nodes + - [x] organizes multiple DAG Nodes to build a storage cluster based on Redis Hash Slots + - [x] provides health report of storage nodes and status of global consistency + - [x] supports dynamic expansion of storage nodes + - [x] supports dynamic scaling of storage nodes ### Milestone 4 @@ -126,7 +126,12 @@ Start 3 datanodes, dagpool and objectstore: ./datanode daemon --listen=127.0.0.1:9013 --datadir=/tmp/dn-data3 -./dagpool daemon --datadir=/tmp/dagpool-db --config=conf/node_config.json +./dagpool daemon --datadir=/tmp/dagpool-db + +# add a dagnode +./dagpool cluster add conf/node_config.json +# allocate slots +./dagpool cluster balance ./objectstore daemon --pool-addr=127.0.0.1:50001 --pool-user=dagpool --pool-password=dagpool ``` diff --git a/cmd/dagpool/cluster.go b/cmd/dagpool/cluster.go new file mode 100644 index 00000000..7fd5688b --- /dev/null +++ b/cmd/dagpool/cluster.go @@ -0,0 +1,350 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/filedag-project/filedag-storage/dag/config" + "github.com/filedag-project/filedag-storage/dag/pool/client" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" + "github.com/filedag-project/filedag-storage/dag/utils" + "github.com/urfave/cli/v2" + "io/ioutil" + "strconv" + "strings" +) + +var clusterCmd = &cli.Command{ + Name: "cluster", + Usage: "Manage dagpool cluster nodes", + Subcommands: []*cli.Command{ + status, + addDagNode, + getDagNode, + removeDagNode, + balanceSlots, + migrateSlots, + repair, + }, +} + +var status = &cli.Command{ + Name: "status", + Usage: "Displays the current status of the cluster", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "the address of dagpool server", + Value: "127.0.0.1:50001", + }, + &cli.BoolFlag{ + Name: "detail", + Usage: "displays the detail of cluster", + }, + }, + Action: func(cctx *cli.Context) error { + addr := cctx.String("address") + + cli, err := client.NewPoolClusterClient(addr) + if err != nil { + return err + } + defer cli.Close(cctx.Context) + reply, err := cli.Status(cctx.Context) + if err != nil { + return err + } + + fmt.Printf("cluster_state: %s\ncluster_dagnodes: %d\ncluster_dagnodes_info:\n", + reply.State, len(reply.Statuses)) + + for _, status := range reply.Statuses { + pairs := utils.ToSlotPairs(status.Pairs) + var slots uint64 + slotsInfo := "" + for _, pair := range pairs { + if slotsInfo != "" { + slotsInfo += "," + } + slots += pair.Count() + slotsInfo += fmt.Sprintf("[%s]", pair) + } + fmt.Printf(" name: %s\n slots: %s (%d slots)\n", + status.Node.Name, slotsInfo, slots) + if cctx.Bool("detail") { + fmt.Printf(" erasure_set:\n nodes:\n") + for idx, nd := range status.Node.Nodes { + st := "fail" + if nd.State != nil && *nd.State { + st = "ok" + } + fmt.Printf(" set_index: %d, rpc_address: %s, state: %s\n", idx, nd.RpcAddress, st) + } + fmt.Printf(" data_blocks: %d\n parity_blocks: %d\n", + status.Node.DataBlocks, status.Node.ParityBlocks) + } + fmt.Println() + } + return nil + }, +} + +var addDagNode = &cli.Command{ + Name: "add", + Usage: "Add a dagnode to the dag pool cluster", + ArgsUsage: "dagnode_config_path [dagnode_config_path2] ... [dagnode_config_pathN]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "the address of dagpool server", + Value: "127.0.0.1:50001", + }, + &cli.StringFlag{ + Name: "format", + Usage: "the format type of dagnode config file", + Value: "json", + }, + }, + Action: func(cctx *cli.Context) error { + addr := cctx.String("address") + if cctx.String("format") != "json" { + return errors.New("not support this format") + } + if cctx.NArg() == 0 { + return errors.New("at least one dagnode configuration file path is required") + } + + cli, err := client.NewPoolClusterClient(addr) + if err != nil { + return err + } + defer cli.Close(cctx.Context) + var dagNodes []*config.DagNodeConfig + for i := 0; i < cctx.NArg(); i++ { + path := cctx.Args().Get(i) + var nc config.DagNodeConfig + cfgBytes, err := ioutil.ReadFile(path) + if err != nil { + return err + } + if err = json.Unmarshal(cfgBytes, &nc); err != nil { + return err + } + dagNodes = append(dagNodes, &nc) + } + successCount := 0 + for _, node := range dagNodes { + if err = cli.AddDagNode(cctx.Context, node); err != nil { + fmt.Printf("Error: add dagnode failed, name=%s, error=%v\n", node.Name, err) + continue + } + successCount++ + } + fmt.Printf("add dagnodes:\ntotal: %v success: %v failed: %v\n", + len(dagNodes), successCount, len(dagNodes)-successCount) + return nil + }, +} + +var getDagNode = &cli.Command{ + Name: "get", + Usage: "Get a dagnode from the dag pool cluster", + ArgsUsage: "dagnode_name", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "the address of dagpool server", + Value: "127.0.0.1:50001", + }, + }, + Action: func(cctx *cli.Context) error { + addr := cctx.String("address") + if cctx.NArg() != 1 { + return errors.New("a dagnode name is required") + } + + cli, err := client.NewPoolClusterClient(addr) + if err != nil { + return err + } + defer cli.Close(cctx.Context) + + dagnode, err := cli.GetDagNode(cctx.Context, cctx.Args().First()) + if err != nil { + return err + } + + fmt.Printf("dagnode_name: %s\n", dagnode.Name) + fmt.Printf("dagnode_set:\n nodes:\n") + for idx, nd := range dagnode.Nodes { + fmt.Printf(" set_index: %d, rpc_address: %s\n", idx, nd) + } + fmt.Printf(" data_blocks: %d\n parity_blocks: %d\n", + dagnode.DataBlocks, dagnode.ParityBlocks) + return nil + }, +} + +var removeDagNode = &cli.Command{ + Name: "remove", + Usage: "Remove a dagnode from the dag pool cluster", + ArgsUsage: "dagnode_name", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "the address of dagpool server", + Value: "127.0.0.1:50001", + }, + }, + Action: func(cctx *cli.Context) error { + addr := cctx.String("address") + if cctx.NArg() != 1 { + return errors.New("a dagnode name is required") + } + + cli, err := client.NewPoolClusterClient(addr) + if err != nil { + return err + } + defer cli.Close(cctx.Context) + + dagnode, err := cli.RemoveDagNode(cctx.Context, cctx.Args().First()) + if err != nil { + return err + } + + fmt.Printf("the dagnode is removed successfully\n") + fmt.Printf("removed_dagnode_name: %s\n", dagnode.Name) + fmt.Printf("removed_dagnode_set:\n nodes:\n") + for idx, nd := range dagnode.Nodes { + fmt.Printf(" set_index: %d, rpc_address: %s\n", idx, nd) + } + fmt.Printf(" data_blocks: %d\n parity_blocks: %d\n", + dagnode.DataBlocks, dagnode.ParityBlocks) + return nil + }, +} + +var balanceSlots = &cli.Command{ + Name: "balance", + Usage: "Balance slots of the dag pool cluster", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "the address of dagpool server", + Value: "127.0.0.1:50001", + }, + }, + Action: func(cctx *cli.Context) error { + addr := cctx.String("address") + + cli, err := client.NewPoolClusterClient(addr) + if err != nil { + return err + } + defer cli.Close(cctx.Context) + return cli.BalanceSlots(cctx.Context) + }, +} + +var migrateSlots = &cli.Command{ + Name: "migrate", + Usage: "Migrate slots from a dagnode to another dagnode", + ArgsUsage: "from_dagnode_name to_dagnode_name start_slot1-end_slot1 [start_slot2-end_slot2] ... [start_slotN-end_slotN]", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "the address of dagpool server", + Value: "127.0.0.1:50001", + }, + }, + Action: func(cctx *cli.Context) error { + addr := cctx.String("address") + if cctx.NArg() < 3 { + return errors.New("at least input three parameters") + } + from := cctx.Args().Get(0) + to := cctx.Args().Get(1) + var slotPairs []slotsmgr.SlotPair + for i := 2; i < cctx.NArg(); i++ { + str := cctx.Args().Get(i) + list := strings.Split(str, "-") + switch len(list) { + case 1: + start, err := strconv.ParseUint(list[0], 10, 32) + if err != nil { + return err + } + slotPairs = append(slotPairs, slotsmgr.SlotPair{ + Start: start, + End: start, + }) + case 2: + start, err := strconv.ParseUint(list[0], 10, 32) + if err != nil { + return err + } + end, err := strconv.ParseUint(list[1], 10, 32) + if err != nil { + return err + } + if start > end { + return errors.New("slots_pair is illegal") + } + slotPairs = append(slotPairs, slotsmgr.SlotPair{ + Start: start, + End: end, + }) + default: + return errors.New("slots_pair is illegal") + } + } + + cli, err := client.NewPoolClusterClient(addr) + if err != nil { + return err + } + defer cli.Close(cctx.Context) + return cli.MigrateSlots(cctx.Context, from, to, slotPairs) + }, +} + +var repair = &cli.Command{ + Name: "repair", + Usage: "Repair a datanode", + ArgsUsage: "dagnode_name from_node_index repair_node_index", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "address", + Usage: "the address of dagpool server", + Value: "127.0.0.1:50001", + }, + }, + Action: func(cctx *cli.Context) error { + addr := cctx.String("address") + if cctx.NArg() < 3 { + return errors.New("at least input three parameters") + } + dagNodeName := cctx.Args().Get(0) + fromIndexStr := cctx.Args().Get(1) + repairIndexStr := cctx.Args().Get(2) + + fromIndex, err := strconv.ParseInt(fromIndexStr, 10, 32) + if err != nil { + return err + } + + repairIndex, err := strconv.ParseInt(repairIndexStr, 10, 32) + if err != nil { + return err + } + + cli, err := client.NewPoolClusterClient(addr) + if err != nil { + return err + } + defer cli.Close(cctx.Context) + + return cli.RepairDataNode(cctx.Context, dagNodeName, int(fromIndex), int(repairIndex)) + }, +} diff --git a/cmd/dagpool/main.go b/cmd/dagpool/main.go index 640d56fc..3fa2b70b 100644 --- a/cmd/dagpool/main.go +++ b/cmd/dagpool/main.go @@ -12,11 +12,12 @@ func main() { local := []*cli.Command{ startCmd, authCmd, + clusterCmd, } app := &cli.App{ - Name: "dag-pool", - Usage: "dag pool daemon", - Version: "0.0.1", + Name: "dagpool", + Usage: "dag pool cluster", + Version: "0.1.0", EnableBashCompletion: true, Commands: local, } diff --git a/cmd/dagpool/server.go b/cmd/dagpool/server.go index 7f7b7ce1..fa4124d4 100644 --- a/cmd/dagpool/server.go +++ b/cmd/dagpool/server.go @@ -2,7 +2,6 @@ package main import ( "context" - "encoding/json" "errors" "github.com/filedag-project/filedag-storage/dag/config" "github.com/filedag-project/filedag-storage/dag/pool/poolservice" @@ -11,12 +10,10 @@ import ( logging "github.com/ipfs/go-log/v2" "github.com/urfave/cli/v2" "google.golang.org/grpc" - "io/ioutil" "net" "os" "os/signal" "path" - "strings" "syscall" "time" ) @@ -41,11 +38,6 @@ var startCmd = &cli.Command{ Usage: "directory to store data in", Value: "./dp-data", }, - &cli.StringFlag{ - Name: "config", - Usage: "set config path", - Value: "./conf/node_config.json", - }, &cli.StringFlag{ Name: "root-user", Usage: "set root user", @@ -84,7 +76,7 @@ func startDagPoolServer(ctx context.Context, cfg config.PoolConfig) { } // new server s := grpc.NewServer() - service, err := poolservice.NewDagPoolService(cfg) + service, err := poolservice.NewDagPoolService(ctx, cfg) if err != nil { log.Fatalf("NewDagPoolService err:%v", err) return @@ -92,6 +84,7 @@ func startDagPoolServer(ctx context.Context, cfg config.PoolConfig) { defer service.Close() proto.RegisterDagPoolServer(s, &server.DagPoolServer{DagPool: service}) + proto.RegisterDagPoolClusterServer(s, &server.DagPoolClusterServer{Cluster: service}) go func() { if err := s.Serve(lis); err != nil { log.Fatalf("failed to serve: %v", err) @@ -133,23 +126,5 @@ func loadPoolConfig(cctx *cli.Context) (config.PoolConfig, error) { return config.PoolConfig{}, err } cfg.GcPeriod = gcPer - nodeConfigPath := cctx.String("config") - - var nodeConfigs []config.DagNodeConfig - for _, path := range strings.Split(nodeConfigPath, ",") { - var nc config.DagNodeConfig - file, err := ioutil.ReadFile(path) - if err != nil { - log.Errorf("ReadFile err:%v", err) - return config.PoolConfig{}, err - } - err = json.Unmarshal(file, &nc) - if err != nil { - log.Errorf("Unmarshal err:%v", err) - return config.PoolConfig{}, err - } - nodeConfigs = append(nodeConfigs, nc) - } - cfg.DagNodeConfig = nodeConfigs return cfg, nil } diff --git a/conf/node_config.json b/conf/node_config.json index 8ce9a7c8..356de237 100644 --- a/conf/node_config.json +++ b/conf/node_config.json @@ -1,18 +1,10 @@ { - "nodes":[ - { - "ip":"127.0.0.1", - "port": "9011" - }, - { - "ip":"127.0.0.1", - "port": "9012" - }, - { - "ip":"127.0.0.1", - "port": "9013" - } + "name": "dag_node1", + "nodes": [ + "127.0.0.1:9011", + "127.0.0.1:9012", + "127.0.0.1:9013" ], - "data_blocks":2, - "parity_blocks":1 -} + "data_blocks": 2, + "parity_blocks": 1 +} \ No newline at end of file diff --git a/conf/node_config2.json b/conf/node_config2.json new file mode 100644 index 00000000..6c00116f --- /dev/null +++ b/conf/node_config2.json @@ -0,0 +1,10 @@ +{ + "name": "dag_node2", + "nodes": [ + "127.0.0.1:9014", + "127.0.0.1:9015", + "127.0.0.1:9016" + ], + "data_blocks": 2, + "parity_blocks": 1 +} \ No newline at end of file diff --git a/conf/node_config3.json b/conf/node_config3.json new file mode 100644 index 00000000..f1253bad --- /dev/null +++ b/conf/node_config3.json @@ -0,0 +1,10 @@ +{ + "name": "dag_node3", + "nodes": [ + "127.0.0.1:9017", + "127.0.0.1:9018", + "127.0.0.1:9019" + ], + "data_blocks": 2, + "parity_blocks": 1 +} \ No newline at end of file diff --git a/dag/config/config.go b/dag/config/config.go index 7a8eaccc..1446589c 100644 --- a/dag/config/config.go +++ b/dag/config/config.go @@ -1,26 +1,34 @@ package config -import "time" +import ( + "github.com/filedag-project/filedag-storage/dag/slotsmgr" + "time" +) //PoolConfig is the configuration for the dag pool type PoolConfig struct { - Listen string `json:"listen"` - DagNodeConfig []DagNodeConfig `json:"dag_node"` - LeveldbPath string `json:"leveldb_path"` - RootUser string `json:"root_user"` - RootPassword string `json:"root_password"` - GcPeriod time.Duration `json:"gc_period"` + Listen string `json:"listen"` + LeveldbPath string `json:"leveldb_path"` + RootUser string `json:"root_user"` + RootPassword string `json:"root_password"` + GcPeriod time.Duration `json:"gc_period"` +} + +//ClusterConfig is the configuration for a cluster +type ClusterConfig struct { + Version int `json:"version"` + Cluster []DagNodeInfo `json:"cluster"` } //DagNodeConfig is the configuration for a dag node type DagNodeConfig struct { - Nodes []DataNodeConfig `json:"nodes"` - DataBlocks int `json:"data_blocks"` - ParityBlocks int `json:"parity_blocks"` + Name string `json:"name"` + Nodes []string `json:"nodes"` // rpc address list of datanodes + DataBlocks int `json:"data_blocks"` // Number of data shards + ParityBlocks int `json:"parity_blocks"` // Number of parity shards } -//DataNodeConfig is the configuration for a datanode -type DataNodeConfig struct { - Ip string `json:"ip"` - Port string `json:"port"` +type DagNodeInfo struct { + Config DagNodeConfig `json:"config"` + SlotPairs []slotsmgr.SlotPair `json:"slot_pairs"` } diff --git a/dag/node/dagnode/data_recovery.go b/dag/node/dagnode/data_recovery.go index 1e07b432..82346393 100644 --- a/dag/node/dagnode/data_recovery.go +++ b/dag/node/dagnode/data_recovery.go @@ -6,14 +6,12 @@ import ( "encoding/binary" "errors" "github.com/filedag-project/filedag-storage/dag/proto" + "github.com/filedag-project/filedag-storage/dag/utils/paralleltask" "github.com/ipfs/go-cid" - logging "github.com/ipfs/go-log/v2" "google.golang.org/protobuf/types/known/emptypb" "io" ) -var log = logging.Logger("dag-node") - // RepairDataNode prepare node repair func (d *DagNode) RepairDataNode(ctx context.Context, fromNodeIndex int, repairNodeIndex int) error { if fromNodeIndex >= len(d.Nodes) { @@ -25,7 +23,7 @@ func (d *DagNode) RepairDataNode(ctx context.Context, fromNodeIndex int, repairN ctx, cancel := context.WithCancel(ctx) defer cancel() - stream, err := d.Nodes[fromNodeIndex].Client.AllKeysChan(ctx, &emptypb.Empty{}) + stream, err := d.Nodes[fromNodeIndex].Client.DataClient.AllKeysChan(ctx, &emptypb.Empty{}) if err != nil { return err } @@ -40,7 +38,7 @@ func (d *DagNode) RepairDataNode(ctx context.Context, fromNodeIndex int, repairN } key := resp.Key - if _, err := repairNode.Client.GetMeta(ctx, &proto.GetMetaRequest{Key: key}); err == nil { + if _, err := repairNode.Client.DataClient.GetMeta(ctx, &proto.GetMetaRequest{Key: key}); err == nil { continue } dataCid, err := cid.Decode(key) @@ -54,31 +52,40 @@ func (d *DagNode) RepairDataNode(ctx context.Context, fromNodeIndex int, repairN continue } - merged := make([][]byte, 0) - for i, node := range d.Nodes { - if i == repairNodeIndex { - merged = append(merged, nil) - continue - } - res, err := node.Client.Get(ctx, &proto.GetRequest{Key: key}) - if err != nil { - log.Errorf("this node[%s:%s] err: %v", node.Ip, node.Port, err) - merged = append(merged, nil) - continue - } - if len(res.Data) == 0 { - log.Errorf("There is no data in this node") - merged = append(merged, nil) - continue - } - merged = append(merged, res.Data) + shards := make([][]byte, len(d.Nodes)) + entryReadQuorum, _ := d.entryQuorum() + task := paralleltask.NewParallelTask(ctx, entryReadQuorum, len(d.Nodes)-entryReadQuorum+1, true) + for i, snode := range d.Nodes { + index := i + tnode := snode + task.Goroutine(func(ctx context.Context) error { + if index == repairNodeIndex { + return errors.New("there is no data in this node") + } + res, err := tnode.Client.DataClient.Get(ctx, &proto.GetRequest{Key: key}) + if err != nil { + log.Errorf("this node[%s] get key err: %v", tnode.RpcAddress, err) + return err + } + if len(res.Data) == 0 { + err = errors.New("there is no data in this node") + return err + } + shards[index] = res.Data + return nil + }) } - enc, err := NewErasure(d.dataBlocks, d.parityBlocks, int64(size)) + if err = task.Wait(); err != nil { + log.Errorw("task error, missing shards", "key", key, "error", err) + continue + } + + enc, err := NewErasure(d.config.DataBlocks, d.config.ParityBlocks, int64(size)) if err != nil { log.Errorf("new erasure fail :%v", err) return err } - err = enc.DecodeDataBlocks(merged) + err = enc.DecodeDataAndParityBlocks(shards) if err != nil { log.Errorf("decode data blocks failed: %v", err) return err @@ -92,13 +99,69 @@ func (d *DagNode) RepairDataNode(ctx context.Context, fromNodeIndex int, repairN log.Errorf("binary.Write failed: %v", err) continue } - if _, err = repairNode.Client.Put(ctx, &proto.AddRequest{ + if _, err = repairNode.Client.DataClient.Put(ctx, &proto.AddRequest{ + Key: key, + Meta: metaBuf.Bytes(), + Data: shards[repairNodeIndex], + }); err != nil { + log.Errorf("data node put failed: %v", err) + return err + } + log.Infow("repair entry success", "key", key) + } +} + +// repairBlock repairs shards of one erasure set +func (d *DagNode) repairBlock(ctx context.Context, key string, blockSize int32, shards [][]byte, repairIndexes []int) error { + for _, repairNodeIndex := range repairIndexes { + if repairNodeIndex >= len(d.Nodes) { + return errors.New("repair index greater than max index of nodes") + } + } + + entryReadQuorum, _ := d.entryQuorum() + availableShards := 0 + for _, shard := range shards { + if shard != nil { + availableShards++ + } + } + if availableShards < entryReadQuorum { + return errors.New("repair index greater than max index of nodes") + } + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + enc, err := NewErasure(d.config.DataBlocks, d.config.ParityBlocks, int64(blockSize)) + if err != nil { + log.Errorf("new erasure fail :%v", err) + return err + } + err = enc.DecodeDataAndParityBlocks(shards) + if err != nil { + log.Errorf("decode data blocks failed: %v", err) + return err + } + + meta := Meta{ + BlockSize: blockSize, + } + for _, index := range repairIndexes { + var metaBuf bytes.Buffer + if err = binary.Write(&metaBuf, binary.LittleEndian, meta); err != nil { + log.Errorf("binary.Write failed: %v", err) + continue + } + if _, err = d.Nodes[index].Client.DataClient.Put(ctx, &proto.AddRequest{ Key: key, Meta: metaBuf.Bytes(), - Data: merged[repairNodeIndex], + Data: shards[index], }); err != nil { - log.Errorf("data node put fail :%v", err) + log.Errorf("data node put failed: %v", err) return err } + log.Infow("repair block shard success", "key", key, "shardIndex", index) } + return nil } diff --git a/dag/node/dagnode/node.go b/dag/node/dagnode/node.go index bdcf07ef..fd63b912 100644 --- a/dag/node/dagnode/node.go +++ b/dag/node/dagnode/node.go @@ -11,21 +11,38 @@ import ( "github.com/filedag-project/filedag-storage/dag/config" "github.com/filedag-project/filedag-storage/dag/node/datanode" "github.com/filedag-project/filedag-storage/dag/proto" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" + "github.com/filedag-project/filedag-storage/dag/utils/paralleltask" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" blockstore "github.com/ipfs/go-ipfs-blockstore" + logging "github.com/ipfs/go-log/v2" "google.golang.org/grpc/codes" + healthpb "google.golang.org/grpc/health/grpc_health_v1" "google.golang.org/grpc/status" "sync" + "time" ) var _ blockstore.Blockstore = (*DagNode)(nil) +const healthCheckService = "grpc.health.v1.Health" + +var log = logging.Logger("dag-node") + +type StorageNode struct { + *datanode.Client + State bool // true: means the data node is health +} + //DagNode Implemented the Blockstore interface type DagNode struct { - Nodes []*datanode.Client - dataBlocks int // Number of data shards - parityBlocks int // Number of parity shards + Nodes []*StorageNode + slots *slotsmgr.SlotsManager + numSlots int + config config.DagNodeConfig + repairQueue chan func(ctx context.Context) + stopCh chan struct{} } type Meta struct { @@ -34,43 +51,160 @@ type Meta struct { //NewDagNode creates a new DagNode func NewDagNode(cfg config.DagNodeConfig) (*DagNode, error) { - var clients []*datanode.Client + numNodes := len(cfg.Nodes) + if numNodes != cfg.DataBlocks+cfg.ParityBlocks || numNodes == 0 { + return nil, errors.New("dag node config is incorrect") + } + clients := make([]*StorageNode, 0, cfg.DataBlocks+cfg.ParityBlocks) for _, c := range cfg.Nodes { dateNode, err := datanode.NewClient(c) if err != nil { return nil, err } - clients = append(clients, dateNode) + clients = append(clients, &StorageNode{Client: dateNode}) } return &DagNode{ - Nodes: clients, - dataBlocks: cfg.DataBlocks, - parityBlocks: cfg.ParityBlocks, + Nodes: clients, + slots: slotsmgr.NewSlotsManager(), + config: cfg, + repairQueue: make(chan func(ctx context.Context), 10000), + stopCh: make(chan struct{}), }, nil } +func (d *DagNode) GetConfig() *config.DagNodeConfig { + return &d.config +} + +func (d *DagNode) GetDataNodeState(setIndex int) bool { + if setIndex < 0 || setIndex >= len(d.Nodes) { + log.Fatalf("input setIndex %v is illegal, size of set is %v", setIndex, len(d.Nodes)) + } + return d.Nodes[setIndex].State +} + +// AddSlot Set the slot bit and return the old value +func (d *DagNode) AddSlot(slot uint64) bool { + old, err := d.slots.Set(slot, true) + if err != nil { + log.Fatal(err) + } + if !old { + d.numSlots++ + } + return old +} + +// ClearSlot Clear the slot bit and return the old value +func (d *DagNode) ClearSlot(slot uint64) bool { + old, err := d.slots.Set(slot, false) + if err != nil { + log.Fatal(err) + } + if old { + d.numSlots-- + } + return old +} + +// GetSlot Get the slot bit +func (d *DagNode) GetSlot(slot uint64) bool { + val, err := d.slots.Get(slot) + if err != nil { + log.Fatal(err) + } + return val +} + +func (d *DagNode) GetSlotPairs() []slotsmgr.SlotPair { + return d.slots.ToSlotPair() +} + +func (d *DagNode) GetNumSlots() int { + return d.numSlots +} + +func (d *DagNode) RunHeartbeatCheck(ctx context.Context) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() + healthCheckAll := func() { + wg := sync.WaitGroup{} + checkCtx, checkCancel := context.WithTimeout(ctx, 15*time.Second) + defer checkCancel() + for _, node := range d.Nodes { + wg.Add(1) + go func(sn *StorageNode) { + defer wg.Done() + sn.State = d.healthCheck(checkCtx, sn.Client) + }(node) + } + wg.Wait() + } + healthCheckAll() + for { + select { + case <-ctx.Done(): + return + case <-d.stopCh: + cancel() + return + case <-ticker.C: + healthCheckAll() + } + } +} + +func (d *DagNode) RunRepairTask(ctx context.Context) { + ctx, cancel := context.WithCancel(ctx) + defer cancel() + for { + select { + case task := <-d.repairQueue: + task(ctx) + case <-ctx.Done(): + return + case <-d.stopCh: + cancel() + return + } + } +} + +func (d *DagNode) healthCheck(ctx context.Context, cli *datanode.Client) bool { + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + check, err := cli.HeartClient.Check(ctx, &healthpb.HealthCheckRequest{Service: healthCheckService}) + if err != nil { + log.Errorf("Check the rpc address:%v err:%v", cli.RpcAddress, err) + return false + } + if check.Status != healthpb.HealthCheckResponse_SERVING { + log.Errorf("the rpc server[%v] status: %v", cli.RpcAddress, check.Status) + return false + } + return true +} + //DeleteBlock deletes a block from the DagNode func (d *DagNode) DeleteBlock(ctx context.Context, cid cid.Cid) (err error) { - log.Warnf("delete block, cid :%v", cid) + log.Warnf("delete block, cid: %v", cid) keyCode := cid.String() - wg := sync.WaitGroup{} - wg.Add(len(d.Nodes)) - for _, node := range d.Nodes { - go func(node *datanode.Client) { - defer func() { - if err := recover(); err != nil { - log.Errorf("%s:%s, keyCode:%s, delete block err :%v", node.Ip, node.Port, keyCode, err) - } - wg.Done() - }() - _, err = node.Client.Delete(ctx, &proto.DeleteRequest{Key: keyCode}) - if err != nil { - log.Debugf("%s:%s, keyCode:%s, delete block err :%v", node.Ip, node.Port, keyCode, err) + _, entryWriteQuorum := d.entryQuorum() + taskCtx := context.Background() + task := paralleltask.NewParallelTask(taskCtx, entryWriteQuorum, len(d.Nodes)-entryWriteQuorum+1, false) + for _, snode := range d.Nodes { + node := snode.Client + task.Goroutine(func(ctx context.Context) error { + var err error + if _, err = node.DataClient.Delete(ctx, &proto.DeleteRequest{Key: keyCode}); err != nil { + log.Errorw("delete error", "datanode", node.RpcAddress, "key", keyCode, "error", err) } - }(node) + return err + }) } - wg.Wait() - return err + return task.Wait() } //Has returns true if the given cid is in the DagNode @@ -86,46 +220,98 @@ func (d *DagNode) Has(ctx context.Context, cid cid.Cid) (bool, error) { func (d *DagNode) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { log.Debugf("get block, cid :%v", cid) keyCode := cid.String() - size, err := d.GetSize(ctx, cid) + meta, _, onlineNodes, err := d.getMetaInfo(ctx, cid) if err != nil { return nil, err } + size := meta.BlockSize + entryReadQuorum, _ := d.entryQuorum() - merged := make([][]byte, len(d.Nodes)) - wg := sync.WaitGroup{} - wg.Add(len(d.Nodes)) - for i, node := range d.Nodes { - go func(i int, node *datanode.Client) { - defer func() { - if err := recover(); err != nil { - log.Errorf("%s:%s, keyCode:%s, kvdb get err :%v", node.Ip, node.Port, keyCode, err) + shards := make([][]byte, len(onlineNodes)) + repairIndexes := make([]bool, len(onlineNodes)) + needRepair := false + task := paralleltask.NewParallelTask(ctx, entryReadQuorum, len(onlineNodes)-entryReadQuorum+1, true) + for i, snode := range onlineNodes { + index := i + tnode := snode + task.Goroutine(func(ctx context.Context) error { + // is offline node or have no block? + if tnode == nil { + // is it online? + if d.Nodes[index].State { + // repair shard + repairIndexes[index] = true + needRepair = true } - wg.Done() - }() - res, err := node.Client.Get(ctx, &proto.GetRequest{Key: keyCode}) + return errors.New("offline node") + } + node := tnode.Client + var err error + res, err := node.DataClient.Get(ctx, &proto.GetRequest{Key: keyCode}) if err != nil { - log.Errorf("%s:%s, keyCode:%s,kvdb get :%v", node.Ip, node.Port, keyCode, err) - merged[i] = nil + log.Errorw("get error", "datanode", node.RpcAddress, "key", keyCode, "error", err) + if st, ok := status.FromError(err); ok && st.Code() != codes.Canceled { + // repair shard + repairIndexes[index] = true + needRepair = true + } } else { - merged[i] = res.Data + shards[index] = res.Data + return nil } - }(i, node) + return err + }) + + } + if err = task.Wait(); err != nil { + log.Errorf("task error: %v", err) + return nil, err } - wg.Wait() - // TODO: After obtaining the shard data that meets the conditions, we can proceed - enc, err := NewErasure(d.dataBlocks, d.parityBlocks, int64(size)) + enc, err := NewErasure(d.config.DataBlocks, d.config.ParityBlocks, int64(size)) if err != nil { log.Errorf("new erasure fail :%v", err) return nil, err } - err = enc.DecodeDataBlocks(merged) + err = enc.DecodeDataBlocks(shards) if err != nil { - log.Errorf("decode date blocks fail :%v", err) + log.Errorf("decode data blocks fail :%v", err) return nil, err } - data := bytes.Join(merged, []byte("")) + + // need repair shards? + if needRepair { + indexes := make([]int, 0) + for i, ok := range repairIndexes { + if ok { + indexes = append(indexes, i) + } + } + repairFunc := func(ctx context.Context) { + repairCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + if err := d.repairBlock(repairCtx, keyCode, size, shards, indexes); err != nil { + log.Errorw("repair block failed", "key", keyCode, "blockSize", size, "indexes", indexes) + } + } + select { + case d.repairQueue <- repairFunc: + default: + log.Warn("repair queue is full, discard this task") + } + } + + // merge to block raw data + shardSize := int(enc.ShardSize()) + data := make([]byte, d.config.DataBlocks*shardSize) + for i, shard := range shards { + if i == d.config.DataBlocks { + break + } + copy(data[i*shardSize:], shard) + } data = data[:size] + b, err := blocks.NewBlockWithCid(data, cid) if err == blocks.ErrWrongHash { return nil, blockstore.ErrHashMismatch @@ -135,17 +321,31 @@ func (d *DagNode) Get(ctx context.Context, cid cid.Cid) (blocks.Block, error) { //GetSize returns the size of the block with the given cid func (d *DagNode) GetSize(ctx context.Context, cid cid.Cid) (int, error) { - metas, errs := readAllMeta(ctx, d.Nodes, cid.String()) + meta, _, _, err := d.getMetaInfo(ctx, cid) + return int(meta.BlockSize), err +} + +func (d *DagNode) getMetaInfo(ctx context.Context, cid cid.Cid) (meta Meta, metas []Meta, onlineNodes []*StorageNode, err error) { + var errs []error + metas, errs = readAllMeta(ctx, d.Nodes, cid.String()) entryReadQuorum, _ := d.entryQuorum() - reducedErr := reduceQuorumErrs(ctx, errs, entryOpIgnoredErrs, len(metas)/2, errErasureReadQuorum) + reducedErr := reduceQuorumErrs(ctx, errs, entryOpIgnoredErrs, entryReadQuorum, errErasureReadQuorum) if reducedErr != nil { - return 0, reducedErr + return meta, nil, nil, reducedErr } - meta, err := findMetaInQuorum(ctx, metas, entryReadQuorum) + meta, err = findMetaInQuorum(ctx, metas, entryReadQuorum) if err != nil { - return 0, err + return meta, nil, nil, err } - return int(meta.BlockSize), err + onlineNodes = make([]*StorageNode, len(metas)) + for i, m := range metas { + if m.BlockSize == meta.BlockSize { + onlineNodes[i] = d.Nodes[i] + } else { + onlineNodes[i] = nil + } + } + return meta, metas, onlineNodes, err } //Put adds the given block to the DagNode @@ -167,7 +367,7 @@ func (d *DagNode) Put(ctx context.Context, block blocks.Block) (err error) { return err } - enc, err := NewErasure(d.dataBlocks, d.parityBlocks, int64(blockDataSize)) + enc, err := NewErasure(d.config.DataBlocks, d.config.ParityBlocks, int64(blockDataSize)) if err != nil { log.Errorf("newErasure fail :%v", err) return err @@ -177,39 +377,28 @@ func (d *DagNode) Put(ctx context.Context, block blocks.Block) (err error) { log.Errorf("encodeData fail :%v", err) return err } - // TODO: Is verify necessary? - ok, err := enc.encoder().Verify(shards) - if err != nil { - log.Errorf("encode fail :%v", err) - return err - } - if ok { - //log.Debugf("encode ok, the data is the same format as Encode. No data is modified") - } - wg := sync.WaitGroup{} - wg.Add(len(d.Nodes)) - for i, node := range d.Nodes { - go func(i int, node *datanode.Client) { - defer func() { - if err := recover(); err != nil { - log.Errorf("%s:%s,keyCode:%s,kvdb put :%v", node.Ip, node.Port, keyCode, err) - } - wg.Done() - }() - if _, err = node.Client.Put(ctx, &proto.AddRequest{ + + _, entryWriteQuorum := d.entryQuorum() + taskCtx := context.Background() + task := paralleltask.NewParallelTask(taskCtx, entryWriteQuorum, len(d.Nodes)-entryWriteQuorum+1, false) + for i, snode := range d.Nodes { + index := i + node := snode.Client + task.Goroutine(func(ctx context.Context) error { + var err error + if _, err = node.DataClient.Put(ctx, &proto.AddRequest{ Key: keyCode, Meta: metaBuf.Bytes(), - Data: shards[i], + Data: shards[index], }); err != nil { - log.Errorf("%s:%s,keyCode:%s,kvdb put :%v", node.Ip, node.Port, keyCode, err) - // TODO: Put failure handling + log.Errorw("put error", "datanode", node.RpcAddress, "key", keyCode, "error", err) } - }(i, node) + return err + }) } - // TODO: If the specified number of successes is met, the write succeeds, + // If the specified number of successes is met, the write succeeds, // or if the specified number of failures is met, the write fails - wg.Wait() - return err + return task.Wait() } //PutMany adds the given blocks to the DagNode @@ -234,23 +423,25 @@ func (d *DagNode) Close() { for _, nd := range d.Nodes { nd.Conn.Close() } + close(d.stopCh) + close(d.repairQueue) } // Returns per entry readQuorum and writeQuorum // readQuorum is the min required nodes to read data. // writeQuorum is the min required nodes to write data. func (d *DagNode) entryQuorum() (entryReadQuorum, entryWriteQuorum int) { - writeQuorum := d.dataBlocks - if d.dataBlocks == d.parityBlocks { + writeQuorum := d.config.DataBlocks + if d.config.DataBlocks == d.config.ParityBlocks { writeQuorum++ } - return d.dataBlocks, writeQuorum + return d.config.DataBlocks, writeQuorum } // Reads all metadata as a Meta slice. // Returns error slice indicating the failed metadata reads. -func readAllMeta(ctx context.Context, nodes []*datanode.Client, key string) ([]Meta, []error) { +func readAllMeta(ctx context.Context, nodes []*StorageNode, key string) ([]Meta, []error) { metadataArray := make([]Meta, len(nodes)) errs := make([]error, len(nodes)) // Read meta in parallel across nodes. @@ -265,7 +456,7 @@ func readAllMeta(ctx context.Context, nodes []*datanode.Client, key string) ([]M errs[index] = errNodeNotFound return } - resp, err := nodes[index].Client.GetMeta(ctx, &proto.GetMetaRequest{Key: key}) + resp, err := nodes[index].Client.DataClient.GetMeta(ctx, &proto.GetMetaRequest{Key: key}) if err != nil { if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { errs[index] = errors.New(st.Message()) diff --git a/dag/node/dagnode/node_test.go b/dag/node/dagnode/node_test.go index 89bce9aa..c90a7621 100644 --- a/dag/node/dagnode/node_test.go +++ b/dag/node/dagnode/node_test.go @@ -5,26 +5,30 @@ import ( "context" "encoding/binary" "fmt" + "github.com/filedag-project/filedag-storage/dag/config" "github.com/filedag-project/filedag-storage/dag/node/datanode" "github.com/filedag-project/filedag-storage/dag/node/datanode/mocks" "github.com/filedag-project/filedag-storage/dag/proto" "github.com/golang/mock/gomock" blocks "github.com/ipfs/go-block-format" + "reflect" "testing" ) func TestDagNode(t *testing.T) { - var clients []*datanode.Client + var clients []*StorageNode for i := 0; i < 3; i++ { cli := &datanode.Client{ - Client: newDatanode(t), + DataClient: newDatanode(t, 2, 1, i), } - clients = append(clients, cli) + clients = append(clients, &StorageNode{Client: cli}) } var d = DagNode{ - Nodes: clients, - dataBlocks: 2, - parityBlocks: 1, + Nodes: clients, + config: config.DagNodeConfig{ + DataBlocks: 2, + ParityBlocks: 1, + }, } content := "123456" block := blocks.NewBlock([]byte(content)) @@ -60,7 +64,7 @@ func TestDagNode(t *testing.T) { } } -func newDatanode(t *testing.T) *mocks.MockDataNodeClient { +func newDatanode(t *testing.T, dataBlocks, parityBlocks int, index int) *mocks.MockDataNodeClient { content := "123456" block := blocks.NewBlock([]byte(content)) meta := Meta{ @@ -70,15 +74,24 @@ func newDatanode(t *testing.T) *mocks.MockDataNodeClient { if err := binary.Write(&metaBuf, binary.LittleEndian, meta); err != nil { t.Fatalf("binary.Write failed: %v", err) } + enc, err := NewErasure(dataBlocks, parityBlocks, int64(meta.BlockSize)) + if err != nil { + t.Fatalf("NewErasure failed: %v", err) + } + shards, err := enc.EncodeData(block.RawData()) + if err != nil { + t.Fatalf("EncodeData failed: %v", err) + } ctrl := gomock.NewController(t) m := mocks.NewMockDataNodeClient(ctrl) - m.EXPECT().Put(gomock.AssignableToTypeOf(context.Background()), gomock.AssignableToTypeOf(&proto.AddRequest{})).AnyTimes().Return(nil, nil) - m.EXPECT().Get(gomock.AssignableToTypeOf(context.Background()), gomock.AssignableToTypeOf(&proto.GetRequest{})).AnyTimes(). - Return(&proto.GetResponse{Data: block.RawData(), Meta: metaBuf.Bytes()}, nil) - m.EXPECT().GetMeta(gomock.AssignableToTypeOf(context.Background()), gomock.AssignableToTypeOf(&proto.GetMetaRequest{})).AnyTimes(). + var ctx = reflect.TypeOf((*context.Context)(nil)).Elem() + m.EXPECT().Put(gomock.AssignableToTypeOf(ctx), gomock.AssignableToTypeOf(&proto.AddRequest{})).AnyTimes().Return(nil, nil) + m.EXPECT().Get(gomock.AssignableToTypeOf(ctx), gomock.AssignableToTypeOf(&proto.GetRequest{})).AnyTimes(). + Return(&proto.GetResponse{Data: shards[index], Meta: metaBuf.Bytes()}, nil) + m.EXPECT().GetMeta(gomock.AssignableToTypeOf(ctx), gomock.AssignableToTypeOf(&proto.GetMetaRequest{})).AnyTimes(). Return(&proto.GetMetaResponse{Meta: metaBuf.Bytes()}, nil) - m.EXPECT().Delete(gomock.AssignableToTypeOf(context.Background()), gomock.AssignableToTypeOf(&proto.DeleteRequest{})).AnyTimes().Return(nil, nil) - m.EXPECT().Size(gomock.AssignableToTypeOf(context.Background()), gomock.AssignableToTypeOf(&proto.SizeRequest{})).AnyTimes(). + m.EXPECT().Delete(gomock.AssignableToTypeOf(ctx), gomock.AssignableToTypeOf(&proto.DeleteRequest{})).AnyTimes().Return(nil, nil) + m.EXPECT().Size(gomock.AssignableToTypeOf(ctx), gomock.AssignableToTypeOf(&proto.SizeRequest{})).AnyTimes(). Return(&proto.SizeResponse{Size: int64(datanode.HeaderSize + 4 + len(block.RawData()))}, nil) return m } diff --git a/dag/node/datanode/client.go b/dag/node/datanode/client.go index 17b6030d..753ba0e8 100644 --- a/dag/node/datanode/client.go +++ b/dag/node/datanode/client.go @@ -1,10 +1,9 @@ package datanode import ( - "fmt" - "github.com/filedag-project/filedag-storage/dag/config" "github.com/filedag-project/filedag-storage/dag/proto" "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" healthpb "google.golang.org/grpc/health/grpc_health_v1" ) @@ -16,25 +15,23 @@ type DataNodeClient interface { //Client is a node that stores erasure-coded sharded data type Client struct { - Client proto.DataNodeClient + DataClient proto.DataNodeClient HeartClient healthpb.HealthClient - Ip string - Port string + RpcAddress string Conn *grpc.ClientConn } //NewClient creates a grpc connection to a slice -func NewClient(cfg config.DataNodeConfig) (datanode *Client, err error) { - conn, err := grpc.Dial(fmt.Sprintf("%s:%s", cfg.Ip, cfg.Port), grpc.WithInsecure()) +func NewClient(rpcAddress string) (datanode *Client, err error) { + conn, err := grpc.Dial(rpcAddress, grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { log.Errorf("did not connect: %v", err) return nil, err } datanode = &Client{ - Client: proto.NewDataNodeClient(conn), + DataClient: proto.NewDataNodeClient(conn), HeartClient: healthpb.NewHealthClient(conn), - Ip: cfg.Ip, - Port: cfg.Port, + RpcAddress: rpcAddress, Conn: conn, } return datanode, nil diff --git a/dag/pool/client/cluster_client.go b/dag/pool/client/cluster_client.go new file mode 100644 index 00000000..2171d2b5 --- /dev/null +++ b/dag/pool/client/cluster_client.go @@ -0,0 +1,124 @@ +package client + +import ( + "context" + "errors" + "github.com/filedag-project/filedag-storage/dag/config" + "github.com/filedag-project/filedag-storage/dag/proto" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" + "github.com/filedag-project/filedag-storage/dag/utils" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/emptypb" +) + +type dagPoolClusterClient struct { + DPClusterClient proto.DagPoolClusterClient + Conn *grpc.ClientConn +} + +//NewPoolClusterClient new a dagPoolClusterClient +func NewPoolClusterClient(addr string) (*dagPoolClusterClient, error) { + conn, err := grpc.Dial(addr, grpc.WithInsecure()) + if err != nil { + log.Errorf("did not connect: %v", err) + return nil, err + } + c := proto.NewDagPoolClusterClient(conn) + return &dagPoolClusterClient{ + DPClusterClient: c, + Conn: conn, + }, nil +} + +//Close the client +func (cli *dagPoolClusterClient) Close(ctx context.Context) { + cli.Conn.Close() +} + +func (cli *dagPoolClusterClient) AddDagNode(ctx context.Context, nodeConfig *config.DagNodeConfig) error { + nodeInfo := utils.ToProtoDagNodeInfo(nodeConfig) + _, err := cli.DPClusterClient.AddDagNode(ctx, nodeInfo) + if err != nil { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { + return errors.New(st.Message()) + } + return err + } + return nil +} + +func (cli *dagPoolClusterClient) GetDagNode(ctx context.Context, dagNodeName string) (*config.DagNodeConfig, error) { + nodeInfo, err := cli.DPClusterClient.GetDagNode(ctx, &proto.GetDagNodeReq{Name: dagNodeName}) + if err != nil { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { + return nil, errors.New(st.Message()) + } + return nil, err + } + return utils.ToDagNodeConfig(nodeInfo), nil +} + +func (cli *dagPoolClusterClient) RemoveDagNode(ctx context.Context, dagNodeName string) (*config.DagNodeConfig, error) { + nodeInfo, err := cli.DPClusterClient.RemoveDagNode(ctx, &proto.RemoveDagNodeReq{Name: dagNodeName}) + if err != nil { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { + return nil, errors.New(st.Message()) + } + return nil, err + } + return utils.ToDagNodeConfig(nodeInfo), nil +} + +func (cli *dagPoolClusterClient) MigrateSlots(ctx context.Context, fromDagNodeName, toDagNodeName string, pairs []slotsmgr.SlotPair) error { + _, err := cli.DPClusterClient.MigrateSlots(ctx, &proto.MigrateSlotsReq{ + FromDagNodeName: fromDagNodeName, + ToDagNodeName: toDagNodeName, + Pairs: utils.ToProtoSlotPairs(pairs), + }) + if err != nil { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { + return errors.New(st.Message()) + } + return err + } + return nil +} + +func (cli *dagPoolClusterClient) BalanceSlots(ctx context.Context) error { + _, err := cli.DPClusterClient.BalanceSlots(ctx, &emptypb.Empty{}) + if err != nil { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { + return errors.New(st.Message()) + } + return err + } + return nil +} + +func (cli *dagPoolClusterClient) Status(ctx context.Context) (*proto.StatusReply, error) { + reply, err := cli.DPClusterClient.Status(ctx, &emptypb.Empty{}) + if err != nil { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { + return nil, errors.New(st.Message()) + } + return nil, err + } + return reply, nil +} + +func (cli *dagPoolClusterClient) RepairDataNode(ctx context.Context, dagNodeName string, fromIndex, repairIndex int) error { + _, err := cli.DPClusterClient.RepairDataNode(ctx, &proto.RepairDataNodeReq{ + DagNodeName: dagNodeName, + FromNodeIndex: int32(fromIndex), + RepairNodeIndex: int32(repairIndex), + }) + if err != nil { + if st, ok := status.FromError(err); ok && st.Code() == codes.Unknown { + return errors.New(st.Message()) + } + return err + } + return nil +} diff --git a/dag/pool/pool.go b/dag/pool/pool.go index 9326edd0..6eeb0847 100644 --- a/dag/pool/pool.go +++ b/dag/pool/pool.go @@ -2,7 +2,10 @@ package pool import ( "context" + "github.com/filedag-project/filedag-storage/dag/config" "github.com/filedag-project/filedag-storage/dag/pool/poolservice/dpuser" + "github.com/filedag-project/filedag-storage/dag/proto" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" // blank import is used to register the IPLD raw codec @@ -11,7 +14,7 @@ import ( //go:generate go run github.com/golang/mock/mockgen -destination=mocks/mock_dagpool.go -package=mocks . DagPool -//DagPool is an interface that defines the basic operations of a dag pool +// DagPool is an interface that defines the basic operations of a dag pool type DagPool interface { Add(ctx context.Context, block blocks.Block, user string, password string, pin bool) error Get(ctx context.Context, c cid.Cid, user string, password string) (blocks.Block, error) @@ -23,3 +26,14 @@ type DagPool interface { UpdateUser(uUser dpuser.DagPoolUser, user string, password string) error Close() error } + +// Cluster is an interface that defines the basic operations of a Cluster +type Cluster interface { + AddDagNode(nodeConfig *config.DagNodeConfig) error + GetDagNode(dagNodeName string) (*config.DagNodeConfig, error) + RemoveDagNode(dagNodeName string) (*config.DagNodeConfig, error) + MigrateSlots(fromDagNodeName, toDagNodeName string, pairs []slotsmgr.SlotPair) error + BalanceSlots() error + Status() (*proto.StatusReply, error) + RepairDataNode(ctx context.Context, dagNodeName string, fromNodeIndex int, repairNodeIndex int) error +} diff --git a/dag/pool/poolservice/cluster.go b/dag/pool/poolservice/cluster.go new file mode 100644 index 00000000..25332c08 --- /dev/null +++ b/dag/pool/poolservice/cluster.go @@ -0,0 +1,590 @@ +package poolservice + +import ( + "context" + "errors" + "fmt" + "github.com/filedag-project/filedag-storage/dag/config" + "github.com/filedag-project/filedag-storage/dag/node/dagnode" + "github.com/filedag-project/filedag-storage/dag/proto" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" + "github.com/ipfs/go-cid" + format "github.com/ipfs/go-ipld-format" + "github.com/syndtr/goleveldb/leveldb" + "sort" + "time" +) + +var ErrDagNodeNotFound = errors.New("this dag node does not exist") +var ErrDagNodeRemove = errors.New("this dag node still has slots and cannot be removed") +var ErrClusterMigrating = errors.New("the cluster is migrating") + +type MigrateSlot struct { + From string + To string + SlotPairs []slotsmgr.SlotPair +} + +func (d *dagPoolService) startNewDagNode(nodeConfig *config.DagNodeConfig) (*dagnode.DagNode, error) { + if _, ok := d.dagNodesMap[nodeConfig.Name]; ok { + return nil, ErrDagNodeAlreadyExist + } + dagNode, err := dagnode.NewDagNode(*nodeConfig) + if err != nil { + log.Errorf("new dagnode err:%v", err) + return nil, err + } + go dagNode.RunHeartbeatCheck(d.parentCtx) + go dagNode.RunRepairTask(d.parentCtx) + d.dagNodesMap[nodeConfig.Name] = dagNode + return dagNode, nil +} + +func (d *dagPoolService) AddDagNode(nodeConfig *config.DagNodeConfig) error { + d.dagNodesLock.Lock() + defer d.dagNodesLock.Unlock() + + dagNode, err := d.startNewDagNode(nodeConfig) + if err != nil { + return err + } + + // update local config + cfg, err := d.loadConfig() + if err != nil { + return err + } + cfg.Version += 1 + for _, node := range cfg.Cluster { + if node.Config.Name == nodeConfig.Name { + log.Fatal("local cluster config is illegal") + } + } + cfg.Cluster = append(cfg.Cluster, config.DagNodeInfo{Config: *nodeConfig}) + if err = d.saveConfig(cfg); err != nil { + // rollback + delete(d.dagNodesMap, nodeConfig.Name) + dagNode.Close() + return err + } + + return nil +} + +func (d *dagPoolService) GetDagNode(dagNodeName string) (*config.DagNodeConfig, error) { + d.dagNodesLock.RLock() + defer d.dagNodesLock.RUnlock() + + if nd, ok := d.dagNodesMap[dagNodeName]; ok { + return nd.GetConfig(), nil + } + return nil, ErrDagNodeNotFound +} + +func (d *dagPoolService) RemoveDagNode(dagNodeName string) (*config.DagNodeConfig, error) { + d.dagNodesLock.Lock() + defer d.dagNodesLock.Unlock() + + if d.state != StateOk { + if d.state == StateMigrating { + return nil, ErrClusterMigrating + } else { + return nil, ErrClusterAvailable + } + } + + if nd, ok := d.dagNodesMap[dagNodeName]; ok { + // make sure the dagnode has no slot + if nd.GetNumSlots() != 0 { + return nil, ErrDagNodeRemove + } + + // update local config + cfg, err := d.loadConfig() + if err != nil { + return nil, err + } + cfg.Version += 1 + for i, node := range cfg.Cluster { + if node.Config.Name == dagNodeName { + cfg.Cluster = append(cfg.Cluster[:i], cfg.Cluster[(i+1):]...) + break + } + } + if err = d.saveConfig(cfg); err != nil { + return nil, err + } + + dagNodeCfg := nd.GetConfig() + delete(d.dagNodesMap, dagNodeName) + // close dagnode + nd.Close() + return dagNodeCfg, nil + } + return nil, ErrDagNodeNotFound +} + +func (d *dagPoolService) MigrateSlots(fromDagNodeName, toDagNodeName string, pairs []slotsmgr.SlotPair) error { + d.dagNodesLock.Lock() + defer d.dagNodesLock.Unlock() + + if d.state == StateMigrating { + return ErrClusterMigrating + } + + err := d.migrateSlotsByName(fromDagNodeName, toDagNodeName, pairs) + if err == nil { + // start to migrate data + select { + case d.migratingCh <- struct{}{}: + default: + } + } + return err +} + +func (d *dagPoolService) migrateSlotsByName(fromDagNodeName, toDagNodeName string, pairs []slotsmgr.SlotPair) error { + fromNode, fromOk := d.dagNodesMap[fromDagNodeName] + toNode, toOk := d.dagNodesMap[toDagNodeName] + if !fromOk || !toOk { + return ErrDagNodeNotFound + } + for _, pair := range pairs { + for slot := pair.Start; slot <= pair.End; slot++ { + if d.slots[slot] != fromNode { + return fmt.Errorf("dagnode[%v] does not own the slot %d", fromDagNodeName, slot) + } + } + } + cfg, err := d.loadConfig() + if err != nil { + return err + } + + d.migrateSlotsByNode(fromNode, toNode, pairs) + + var updateSlots []uint16 + rollback := func() { + d.migrateSlotsByNode(toNode, fromNode, pairs) + for _, idx := range updateSlots { + if errR := d.slotMigrateRepo.Remove(idx); errR != nil { + log.Warnw("slotMigrateRepo.Remove error", "slot", idx) + } + } + } + for _, pair := range pairs { + for slot := pair.Start; slot <= pair.End; slot++ { + if err = d.slotMigrateRepo.Set(uint16(slot), fromDagNodeName); err != nil { + // rollback + rollback() + return err + } + updateSlots = append(updateSlots, uint16(slot)) + } + } + + // update local config + cfg.Version += 1 + cfg.Cluster = nil + for _, node := range d.dagNodesMap { + dagNode := config.DagNodeInfo{} + dagNode.Config = *node.GetConfig() + dagNode.SlotPairs = node.GetSlotPairs() + cfg.Cluster = append(cfg.Cluster, dagNode) + } + if err = d.saveConfig(cfg); err != nil { + // rollback + rollback() + return err + } + d.state = StateMigrating + + return nil +} + +func (d *dagPoolService) migrateSlotsByNode(fromNode, toNode *dagnode.DagNode, pairs []slotsmgr.SlotPair) { + for _, pair := range pairs { + for slot := pair.Start; slot <= pair.End; slot++ { + fromNode.ClearSlot(slot) + toNode.AddSlot(slot) + + d.slots[slot] = toNode + d.importingSlotsFrom[slot] = fromNode + } + } +} + +func (d *dagPoolService) migrateSlotsDataTask(ctx context.Context) { + for { + select { + case <-ctx.Done(): + return + case _, ok := <-d.migratingCh: + if !ok { + return + } + + numSlotOk := 0 + for slot, from := range d.importingSlotsFrom { + if from == nil { + numSlotOk++ + continue + } + to := d.slots[slot] + toName := to.GetConfig().Name + + // slot data migrate from 'from' to 'to' + ch, err := d.slotKeyRepo.AllKeysChan(ctx, uint16(slot), "") + if err != nil { + log.Fatal(err) + } + toMigrateSlots := 0 + successMigrateSlots := 0 + for entry := range ch { + if entry.Value == toName { + continue + } + toMigrateSlots++ + blkCid, err := cid.Parse(entry.Key) + if err != nil { + log.Errorf("slotKeyRepo parse cid error, slot: %v cid: %v, error: %v", slot, entry.Key, err) + continue + } + bk, err := from.Get(ctx, blkCid) + if err != nil { + if format.IsNotFound(err) { + successMigrateSlots++ + continue + } + log.Errorw("migrating get block error", "from_node", from.GetConfig().Name, "slot", slot, "cid", blkCid, "err", err) + continue + } + if err = to.Put(ctx, bk); err != nil { + log.Errorw("migrating put block error", "to_node", toName, "slot", slot, "cid", entry.Key, "err", err) + continue + } + + if err = d.slotKeyRepo.Set(uint16(slot), entry.Key, toName); err != nil { + log.Errorw("slotKeyRepo set key error", "to_node", toName, "slot", slot, "cid", entry.Key, "err", err) + continue + } + if err = from.DeleteBlock(ctx, blkCid); err != nil { + log.Warnw("migrating delete block error", "from_node", from.GetConfig().Name, "slot", slot, "cid", blkCid, "err", err) + } + successMigrateSlots++ + } + if toMigrateSlots == successMigrateSlots { + // all migrated + if err = d.slotMigrateRepo.Remove(uint16(slot)); err == nil { + d.importingSlotsFrom[slot] = nil + numSlotOk++ + } else { + log.Errorw("slotMigrateRepo.Remove failed", "slot", slot) + } + } + } + // is migration done? + if numSlotOk == slotsmgr.ClusterSlots { + if d.checkAllSlots() { + d.state = StateOk + } else { + d.state = StateFail + } + } else { + // try again + time.AfterFunc(time.Minute, func() { + d.migratingCh <- struct{}{} + }) + } + } + } +} + +// initSlots Perform the slots allocation for the first time +func (d *dagPoolService) initSlots() error { + cfg, err := d.loadConfig() + if err != nil { + return err + } + + // calculate number of slots each dagnode + nodesNum := len(d.dagNodesMap) + if nodesNum == 0 { + return errors.New("please add the dagnodes first") + } + piece := slotsmgr.ClusterSlots / nodesNum + remind := slotsmgr.ClusterSlots - piece*nodesNum + + var nameList []string + for name := range d.dagNodesMap { + nameList = append(nameList, name) + } + sort.Strings(nameList) + curIndex := 0 + cfg.Cluster = nil + for i := 0; i < nodesNum; i++ { + curPiece := piece + if remind > 0 { + curPiece += 1 + remind-- + } + + node := d.dagNodesMap[nameList[i]] + for start := curIndex; start <= curIndex+curPiece-1; start++ { + node.AddSlot(uint64(start)) + + if d.slots[start] != nil { + log.Fatal("the slot state is inconsistent") + } + d.slots[start] = node + } + + dagNode := config.DagNodeInfo{} + dagNode.Config = *node.GetConfig() + dagNode.SlotPairs = node.GetSlotPairs() + cfg.Cluster = append(cfg.Cluster, dagNode) + + curIndex += curPiece + } + // save config + cfg.Version += 1 + if err = d.saveConfig(cfg); err != nil { + // rollback + for i := 0; i < nodesNum; i++ { + node := d.dagNodesMap[nameList[i]] + slotPairs := node.GetSlotPairs() + for _, pair := range slotPairs { + for slot := pair.Start; slot <= pair.End; slot++ { + node.ClearSlot(slot) + } + } + if node.GetNumSlots() != 0 { + log.Fatal("the slot state is inconsistent") + } + } + var empty [slotsmgr.ClusterSlots]*dagnode.DagNode + d.slots = empty + return err + } + // initialization is complete + d.state = StateOk + + return nil +} + +func (d *dagPoolService) BalanceSlots() error { + d.dagNodesLock.Lock() + defer d.dagNodesLock.Unlock() + + if d.state == StateMigrating { + return ErrClusterMigrating + } + + // calculate number of slots each dagnode + nodesNum := len(d.dagNodesMap) + if nodesNum == 0 { + return errors.New("please add the dagnodes first") + } + piece := slotsmgr.ClusterSlots / nodesNum + remain := slotsmgr.ClusterSlots - piece*nodesNum + + var nameList []string + for name := range d.dagNodesMap { + nameList = append(nameList, name) + } + sort.Strings(nameList) + + // check the slots + slotsTmp := slotsmgr.NewSlotsManager() + for slot, node := range d.slots { + if node == nil { + slotsTmp.Set(uint64(slot), true) + } + } + unAllocatedSlots := slotsTmp.Count() + if unAllocatedSlots > 0 { + if unAllocatedSlots == slotsmgr.ClusterSlots { + // init slots + return d.initSlots() + } else { + // slots will be assigned to the first node + pairs := slotsTmp.ToSlotPair() + firstNode := d.dagNodesMap[nameList[0]] + for _, pair := range pairs { + for slot := pair.Start; slot <= pair.End; slot++ { + if err := d.addSlot(firstNode, slot); err != nil { + return err + } + } + } + } + } + + type MigrateInfo struct { + DagNodeName string + NumSlots int + } + availableList := make([]MigrateInfo, 0) + requireList := make([]MigrateInfo, 0) + for i := 0; i < nodesNum; i++ { + expectedPiece := piece + if remain > 0 { + expectedPiece += 1 + remain-- + } + node := d.dagNodesMap[nameList[i]] + numSlots := node.GetNumSlots() + // Is it necessary to adjust? + if expectedPiece == numSlots { + continue + } + if expectedPiece < numSlots { + availableList = append(availableList, MigrateInfo{ + DagNodeName: nameList[i], + NumSlots: numSlots - expectedPiece, + }) + } else { + requireList = append(requireList, MigrateInfo{ + DagNodeName: nameList[i], + NumSlots: expectedPiece - numSlots, + }) + } + } + + // calculate migrate slots + var migrateSlots []*MigrateSlot + var available MigrateInfo + var availableSlotPairs []slotsmgr.SlotPair + for _, require := range requireList { + requireSlots := require.NumSlots + for { + if requireSlots == 0 { + break + } + if available.NumSlots == 0 { + if len(availableList) == 0 { + log.Fatal("the slot state is inconsistent") + } + available = availableList[0] + availableList = availableList[1:] + + node := d.dagNodesMap[available.DagNodeName] + availableSlotPairs = node.GetSlotPairs() + } + + toMigrateSlots := available.NumSlots + if toMigrateSlots > requireSlots { + toMigrateSlots = requireSlots + } + remain := toMigrateSlots + var migrateSlotPairs []slotsmgr.SlotPair + for index := len(availableSlotPairs) - 1; index >= 0; index-- { + if remain == 0 { + break + } + if remain >= int(availableSlotPairs[index].Count()) { + migrateSlotPairs = append(migrateSlotPairs, availableSlotPairs[index]) + remain -= int(availableSlotPairs[index].Count()) + available.NumSlots -= int(availableSlotPairs[index].Count()) + availableSlotPairs = availableSlotPairs[:index] + } else { + part := slotsmgr.SlotPair{ + Start: availableSlotPairs[index].End - uint64(remain) + 1, + End: availableSlotPairs[index].End, + } + migrateSlotPairs = append(migrateSlotPairs, part) + availableSlotPairs[index] = slotsmgr.SlotPair{ + Start: availableSlotPairs[index].Start, + End: part.Start - 1, + } + available.NumSlots -= remain + remain = 0 + } + } + migrateSlot := MigrateSlot{ + From: available.DagNodeName, + To: require.DagNodeName, + SlotPairs: migrateSlotPairs, + } + migrateSlots = append(migrateSlots, &migrateSlot) + requireSlots -= toMigrateSlots + } + } + + var err error + migrated := false + for _, migrate := range migrateSlots { + if err = d.migrateSlotsByName(migrate.From, migrate.To, migrate.SlotPairs); err != nil { + break + } + migrated = true + } + + if migrated { + // start to migrate data + select { + case d.migratingCh <- struct{}{}: + default: + } + } + + return err +} + +func (d *dagPoolService) Status() (*proto.StatusReply, error) { + d.dagNodesLock.RLock() + defer d.dagNodesLock.RUnlock() + + list := make([]*proto.DagNodeStatus, 0, len(d.dagNodesMap)) + var nameList []string + for name := range d.dagNodesMap { + nameList = append(nameList, name) + } + sort.Strings(nameList) + nodesNum := len(nameList) + for i := 0; i < nodesNum; i++ { + node := d.dagNodesMap[nameList[i]] + pairs := node.GetSlotPairs() + newPairs := make([]*proto.SlotPair, 0, len(pairs)) + for _, p := range pairs { + newPairs = append(newPairs, &proto.SlotPair{Start: uint32(p.Start), End: uint32(p.End)}) + } + cfg := node.GetConfig() + dataNodes := make([]*proto.DataNodeInfo, 0, len(cfg.Nodes)) + for idx, nd := range cfg.Nodes { + state := node.GetDataNodeState(idx) + dataNodes = append(dataNodes, &proto.DataNodeInfo{ + RpcAddress: nd, + State: &state, + }) + } + st := &proto.DagNodeStatus{ + Node: &proto.DagNodeInfo{ + Name: cfg.Name, + Nodes: dataNodes, + DataBlocks: int32(cfg.DataBlocks), + ParityBlocks: int32(cfg.ParityBlocks), + }, + Pairs: newPairs, + } + list = append(list, st) + } + return &proto.StatusReply{ + State: d.state.String(), + Statuses: list, + }, nil +} + +func (d *dagPoolService) loadConfig() (*config.ClusterConfig, error) { + var cfg config.ClusterConfig + if err := d.db.Get(clusterConfig, &cfg); err != nil { + if err != leveldb.ErrNotFound { + return nil, fmt.Errorf("load cluster config failed, error: %v", err) + } + } + return &cfg, nil +} + +func (d *dagPoolService) saveConfig(cfg *config.ClusterConfig) error { + return d.db.Put(clusterConfig, cfg) +} diff --git a/dag/pool/poolservice/dnm/heart_beating_test.go b/dag/pool/poolservice/dnm/heart_beating_test.go deleted file mode 100644 index 89a97a0b..00000000 --- a/dag/pool/poolservice/dnm/heart_beating_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package dnm - -import ( - "github.com/filedag-project/filedag-storage/dag/config" - "github.com/filedag-project/filedag-storage/dag/node/datanode" - "github.com/filedag-project/filedag-storage/objectservice/uleveldb" - logging "github.com/ipfs/go-log/v2" - "testing" - "time" -) - -func TestHeart_beating(t *testing.T) { - logging.SetLogLevel("*", "DEBUG") - db, err := uleveldb.OpenDb(t.TempDir()) - if err != nil { - log.Errorf("err %v", err) - } - r := NewRecordSys(db) - go datanode.StartDataNodeServer(":9010", datanode.KVBadge, t.TempDir()) - time.Sleep(time.Second) - var a []*datanode.Client - - datanodeClient, err := datanode.NewClient(config.DataNodeConfig{ - Ip: "", - Port: ":9010", - }) - if err != nil { - return - } - a = append(a, datanodeClient) - - err = r.HandleDagNode(a, "test") - if err != nil { - return - } - time.Sleep(time.Second * 10) - log.Debugf("the node : %+v", r.RN) -} diff --git a/dag/pool/poolservice/dnm/record.go b/dag/pool/poolservice/dnm/record.go deleted file mode 100644 index 19df2ea8..00000000 --- a/dag/pool/poolservice/dnm/record.go +++ /dev/null @@ -1,135 +0,0 @@ -package dnm - -import ( - "context" - "github.com/filedag-project/filedag-storage/dag/node/datanode" - "github.com/filedag-project/filedag-storage/objectservice/uleveldb" - logging "github.com/ipfs/go-log/v2" - "golang.org/x/xerrors" - healthpb "google.golang.org/grpc/health/grpc_health_v1" - "strconv" - "sync" - "time" -) - -//NodeRecordSys is a struct for record the dag node -type NodeRecordSys struct { - Db *uleveldb.ULevelDB - RN map[string]*dagNodeInfo - NodeLock sync.Mutex -} -type dagNodeInfo struct { - status bool - dataNodeInfo map[string]*dataNodeInfo -} -type dataNodeInfo struct { - name string - status bool - ip string - port string -} - -const healthCheckService = "grpc.health.v1.Health" -const dagPoolRecord = "dagPoolRecord/" - -var log = logging.Logger("data-node-manager") - -//NewRecordSys create a new record system -func NewRecordSys(db *uleveldb.ULevelDB) *NodeRecordSys { - return &NodeRecordSys{Db: db, RN: make(map[string]*dagNodeInfo)} -} - -//Add a new record -func (r *NodeRecordSys) Add(cid string, name string) error { - return r.Db.Put(dagPoolRecord+cid, name) -} - -//HandleDagNode handle the dag node -func (r *NodeRecordSys) HandleDagNode(cons []*datanode.Client, name string) error { - m := make(map[string]*dataNodeInfo) - for i, c := range cons { - var dni = dataNodeInfo{ - name: strconv.Itoa(i), - status: true, - ip: c.Ip, - port: c.Port, - } - m[strconv.Itoa(i)] = &dni - } - tmp := dagNodeInfo{ - status: true, - dataNodeInfo: m, - } - r.RN[name] = &tmp - for i, c := range cons { - go r.handleConn(c, name, strconv.Itoa(i)) - } - return nil -} -func (r *NodeRecordSys) handleConn(c *datanode.Client, name string, dataName string) { - - for { - r.NodeLock.Lock() - dni := r.RN[name].dataNodeInfo[dataName] - log.Debugf("heart") - check, err := c.HeartClient.Check(context.TODO(), &healthpb.HealthCheckRequest{Service: healthCheckService}) - if err != nil { - log.Errorf("Check the %v ip:%v,port:%v err:%v", dni.name, dni.ip, dni.port, err) - r.Remove(name, dataName) - return - } - if check.Status != healthpb.HealthCheckResponse_SERVING { - log.Errorf("the %v ip:%v,port:%v not ser", dni.name, dni.ip, dni.port) - r.Remove(name, dataName) - } - r.NodeLock.Unlock() - time.Sleep(time.Second * 10) - } -} - -//Remove a record -func (r *NodeRecordSys) Remove(name, dataName string) { - r.RN[name].dataNodeInfo[dataName].status = false - count := 0 - for _, info := range r.RN[name].dataNodeInfo { - if !info.status { - count++ - } - if count >= 2 { - r.RN[name].status = false - break - } - } -} - -//Get a record by cid -func (r *NodeRecordSys) Get(cid string) (string, error) { - var name string - err := r.Db.Get(dagPoolRecord+cid, &name) - if err != nil { - return "", err - } - return name, nil -} - -//GetNameUseIp get the name by ip -func (r *NodeRecordSys) GetNameUseIp(ip string) (string, error) { - for name, n := range r.RN { - for _, i := range n.dataNodeInfo { - if i.ip == ip { - return name, nil - } - } - } - return "", xerrors.Errorf("no dagnode") -} - -//GetCanUseNode get the can use node -func (r *NodeRecordSys) GetCanUseNode() string { - for n, st := range r.RN { - if st.status == true { - return n - } - } - return "" -} diff --git a/dag/pool/poolservice/gc.go b/dag/pool/poolservice/gc.go index 83b26e6f..8ab448ef 100644 --- a/dag/pool/poolservice/gc.go +++ b/dag/pool/poolservice/gc.go @@ -68,16 +68,12 @@ func (d *dagPoolService) runGC(ctx context.Context) error { log.Warnw("decode cid error", "cid", key, "error", err) continue } - node, err := d.getDagNodeInfo(ctx, blkCid) - if err != nil { - return err - } if err = d.cacheSet.Remove(key); err != nil { log.Warnw("remove cache key error", "cid", key, "error", err) continue } log.Infow("delete block", "cid", key) - if err = node.DeleteBlock(ctx, blkCid); err != nil { + if err = d.deleteBlock(ctx, blkCid); err != nil { if err := d.cacheSet.Add(key); err != nil { log.Errorw("rollback cache key error", "cid", key, "error", err) } diff --git a/dag/pool/poolservice/gc_test.go b/dag/pool/poolservice/gc_test.go index 17a29905..df3e9492 100644 --- a/dag/pool/poolservice/gc_test.go +++ b/dag/pool/poolservice/gc_test.go @@ -81,7 +81,7 @@ func Test_Gc(t *testing.T) { var startgc = make(chan int) var interruptGC bool -func (d dagPoolService) GCTest(ctx context.Context) { +func (d *dagPoolService) GCTest(ctx context.Context) { timer := time.NewTimer(d.gcPeriod) defer timer.Stop() for { @@ -143,10 +143,6 @@ func (d *dagPoolService) runGCTest(ctx context.Context) error { log.Warnw("decode cid error", "cid", key, "error", err) continue } - node, err := d.getDagNodeInfo(ctx, blkCid) - if err != nil { - return err - } if err = d.cacheSet.Remove(key); err != nil { log.Warnw("remove cache key error", "cid", key, "error", err) continue @@ -158,7 +154,7 @@ func (d *dagPoolService) runGCTest(ctx context.Context) error { time.Sleep(time.Second) log.Infow("delete block", "cid", key) - if err = node.DeleteBlock(ctx, blkCid); err != nil { + if err = d.deleteBlock(ctx, blkCid); err != nil { if err := d.cacheSet.Add(key); err != nil { log.Errorw("rollback cache key error", "cid", key, "error", err) } diff --git a/dag/pool/poolservice/hash_slot.go b/dag/pool/poolservice/hash_slot.go new file mode 100644 index 00000000..d859db18 --- /dev/null +++ b/dag/pool/poolservice/hash_slot.go @@ -0,0 +1,197 @@ +package poolservice + +import ( + "context" + "errors" + "fmt" + "github.com/filedag-project/filedag-storage/dag/node/dagnode" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" + "github.com/howeyc/crc16" + blocks "github.com/ipfs/go-block-format" + "github.com/ipfs/go-cid" + format "github.com/ipfs/go-ipld-format" +) + +const clusterConfig = "cluster-cfg" + +var ErrDagNodeAlreadyExist = errors.New("this dag node already exists") +var ErrClusterAvailable = errors.New("cluster is unavailable, please check the slots") + +func keyHashSlot(key string) uint16 { + return crc16.Checksum([]byte(key), crc16.IBMTable) & 0x3FFF +} + +func (d *dagPoolService) clusterInit() error { + cfg, err := d.loadConfig() + if err != nil { + return err + } + + for _, dagNodeConfig := range cfg.Cluster { + dagNode, err := d.startNewDagNode(&dagNodeConfig.Config) + if err != nil { + return err + } + for _, pair := range dagNodeConfig.SlotPairs { + for idx := pair.Start; idx <= pair.End; idx++ { + if err := d.addSlot(dagNode, idx); err != nil { + return err + } + } + } + } + + // load migrating slot + ch, err := d.slotMigrateRepo.AllKeysChan(d.parentCtx) + if err != nil { + return err + } + for entry := range ch { + if dagNode, ok := d.dagNodesMap[entry.Value]; ok { + d.importingSlotsFrom[entry.Slot] = dagNode + d.state = StateMigrating + } else { + return fmt.Errorf("not exist the dag node, slot:%v dagNodeName:%v", entry.Slot, entry.Value) + } + } + + if !d.checkAllSlots() { + d.state = StateFail + log.Warn("please allocate all the slots") + } + if d.state == StateMigrating { + // start to migrate data + select { + case d.migratingCh <- struct{}{}: + default: + } + } + + return nil +} + +func (d *dagPoolService) checkAllSlots() bool { + for _, node := range d.slots { + if node == nil { + return false + } + } + return true +} + +func (d *dagPoolService) addSlot(node *dagnode.DagNode, slot uint64) error { + if d.slots[slot] != nil { + return errors.New("slot already exists") + } + node.AddSlot(slot) + d.slots[slot] = node + return nil +} + +func (d *dagPoolService) delSlot(slot uint64) error { + if d.slots[slot] == nil { + return errors.New("slot does not exist") + } + + if !d.slots[slot].ClearSlot(slot) { + log.Fatal("the slot state is inconsistent") + } + d.slots[slot] = nil + return nil +} + +// Delete all the slots associated with the specified node. +// The number of deleted slots is returned. +func (d *dagPoolService) delNodeSlots(node *dagnode.DagNode) int { + deleted := 0 + + for j := 0; j < slotsmgr.ClusterSlots; j++ { + if node.GetSlot(uint64(j)) { + d.delSlot(uint64(j)) + deleted++ + } + } + return deleted +} + +// readBlock read block from dagnode +func (d *dagPoolService) readBlock(ctx context.Context, c cid.Cid) (blocks.Block, error) { + if d.state == StateFail { + return nil, ErrClusterAvailable + } + slot := keyHashSlot(c.String()) + if node := d.importingSlotsFrom[slot]; node != nil { + b, err := node.Get(ctx, c) + if err == nil { + return b, nil + } + } + b, err := d.slots[slot].Get(ctx, c) + if err != nil { + if format.IsNotFound(err) { + return nil, err + } + return nil, fmt.Errorf("failed to get block for %s: %v", c, err) + } + return b, nil +} + +// readBlockSize read block size from dagnode +func (d *dagPoolService) readBlockSize(ctx context.Context, c cid.Cid) (int, error) { + if d.state == StateFail { + return 0, ErrClusterAvailable + } + slot := keyHashSlot(c.String()) + if node := d.importingSlotsFrom[slot]; node != nil { + size, err := node.GetSize(ctx, c) + if err == nil { + return size, nil + } + } + return d.slots[slot].GetSize(ctx, c) +} + +// putBlock put block to dagnode +func (d *dagPoolService) putBlock(ctx context.Context, block blocks.Block) error { + if d.state == StateFail { + return ErrClusterAvailable + } + blkCid := block.Cid() + slot := keyHashSlot(blkCid.String()) + selNode := d.slots[slot] + if err := selNode.Put(ctx, block); err != nil { + return err + } + + if err := d.slotKeyRepo.Set(slot, blkCid.String(), selNode.GetConfig().Name); err != nil { + // rollback + if delerr := selNode.DeleteBlock(ctx, blkCid); delerr != nil { + log.Errorw("rollback block error", "slot", slot, "cid", blkCid, "error", delerr) + } + + return err + } + return nil +} + +// deleteBlock delete block from dagnode +func (d *dagPoolService) deleteBlock(ctx context.Context, c cid.Cid) error { + if d.state == StateFail { + return ErrClusterAvailable + } + slot := keyHashSlot(c.String()) + if err := d.slotKeyRepo.Remove(slot, c.String()); err != nil { + return err + } + + selNode := d.slots[slot] + if err := selNode.DeleteBlock(ctx, c); err != nil { + // rollback + if dberr := d.slotKeyRepo.Set(slot, c.String(), selNode.GetConfig().Name); dberr != nil { + log.Errorw("rollback slot entry error", "slot", slot, "cid", c, "error", dberr) + return nil + } + return err + } + return nil +} diff --git a/dag/pool/poolservice/mul_node.go b/dag/pool/poolservice/mul_node.go deleted file mode 100644 index f21633af..00000000 --- a/dag/pool/poolservice/mul_node.go +++ /dev/null @@ -1,65 +0,0 @@ -package poolservice - -import ( - "context" - "github.com/filedag-project/filedag-storage/dag/node/dagnode" - "github.com/ipfs/go-cid" -) - -// getDagNodeInfo get the DagNode -func (d *dagPoolService) getDagNodeInfo(ctx context.Context, c cid.Cid) (*dagnode.DagNode, error) { - //todo mul node - get, err := d.nrSys.Get(c.String()) - if err != nil { - return nil, err - } - return d.dagNodes[get], nil -} - -// choseDagNode chose the DagNode for the Cid -func (d *dagPoolService) choseDagNode(ctx context.Context, c cid.Cid) (*dagnode.DagNode, error) { - //todo mul node - dn := d.nrSys.GetCanUseNode() - err := d.nrSys.Add(c.String(), dn) - if err != nil { - return nil, err - } - return d.dagNodes[dn], nil -} - -// getNodeUseIP get the DagNode -func (d *dagPoolService) getNodeUseIP(ctx context.Context, ip string) (*dagnode.DagNode, error) { - //todo mul node - get, err := d.nrSys.GetNameUseIp(ip) - if err != nil { - return nil, err - } - return d.dagNodes[get], nil -} - -// -//// GetNodes get the DagNode -//func (d *Pool) GetNodes(ctx context.Context, cids []cid.Cid) map[*node.DagNode][]cid.Cid { -// //todo mul node -// // -// m := make(map[*node.DagNode][]cid.Cid) -// for _, c := range cids { -// get, err := d.NRSys.Get(c.String()) -// if err != nil { -// return nil -// } -// m[d.DagNodes[get]] = append(m[d.DagNodes[get]], c) -// } -// return m -//} -// -//// UseNodes get the DagNode -//func (d *Pool) UseNodes(ctx context.Context, c []cid.Cid) *node.DagNode { -// //todo mul node -// dn := d.NRSys.GetCanUseNode() -// err := d.NRSys.Add(c[0].String(), dn) -// if err != nil { -// return nil -// } -// return d.DagNodes[dn] -//} diff --git a/dag/pool/poolservice/pin_ref_test.go b/dag/pool/poolservice/pin_ref_test.go index c508516f..148da45e 100644 --- a/dag/pool/poolservice/pin_ref_test.go +++ b/dag/pool/poolservice/pin_ref_test.go @@ -153,39 +153,36 @@ func startTestDagPoolServer(t *testing.T) *dagPoolService { go datanode.StartDataNodeServer(":9023", datanode.KVBadge, t.TempDir()) time.Sleep(time.Second) var ( - dagdc = []config.DataNodeConfig{ - { - Ip: "127.0.0.1", - Port: "9021", - }, - { - Ip: "127.0.0.1", - Port: "9022", - }, - { - Ip: "127.0.0.1", - Port: "9023", - }, + dagdc = []string{ + "127.0.0.1:9021", + "127.0.0.1:9022", + "127.0.0.1:9023", } - dagc = []config.DagNodeConfig{ - { - Nodes: dagdc, - DataBlocks: 2, - ParityBlocks: 1, - }, + dagc = config.DagNodeConfig{ + Name: "dagnode1", + Nodes: dagdc, + DataBlocks: 2, + ParityBlocks: 1, } cfg = config.PoolConfig{ - Listen: "127.0.0.1:50002", - DagNodeConfig: dagc, - LeveldbPath: t.TempDir(), - RootUser: user, - RootPassword: pass, - GcPeriod: time.Second * 5, + Listen: "127.0.0.1:50002", + LeveldbPath: t.TempDir(), + RootUser: user, + RootPassword: pass, + GcPeriod: time.Second * 5, } ) - service, err := NewDagPoolService(cfg) + service, err := NewDagPoolService(context.TODO(), cfg) if err != nil { t.Fatalf("NewDagPoolService err:%v", err) } + err = service.AddDagNode(&dagc) + if err != nil { + t.Fatalf("AddDagNode err:%v", err) + } + err = service.BalanceSlots() + if err != nil { + t.Fatalf("BalanceSlots err:%v", err) + } return service } diff --git a/dag/pool/poolservice/pool.go b/dag/pool/poolservice/pool.go index 26dc2013..2425ef01 100644 --- a/dag/pool/poolservice/pool.go +++ b/dag/pool/poolservice/pool.go @@ -2,20 +2,22 @@ package poolservice import ( "context" - "fmt" "github.com/filedag-project/filedag-storage/dag/config" "github.com/filedag-project/filedag-storage/dag/node/dagnode" "github.com/filedag-project/filedag-storage/dag/pool" - "github.com/filedag-project/filedag-storage/dag/pool/poolservice/dnm" "github.com/filedag-project/filedag-storage/dag/pool/poolservice/dpuser" "github.com/filedag-project/filedag-storage/dag/pool/poolservice/dpuser/upolicy" "github.com/filedag-project/filedag-storage/dag/pool/poolservice/reference" + "github.com/filedag-project/filedag-storage/dag/pool/poolservice/slotkeyrepo" + "github.com/filedag-project/filedag-storage/dag/pool/poolservice/slotmigraterepo" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" "github.com/filedag-project/filedag-storage/objectservice/uleveldb" blocks "github.com/ipfs/go-block-format" "github.com/ipfs/go-cid" format "github.com/ipfs/go-ipld-format" logging "github.com/ipfs/go-log/v2" "golang.org/x/xerrors" + "sync" "time" ) @@ -23,22 +25,53 @@ var log = logging.Logger("dag-pool") var _ pool.DagPool = &dagPoolService{} +type ClusterState int + +func (cs ClusterState) String() string { + switch cs { + case StateOk: + return "ok" + case StateFail: + return "fail" + case StateMigrating: + return "migrating" + default: + return "unknown" + } +} + +const ( + StateOk ClusterState = iota + StateMigrating + StateFail +) + // dagPoolService is an IPFS Merkle DAG service. type dagPoolService struct { - dagNodes map[string]*dagnode.DagNode - iam *dpuser.IdentityUserSys - nrSys *dnm.NodeRecordSys - db *uleveldb.ULevelDB + slots [slotsmgr.ClusterSlots]*dagnode.DagNode + importingSlotsFrom [slotsmgr.ClusterSlots]*dagnode.DagNode + + dagNodesMap map[string]*dagnode.DagNode + dagNodesLock sync.RWMutex + + state ClusterState + parentCtx context.Context + migratingCh chan struct{} - refCounter *reference.RefCounter - cacheSet *reference.CacheSet + iam *dpuser.IdentityUserSys + db *uleveldb.ULevelDB + + refCounter *reference.RefCounter + cacheSet *reference.CacheSet + slotKeyRepo *slotkeyrepo.SlotKeyRepo + slotMigrateRepo *slotmigraterepo.SlotMigrateRepo gcControl *GcControl gcPeriod time.Duration } // NewDagPoolService constructs a new DAGPool (using the default implementation). -func NewDagPoolService(cfg config.PoolConfig) (*dagPoolService, error) { +func NewDagPoolService(ctx context.Context, cfg config.PoolConfig) (*dagPoolService, error) { db, err := uleveldb.OpenDb(cfg.LeveldbPath) if err != nil { return nil, err @@ -49,31 +82,28 @@ func NewDagPoolService(cfg config.PoolConfig) (*dagPoolService, error) { } cacheSet := reference.NewCacheSet(db) refCounter := reference.NewRefCounter(db, cacheSet) - dn := make(map[string]*dagnode.DagNode) - var nrs = dnm.NewRecordSys(db) - for num, c := range cfg.DagNodeConfig { - bs, err := dagnode.NewDagNode(c) - if err != nil { - log.Errorf("new dagnode err:%v", err) - return nil, err - } - name := "the" + fmt.Sprintf("%v", num) - err = nrs.HandleDagNode(bs.Nodes, name) - if err != nil { - return nil, err - } - dn[name] = bs - } - return &dagPoolService{ - dagNodes: dn, - iam: i, - nrSys: nrs, - db: db, - refCounter: refCounter, - cacheSet: cacheSet, - gcControl: NewGcControl(), - gcPeriod: cfg.GcPeriod, - }, nil + + serv := &dagPoolService{ + dagNodesMap: make(map[string]*dagnode.DagNode), + parentCtx: ctx, + migratingCh: make(chan struct{}), + iam: i, + db: db, + refCounter: refCounter, + cacheSet: cacheSet, + slotKeyRepo: slotkeyrepo.NewSlotKeyRepo(db), + slotMigrateRepo: slotmigraterepo.NewSlotMigrateRepo(db), + gcControl: NewGcControl(), + gcPeriod: cfg.GcPeriod, + } + // process migrating task + go serv.migrateSlotsDataTask(ctx) + + if err = serv.clusterInit(); err != nil { + return nil, err + } + + return serv, nil } // Add adds a node to the dagPoolService, storing the block in the BlockService @@ -84,11 +114,7 @@ func (d *dagPoolService) Add(ctx context.Context, block blocks.Block, user strin key := block.Cid().String() addBlock := func() error { - selNode, err := d.choseDagNode(ctx, block.Cid()) - if err != nil { - return err - } - return selNode.Put(ctx, block) + return d.putBlock(ctx, block) } if pin { @@ -121,19 +147,7 @@ func (d *dagPoolService) Get(ctx context.Context, c cid.Cid, user string, passwo return nil, format.ErrNotFound{Cid: c} } - getNode, err := d.getDagNodeInfo(ctx, c) - if err != nil { - return nil, err - } - b, err := getNode.Get(ctx, c) - if err != nil { - if format.IsNotFound(err) { - return nil, err - } - return nil, fmt.Errorf("failed to get block for %s: %v", c, err) - } - - return b, nil + return d.readBlock(ctx, c) } //Remove remove block from DAGPool @@ -163,11 +177,7 @@ func (d *dagPoolService) GetSize(ctx context.Context, c cid.Cid, user string, pa ctx, cancel := context.WithCancel(ctx) defer cancel() - getNode, err := d.getDagNodeInfo(ctx, c) - if err != nil { - return 0, err - } - return getNode.GetSize(ctx, c) + return d.readBlockSize(ctx, c) } //AddUser add a user @@ -240,6 +250,15 @@ func (d *dagPoolService) UpdateUser(uUser dpuser.DagPoolUser, user string, passw //Close the dagPoolService func (d *dagPoolService) Close() error { + func() { + d.dagNodesLock.RLock() + defer d.dagNodesLock.RUnlock() + + for _, node := range d.dagNodesMap { + node.Close() + } + }() + close(d.migratingCh) return d.db.Close() } diff --git a/dag/pool/poolservice/repair.go b/dag/pool/poolservice/repair.go new file mode 100644 index 00000000..1ddacc6f --- /dev/null +++ b/dag/pool/poolservice/repair.go @@ -0,0 +1,20 @@ +package poolservice + +import ( + "context" + "github.com/filedag-project/filedag-storage/dag/node/dagnode" +) + +func (d *dagPoolService) RepairDataNode(ctx context.Context, dagNodeName string, fromNodeIndex int, repairNodeIndex int) error { + node, ok := func() (*dagnode.DagNode, bool) { + d.dagNodesLock.RLock() + defer d.dagNodesLock.RUnlock() + nd, ok := d.dagNodesMap[dagNodeName] + return nd, ok + }() + if !ok { + return ErrDagNodeNotFound + } + + return node.RepairDataNode(ctx, fromNodeIndex, repairNodeIndex) +} diff --git a/dag/pool/poolservice/slotkeyrepo/slot_key_repo.go b/dag/pool/poolservice/slotkeyrepo/slot_key_repo.go new file mode 100644 index 00000000..bef1d4a8 --- /dev/null +++ b/dag/pool/poolservice/slotkeyrepo/slot_key_repo.go @@ -0,0 +1,87 @@ +package slotkeyrepo + +import ( + "context" + "fmt" + "github.com/filedag-project/filedag-storage/objectservice/uleveldb" + "github.com/syndtr/goleveldb/leveldb" + "strings" +) + +const SlotPrefix = "slot/" + +// SlotKeyRepo saves information about the slot and cid key mapping. +type SlotKeyRepo struct { + db *uleveldb.ULevelDB +} + +func NewSlotKeyRepo(db *uleveldb.ULevelDB) *SlotKeyRepo { + return &SlotKeyRepo{db: db} +} + +func (s *SlotKeyRepo) Set(slot uint16, key string, value string) error { + return s.db.Put(fmt.Sprintf("%s%v/%s", SlotPrefix, slot, key), value) +} + +func (s *SlotKeyRepo) Get(slot uint16, key string) (value string, err error) { + err = s.db.Get(fmt.Sprintf("%s%v/%s", SlotPrefix, slot, key), &value) + return value, err +} + +func (s *SlotKeyRepo) Has(slot uint16, key string) (bool, error) { + var val string + err := s.db.Get(fmt.Sprintf("%s%v/%s", SlotPrefix, slot, key), &val) + if err != nil { + if err == leveldb.ErrNotFound { + return false, nil + } + return false, err + } + return true, nil +} + +func (s *SlotKeyRepo) Remove(slot uint16, key string) error { + return s.db.Delete(fmt.Sprintf("%s%v/%s", SlotPrefix, slot, key)) +} + +type SlotKeyEntry struct { + Slot uint16 + Key string + Value string +} + +func (s *SlotKeyRepo) AllKeysChan(ctx context.Context, slot uint16, seekSlotKey string) (<-chan *SlotKeyEntry, error) { + prefix := fmt.Sprintf("%s%v/", SlotPrefix, slot) + if seekSlotKey != "" { + seekSlotKey = fmt.Sprintf("%s%v/%s", SlotPrefix, slot, seekSlotKey) + } + all, err := s.db.ReadAllChan(ctx, prefix, seekSlotKey) + if err != nil { + return nil, err + } + kc := make(chan *SlotKeyEntry) + go func() { + defer close(kc) + for entry := range all { + strs := strings.Split(entry.Key, "/") + if len(strs) < 3 { + return + } + var val string + if err = entry.UnmarshalValue(&val); err != nil { + return + } + select { + case <-ctx.Done(): + return + case kc <- &SlotKeyEntry{ + Slot: slot, + Key: strs[2], + Value: val, + }: + } + } + }() + + return kc, nil +} diff --git a/dag/pool/poolservice/slotmigraterepo/slot_migrate_repo.go b/dag/pool/poolservice/slotmigraterepo/slot_migrate_repo.go new file mode 100644 index 00000000..b5c94cd6 --- /dev/null +++ b/dag/pool/poolservice/slotmigraterepo/slot_migrate_repo.go @@ -0,0 +1,86 @@ +package slotmigraterepo + +import ( + "context" + "fmt" + "github.com/filedag-project/filedag-storage/objectservice/uleveldb" + "github.com/syndtr/goleveldb/leveldb" + "strconv" + "strings" +) + +const SlotMigratePrefix = "migrate/" + +// SlotMigrateRepo saves information about the slot to be transferred. +type SlotMigrateRepo struct { + db *uleveldb.ULevelDB +} + +func NewSlotMigrateRepo(db *uleveldb.ULevelDB) *SlotMigrateRepo { + return &SlotMigrateRepo{db: db} +} + +func (s *SlotMigrateRepo) Set(slot uint16, value string) error { + return s.db.Put(fmt.Sprintf("%s%v", SlotMigratePrefix, slot), value) +} + +func (s *SlotMigrateRepo) Get(slot uint16) (value string, err error) { + err = s.db.Get(fmt.Sprintf("%s%v", SlotMigratePrefix, slot), &value) + return value, err +} + +func (s *SlotMigrateRepo) Has(slot uint16) (bool, error) { + var val string + err := s.db.Get(fmt.Sprintf("%s%v", SlotMigratePrefix, slot), &val) + if err != nil { + if err == leveldb.ErrNotFound { + return false, nil + } + return false, err + } + return true, nil +} + +func (s *SlotMigrateRepo) Remove(slot uint16) error { + return s.db.Delete(fmt.Sprintf("%s%v", SlotMigratePrefix, slot)) +} + +type Entry struct { + Slot uint16 + Value string +} + +func (s *SlotMigrateRepo) AllKeysChan(ctx context.Context) (<-chan *Entry, error) { + all, err := s.db.ReadAllChan(ctx, SlotMigratePrefix, "") + if err != nil { + return nil, err + } + kc := make(chan *Entry) + go func() { + defer close(kc) + for entry := range all { + strs := strings.Split(entry.Key, "/") + if len(strs) < 2 { + return + } + slot, err := strconv.ParseUint(strs[1], 10, 32) + if err != nil { + return + } + var val string + if err = entry.UnmarshalValue(&val); err != nil { + return + } + select { + case <-ctx.Done(): + return + case kc <- &Entry{ + Slot: uint16(slot), + Value: val, + }: + } + } + }() + + return kc, nil +} diff --git a/dag/pool/poolservice/status.go b/dag/pool/poolservice/status.go new file mode 100644 index 00000000..4b5b60fd --- /dev/null +++ b/dag/pool/poolservice/status.go @@ -0,0 +1,5 @@ +package poolservice + +func (d *dagPoolService) genStatusDescription() string { + return "not implemented" +} diff --git a/dag/pool/server/dagpool_cluster_server.go b/dag/pool/server/dagpool_cluster_server.go new file mode 100644 index 00000000..eea8bcec --- /dev/null +++ b/dag/pool/server/dagpool_cluster_server.go @@ -0,0 +1,73 @@ +package server + +import ( + "context" + "github.com/filedag-project/filedag-storage/dag/pool" + "github.com/filedag-project/filedag-storage/dag/proto" + "github.com/filedag-project/filedag-storage/dag/utils" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/emptypb" +) + +// DagPoolClusterServer is used to implement DagPoolClusterServer. +type DagPoolClusterServer struct { + proto.UnimplementedDagPoolClusterServer + Cluster pool.Cluster +} + +func (s *DagPoolClusterServer) AddDagNode(ctx context.Context, node *proto.DagNodeInfo) (*emptypb.Empty, error) { + cfg := utils.ToDagNodeConfig(node) + if err := s.Cluster.AddDagNode(cfg); err != nil { + return nil, status.Errorf(codes.Unknown, err.Error()) + } + return &emptypb.Empty{}, nil +} + +func (s *DagPoolClusterServer) GetDagNode(ctx context.Context, req *proto.GetDagNodeReq) (*proto.DagNodeInfo, error) { + node, err := s.Cluster.GetDagNode(req.Name) + if err != nil { + return nil, status.Errorf(codes.Unknown, err.Error()) + } + + return utils.ToProtoDagNodeInfo(node), nil +} + +func (s *DagPoolClusterServer) RemoveDagNode(ctx context.Context, req *proto.RemoveDagNodeReq) (*proto.DagNodeInfo, error) { + node, err := s.Cluster.RemoveDagNode(req.Name) + if err != nil { + return nil, status.Errorf(codes.Unknown, err.Error()) + } + + return utils.ToProtoDagNodeInfo(node), nil +} + +func (s *DagPoolClusterServer) MigrateSlots(ctx context.Context, req *proto.MigrateSlotsReq) (*emptypb.Empty, error) { + newPairs := utils.ToSlotPairs(req.Pairs) + if err := s.Cluster.MigrateSlots(req.FromDagNodeName, req.ToDagNodeName, newPairs); err != nil { + return nil, status.Errorf(codes.Unknown, err.Error()) + } + return &emptypb.Empty{}, nil +} + +func (s *DagPoolClusterServer) BalanceSlots(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { + if err := s.Cluster.BalanceSlots(); err != nil { + return nil, status.Errorf(codes.Unknown, err.Error()) + } + return &emptypb.Empty{}, nil +} + +func (s *DagPoolClusterServer) Status(context.Context, *emptypb.Empty) (*proto.StatusReply, error) { + st, err := s.Cluster.Status() + if err != nil { + return nil, status.Errorf(codes.Unknown, err.Error()) + } + return st, nil +} + +func (s *DagPoolClusterServer) RepairDataNode(ctx context.Context, req *proto.RepairDataNodeReq) (*emptypb.Empty, error) { + if err := s.Cluster.RepairDataNode(ctx, req.DagNodeName, int(req.FromNodeIndex), int(req.RepairNodeIndex)); err != nil { + return nil, status.Errorf(codes.Unknown, err.Error()) + } + return &emptypb.Empty{}, nil +} diff --git a/dag/proto/dagpool.pb.go b/dag/proto/dagpool.pb.go index 2b6b6a3f..702fe2ab 100644 --- a/dag/proto/dagpool.pb.go +++ b/dag/proto/dagpool.pb.go @@ -9,6 +9,7 @@ package proto import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" + emptypb "google.golang.org/protobuf/types/known/emptypb" reflect "reflect" sync "sync" ) @@ -971,89 +972,653 @@ func (x *UpdateUserReply) GetMessage() string { return "" } +type DataNodeInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RpcAddress string `protobuf:"bytes,1,opt,name=rpcAddress,proto3" json:"rpcAddress,omitempty"` + State *bool `protobuf:"varint,2,opt,name=state,proto3,oneof" json:"state,omitempty"` +} + +func (x *DataNodeInfo) Reset() { + *x = DataNodeInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DataNodeInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DataNodeInfo) ProtoMessage() {} + +func (x *DataNodeInfo) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DataNodeInfo.ProtoReflect.Descriptor instead. +func (*DataNodeInfo) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{17} +} + +func (x *DataNodeInfo) GetRpcAddress() string { + if x != nil { + return x.RpcAddress + } + return "" +} + +func (x *DataNodeInfo) GetState() bool { + if x != nil && x.State != nil { + return *x.State + } + return false +} + +type DagNodeInfo struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Nodes []*DataNodeInfo `protobuf:"bytes,2,rep,name=nodes,proto3" json:"nodes,omitempty"` + DataBlocks int32 `protobuf:"varint,3,opt,name=dataBlocks,proto3" json:"dataBlocks,omitempty"` + ParityBlocks int32 `protobuf:"varint,4,opt,name=parityBlocks,proto3" json:"parityBlocks,omitempty"` +} + +func (x *DagNodeInfo) Reset() { + *x = DagNodeInfo{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DagNodeInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DagNodeInfo) ProtoMessage() {} + +func (x *DagNodeInfo) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DagNodeInfo.ProtoReflect.Descriptor instead. +func (*DagNodeInfo) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{18} +} + +func (x *DagNodeInfo) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *DagNodeInfo) GetNodes() []*DataNodeInfo { + if x != nil { + return x.Nodes + } + return nil +} + +func (x *DagNodeInfo) GetDataBlocks() int32 { + if x != nil { + return x.DataBlocks + } + return 0 +} + +func (x *DagNodeInfo) GetParityBlocks() int32 { + if x != nil { + return x.ParityBlocks + } + return 0 +} + +type GetDagNodeReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *GetDagNodeReq) Reset() { + *x = GetDagNodeReq{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetDagNodeReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetDagNodeReq) ProtoMessage() {} + +func (x *GetDagNodeReq) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetDagNodeReq.ProtoReflect.Descriptor instead. +func (*GetDagNodeReq) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{19} +} + +func (x *GetDagNodeReq) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type RemoveDagNodeReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *RemoveDagNodeReq) Reset() { + *x = RemoveDagNodeReq{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RemoveDagNodeReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RemoveDagNodeReq) ProtoMessage() {} + +func (x *RemoveDagNodeReq) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RemoveDagNodeReq.ProtoReflect.Descriptor instead. +func (*RemoveDagNodeReq) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{20} +} + +func (x *RemoveDagNodeReq) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type SlotPair struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Start uint32 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"` + End uint32 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"` +} + +func (x *SlotPair) Reset() { + *x = SlotPair{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SlotPair) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SlotPair) ProtoMessage() {} + +func (x *SlotPair) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SlotPair.ProtoReflect.Descriptor instead. +func (*SlotPair) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{21} +} + +func (x *SlotPair) GetStart() uint32 { + if x != nil { + return x.Start + } + return 0 +} + +func (x *SlotPair) GetEnd() uint32 { + if x != nil { + return x.End + } + return 0 +} + +type MigrateSlotsReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + FromDagNodeName string `protobuf:"bytes,1,opt,name=fromDagNodeName,proto3" json:"fromDagNodeName,omitempty"` + ToDagNodeName string `protobuf:"bytes,2,opt,name=toDagNodeName,proto3" json:"toDagNodeName,omitempty"` + Pairs []*SlotPair `protobuf:"bytes,3,rep,name=pairs,proto3" json:"pairs,omitempty"` +} + +func (x *MigrateSlotsReq) Reset() { + *x = MigrateSlotsReq{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MigrateSlotsReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MigrateSlotsReq) ProtoMessage() {} + +func (x *MigrateSlotsReq) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MigrateSlotsReq.ProtoReflect.Descriptor instead. +func (*MigrateSlotsReq) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{22} +} + +func (x *MigrateSlotsReq) GetFromDagNodeName() string { + if x != nil { + return x.FromDagNodeName + } + return "" +} + +func (x *MigrateSlotsReq) GetToDagNodeName() string { + if x != nil { + return x.ToDagNodeName + } + return "" +} + +func (x *MigrateSlotsReq) GetPairs() []*SlotPair { + if x != nil { + return x.Pairs + } + return nil +} + +type DagNodeStatus struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Node *DagNodeInfo `protobuf:"bytes,1,opt,name=node,proto3" json:"node,omitempty"` + Pairs []*SlotPair `protobuf:"bytes,2,rep,name=pairs,proto3" json:"pairs,omitempty"` +} + +func (x *DagNodeStatus) Reset() { + *x = DagNodeStatus{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DagNodeStatus) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DagNodeStatus) ProtoMessage() {} + +func (x *DagNodeStatus) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[23] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DagNodeStatus.ProtoReflect.Descriptor instead. +func (*DagNodeStatus) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{23} +} + +func (x *DagNodeStatus) GetNode() *DagNodeInfo { + if x != nil { + return x.Node + } + return nil +} + +func (x *DagNodeStatus) GetPairs() []*SlotPair { + if x != nil { + return x.Pairs + } + return nil +} + +type StatusReply struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + State string `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + Statuses []*DagNodeStatus `protobuf:"bytes,2,rep,name=statuses,proto3" json:"statuses,omitempty"` +} + +func (x *StatusReply) Reset() { + *x = StatusReply{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[24] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StatusReply) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StatusReply) ProtoMessage() {} + +func (x *StatusReply) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[24] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StatusReply.ProtoReflect.Descriptor instead. +func (*StatusReply) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{24} +} + +func (x *StatusReply) GetState() string { + if x != nil { + return x.State + } + return "" +} + +func (x *StatusReply) GetStatuses() []*DagNodeStatus { + if x != nil { + return x.Statuses + } + return nil +} + +type RepairDataNodeReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + DagNodeName string `protobuf:"bytes,1,opt,name=dagNodeName,proto3" json:"dagNodeName,omitempty"` + FromNodeIndex int32 `protobuf:"varint,2,opt,name=fromNodeIndex,proto3" json:"fromNodeIndex,omitempty"` + RepairNodeIndex int32 `protobuf:"varint,3,opt,name=repairNodeIndex,proto3" json:"repairNodeIndex,omitempty"` +} + +func (x *RepairDataNodeReq) Reset() { + *x = RepairDataNodeReq{} + if protoimpl.UnsafeEnabled { + mi := &file_dagpool_proto_msgTypes[25] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RepairDataNodeReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RepairDataNodeReq) ProtoMessage() {} + +func (x *RepairDataNodeReq) ProtoReflect() protoreflect.Message { + mi := &file_dagpool_proto_msgTypes[25] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RepairDataNodeReq.ProtoReflect.Descriptor instead. +func (*RepairDataNodeReq) Descriptor() ([]byte, []int) { + return file_dagpool_proto_rawDescGZIP(), []int{25} +} + +func (x *RepairDataNodeReq) GetDagNodeName() string { + if x != nil { + return x.DagNodeName + } + return "" +} + +func (x *RepairDataNodeReq) GetFromNodeIndex() int32 { + if x != nil { + return x.FromNodeIndex + } + return 0 +} + +func (x *RepairDataNodeReq) GetRepairNodeIndex() int32 { + if x != nil { + return x.RepairNodeIndex + } + return 0 +} + var File_dagpool_proto protoreflect.FileDescriptor var file_dagpool_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x64, 0x61, 0x67, 0x70, 0x6f, 0x6f, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x3a, 0x0a, 0x08, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, - 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x22, 0x55, 0x0a, 0x06, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, - 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6f, - 0x63, 0x6b, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x70, 0x69, 0x6e, 0x22, 0x1c, 0x0a, 0x08, 0x41, 0x64, 0x64, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x63, 0x69, 0x64, 0x22, 0x3f, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x71, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x63, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x20, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x43, 0x0a, 0x0a, 0x47, 0x65, - 0x74, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, - 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, - 0x22, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, - 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, - 0x69, 0x7a, 0x65, 0x22, 0x58, 0x0a, 0x09, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, - 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, - 0x69, 0x64, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0x3a, 0x0a, 0x08, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, + 0x55, 0x0a, 0x06, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, + 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x12, + 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, + 0x75, 0x73, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x03, 0x70, 0x69, 0x6e, 0x22, 0x1c, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x63, 0x69, 0x64, 0x22, 0x3f, 0x0a, 0x06, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x12, 0x10, + 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x69, 0x64, + 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x20, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x05, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x43, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x53, 0x69, + 0x7a, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x63, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, + 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x22, 0x0a, 0x0c, + 0x47, 0x65, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x12, 0x0a, 0x04, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, + 0x22, 0x58, 0x0a, 0x09, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, + 0x03, 0x63, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x69, 0x64, 0x12, + 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, + 0x75, 0x73, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x6e, 0x70, 0x69, 0x6e, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x05, 0x75, 0x6e, 0x70, 0x69, 0x6e, 0x22, 0x27, 0x0a, 0x0b, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x75, 0x6e, 0x70, 0x69, 0x6e, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x75, 0x6e, 0x70, 0x69, 0x6e, 0x22, 0x27, 0x0a, - 0x0b, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x9d, 0x01, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, - 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, - 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, - 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x63, 0x61, - 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x22, 0x28, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x50, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, + 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, + 0x69, 0x74, 0x79, 0x22, 0x28, 0x0a, 0x0c, 0x41, 0x64, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x50, 0x0a, + 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x23, + 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, + 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x2b, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4f, 0x0a, 0x0c, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x23, 0x0a, 0x04, + 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, + 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x60, 0x0a, + 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, + 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x22, + 0xb2, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, - 0x6d, 0x65, 0x22, 0x2b, 0x0a, 0x0f, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x4f, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, - 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, - 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, - 0x22, 0x60, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, - 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, - 0x74, 0x79, 0x22, 0xb2, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x12, 0x23, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x6f, 0x6f, 0x6c, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, - 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x77, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x43, 0x61, 0x70, 0x61, - 0x63, 0x69, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x43, - 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x22, 0x2b, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x32, 0xae, 0x03, 0x0a, 0x07, 0x44, 0x61, 0x67, 0x50, 0x6f, 0x6f, 0x6c, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, + 0x77, 0x6f, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6e, 0x65, 0x77, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x6e, 0x65, 0x77, 0x43, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, + 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6e, 0x65, 0x77, 0x43, 0x61, 0x70, 0x61, + 0x63, 0x69, 0x74, 0x79, 0x22, 0x2b, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, + 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x22, 0x53, 0x0a, 0x0c, 0x44, 0x61, 0x74, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x70, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x12, 0x19, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x00, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x88, 0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x22, 0x90, 0x01, 0x0a, 0x0b, 0x44, 0x61, 0x67, 0x4e, 0x6f, + 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x05, 0x6e, 0x6f, + 0x64, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, + 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x42, 0x6c, 0x6f, + 0x63, 0x6b, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x70, 0x61, 0x72, 0x69, 0x74, 0x79, 0x42, + 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x70, 0x61, 0x72, + 0x69, 0x74, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x22, 0x23, 0x0a, 0x0d, 0x47, 0x65, 0x74, + 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x26, + 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x32, 0x0a, 0x08, 0x53, 0x6c, 0x6f, 0x74, 0x50, 0x61, + 0x69, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x88, 0x01, 0x0a, 0x0f, 0x4d, + 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x12, 0x28, + 0x0a, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x66, 0x72, 0x6f, 0x6d, 0x44, 0x61, 0x67, + 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x74, 0x6f, 0x44, 0x61, + 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x74, 0x6f, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x25, + 0x0a, 0x05, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, + 0x70, 0x61, 0x69, 0x72, 0x73, 0x22, 0x5e, 0x0a, 0x0d, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x26, 0x0a, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x61, 0x67, + 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x04, 0x6e, 0x6f, 0x64, 0x65, 0x12, 0x25, + 0x0a, 0x05, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x50, 0x61, 0x69, 0x72, 0x52, 0x05, + 0x70, 0x61, 0x69, 0x72, 0x73, 0x22, 0x55, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x08, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x52, 0x08, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x65, 0x73, 0x22, 0x85, 0x01, 0x0a, + 0x11, 0x52, 0x65, 0x70, 0x61, 0x69, 0x72, 0x44, 0x61, 0x74, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x52, + 0x65, 0x71, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x66, 0x72, 0x6f, 0x6d, 0x4e, 0x6f, 0x64, 0x65, + 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x66, 0x72, 0x6f, + 0x6d, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, + 0x70, 0x61, 0x69, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0f, 0x72, 0x65, 0x70, 0x61, 0x69, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x49, + 0x6e, 0x64, 0x65, 0x78, 0x32, 0xae, 0x03, 0x0a, 0x07, 0x44, 0x61, 0x67, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x27, 0x0a, 0x03, 0x41, 0x64, 0x64, 0x12, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x65, 0x71, 0x1a, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x27, 0x0a, 0x03, 0x47, 0x65, 0x74, @@ -1080,8 +1645,37 @@ var file_dagpool_proto_rawDesc = []byte{ 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x6c, 0x79, 0x22, 0x00, 0x32, 0xc8, 0x03, 0x0a, 0x0e, 0x44, 0x61, 0x67, 0x50, 0x6f, 0x6f, + 0x6c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x44, + 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, + 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x44, 0x61, 0x67, 0x4e, 0x6f, + 0x64, 0x65, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x61, + 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x3e, + 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x12, + 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x44, 0x61, + 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x44, 0x61, 0x67, 0x4e, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x40, + 0x0a, 0x0c, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x73, 0x12, 0x16, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x69, 0x67, 0x72, 0x61, 0x74, 0x65, 0x53, 0x6c, + 0x6f, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, + 0x12, 0x40, 0x0a, 0x0c, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x6c, 0x6f, 0x74, 0x73, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x00, 0x12, 0x36, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0e, 0x52, 0x65, + 0x70, 0x61, 0x69, 0x72, 0x44, 0x61, 0x74, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x70, 0x61, 0x69, 0x72, 0x44, 0x61, 0x74, 0x61, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, + 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1096,25 +1690,35 @@ func file_dagpool_proto_rawDescGZIP() []byte { return file_dagpool_proto_rawDescData } -var file_dagpool_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_dagpool_proto_msgTypes = make([]protoimpl.MessageInfo, 26) var file_dagpool_proto_goTypes = []interface{}{ - (*PoolUser)(nil), // 0: proto.PoolUser - (*AddReq)(nil), // 1: proto.AddReq - (*AddReply)(nil), // 2: proto.AddReply - (*GetReq)(nil), // 3: proto.GetReq - (*GetReply)(nil), // 4: proto.GetReply - (*GetSizeReq)(nil), // 5: proto.GetSizeReq - (*GetSizeReply)(nil), // 6: proto.GetSizeReply - (*RemoveReq)(nil), // 7: proto.RemoveReq - (*RemoveReply)(nil), // 8: proto.RemoveReply - (*AddUserReq)(nil), // 9: proto.AddUserReq - (*AddUserReply)(nil), // 10: proto.AddUserReply - (*RemoveUserReq)(nil), // 11: proto.RemoveUserReq - (*RemoveUserReply)(nil), // 12: proto.RemoveUserReply - (*QueryUserReq)(nil), // 13: proto.QueryUserReq - (*QueryUserReply)(nil), // 14: proto.QueryUserReply - (*UpdateUserReq)(nil), // 15: proto.UpdateUserReq - (*UpdateUserReply)(nil), // 16: proto.UpdateUserReply + (*PoolUser)(nil), // 0: proto.PoolUser + (*AddReq)(nil), // 1: proto.AddReq + (*AddReply)(nil), // 2: proto.AddReply + (*GetReq)(nil), // 3: proto.GetReq + (*GetReply)(nil), // 4: proto.GetReply + (*GetSizeReq)(nil), // 5: proto.GetSizeReq + (*GetSizeReply)(nil), // 6: proto.GetSizeReply + (*RemoveReq)(nil), // 7: proto.RemoveReq + (*RemoveReply)(nil), // 8: proto.RemoveReply + (*AddUserReq)(nil), // 9: proto.AddUserReq + (*AddUserReply)(nil), // 10: proto.AddUserReply + (*RemoveUserReq)(nil), // 11: proto.RemoveUserReq + (*RemoveUserReply)(nil), // 12: proto.RemoveUserReply + (*QueryUserReq)(nil), // 13: proto.QueryUserReq + (*QueryUserReply)(nil), // 14: proto.QueryUserReply + (*UpdateUserReq)(nil), // 15: proto.UpdateUserReq + (*UpdateUserReply)(nil), // 16: proto.UpdateUserReply + (*DataNodeInfo)(nil), // 17: proto.DataNodeInfo + (*DagNodeInfo)(nil), // 18: proto.DagNodeInfo + (*GetDagNodeReq)(nil), // 19: proto.GetDagNodeReq + (*RemoveDagNodeReq)(nil), // 20: proto.RemoveDagNodeReq + (*SlotPair)(nil), // 21: proto.SlotPair + (*MigrateSlotsReq)(nil), // 22: proto.MigrateSlotsReq + (*DagNodeStatus)(nil), // 23: proto.DagNodeStatus + (*StatusReply)(nil), // 24: proto.StatusReply + (*RepairDataNodeReq)(nil), // 25: proto.RepairDataNodeReq + (*emptypb.Empty)(nil), // 26: google.protobuf.Empty } var file_dagpool_proto_depIdxs = []int32{ 0, // 0: proto.AddReq.user:type_name -> proto.PoolUser @@ -1125,27 +1729,46 @@ var file_dagpool_proto_depIdxs = []int32{ 0, // 5: proto.RemoveUserReq.user:type_name -> proto.PoolUser 0, // 6: proto.QueryUserReq.user:type_name -> proto.PoolUser 0, // 7: proto.UpdateUserReq.user:type_name -> proto.PoolUser - 1, // 8: proto.DagPool.Add:input_type -> proto.AddReq - 3, // 9: proto.DagPool.Get:input_type -> proto.GetReq - 7, // 10: proto.DagPool.Remove:input_type -> proto.RemoveReq - 5, // 11: proto.DagPool.GetSize:input_type -> proto.GetSizeReq - 9, // 12: proto.DagPool.AddUser:input_type -> proto.AddUserReq - 11, // 13: proto.DagPool.RemoveUser:input_type -> proto.RemoveUserReq - 13, // 14: proto.DagPool.QueryUser:input_type -> proto.QueryUserReq - 15, // 15: proto.DagPool.UpdateUser:input_type -> proto.UpdateUserReq - 2, // 16: proto.DagPool.Add:output_type -> proto.AddReply - 4, // 17: proto.DagPool.Get:output_type -> proto.GetReply - 8, // 18: proto.DagPool.Remove:output_type -> proto.RemoveReply - 6, // 19: proto.DagPool.GetSize:output_type -> proto.GetSizeReply - 10, // 20: proto.DagPool.AddUser:output_type -> proto.AddUserReply - 12, // 21: proto.DagPool.RemoveUser:output_type -> proto.RemoveUserReply - 14, // 22: proto.DagPool.QueryUser:output_type -> proto.QueryUserReply - 16, // 23: proto.DagPool.UpdateUser:output_type -> proto.UpdateUserReply - 16, // [16:24] is the sub-list for method output_type - 8, // [8:16] is the sub-list for method input_type - 8, // [8:8] is the sub-list for extension type_name - 8, // [8:8] is the sub-list for extension extendee - 0, // [0:8] is the sub-list for field type_name + 17, // 8: proto.DagNodeInfo.nodes:type_name -> proto.DataNodeInfo + 21, // 9: proto.MigrateSlotsReq.pairs:type_name -> proto.SlotPair + 18, // 10: proto.DagNodeStatus.node:type_name -> proto.DagNodeInfo + 21, // 11: proto.DagNodeStatus.pairs:type_name -> proto.SlotPair + 23, // 12: proto.StatusReply.statuses:type_name -> proto.DagNodeStatus + 1, // 13: proto.DagPool.Add:input_type -> proto.AddReq + 3, // 14: proto.DagPool.Get:input_type -> proto.GetReq + 7, // 15: proto.DagPool.Remove:input_type -> proto.RemoveReq + 5, // 16: proto.DagPool.GetSize:input_type -> proto.GetSizeReq + 9, // 17: proto.DagPool.AddUser:input_type -> proto.AddUserReq + 11, // 18: proto.DagPool.RemoveUser:input_type -> proto.RemoveUserReq + 13, // 19: proto.DagPool.QueryUser:input_type -> proto.QueryUserReq + 15, // 20: proto.DagPool.UpdateUser:input_type -> proto.UpdateUserReq + 18, // 21: proto.DagPoolCluster.AddDagNode:input_type -> proto.DagNodeInfo + 19, // 22: proto.DagPoolCluster.GetDagNode:input_type -> proto.GetDagNodeReq + 20, // 23: proto.DagPoolCluster.RemoveDagNode:input_type -> proto.RemoveDagNodeReq + 22, // 24: proto.DagPoolCluster.MigrateSlots:input_type -> proto.MigrateSlotsReq + 26, // 25: proto.DagPoolCluster.BalanceSlots:input_type -> google.protobuf.Empty + 26, // 26: proto.DagPoolCluster.Status:input_type -> google.protobuf.Empty + 25, // 27: proto.DagPoolCluster.RepairDataNode:input_type -> proto.RepairDataNodeReq + 2, // 28: proto.DagPool.Add:output_type -> proto.AddReply + 4, // 29: proto.DagPool.Get:output_type -> proto.GetReply + 8, // 30: proto.DagPool.Remove:output_type -> proto.RemoveReply + 6, // 31: proto.DagPool.GetSize:output_type -> proto.GetSizeReply + 10, // 32: proto.DagPool.AddUser:output_type -> proto.AddUserReply + 12, // 33: proto.DagPool.RemoveUser:output_type -> proto.RemoveUserReply + 14, // 34: proto.DagPool.QueryUser:output_type -> proto.QueryUserReply + 16, // 35: proto.DagPool.UpdateUser:output_type -> proto.UpdateUserReply + 26, // 36: proto.DagPoolCluster.AddDagNode:output_type -> google.protobuf.Empty + 18, // 37: proto.DagPoolCluster.GetDagNode:output_type -> proto.DagNodeInfo + 18, // 38: proto.DagPoolCluster.RemoveDagNode:output_type -> proto.DagNodeInfo + 26, // 39: proto.DagPoolCluster.MigrateSlots:output_type -> google.protobuf.Empty + 26, // 40: proto.DagPoolCluster.BalanceSlots:output_type -> google.protobuf.Empty + 24, // 41: proto.DagPoolCluster.Status:output_type -> proto.StatusReply + 26, // 42: proto.DagPoolCluster.RepairDataNode:output_type -> google.protobuf.Empty + 28, // [28:43] is the sub-list for method output_type + 13, // [13:28] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_dagpool_proto_init() } @@ -1358,16 +1981,125 @@ func file_dagpool_proto_init() { return nil } } + file_dagpool_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DataNodeInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DagNodeInfo); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetDagNodeReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RemoveDagNodeReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SlotPair); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MigrateSlotsReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DagNodeStatus); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StatusReply); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_dagpool_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RepairDataNodeReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } + file_dagpool_proto_msgTypes[17].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_dagpool_proto_rawDesc, NumEnums: 0, - NumMessages: 17, + NumMessages: 26, NumExtensions: 0, - NumServices: 1, + NumServices: 2, }, GoTypes: file_dagpool_proto_goTypes, DependencyIndexes: file_dagpool_proto_depIdxs, diff --git a/dag/proto/dagpool.proto b/dag/proto/dagpool.proto index 2401fceb..664ddc0e 100644 --- a/dag/proto/dagpool.proto +++ b/dag/proto/dagpool.proto @@ -1,5 +1,7 @@ syntax = "proto3"; +import "google/protobuf/empty.proto"; + package proto; option go_package = '../proto'; @@ -101,3 +103,61 @@ message UpdateUserReq{ message UpdateUserReply { string message = 1; } + + +service DagPoolCluster { + rpc AddDagNode (DagNodeInfo) returns (google.protobuf.Empty) {} + rpc GetDagNode (GetDagNodeReq) returns (DagNodeInfo) {} + rpc RemoveDagNode (RemoveDagNodeReq) returns (DagNodeInfo) {} + rpc MigrateSlots (MigrateSlotsReq) returns (google.protobuf.Empty) {} + rpc BalanceSlots (google.protobuf.Empty) returns (google.protobuf.Empty) {} + rpc Status (google.protobuf.Empty) returns (StatusReply) {} + rpc RepairDataNode (RepairDataNodeReq) returns (google.protobuf.Empty) {} +} + +message DataNodeInfo { + string rpcAddress = 1; + optional bool state = 2; +} + +message DagNodeInfo { + string name = 1; + repeated DataNodeInfo nodes = 2; + int32 dataBlocks = 3; + int32 parityBlocks = 4; +} + +message GetDagNodeReq { + string name = 1; +} + +message RemoveDagNodeReq { + string name = 1; +} + +message SlotPair { + uint32 start = 1; + uint32 end = 2; +} + +message MigrateSlotsReq { + string fromDagNodeName = 1; + string toDagNodeName = 2; + repeated SlotPair pairs = 3; +} + +message DagNodeStatus { + DagNodeInfo node = 1; + repeated SlotPair pairs = 2; +} + +message StatusReply { + string state = 1; + repeated DagNodeStatus statuses = 2; +} + +message RepairDataNodeReq { + string dagNodeName = 1; + int32 fromNodeIndex = 2; + int32 repairNodeIndex = 3; +} diff --git a/dag/proto/dagpool_grpc.pb.go b/dag/proto/dagpool_grpc.pb.go index 0de391c8..26251e79 100644 --- a/dag/proto/dagpool_grpc.pb.go +++ b/dag/proto/dagpool_grpc.pb.go @@ -11,6 +11,7 @@ import ( grpc "google.golang.org/grpc" codes "google.golang.org/grpc/codes" status "google.golang.org/grpc/status" + emptypb "google.golang.org/protobuf/types/known/emptypb" ) // This is a compile-time assertion to ensure that this generated file @@ -355,3 +356,305 @@ var DagPool_ServiceDesc = grpc.ServiceDesc{ Streams: []grpc.StreamDesc{}, Metadata: "dagpool.proto", } + +// DagPoolClusterClient is the client API for DagPoolCluster service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type DagPoolClusterClient interface { + AddDagNode(ctx context.Context, in *DagNodeInfo, opts ...grpc.CallOption) (*emptypb.Empty, error) + GetDagNode(ctx context.Context, in *GetDagNodeReq, opts ...grpc.CallOption) (*DagNodeInfo, error) + RemoveDagNode(ctx context.Context, in *RemoveDagNodeReq, opts ...grpc.CallOption) (*DagNodeInfo, error) + MigrateSlots(ctx context.Context, in *MigrateSlotsReq, opts ...grpc.CallOption) (*emptypb.Empty, error) + BalanceSlots(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) + Status(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StatusReply, error) + RepairDataNode(ctx context.Context, in *RepairDataNodeReq, opts ...grpc.CallOption) (*emptypb.Empty, error) +} + +type dagPoolClusterClient struct { + cc grpc.ClientConnInterface +} + +func NewDagPoolClusterClient(cc grpc.ClientConnInterface) DagPoolClusterClient { + return &dagPoolClusterClient{cc} +} + +func (c *dagPoolClusterClient) AddDagNode(ctx context.Context, in *DagNodeInfo, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/proto.DagPoolCluster/AddDagNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dagPoolClusterClient) GetDagNode(ctx context.Context, in *GetDagNodeReq, opts ...grpc.CallOption) (*DagNodeInfo, error) { + out := new(DagNodeInfo) + err := c.cc.Invoke(ctx, "/proto.DagPoolCluster/GetDagNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dagPoolClusterClient) RemoveDagNode(ctx context.Context, in *RemoveDagNodeReq, opts ...grpc.CallOption) (*DagNodeInfo, error) { + out := new(DagNodeInfo) + err := c.cc.Invoke(ctx, "/proto.DagPoolCluster/RemoveDagNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dagPoolClusterClient) MigrateSlots(ctx context.Context, in *MigrateSlotsReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/proto.DagPoolCluster/MigrateSlots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dagPoolClusterClient) BalanceSlots(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/proto.DagPoolCluster/BalanceSlots", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dagPoolClusterClient) Status(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*StatusReply, error) { + out := new(StatusReply) + err := c.cc.Invoke(ctx, "/proto.DagPoolCluster/Status", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *dagPoolClusterClient) RepairDataNode(ctx context.Context, in *RepairDataNodeReq, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, "/proto.DagPoolCluster/RepairDataNode", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// DagPoolClusterServer is the server API for DagPoolCluster service. +// All implementations must embed UnimplementedDagPoolClusterServer +// for forward compatibility +type DagPoolClusterServer interface { + AddDagNode(context.Context, *DagNodeInfo) (*emptypb.Empty, error) + GetDagNode(context.Context, *GetDagNodeReq) (*DagNodeInfo, error) + RemoveDagNode(context.Context, *RemoveDagNodeReq) (*DagNodeInfo, error) + MigrateSlots(context.Context, *MigrateSlotsReq) (*emptypb.Empty, error) + BalanceSlots(context.Context, *emptypb.Empty) (*emptypb.Empty, error) + Status(context.Context, *emptypb.Empty) (*StatusReply, error) + RepairDataNode(context.Context, *RepairDataNodeReq) (*emptypb.Empty, error) + mustEmbedUnimplementedDagPoolClusterServer() +} + +// UnimplementedDagPoolClusterServer must be embedded to have forward compatible implementations. +type UnimplementedDagPoolClusterServer struct { +} + +func (UnimplementedDagPoolClusterServer) AddDagNode(context.Context, *DagNodeInfo) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddDagNode not implemented") +} +func (UnimplementedDagPoolClusterServer) GetDagNode(context.Context, *GetDagNodeReq) (*DagNodeInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetDagNode not implemented") +} +func (UnimplementedDagPoolClusterServer) RemoveDagNode(context.Context, *RemoveDagNodeReq) (*DagNodeInfo, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveDagNode not implemented") +} +func (UnimplementedDagPoolClusterServer) MigrateSlots(context.Context, *MigrateSlotsReq) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method MigrateSlots not implemented") +} +func (UnimplementedDagPoolClusterServer) BalanceSlots(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method BalanceSlots not implemented") +} +func (UnimplementedDagPoolClusterServer) Status(context.Context, *emptypb.Empty) (*StatusReply, error) { + return nil, status.Errorf(codes.Unimplemented, "method Status not implemented") +} +func (UnimplementedDagPoolClusterServer) RepairDataNode(context.Context, *RepairDataNodeReq) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method RepairDataNode not implemented") +} +func (UnimplementedDagPoolClusterServer) mustEmbedUnimplementedDagPoolClusterServer() {} + +// UnsafeDagPoolClusterServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to DagPoolClusterServer will +// result in compilation errors. +type UnsafeDagPoolClusterServer interface { + mustEmbedUnimplementedDagPoolClusterServer() +} + +func RegisterDagPoolClusterServer(s grpc.ServiceRegistrar, srv DagPoolClusterServer) { + s.RegisterService(&DagPoolCluster_ServiceDesc, srv) +} + +func _DagPoolCluster_AddDagNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DagNodeInfo) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DagPoolClusterServer).AddDagNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.DagPoolCluster/AddDagNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DagPoolClusterServer).AddDagNode(ctx, req.(*DagNodeInfo)) + } + return interceptor(ctx, in, info, handler) +} + +func _DagPoolCluster_GetDagNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetDagNodeReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DagPoolClusterServer).GetDagNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.DagPoolCluster/GetDagNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DagPoolClusterServer).GetDagNode(ctx, req.(*GetDagNodeReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _DagPoolCluster_RemoveDagNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RemoveDagNodeReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DagPoolClusterServer).RemoveDagNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.DagPoolCluster/RemoveDagNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DagPoolClusterServer).RemoveDagNode(ctx, req.(*RemoveDagNodeReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _DagPoolCluster_MigrateSlots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MigrateSlotsReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DagPoolClusterServer).MigrateSlots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.DagPoolCluster/MigrateSlots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DagPoolClusterServer).MigrateSlots(ctx, req.(*MigrateSlotsReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _DagPoolCluster_BalanceSlots_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DagPoolClusterServer).BalanceSlots(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.DagPoolCluster/BalanceSlots", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DagPoolClusterServer).BalanceSlots(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _DagPoolCluster_Status_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DagPoolClusterServer).Status(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.DagPoolCluster/Status", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DagPoolClusterServer).Status(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + +func _DagPoolCluster_RepairDataNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RepairDataNodeReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DagPoolClusterServer).RepairDataNode(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/proto.DagPoolCluster/RepairDataNode", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DagPoolClusterServer).RepairDataNode(ctx, req.(*RepairDataNodeReq)) + } + return interceptor(ctx, in, info, handler) +} + +// DagPoolCluster_ServiceDesc is the grpc.ServiceDesc for DagPoolCluster service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var DagPoolCluster_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "proto.DagPoolCluster", + HandlerType: (*DagPoolClusterServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "AddDagNode", + Handler: _DagPoolCluster_AddDagNode_Handler, + }, + { + MethodName: "GetDagNode", + Handler: _DagPoolCluster_GetDagNode_Handler, + }, + { + MethodName: "RemoveDagNode", + Handler: _DagPoolCluster_RemoveDagNode_Handler, + }, + { + MethodName: "MigrateSlots", + Handler: _DagPoolCluster_MigrateSlots_Handler, + }, + { + MethodName: "BalanceSlots", + Handler: _DagPoolCluster_BalanceSlots_Handler, + }, + { + MethodName: "Status", + Handler: _DagPoolCluster_Status_Handler, + }, + { + MethodName: "RepairDataNode", + Handler: _DagPoolCluster_RepairDataNode_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "dagpool.proto", +} diff --git a/dag/slotsmgr/bitset.go b/dag/slotsmgr/bitset.go new file mode 100644 index 00000000..152ed9d3 --- /dev/null +++ b/dag/slotsmgr/bitset.go @@ -0,0 +1,63 @@ +package slotsmgr + +import "errors" + +const ( + shift = 6 // 2^6 = 64 + mask = 0x3f // 63 +) + +var IndexOutOfBoundError = errors.New("index should be less than max size") + +type BitSet struct { + data []uint64 // 64 bits + max uint64 +} + +func NewBitSet(size uint64) *BitSet { + return &BitSet{ + data: make([]uint64, size>>shift+1), + max: size, + } +} + +func (bs *BitSet) Get(index uint64) (bool, error) { + if index >= bs.max { + return false, IndexOutOfBoundError + } + idx := index >> shift + return bs.data[idx]&(1<= bs.max { + return false, IndexOutOfBoundError + } + idx := index >> shift + oldValue, err = bs.Get(index) + if err != nil { + return false, err + } + if !oldValue && value { + bs.data[idx] |= 1 << uint(index&mask) // The corresponding bit is set to 1 + } else if oldValue && !value { + bs.data[idx] &^= 1 << uint(index&mask) // The corresponding bit is set to 0 + } + return oldValue, nil +} + +func (bs *BitSet) Count() uint64 { + var count uint64 + for _, b := range bs.data { + count += swar(b) + } + return count +} + +func swar(i uint64) uint64 { + i = (i & 0x5555555555555555) + ((i >> 1) & 0x5555555555555555) + i = (i & 0x3333333333333333) + ((i >> 2) & 0x3333333333333333) + i = (i & 0x0F0F0F0F0F0F0F0F) + ((i >> 4) & 0x0F0F0F0F0F0F0F0F) + i = (i * 0x0101010101010101) >> 56 + return i +} diff --git a/dag/slotsmgr/slots_mgr.go b/dag/slotsmgr/slots_mgr.go new file mode 100644 index 00000000..21885692 --- /dev/null +++ b/dag/slotsmgr/slots_mgr.go @@ -0,0 +1,93 @@ +package slotsmgr + +import ( + "errors" + "fmt" +) + +const ClusterSlots = 16384 + +var IndexRangeError = errors.New("end index should be equal or greater than start index") + +// SlotPair means a range of [start, end] +type SlotPair struct { + Start uint64 + End uint64 +} + +func (sp SlotPair) String() string { + if sp.Start == sp.End { + return fmt.Sprintf("%v", sp.Start) + } + return fmt.Sprintf("%v-%v", sp.Start, sp.End) +} + +func (sp SlotPair) Count() uint64 { + return sp.End - sp.Start + 1 +} + +type SlotsManager struct { + bitset *BitSet +} + +func NewSlotsManager() *SlotsManager { + return &SlotsManager{ + bitset: NewBitSet(ClusterSlots), + } +} + +func (hs *SlotsManager) Get(index uint64) (bool, error) { + return hs.bitset.Get(index) +} + +func (hs *SlotsManager) Set(index uint64, value bool) (bool, error) { + return hs.bitset.Set(index, value) +} + +func (hs *SlotsManager) Count() uint64 { + return hs.bitset.Count() +} + +func (hs *SlotsManager) SetRange(pair SlotPair, value bool) error { + if pair.Start > pair.End { + return IndexRangeError + } + for i := pair.Start; i <= pair.End; i++ { + if _, err := hs.bitset.Set(i, value); err != nil { + return err + } + } + return nil +} + +func (hs *SlotsManager) ToSlotPair() []SlotPair { + var slotPairs []SlotPair + pair := SlotPair{} + isSetStart := false + for i, n := range hs.bitset.data { + if !isSetStart && n == 0 { + continue + } + if isSetStart && n == 0xffffffffffffffff { + continue + } + start := i << shift + end := (i + 1) << shift + for ; start < end; start++ { + if n&(1<= et.entrySuccessQuorum { + return nil + } + } else { + failureCount += 1 + if failureCount >= et.entryFailureQuorum { + // return last error + return err + } + } + + case <-et.cancelCtx.Done(): + return et.cancelCtx.Err() + } + } + +} + +func (et *ParallelTask) clean() { + go func() { + et.cancel() + et.wg.Wait() + close(et.resCh) + }() +} diff --git a/dag/utils/utils.go b/dag/utils/utils.go new file mode 100644 index 00000000..0bcf1291 --- /dev/null +++ b/dag/utils/utils.go @@ -0,0 +1,53 @@ +package utils + +import ( + "github.com/filedag-project/filedag-storage/dag/config" + "github.com/filedag-project/filedag-storage/dag/proto" + "github.com/filedag-project/filedag-storage/dag/slotsmgr" +) + +func ToDagNodeConfig(node *proto.DagNodeInfo) *config.DagNodeConfig { + dataNodes := make([]string, 0, len(node.Nodes)) + for _, nd := range node.Nodes { + dataNodes = append(dataNodes, nd.RpcAddress) + } + cfg := &config.DagNodeConfig{ + Name: node.Name, + Nodes: dataNodes, + DataBlocks: int(node.DataBlocks), + ParityBlocks: int(node.ParityBlocks), + } + return cfg +} + +func ToProtoDagNodeInfo(node *config.DagNodeConfig) *proto.DagNodeInfo { + dataNodes := make([]*proto.DataNodeInfo, 0, len(node.Nodes)) + for _, nd := range node.Nodes { + dataNodes = append(dataNodes, &proto.DataNodeInfo{ + RpcAddress: nd, + }) + } + nodeInfo := &proto.DagNodeInfo{ + Name: node.Name, + Nodes: dataNodes, + DataBlocks: int32(node.DataBlocks), + ParityBlocks: int32(node.ParityBlocks), + } + return nodeInfo +} + +func ToSlotPairs(pairs []*proto.SlotPair) []slotsmgr.SlotPair { + newPairs := make([]slotsmgr.SlotPair, 0, len(pairs)) + for _, p := range pairs { + newPairs = append(newPairs, slotsmgr.SlotPair{Start: uint64(p.Start), End: uint64(p.End)}) + } + return newPairs +} + +func ToProtoSlotPairs(pairs []slotsmgr.SlotPair) []*proto.SlotPair { + newPairs := make([]*proto.SlotPair, 0, len(pairs)) + for _, p := range pairs { + newPairs = append(newPairs, &proto.SlotPair{Start: uint32(p.Start), End: uint32(p.End)}) + } + return newPairs +} diff --git a/docs/Architecture-m3.png b/docs/Architecture-m3.png new file mode 100644 index 00000000..9d80549e Binary files /dev/null and b/docs/Architecture-m3.png differ diff --git a/docs/architecture-cn.md b/docs/architecture-cn.md index 76b714a3..c50a4e8f 100644 --- a/docs/architecture-cn.md +++ b/docs/architecture-cn.md @@ -1,11 +1,11 @@ # Architecture -![comparison diagram](./Architecture-m1.png) +![comparison diagram](./Architecture-m3.png) -FileDag Storage Milestone 1的整体架构是分层的,由三个部分组成:存储层、池层和对象层。每一层实现都是独立的、灵活的、可持续迭代的,因为它们之间只通过RPC协议进行交互。 +FileDag Storage Milestone 3的整体架构是分层的,由三个部分组成:存储层、池层和对象层。每一层实现都是独立的、灵活的、可持续迭代的,因为它们之间只通过RPC协议进行交互。 我们来看看最底层Storage layer,它主要关注数据块的存储,解决快速高效的读写问题。目前采用的是键值存储方案。 -中间层Pool层主要管理DAG结构化数据的读写和访问权限控制。它管理DagNode集群。每个DagNode管理多个datanode,采用Erasure Coding分片技术。每个片段通过DataNode Client存储到相应的DataNode服务中。已经根据Milestone 1实现了单个DagNode方案。DagPool客户端实现了块存储接口,可以在任何需要块存储的地方使用。 +中间层Pool层主要管理DAG结构化数据的读写和访问权限控制。它管理DagNode集群。每个DagNode管理多个datanode,采用Erasure Coding分片技术。每个片段通过DataNode Client存储到相应的DataNode服务中。DagPool客户端实现了块存储接口,可以在任何需要块存储的地方使用。 最后,最上层对象层实现对象存储的全部功能,主要分为S3、IAM和Store。因此,FileDag Storage兼容S3接口,具有身份权限控制。 diff --git a/docs/architecture.md b/docs/architecture.md index 6b4c02e0..741ba20d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -1,11 +1,11 @@ # Architecture -![comparison diagram](./Architecture-m1.png) +![comparison diagram](./Architecture-m3.png) -The overall architecture of FileDag Storage Milestone 1 is layered and consists of three parts: Storage Layer, Pool Layer, and Object Layer. Each layer of implementation is independent, flexible, and continuously evolving because they interact with each other only through the RPC protocol. +The overall architecture of FileDag Storage Milestone 3 is layered and consists of three parts: Storage Layer, Pool Layer, and Object Layer. Each layer of implementation is independent, flexible, and continuously evolving because they interact with each other only through the RPC protocol. Let's take a look at the lowest layer Storage Layer, which mainly focuses on the Storage of data blocks and solves the problem of fast and efficient read and write. Currently, the key value Storage scheme is adopted. -The middle layer, Pool Layer, mainly manages the read/write and access permission control of DAG structured data. It manages DagNode cluster. Each DagNode manages several Datanodes and adopts Erasure Coding fragmentation technology. Each fragment is stored to the corresponding DataNode service through the DataNode Client. A single DagNode scheme has been implemented according to milestone 1. DagPool Client implements the blockstore interface and can be used anywhere blockstore is required. +The middle layer, Pool Layer, mainly manages the read/write and access permission control of DAG structured data. It manages DagNode cluster. Each DagNode manages several Datanodes and adopts Erasure Coding fragmentation technology. Each fragment is stored to the corresponding DataNode service through the DataNode Client. DagPool Client implements the blockstore interface and can be used anywhere blockstore is required. Finally, the upper layer Object Layer implements the whole functions of Object storage, which is mainly divided into S3, IAM and Store. Therefore, FileDag Storage is compatible with S3 interfaces and has identity permission control. \ No newline at end of file diff --git a/example/dagpool/main.go b/example/dagpool/main.go index 37dd09be..11e10a7d 100644 --- a/example/dagpool/main.go +++ b/example/dagpool/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "flag" "fmt" @@ -66,16 +67,26 @@ func run(leveldbPath, listenAddr, nodeConfigPath, user, pass string) { nodeConfigs = append(nodeConfigs, nc) } cfg := config.PoolConfig{ - DagNodeConfig: nodeConfigs, - LeveldbPath: leveldbPath, - RootUser: user, - RootPassword: pass, + LeveldbPath: leveldbPath, + RootUser: user, + RootPassword: pass, } - service, err := poolservice.NewDagPoolService(cfg) + service, err := poolservice.NewDagPoolService(context.TODO(), cfg) if err != nil { fmt.Printf("NewDagPoolService err:%v\n", err) return } + for _, nd := range nodeConfigs { + err = service.AddDagNode(&nd) + if err != nil { + fmt.Printf("AddDagNode err:%v\n", err) + return + } + } + if err = service.BalanceSlots(); err != nil { + fmt.Printf("BalanceSlots err:%v\n", err) + return + } proto.RegisterDagPoolServer(s, &server.DagPoolServer{DagPool: service}) fmt.Printf("server listening at %v\n", lis.Addr()) if err := s.Serve(lis); err != nil { diff --git a/go.mod b/go.mod index c936b9bc..87ac5605 100644 --- a/go.mod +++ b/go.mod @@ -32,13 +32,13 @@ require ( github.com/libp2p/go-buffer-pool v0.0.2 github.com/rs/cors v1.8.2 github.com/shirou/gopsutil v3.21.11+incompatible - github.com/stretchr/testify v1.7.1 + github.com/stretchr/testify v1.8.0 github.com/syndtr/goleveldb v1.0.0 github.com/urfave/cli/v2 v2.16.3 github.com/vmihailenco/msgpack/v5 v5.3.5 - go.uber.org/zap v1.19.1 + go.uber.org/zap v1.21.0 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 - google.golang.org/grpc v1.40.0 + google.golang.org/grpc v1.44.0 google.golang.org/protobuf v1.28.0 ) @@ -56,7 +56,8 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.1 // indirect - github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f // indirect + github.com/google/go-cmp v0.5.8 // indirect + github.com/gopherjs/gopherjs v0.0.0-20220104163920-15ed2e8cf2bd // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-bitfield v1.0.0 // indirect @@ -79,7 +80,7 @@ require ( github.com/libp2p/go-libp2p-core v0.9.0 // indirect github.com/libp2p/go-libp2p-record v0.1.3 // indirect github.com/libp2p/go-libp2p-testing v0.4.2 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect github.com/minio/sha256-simd v1.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -95,10 +96,10 @@ require ( github.com/onsi/gomega v1.13.0 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/smartystreets/assertions v1.0.1 // indirect + github.com/smartystreets/assertions v1.1.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/numcpus v0.4.0 // indirect @@ -111,14 +112,14 @@ require ( go.opentelemetry.io/otel v1.7.0 // indirect go.opentelemetry.io/otel/trace v1.7.0 // indirect go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.7.0 // indirect + go.uber.org/multierr v1.8.0 // indirect go4.org v0.0.0-20200411211856-f5505b9728dd // indirect - golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect + golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa // indirect + golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e // indirect + golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect golang.org/x/text v0.3.7 // indirect - google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect + google.golang.org/genproto v0.0.0-20220302033224-9aa15565e42a // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/blake3 v1.1.6 // indirect diff --git a/go.sum b/go.sum index 62c8ef70..1581d925 100644 --- a/go.sum +++ b/go.sum @@ -15,6 +15,11 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -23,6 +28,7 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -81,6 +87,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw= github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= @@ -117,8 +124,13 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -127,10 +139,12 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= @@ -169,8 +183,11 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= @@ -210,6 +227,7 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -234,6 +252,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -252,6 +271,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -266,11 +286,14 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -280,6 +303,7 @@ github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -287,6 +311,10 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -299,8 +327,8 @@ github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE0 github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f h1:KMlcu9X58lhTA/KrfX8Bi1LQSO4pzoVjTiL3h4Jk+Zk= -github.com/gopherjs/gopherjs v0.0.0-20190812055157-5d271430af9f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20220104163920-15ed2e8cf2bd h1:D/H64OK+VY7O0guGbCQaFKwAZlU5t764R++kgIdAGog= +github.com/gopherjs/gopherjs v0.0.0-20220104163920-15ed2e8cf2bd/go.mod h1:cz9oNYuRUWGdHmLF2IodMLkAhcPtXeULvcBNagUrxTI= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= @@ -317,7 +345,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU= github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -349,6 +379,7 @@ github.com/huin/goupnp v1.0.2 h1:RfGLP+h3mvisuWEyybxNq5Eft3NWhHLPeUN72kpKZoI= github.com/huin/goupnp v1.0.2/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM= github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= @@ -526,6 +557,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk= github.com/koron/go-ssdp v0.0.2 h1:fL3wAoyT6hXHQlORyXUW4Q23kkQpJRgEAYcZB5BR71o= github.com/koron/go-ssdp v0.0.2/go.mod h1:XoLfkAiA2KeZsYh4DbHxD7h3nR2AZNqVQOa+LJuqPYs= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -735,6 +767,7 @@ github.com/lucas-clemente/quic-go v0.21.2/go.mod h1:vF5M1XqhBAHgbjKcJOXY3JZz3GP0 github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= @@ -751,8 +784,9 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -783,6 +817,7 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -865,6 +900,7 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -904,6 +940,7 @@ github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIw github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= @@ -912,8 +949,10 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polydawn/refmt v0.0.0-20190221155625-df39d6c2d992/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20190807091052-3d65705ee9f1/go.mod h1:uIp+gprXxxrWSjjklXD+mN4wed/tMfjMMmN/9+JsA9o= github.com/polydawn/refmt v0.0.0-20201211092308-30ac6d18308e h1:ZOcivgkkFRnjfoTcGsDq3UQYiBmekwLA+qg0OjyB/ls= @@ -976,6 +1015,7 @@ github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIl github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= @@ -985,6 +1025,7 @@ github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9A github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= @@ -994,13 +1035,14 @@ github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1l github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w= -github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck= +github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/goconvey v0.0.0-20190222223459-a17d461953aa/go.mod h1:2RVY1rIf+2J2o/IM9+vPq9RzmHDSseB7FoXiSNIUsoU= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1016,27 +1058,36 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -1089,6 +1140,9 @@ github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPR github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= @@ -1098,6 +1152,7 @@ go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk= @@ -1113,23 +1168,27 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8= +go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= +go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= +go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20200411211856-f5505b9728dd h1:BNJlw5kRTzdmyfh5U8F93HA2OwkP7ZGwA51eJ/0wKOU= go4.org v0.0.0-20200411211856-f5505b9728dd/go.mod h1:CIiUVy99QCPfoE13bO4EZaz5GZMZXMSBGhxRdsvzbkg= @@ -1150,6 +1209,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1160,9 +1220,10 @@ golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa h1:zuSxTR4o9y82ebqCUJYNGJbGPo6sKVl54f/TVDObg1c= +golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1186,6 +1247,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -1194,6 +1257,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1239,7 +1304,9 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= @@ -1248,8 +1315,10 @@ golang.org/x/net v0.0.0-20210423184538-5f58ad60dda6/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1257,6 +1326,13 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1329,16 +1405,24 @@ golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1349,8 +1433,10 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e h1:CsOuNlbOuf0mzxJIefr6Q4uAUetRUwZE4qt7VfzP+xo= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1359,6 +1445,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -1390,6 +1478,7 @@ golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1418,9 +1507,16 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1447,6 +1543,12 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1455,6 +1557,7 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -1489,8 +1592,20 @@ google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEY google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20220302033224-9aa15565e42a h1:uqouglH745GoGeZ1YFZbPBiu961tgi/9Qm5jaorajjQ= +google.golang.org/genproto v0.0.0-20220302033224-9aa15565e42a/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1514,9 +1629,14 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= +google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1543,6 +1663,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8= gopkg.in/src-d/go-log.v1 v1.0.1/go.mod h1:GN34hKP0g305ysm2/hctJ0Y8nWP3zxXXJ8GFabTyABE= diff --git a/testscript/cluster/cluster-data-clean.sh b/testscript/cluster/cluster-data-clean.sh new file mode 100755 index 00000000..89d86788 --- /dev/null +++ b/testscript/cluster/cluster-data-clean.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +rm -rf /tmp/dn-data* +rm -f /tmp/dn*.log +rm -rf /tmp/dp-db +rm -f /tmp/dp.log +rm -rf /tmp/store-data +rm -f /tmp/objstore.log \ No newline at end of file diff --git a/testscript/cluster/cluster-init.sh b/testscript/cluster/cluster-init.sh new file mode 100755 index 00000000..6e3ae681 --- /dev/null +++ b/testscript/cluster/cluster-init.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +dir=$(dirname $0) + +$dir/../../dagpool cluster add $dir/../../conf/node_config.json $dir/../../conf/node_config2.json $dir/../../conf/node_config3.json +$dir/../../dagpool cluster balance \ No newline at end of file diff --git a/testscript/cluster/cluster-start.sh b/testscript/cluster/cluster-start.sh new file mode 100755 index 00000000..8b102b6d --- /dev/null +++ b/testscript/cluster/cluster-start.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +dir=$(dirname $0) + +$dir/datanodes-start.sh + +nohup $dir/../../dagpool daemon --datadir=/tmp/dp-db > /tmp/dp.log 2>&1 & + +nohup $dir/../../objectstore daemon --datadir=/tmp/store-data --pool-addr=127.0.0.1:50001 --pool-user=dagpool --pool-password=dagpool > /tmp/objstore.log 2>&1 & \ No newline at end of file diff --git a/testscript/cluster/cluster-stop.sh b/testscript/cluster/cluster-stop.sh new file mode 100755 index 00000000..ecdcab8e --- /dev/null +++ b/testscript/cluster/cluster-stop.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +dir=$(dirname $0) + +$dir/datanodes-stop.sh + +ps -ef | grep dagpool | awk '{print $2}' | xargs kill + +ps -ef | grep objectstore | awk '{print $2}' | xargs kill \ No newline at end of file diff --git a/testscript/cluster/datanodes-start.sh b/testscript/cluster/datanodes-start.sh new file mode 100755 index 00000000..36faeac6 --- /dev/null +++ b/testscript/cluster/datanodes-start.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +dir=$(dirname $0) + +nohup $dir/../../datanode daemon --listen=127.0.0.1:9011 --datadir=/tmp/dn-data1 > /tmp/dn1.log 2>&1 & +nohup $dir/../../datanode daemon --listen=127.0.0.1:9012 --datadir=/tmp/dn-data2 > /tmp/dn2.log 2>&1 & +nohup $dir/../../datanode daemon --listen=127.0.0.1:9013 --datadir=/tmp/dn-data3 > /tmp/dn3.log 2>&1 & + +nohup $dir/../../datanode daemon --listen=127.0.0.1:9014 --datadir=/tmp/dn-data4 > /tmp/dn4.log 2>&1 & +nohup $dir/../../datanode daemon --listen=127.0.0.1:9015 --datadir=/tmp/dn-data5 > /tmp/dn5.log 2>&1 & +nohup $dir/../../datanode daemon --listen=127.0.0.1:9016 --datadir=/tmp/dn-data6 > /tmp/dn6.log 2>&1 & + +nohup $dir/../../datanode daemon --listen=127.0.0.1:9017 --datadir=/tmp/dn-data7 > /tmp/dn7.log 2>&1 & +nohup $dir/../../datanode daemon --listen=127.0.0.1:9018 --datadir=/tmp/dn-data8 > /tmp/dn8.log 2>&1 & +nohup $dir/../../datanode daemon --listen=127.0.0.1:9019 --datadir=/tmp/dn-data9 > /tmp/dn9.log 2>&1 & \ No newline at end of file diff --git a/testscript/cluster/datanodes-stop.sh b/testscript/cluster/datanodes-stop.sh new file mode 100755 index 00000000..a3321422 --- /dev/null +++ b/testscript/cluster/datanodes-stop.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +ps -ef | grep datanode | awk '{print $2}' | xargs kill